Как рассчитать подходящую ширину обводки с учетом UIFont с любым pointSize? - PullRequest
0 голосов
/ 15 декабря 2018

Я хотел бы применить один текст сплошной линии к тексту.Это легко получить, используя NSAttributedString, указав .strokeWidth.Однако я считаю, что было бы сложно определить, что strokeWidth должно быть предоставлено UIFont для визуализации в любой данный pointSize.Я легко могу сказать, что при размере точки 50 ширина штриха 1 выглядит великолепно.Я интуитивно предположил, что если вы удвоите размер шрифта, вы должны удвоить ширину обводки, таким образом, при масштабировании шрифта обводка будет пропорционально масштабироваться, и в результате толщина обводки будет соответствовать исходному «базовому» размеру шрифта.Однако это не то, что происходит.По мере пропорционального увеличения размера шрифта и ширины обводки ширина обводки становится слишком толстой.

enter image description here

На снимке экрана здесь показана первая строка размера шрифта50 и ширина обводки 1. Следующая строка удваивается, поэтому размер шрифта 100 обводки шириной 2, и это повторяется до последней строки, которая равна 350 против 7.

Я считаю, что это происходит, потому что обводка отображаетсякак внутрь, так и наружу.Его центр находится на краю персонажа, затем он расширяется в обоих направлениях.Вы можете увидеть это, если сравнить эти два изображения, это без примененного обводки.

enter image description here

Так как размер шрифта увеличивается, ширина обводки должнане увеличиваться пропорционально, его нужно увеличивать более медленными темпами, чтобы толщина была одинаковой для всех размеров.Я пытаюсь определить правильный способ вычисления этого значения.

Итак, учитывая базовую конфигурацию, которая выглядит желательной (скажем, размер шрифта 50pt и ширину обводки 1pt) и новый pointSize (например, 350pt)как правильно рассчитать strokeWidth?Или, возможно, мне следует использовать другое значение, отличное от pointSize?

Мой текущий алгоритм, который пропорционально масштабирует его:
let strokeWidth = font.pointSize / 50 (просто решение для x в 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)

1 Ответ

0 голосов
/ 16 декабря 2018

С документация для .strokeWidth (выделение добавлено):

Значением этого атрибута является NSNumber объект, содержащий значение с плавающей запятой.Это значение представляет величину для изменения ширины обводки, и указывается в процентах от размера точки шрифта .Укажите 0 (по умолчанию) для дополнительных изменений.Укажите положительные значения, чтобы изменить только ширину обводки.Укажите отрицательные значения для обводки и заливки текста.Например, типичное значение для выделенного текста будет 3,0.

Таким образом, значение уже масштабируется до размера шрифта.Вы не должны также масштабировать это самостоятельно.Выберите значение, которое дает относительную ширину обводки, которая вам нравится при любом заданном размере шрифта, и используйте его для всех размеров шрифта.

...