136 lines
4.3 KiB
Swift
136 lines
4.3 KiB
Swift
#if os(iOS)
|
|
import UIKit
|
|
#elseif os(OSX)
|
|
import AppKit
|
|
#endif
|
|
|
|
open class Text: Node {
|
|
|
|
public let textVar: Variable<String>
|
|
open var text: String {
|
|
get { return textVar.value }
|
|
set(val) { textVar.value = val }
|
|
}
|
|
|
|
public let fontVar: Variable<Font?>
|
|
open var font: Font? {
|
|
get { return fontVar.value }
|
|
set(val) { fontVar.value = val }
|
|
}
|
|
|
|
public let fillVar: Variable<Fill?>
|
|
open var fill: Fill? {
|
|
get { return fillVar.value }
|
|
set(val) { fillVar.value = val }
|
|
}
|
|
|
|
public let strokeVar: Variable<Stroke?>
|
|
open var stroke: Stroke? {
|
|
get { return strokeVar.value }
|
|
set(val) { strokeVar.value = val }
|
|
}
|
|
|
|
public let alignVar: Variable<Align>
|
|
open var align: Align {
|
|
get { return alignVar.value }
|
|
set(val) { alignVar.value = val }
|
|
}
|
|
|
|
public let baselineVar: Variable<Baseline>
|
|
open var baseline: Baseline {
|
|
get { return baselineVar.value }
|
|
set(val) { baselineVar.value = val }
|
|
}
|
|
|
|
public let kerningVar: Variable<Float>
|
|
open var kerning: Float {
|
|
get { return kerningVar.value }
|
|
set(val) { kerningVar.value = val }
|
|
}
|
|
|
|
public init(text: String, font: Font? = nil, fill: Fill? = Color.black, stroke: Stroke? = nil, align: Align = .min, baseline: Baseline = .top, kerning: Float = 0.0, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, mask: Node? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
|
|
self.textVar = Variable<String>(text)
|
|
self.fontVar = Variable<Font?>(font)
|
|
self.fillVar = Variable<Fill?>(fill)
|
|
self.strokeVar = Variable<Stroke?>(stroke)
|
|
self.alignVar = Variable<Align>(align)
|
|
self.baselineVar = Variable<Baseline>(baseline)
|
|
self.kerningVar = Variable<Float>(kerning)
|
|
super.init(
|
|
place: place,
|
|
opaque: opaque,
|
|
opacity: opacity,
|
|
clip: clip,
|
|
mask: mask,
|
|
effect: effect,
|
|
visible: visible,
|
|
tag: tag
|
|
)
|
|
}
|
|
|
|
override open var bounds: Rect {
|
|
let font: MFont
|
|
if let f = self.font {
|
|
|
|
if let customFont = RenderUtils.loadFont(name: f.name, size: f.size, weight: f.weight) {
|
|
font = customFont
|
|
} else {
|
|
font = MFont.systemFont(ofSize: CGFloat(f.size), weight: getWeight(f.weight))
|
|
}
|
|
} else {
|
|
font = MFont.systemFont(ofSize: MFont.mSystemFontSize)
|
|
}
|
|
var stringAttributes: [NSAttributedString.Key: AnyObject] = [:]
|
|
stringAttributes[NSAttributedString.Key.font] = font
|
|
if self.kerning != 0.0 {
|
|
stringAttributes[NSAttributedString.Key.kern] = NSNumber(value: self.kerning)
|
|
}
|
|
let size = (text as NSString).size(withAttributes: stringAttributes)
|
|
return Rect(
|
|
x: calculateAlignmentOffset(font: font),
|
|
y: calculateBaselineOffset(font: font),
|
|
w: size.width.doubleValue,
|
|
h: size.height.doubleValue
|
|
)
|
|
}
|
|
|
|
fileprivate func getWeight(_ weight: String) -> MFont.Weight {
|
|
switch weight {
|
|
case "normal":
|
|
return MFont.Weight.regular
|
|
case "bold":
|
|
return MFont.Weight.bold
|
|
case "bolder":
|
|
return MFont.Weight.semibold
|
|
case "lighter":
|
|
return MFont.Weight.light
|
|
default:
|
|
return MFont.Weight.regular
|
|
}
|
|
}
|
|
|
|
fileprivate func calculateBaselineOffset(font: MFont) -> Double {
|
|
var baselineOffset = 0.0
|
|
switch baseline {
|
|
case .alphabetic:
|
|
baselineOffset = font.ascender.doubleValue
|
|
case .bottom:
|
|
baselineOffset = (font.ascender - font.descender).doubleValue
|
|
case .mid:
|
|
baselineOffset = ((font.ascender - font.descender) / 2).doubleValue
|
|
default:
|
|
break
|
|
}
|
|
return -baselineOffset
|
|
}
|
|
|
|
fileprivate func calculateAlignmentOffset(font: MFont) -> Double {
|
|
let textAttributes = [
|
|
NSAttributedString.Key.font: font
|
|
]
|
|
let textSize = NSString(string: text).size(withAttributes: textAttributes)
|
|
return -align.align(size: textSize.width.doubleValue)
|
|
}
|
|
|
|
}
|