mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
102 lines
3.6 KiB
Swift
102 lines
3.6 KiB
Swift
import Foundation
|
|
import UIKit
|
|
|
|
public final class Text: Component {
|
|
private final class MeasureState: Equatable {
|
|
let attributedText: NSAttributedString
|
|
let availableSize: CGSize
|
|
let size: CGSize
|
|
|
|
init(attributedText: NSAttributedString, availableSize: CGSize, size: CGSize) {
|
|
self.attributedText = attributedText
|
|
self.availableSize = availableSize
|
|
self.size = size
|
|
}
|
|
|
|
static func ==(lhs: MeasureState, rhs: MeasureState) -> Bool {
|
|
if !lhs.attributedText.isEqual(rhs.attributedText) {
|
|
return false
|
|
}
|
|
if lhs.availableSize != rhs.availableSize {
|
|
return false
|
|
}
|
|
if lhs.size != rhs.size {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
public final class View: UIView {
|
|
private var measureState: MeasureState?
|
|
|
|
public func update(component: Text, availableSize: CGSize) -> CGSize {
|
|
let attributedText = NSAttributedString(string: component.text, attributes: [
|
|
NSAttributedString.Key.font: component.font,
|
|
NSAttributedString.Key.foregroundColor: component.color
|
|
])
|
|
|
|
if let measureState = self.measureState {
|
|
if measureState.attributedText.isEqual(to: attributedText) && measureState.availableSize == availableSize {
|
|
return measureState.size
|
|
}
|
|
}
|
|
|
|
var boundingRect = attributedText.boundingRect(with: availableSize, options: .usesLineFragmentOrigin, context: nil)
|
|
boundingRect.size.width = ceil(boundingRect.size.width)
|
|
boundingRect.size.height = ceil(boundingRect.size.height)
|
|
|
|
let measureState = MeasureState(attributedText: attributedText, availableSize: availableSize, size: boundingRect.size)
|
|
if #available(iOS 10.0, *) {
|
|
let renderer = UIGraphicsImageRenderer(bounds: CGRect(origin: CGPoint(), size: measureState.size))
|
|
let image = renderer.image { context in
|
|
UIGraphicsPushContext(context.cgContext)
|
|
measureState.attributedText.draw(at: CGPoint())
|
|
UIGraphicsPopContext()
|
|
}
|
|
self.layer.contents = image.cgImage
|
|
} else {
|
|
UIGraphicsBeginImageContextWithOptions(measureState.size, false, 0.0)
|
|
measureState.attributedText.draw(at: CGPoint())
|
|
self.layer.contents = UIGraphicsGetImageFromCurrentImageContext()?.cgImage
|
|
UIGraphicsEndImageContext()
|
|
}
|
|
|
|
self.measureState = measureState
|
|
|
|
return boundingRect.size
|
|
}
|
|
}
|
|
|
|
public let text: String
|
|
public let font: UIFont
|
|
public let color: UIColor
|
|
|
|
public init(text: String, font: UIFont, color: UIColor) {
|
|
self.text = text
|
|
self.font = font
|
|
self.color = color
|
|
}
|
|
|
|
public static func ==(lhs: Text, rhs: Text) -> Bool {
|
|
if lhs.text != rhs.text {
|
|
return false
|
|
}
|
|
if !lhs.font.isEqual(rhs.font) {
|
|
return false
|
|
}
|
|
if !lhs.color.isEqual(rhs.color) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
public func makeView() -> View {
|
|
return View()
|
|
}
|
|
|
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
|
return view.update(component: self, availableSize: availableSize)
|
|
}
|
|
}
|