Search code examples
swiftxcodemacoscocoanslayoutmanager

drawGlyphsForGlyphRange in Swift (Displaying Invisible characters). replaceGlyphAtIndex deprecated


I am trying to show Invisible characters using below class & func, and it is working fine.

But replaceGlyphAtIndex is deprecated in OS X 10.11 and we need to use setGlyhs()

setGlyphs(<#T##glyphs: UnsafePointer<CGGlyph>##UnsafePointer<CGGlyph>#>, properties: <#T##UnsafePointer<NSGlyphProperty>#>, characterIndexes: <#T##UnsafePointer<Int>#>, font: <#T##NSFont#>, forGlyphRange: <#T##NSRange#>)

But i am having difficulties on how to convert replaceGlyphAtIndex to setGlyphs. Can any one suggest me how to convert below replaceGlyphAtIndex to setGlyphs()?

I tried as below but it is crashing.

let data = String(g).dataUsingEncoding(NSUTF8StringEncoding)
let cgG = UnsafePointer<CGGlyph>(data!.bytes)
self.setGlyphs(cgG, properties: nil, characterIndexes: UnsafePointer<Int>(bitPattern: characterIndex), font: font as! NSFont, forGlyphRange: NSMakeRange(glyphIndex, 1))

Can any one let me know whats going wrong in the above line of code?

class MyLayoutManager: NSLayoutManager {

override func drawGlyphsForGlyphRange(glyphsToShow: NSRange, atPoint origin: NSPoint) {
    if let storage = self.textStorage {
        let s = storage.string
        let startIndex = s.startIndex

        for glyphIndex in glyphsToShow.location ..< glyphsToShow.location + glyphsToShow.length {
            let characterIndex = self.characterIndexForGlyphAtIndex(glyphIndex)
            let ch = s[startIndex.advancedBy(characterIndex)]
            switch ch {
            case " ": //Blank Space
                let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                if let font = attrs[NSFontAttributeName] {
                    let g = font.glyphWithName("period")//("periodcentered")
                    self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)


                    //                        let data = String(g).dataUsingEncoding(NSUTF8StringEncoding)
                    //                        let cgG = UnsafePointer<CGGlyph>(data!.bytes)
                    //
                    //                        self.setGlyphs(cgG, properties: nil, characterIndexes: UnsafePointer<Int>(bitPattern: characterIndex), font: font as! NSFont, forGlyphRange: NSMakeRange(glyphIndex, 1))
                }
            case "\n": //New Line
                let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                if let font = attrs[NSFontAttributeName] {
                    let g = font.glyphWithName("logicalnot")
                    self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)
                }
            case newLineUniCodeStr:
                let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                if let font = attrs[NSFontAttributeName] {
                    let g = font.glyphWithName("logicalnot")
                    self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)
                }
            default:
                break
            }
        }
    }
    super.drawGlyphsForGlyphRange(glyphsToShow, atPoint: origin)
}

}


Solution

  • I found another way to display Glyphs. (Posting my code below as it may be useful to others)

    override func drawGlyphsForGlyphRange(glyphsToShow: NSRange, atPoint origin: NSPoint) {
        if let storage = self.textStorage {
            let s = storage.string
            let startIndex = s.startIndex
    
            var padding:CGFloat = 0
            for glyphIndex in glyphsToShow.location ..< glyphsToShow.location + glyphsToShow.length {
                let characterIndex = self.characterIndexForGlyphAtIndex(glyphIndex)
                if characterIndex < s.characters.count
                {
                    var glyphStr = ""
                    let ch = s[startIndex.advancedBy(characterIndex)]
                    switch ch {
                    case " ": //Blank Space
                        glyphStr = periodCenteredUniCodeStr
                    case "\n": //New Line
                        glyphStr = lineBreakUniCodeStr
                    case newLineUniCodeStr:
                        glyphStr = lineBreakUniCodeStr
                        padding += 5
                    default:
                        break
                    }
                    var glyphPoint = self.locationForGlyphAtIndex(glyphIndex)
                    let glyphRect = self.lineFragmentRectForGlyphAtIndex(glyphIndex, effectiveRange: nil)
                    if glyphStr.characters.count > 0{
                        glyphPoint.x = glyphPoint.x + glyphRect.origin.x
                        glyphPoint.y = glyphRect.origin.y
                        NSString(string: glyphStr).drawInRect(NSMakeRect(glyphPoint.x, glyphPoint.y, 10, 10), withAttributes: nil)
                    }
                }else{
                    print("Wrong count here")
                }
            }
    
        }
        super.drawGlyphsForGlyphRange(glyphsToShow, atPoint: origin)
    }