CTFontDrawGlyphs绘制编辑时间不正确的位置

:我代替我的原代码存根与自足版本CTFontDrawGlyphs绘制编辑时间不正确的位置

我使用Quartz2D画音乐符号的CGContext上。我正在使用Swift 4在Playground中做这件事。

音符由用于音符的单个CGGlyph和用于茎的线原语组成。字形取自音乐字体“bravura”。 书写笔字形的x位置正好位于其左边缘。茎必须完全对齐这个原点,因此它的X位置必须是纸头的X位置+茎的厚度/ 2.

我有一个函数,它将CGFloat作为x位置并绘制字形和干到CGContext。当x的值是像30.0这样的四舍五入值时,这可以很好地工作。然而,当值就像是30.9的分数,茎被错位:

很明显,该线正确绘制,但字形忽略CGFloat的小数部分。当我将x值进一步提高到31.0时,两个部分再次同步。

这里是简化代码,这会在你的XCode9游乐场工作:

import PlaygroundSupport 

import Cocoa

let fontSize = CGFloat(64)

// uncomment the next paragraph if you have added the "Bravura" Font to the ressources folder

/*

let fontURL = Bundle.main.url(forResource: "Bravura", withExtension: "otf")

CTFontManagerRegisterFontsForURL(fontURL! as CFURL, CTFontManagerScope.process, nil)

var font = CTFontCreateWithName("Bravura" as CFString, fontSize, nil)

*/

// comment out the next line if you use Bravura

var font = CTFontCreateWithName("Helvetica" as CFString, fontSize, nil)

func drawAtXPosition(_ posX: CGFloat, inContext context: CGContext) {

// draw font glyph (notehead)

var glyph = CTFontGetGlyphWithName(font, "uniE0A3" as CFString)

var notePosition = CGPoint(x: posX, y: 100)

CTFontDrawGlyphs(font, &glyph, &notePosition, 1, context)

// draw line (note stem)

let stemThickness = CGFloat(fontSize/4*0.12)

let x: CGFloat = posX + stemThickness/2

let y: CGFloat = 100 - (0.168 * fontSize/4)

let stemBegin = CGPoint(x:x, y:y)

let stemEnd = CGPoint(x:x, y: y - (3.5 * fontSize/4))

context.setLineWidth(stemThickness)

context.strokeLineSegments(between: [stemBegin, stemEnd])

}

class MyView: NSView {

override func draw(_ rect: CGRect) {

let context = NSGraphicsContext.current!.cgContext

context.setStrokeColor(CGColor.black)

context.setFillColor(CGColor.black)

drawAtXPosition(100, inContext: context) // this draws as expected

drawAtXPosition(200.99, inContext: context) // here the glyph is drawn at x=200, while the line is correctly drawn at 200.99

}

}

var myView = MyView(frame: CGRect(x: 0, y: 0, width: 500, height: 200))

let myViewController = NSViewController()

myViewController.view = myView

PlaygroundPage.current.liveView = myViewController

您可以从下载音乐字体 “炫耀的表现” ......

https://www.smufl.org/fonts/

...但我重写了代码,因此它默认使用Helvetica,这也适用于演示。

作为我原始代码中的解决方法,我在将x值传递给绘图函数之前实现了Foundation的.rounded()方法。这是有效的,但恐怕在小字号(整个代码的写入使得所有的字体都是围绕字体大小)时,这种不准确将会引起人们的注意。

我遇到了CGContext的setShouldSubpixelPositionFonts和setAllowsFontSubpixelPositioning方法,但将它们设置为true并没有做任何改变。

那么,有没有一种方法可以像原始图一样精确绘制字体对象(必须有一个)?或者,我担心将CGFloats四舍五入到Ints是不合理的?

回答:

无尽的挖掘后,我找到了解决办法:

这是不够的设定

context.setShouldSubpixelPositionFonts(true) 

您还可以设置

context.setShouldSubpixelQuantizeFonts(false) 

,因为后者似乎超越了前者。

以上是 CTFontDrawGlyphs绘制编辑时间不正确的位置 的全部内容, 来源链接: utcz.com/qa/258343.html

回到顶部