Я использую CoreGraphics для рисования отдельных глифов вместе с примитивами в CGContext. Следующий код работает на быстрой игровой площадке в XCode 9.2. При запуске на игровой площадке маленький прямоугольник с двойной буквой A должен появиться в заданных координатах в liveView игровой площадки.
import Cocoa
import PlaygroundSupport
class MyView: NSView {
init(inFrame: CGRect) {
super.init(frame: inFrame)
}
required init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
// setup context properties
let context: CGContext = NSGraphicsContext.current!.cgContext
context.setStrokeColor(CGColor.black)
context.setTextDrawingMode(.fill)
context.setFillColor(CGColor(red: 0.99, green: 0.99, blue: 0.85, alpha: 1))
context.beginPath()
context.addRect(rect)
context.fillPath()
context.setFillColor(.black)
// prepare variables and constants
var font = CTFontCreateWithName("Helvetica" as CFString, 48, nil)
var glyph = CTFontGetGlyphWithName(font, "A" as CFString)
var glyph1Position = CGPoint(x: self.frame.minX, y: self.frame.maxY/2)
var glyph2Position = CGPoint(x: self.frame.minX+150, y: self.frame.maxY/2)
let text = "Hello"
var textOrigin = NSPoint(x: self.frame.minX+50, y: self.frame.maxY/2)
// draw one character
CTFontDrawGlyphs(font, &glyph, &glyph1Position, 1, context)
// *** *** when the next line is uncommented the bug appears *** ***
// text.draw(at: textOrigin)
CTFontDrawGlyphs(font, &glyph, &glyph2Position, 1, context)
}
}
var frameRect = CGRect(x: 0, y: 0, width: 200, height: 100)
PlaygroundPage.current.liveView = MyView(inFrame: frameRect)
Теперь я хочу нарисовать обычный текст в том же контексте. Однако, когда текстовая строка рисуется между рисованием двух глифов с помощью собственного метода рисования, текущий контекст кажется испорченным, второй глиф не отображается. Когда текст рисуется после того, как оба одиночных глифа нарисованы, все в порядке.
Таким образом, очевидно, что рисование текста влияет на текущий CGContext, но я не могу понять, что именно происходит. Я попробовал метод saveGstate() перед рисованием строки и последующим восстановлением, но безуспешно.
Так же пробовал методами CoreText создать атрибутированную String с CTFramesetterCreateWithAttributedString и показать ее с CTFramesetterCreateFrame, тоже не работает, тут после создания фреймсеттера перепутался контекст.
Моя реальная игровая площадка более сложная, там глифы не исчезают полностью, а отображаются в неправильном вертикальном положении, но основная проблема - и вопрос тот же:
Как я могу нарисовать текст в currentContext без каких-либо других изменений в контексте, выполняемых в фоновом режиме?