ios - 给定具有任何pointSize的UIFont,如何计算适当的笔划宽度?
问题描述
我想将单个实线笔划应用于文本。这很容易通过NSAttributedString
指定.strokeWidth
. 但是,我发现确定strokeWidth
应该UIFont
在任何给定的情况下呈现什么是棘手的pointSize
。我可以很容易地说,在点大小为 50 时,笔画宽度为 1 看起来很棒。我直观地假设,如果将字体大小加倍,则应该将笔划宽度加倍,因此当字体缩放时,笔划将按比例缩放,并导致笔划粗细看起来与原始“基本”字体大小一致。然而,这不是发生的事情。随着字体大小和笔画宽度成比例增加,笔画宽度变得太粗了。
此处的屏幕截图显示第一行的字体大小为 50,笔划宽度为 1。下一行被加倍,因此字体大小为 100,笔划宽度为 2,并重复此操作,直到最后一行是 350 vs 7。
我相信这是因为笔画是向内和向外渲染的。它的中心位于角色的边缘,然后向两个方向扩展。如果您比较这两张图片,您可以看到这一点,这张没有应用笔划。
因此,随着字体大小的增加,笔划宽度不应按比例增加,它需要以较慢的速度增加,以确保所有尺寸的粗细一致。我正在尝试确定计算此值的正确方法。
所以给定一个看起来很理想的基本配置(比如说 50pt 字体大小和 1pt 笔划宽度)和一个新配置pointSize
(例如 350pt),你如何计算正确的strokeWidth
?或者也许我不应该使用不同的值pointSize
?
我当前按比例缩放的算法是:(
let strokeWidth = font.pointSize / 50
只需求解 x in 1/50 = x/pointSize
)
这是我用来绘制此文本的代码:
let text = "hello"
let imageRect = CGRect(x: 0, y: 0, width: 343 * 3, height: 500 * 3)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let alphaInfo = CGImageAlphaInfo.premultipliedLast.rawValue
let bitmapContext = CGContext(data: nil, width: Int(imageRect.width), height: Int(imageRect.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: alphaInfo)!
bitmapContext.setAlpha(1)
bitmapContext.setTextDrawingMode(CGTextDrawingMode.fill)
//1
bitmapContext.textPosition = CGPoint(x: 40, y: 1080)
let displayLineText1 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 50), .strokeColor: UIColor.red, .strokeWidth: 1]))
CTLineDraw(displayLineText1, bitmapContext)
//2
bitmapContext.textPosition = CGPoint(x: 40, y: 1000)
let displayLineText2 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 100), .strokeColor: UIColor.red, .strokeWidth: 2]))
CTLineDraw(displayLineText2, bitmapContext)
//3
bitmapContext.textPosition = CGPoint(x: 40, y: 875)
let displayLineText3 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 150), .strokeColor: UIColor.red, .strokeWidth: 3]))
CTLineDraw(displayLineText3, bitmapContext)
//4
bitmapContext.textPosition = CGPoint(x: 40, y: 725)
let displayLineText4 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 200), .strokeColor: UIColor.red, .strokeWidth: 4]))
CTLineDraw(displayLineText4, bitmapContext)
//5
bitmapContext.textPosition = CGPoint(x: 40, y: 540)
let displayLineText5 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 250), .strokeColor: UIColor.red, .strokeWidth: 5]))
CTLineDraw(displayLineText5, bitmapContext)
//6
bitmapContext.textPosition = CGPoint(x: 40, y: 310)
let displayLineText6 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 300), .strokeColor: UIColor.red, .strokeWidth: 6]))
CTLineDraw(displayLineText6, bitmapContext)
//7
bitmapContext.textPosition = CGPoint(x: 40, y: 40)
let displayLineText7 = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 350), .strokeColor: UIColor.red, .strokeWidth: 7]))
CTLineDraw(displayLineText7, bitmapContext)
let textCGImage = bitmapContext.makeImage()!
let textImage = CIImage(cgImage: textCGImage)
解决方案
从(重点添加)的文档中:.strokeWidth
该属性的值是一个
NSNumber
包含浮点值的对象。此值表示更改笔画宽度的量,并指定为字体点大小的百分比。指定 0(默认值)表示不进行其他更改。指定正值以单独更改笔划宽度。指定负值来描边和填充文本。例如,轮廓文本的典型值为 3.0。
因此,该值已经缩放到字体大小。您也不应该自己缩放它。选择一个值,该值可以在任何给定字体大小下给出您喜欢的相对笔画宽度,并将其用于所有字体大小。
推荐阅读
- docker - 如何从运行在 Pod 中的容器访问 Node 服务
- stm32 - STM32 HSE不稳定频率
- ios - 禁用错误的电话号码链接检测 UITextView Swift
- scala - Spark - 将 Array[Array[Map[String,String]]] 类型的列处理成 udf 时出现 java.lang.ClassCastException
- python - 为什么python输出不能正确保存
- javascript - 我如何在javascript中返回两个对象
- haskell - 为什么 GHC 在使用 Coercible 约束时会自相矛盾?
- apache-kafka - 如何解析包含 Union、Map、Array 等的嵌套 GenericRecord?
- ios - 使用未解析的标识符“地图”SwiftUI
- python - 终止循环的问题