NSTextView サブクラスで改行文字などの非表示の文字を表示しようとしています。NSLayoutManager の drawGlyph メソッドをオーバーライドするような通常のアプローチは、遅すぎて複数ページのレイアウトで適切に機能しないため、お勧めできません。
私がやろうとしているのは、NSLayoutManager の setGlyph メソッドをオーバーライドして、非表示の "\n" グリフを "¶" グリフに、" " を "∙" に置き換えることです。
また、" " スペース グリフでは機能しますが、改行文字には影響しません。
public override func setGlyphs(_ glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: Font, forGlyphRange glyphRange: NSRange) {
var substring = (self.currentTextStorage.string as NSString).substring(with: glyphRange)
// replace invisible characters with visible
if PreferencesManager.shared.shouldShowInvisibles == true {
substring = substring.replacingOccurrences(of: " ", with: "\u{00B7}")
substring = substring.replacingOccurrences(of: "\n", with: "u{00B6}")
}
// create a CFString
let stringRef = substring as CFString
let count = CFStringGetLength(stringRef)
// convert processed string to the C-pointer
let cfRange = CFRangeMake(0, count)
let fontRef = CTFontCreateWithName(aFont.fontName as CFString?, aFont.pointSize, nil)
let characters = UnsafeMutablePointer<UniChar>.allocate(capacity: MemoryLayout<UniChar>.size * count)
CFStringGetCharacters(stringRef, cfRange, characters)
// get glyphs for the pointer of characters
let glyphsRef = UnsafeMutablePointer<CGGlyph>.allocate(capacity: MemoryLayout<CGGlyph>.size * count)
CTFontGetGlyphsForCharacters(fontRef, characters, glyphsRef, count)
// set those glyphs
super.setGlyphs(glyphsRef, properties:props, characterIndexes: charIndexes, font: aFont, forGlyphRange: glyphRange)
}
それから私はアイデアを思いつきました: NSTypesetter は、まったく処理してはならないような新しい行の文字範囲をマークしているようです。そこで、NSTypesetter をサブクラス化し、メソッドをオーバーライドしました。
override func setNotShownAttribute(_ flag: Bool, forGlyphRange glyphRange: NSRange) {
let theFlag = PreferencesManager.shared.shouldShowInvisibles == true ? false : true
super.setNotShownAttribute(theFlag, forGlyphRange: glyphRange)
}
しかし、それは機能していません。NSLayoutManager は、作成したグリフに関係なく、改行文字のグリフを生成しません。
私は何を間違っていますか?