:我代替我的原代碼存根與自足版本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, ¬ePosition, 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
您可以從下載音樂字體 「炫耀的表現」 ......
...但我重寫了代碼,因此它默認使用Helvetica,這也適用於演示。
作爲我原始代碼中的解決方法,我在將x值傳遞給繪圖函數之前實現了Foundation的.rounded()方法。這是有效的,但恐怕在小字號(整個代碼的寫入使得所有的字體都是圍繞字體大小)時,這種不準確將會引起人們的注意。
我遇到了CGContext的setShouldSubpixelPositionFonts和setAllowsFontSubpixelPositioning方法,但將它們設置爲true並沒有做任何改變。
那麼,有沒有一種方法可以像原始圖一樣精確繪製字體對象(必須有一個)?或者,我擔心將CGFloats四捨五入到Ints是不合理的?
添加完整的自包含代碼可能會有幫助,其他人可以將其複製到Playground中以重現問題並嘗試可能的解決方案。 –
謝謝指出。隨着我的第一個版本,我希望能夠找到遇到同樣問題的人,所以我很快包裝了一些線來證明問題。正如你所看到的,一個工作版本實際上需要更多的代碼,但現在我終於有時間重寫我的第一個版本了。 – MassMover