确定便携式Swift中的字符串边界框?

时间:2019-06-11 17:23:56

标签: swift fonts

如何在便携式Swift中使用特定字体确定字符串的边界框?

是否有跨平台(Linux,iOS,macOS等)替代当前特定于平台的UIFontNSFont方法?

iOS示例

import UIKit

let uiFont = UIFont(...)
let nsString = NSString(string: "Hello!")
let boundingBox: CGSize = 
     nsString.size(withAttributes: [NSAttributedString.Key.font: uiFont])

macOS示例

import Cocoa

let nsFont = NSFont(...)
let nsString = NSString(string: "Hello!")
let boundingBox: NSSize = 
     nsString.size(withAttributes: [NSAttributedString.Key.font: nsFont])

应用说明:这个问题是总体目标的组成部分,该目标是能够在Swift生成的SVG文件中布局文本字符串。

1 个答案:

答案 0 :(得分:0)

快速

import Foundation

public static func getStringWidth() {
    // PostScript name: DejaVuSansMono
    //       Full name: DejaVu Sans Mono
    //           Style: Book
    //            Kind: OpenType TrueType
    //     Unique name: DejaVu Sans Mono
    let cfsFontName: CFString = "DejaVu Sans Mono" as CFString

    // Use either the font's PostScript name or full name
    guard let cgFont = CGFont(cfsFontName) else {
        return
    }

    let ctFont: CTFont = CTFontCreateWithGraphicsFont(
        cgFont, // graphicsFont: CGFont
        12.0,   // size: CGFloat
        nil,    // matrix: UnsafePointer<CGAffineTransforms>?
        nil     // attributes: CTFontDescriptor?
    )

    let str = "Hello!"

    var unichars = [UniChar](str.utf16)
    var glyphs = [CGGlyph](repeating: 0, count: unichars.count)

    guard CTFontGetGlyphsForCharacters(
        ctFont,    // font: CTFont
        &unichars, // characters: UnsafePointer<UniChar>
        &glyphs,   // UnsafeMutablePointer<CGGlyph>
        unichars.count // count: CFIndex
        )
        else {
        return
    }

    let glyphsCount = glyphs.count
    var advances = [CGSize](
        repeating: CGSize(width: 0.0, height: 0.0), 
        count: glyphsCount
    )
    let width = CTFontGetAdvancesForGlyphs(
        ctFont,      // font: CTFont
        CTFontOrientation.horizontal, // orientation: CFFontOrientation
        glyphs,      // glyphs: UnsafePointer<CGGlyph>
        &advances,   // advances: UnsafeMutablePointer<CGSize>?
        glyphsCount // count: CFIndex
    )
    print("width=\(width)")
    print("advances=\(advances)")

    var boundingRects = [CGRect](
        repeating: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 0.0), 
        count: glyphsCount
    )

    // Result: font design metrics transformed into font space.
    let boundingBox = CTFontGetBoundingRectsForGlyphs(
        ctFont,         // font: CTFont
        .horizontal,    // orientation: CFFontOrientation
        glyphs,         // glyphs: UnsafePointer<CGGlyph>
        &boundingRects, // boundingRects: UnsafeMutablePointer<CGRect>?
        glyphsCount     // count: CFIndex
    )
    print("boundingBox=\(boundingBox)")
    print("boundingRects=\(boundingRects)")
}

结果

width=43.34765625
advances=[(7.224609375, 0.0), (7.224609375, 0.0), (7.224609375, 0.0), (7.224609375, 0.0), (7.224609375, 0.0), (7.224609375, 0.0)]

boundingBox=(0.720703125, -0.169921875, 5.794921875, 9.3515625)
boundingRects=[(0.802734375, 0.0, 5.619140625, 8.748046875), (0.720703125, -0.169921875, 5.794921875, 6.890625), (0.9375, 0.0, 5.12109375, 9.181640625), (0.9375, 0.0, 5.12109375, 9.181640625), (0.802734375, -0.169921875, 5.619140625, 6.890625), (3.0234375, 0.0, 1.189453125, 8.748046875)]