如何管理文本字形边界 [英] How to manage text glyph boundary

查看:198
本文介绍了如何管理文本字形边界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个时钟应用程序,并且我想用可以是任意字符集/字体的字符来标记小时。我想在一个框架中框架字符,并尽可能地填充它。我怎样才能做到这一点?如果我使用 UILabel ,则会在字形周围插入空格。以下是显示两个标签的示例,两个标签的字体相同但字符不同。希伯来语数字看起来都比阿拉伯数字短。有没有一种方法来确定字形的大小或以某种方式将字形推出适合框架?



< a href =https://i.stack.imgur.com/TkT5y.png =nofollow noreferrer>

正如你所看到的,尽管被添加到一个更高的UILabel中,希伯来数字更短。



编辑:自发布以来,我做了第一遍使用核心文本,看看是否可以解决我的问题。它似乎不会。请参阅将希伯来字形与阿拉伯数字字形进行比较的插图。他们黄色是标签界限。绿色是由核心文本报告的字形矩形。我希望能得到一个矩形的字形齐平,但它看起来像希伯来字形包括上面和旁边的空间,我希望是字形。还有什么我应该检查?

解决方案

不知道你使用Obj-C还是Swift,但是你可以把它粘贴到Swift Playground页面来查看结果:

 导入UIKit 
导入CoreText
导入PlaygroundSupport


class PathView:UIView {

var myPath:UIBezierPath?

重写func draw(_ rect:CGRect){

如果让pth = myPath {

UIColor.red.setStroke()

//字形路径被倒置,所以垂直翻转
let flipY = CGAffineTransform(scaleX:1,y:-1.0)

//字形路径可能偏移x coord和高度(因为它被翻转)
let translate = CGAffineTransform(translationX:-pth.bounds.origin.x,y:pth.bounds.size.height + pth.bounds.origin.y)

//应用变换
pth.apply(flipY)
pth.apply(translate)

//笔画路径
pth.stroke()

//打印修改/引用的路径
print(pth)

}

}



class TestViewController:UIViewController {

override func viewDidLoad(){
super.viewDidLoad()

//蓝色背景,所以我们可以看到框架
view.backgroundColor = UIColor(红色:0.25,绿色:0.5,蓝色:01.0,alpha:1.0)

//使用大字体,这样我们可以很容易地看到
let font = UIFont(name:Times,size:160)!

//希伯来字符8
var unichars = [UniChar](ח。utf16)
unichars = [UniChar](י。utf16)

// init字形数组
var glyphs = [CGGlyph](repeatElement(0,count:unichars.count))

getGlyphs = CTFontGetGlyphsForCharacters(font,& unichars ,& glyphs,unichars.count)

如果gotGlyphs {
//获取cgPath为字符
let cgpath = CTFontCreatePathForGlyph(font,glyphs [0],nil) !

//将其转换为UIBezierPath
让路径= UIBezierPath(cgPath:cgpath)

var r = path.bounds

//让我们在40,40
r = r.offsetBy(dx:40.0,dy:40.0)

让pView = PathView(frame:r)
pView.backgroundColor = .white
pView.myPath = path

view.addSubview(pView)

//打印调试/引用的边界和路径数据
print (path:,path.bounds)
print()
print(path)$ b $ print()
}

}



让vc = TestViewController()
PlaygroundPage.current.liveView = vc

需要大量的错误检查/处理,但这可能为您找到并使用实际字符字形的边界(而不是标签帧)开了个好头。



结果:


Suppose I have a clock app, and I want to label the hours with characters that could be in an arbitrary character set/font. I'd like to frame the character in a frame and fill it as much as possible. How can I do that? If I use a UILabel, space gets inserted around the glyph. Here are examples showing two labels, both with the same font but with different characters. The Hebrew numerals all seem shorter than the Arabic numerals. Is there a way to determine the size of the glyphs or somehow push the glyphs out to fit the frame?

As you can see, the Hebrew numeral is shorter even though it's being added to a taller UILabel.

Edit: Since posting, I made a first pass of using core text to see if that could resolve my problem. It seems that it will not. See these illustrations comparing a Hebrew glyph to an Arabic numeral glyph. They yellow is the label bounds. The green is the glyph rectangle reported by core text. I was hoping to get a rectangle flush to the glyph, but it looks like the Hebrew glyphs include space above and beside what I expected to be the glyph. Is there something else I should be checking?

解决方案

I don't know if you use Obj-C or Swift, but you can paste this into a Swift Playground page to see the result:

Minor Edits

import UIKit
import CoreText
import PlaygroundSupport


class PathView: UIView {

    var myPath: UIBezierPath?

    override func draw(_ rect: CGRect) {

        if let pth = myPath {

            UIColor.red.setStroke()

            // glyph path is inverted, so flip vertically
            let flipY = CGAffineTransform(scaleX: 1, y: -1.0)

            // glyph path may be offset on the x coord, and by the height (because it's flipped)
            let translate = CGAffineTransform(translationX: -pth.bounds.origin.x, y: pth.bounds.size.height + pth.bounds.origin.y)

            // apply the transforms
            pth.apply(flipY)
            pth.apply(translate)

            // stroke the path
            pth.stroke()

            // print the modified path for debug / reference
            print(pth)

        }

    }

}

class TestViewController : UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // blue background so we can see framing
        view.backgroundColor = UIColor(red: 0.25, green: 0.5, blue: 01.0, alpha: 1.0)

        // use a large font so we can see it easily
        let font = UIFont(name: "Times", size: 160)!

        // Hebrew character for 8
        var unichars = [UniChar]("ח".utf16)
        unichars = [UniChar]("י".utf16)

        // init glyphs array
        var glyphs = [CGGlyph](repeatElement(0, count: unichars.count))

        let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count)

        if gotGlyphs {
            // get the cgPath for the character
            let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)!

            // convert it to a UIBezierPath
            let path = UIBezierPath(cgPath: cgpath)

            var r = path.bounds

            // let's show it at 40,40
            r = r.offsetBy(dx: 40.0, dy: 40.0)

            let pView = PathView(frame: r)
            pView.backgroundColor = .white
            pView.myPath = path

            view.addSubview(pView)

            // print bounds and path data for debug / reference
            print("bounds of path:", path.bounds)
            print()
            print(path)
            print()
        }

    }

}

let vc = TestViewController()
PlaygroundPage.current.liveView = vc

Lots of error checking / handling needed, but this may give you a good start on finding and using the bounds of the actual character glyphs (instead of the label frames).

Result:

这篇关于如何管理文本字形边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆