You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If I'm properly understand to solve issue with NSTextLayoutManager.setRenderingAttributes() we literally have to manually setup own "temporary attributes" system. E.g. create a storage to keep instances of NSRange together with needed attributes.
Then in appropriate drawing method we have to draw not a whole fragment (NSTextLayoutFragment), but rather perform line by line drawing (every NSTextLineFragment). But instead of drawing via NSTextLineFragment.draw(at:in:) we have to create a CTLine with appropriate attributes from custom "temporary attributes" storage and finally draw modified attributed string via CTLineDraw().
E.g.
classCoreTextTextView:CMinimalisticTextView{overridevarisFlipped:Bool{returntrue // Setting to `false` will make `NSTextLineFragment.draw(at:in)` working incorrectly.
}overridefunc drawLayoutFragments(_ fragmentsToDraw:[NSTextLayoutFragment], in context:NSGraphicsContext){func drawLineFragment(_ lineFragment:NSTextLineFragment, at point:CGPoint){#if true // If true, the CTLine will be drawn on top of NSTextLineFragment (for sanity/geonetry check).
lineFragment.draw(at: point, in: context.cgContext)#endifletcgContext= context.cgContext
cgContext.saveGState()letsubstring= lineFragment.attributedString.attributedSubstring(from: lineFragment.characterRange)letnewString=NSMutableAttributedString(attributedString: substring)
newString.addAttribute(.foregroundColor, value:NSColor.yellow, range:NSRange(location:0, length: newString.length))
newString.addAttribute(.foregroundColor, value:NSColor.blue, range:NSRange(location:1, length:1))
newString.addAttribute(.underlineStyle, value:NSUnderlineStyle.single.rawValue, range:NSRange(location:2, length:4))
newString.addAttribute(.underlineColor, value:NSColor.magenta, range:NSRange(location:2, length:4))letctLine=CTLineCreateWithAttributedString(newString)
cgContext.textMatrix =CGAffineTransform(scaleX:1, y: isFlipped ?-1:1)
cgContext.textPosition = point.offsetBy(dx:0, dy: isFlipped ? lineFragment.glyphOrigin.y:0)CTLineDraw(ctLine, cgContext)
cgContext.restoreGState()}fortextLayoutFragmentin fragmentsToDraw {varoffset:CGFloat=0forlineFragmentin textLayoutFragment.textLineFragments {letpoint= textLayoutFragment.layoutFragmentFrame.origin.offsetY(dy: offset)drawLineFragment(lineFragment, at: point)
offset += lineFragment.typographicBounds.height
}}}}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
If I'm properly understand to solve issue with
NSTextLayoutManager.setRenderingAttributes()we literally have to manually setup own "temporary attributes" system. E.g. create a storage to keep instances of NSRange together with needed attributes.Then in appropriate drawing method we have to draw not a whole fragment (
NSTextLayoutFragment), but rather perform line by line drawing (everyNSTextLineFragment). But instead of drawing viaNSTextLineFragment.draw(at:in:)we have to create aCTLinewith appropriate attributes from custom "temporary attributes" storage and finally draw modified attributed string viaCTLineDraw().E.g.
Beta Was this translation helpful? Give feedback.
All reactions