def getFont(familyName, size=200, location=None): attributes = {CoreText.kCTFontFamilyNameAttribute: familyName} descriptor = CoreText.CTFontDescriptorCreateWithAttributes(attributes); if location: for tag, value in location.items(): descriptor = CoreText.CTFontDescriptorCreateCopyWithVariable(descriptor, tagToInt(tag), value) return CoreText.CTFontCreateWithFontDescriptor(descriptor, size, [1, 0, 0, 1, 0, 0])
class TextRun(object): def __init__(self, ctRun, runIndex): self.runIndex = runIndex # Index of the run in the TextLine self._ctRun = ctRun self.glyphCount = gc = CoreText.CTRunGetGlyphCount(ctRun) attrs = CoreText.CTRunGetAttributes(ctRun) self.nsFont = attrs['NSFont'] #self.fontDescriptor = f.fontDescriptor() self.fill = attrs['NSColor'] self.nsParagraphStyle = attrs['NSParagraphStyle'] self.iStart, self.iEnd = CoreText.CTRunGetStringRange(ctRun) self.string = u'' # Hack for now to find the string in repr-string if self._ctLine. for index, part in enumerate( ` ctRun `.split('"')[1].split('\\u')): if index == 0: self.string += part elif len(part) >= 4: self.string += unichr(int(part[0:4], 16)) self.string += part[4:] self.stringIndices = CoreText.CTRunGetStringIndicesPtr(ctRun)[0:gc] #CoreText.CTRunGetStringIndices(ctRun._ctRun, CoreText.CFRange(0, 5), None)[4] self.advances = CoreText.CTRunGetAdvances(ctRun, CoreText.CFRange(0, 5), None) self.positions = CoreText.CTRunGetPositionsPtr(ctRun)[0:gc] #CoreText.CTRunGetPositions(ctRun, CoreText.CFRange(0, 5), None)[4] #self.glyphFontIndices = CoreText.CTRunGetGlyphsPtr(ctRun)[0:gc] #print(CoreText.CTRunGetGlyphs(ctRun, CoreText.CFRange(0, 5), None)[0:5]) self.status = CoreText.CTRunGetStatus(ctRun)
def _getTypesetterLinesWithPath(self, attrString, path, offset=None): # get lines for an attribute string with a given path if offset is None: offset = 0, 0 setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) frame = CoreText.CTFramesetterCreateFrame(setter, offset, path, None) return CoreText.CTFrameGetLines(frame)
class TextLine(object): def __init__(self, ctLine, p, lineIndex): self._ctLine = ctLine self.x, self.y = p # Relative position from top of TextBox self.lineIndex = lineIndex # Vertical line index in TextBox. self.glyphCount = CoreText.CTLineGetGlyphCount(ctLine) self.string = '' self.runs = [] #print ctLine for runIndex, ctRun in enumerate(CoreText.CTLineGetGlyphRuns(ctLine)): textRun = TextRun(ctRun, runIndex) self.runs.append(textRun) self.string += textRun.string def __repr__(self): return '[TextLine #%d Glyphs:%d Runs:%d]' % ( self.lineIndex, self.glyphCount, len(self.runs)) def __len__(self): return self.glyphCount def __getitem__(self, index): return self.runs[index] def getIndexForPosition(self, (x, y)): return CoreText.CTLineGetStringIndexForPosition( self._ctLine, CoreText.CGPoint(x, y))[0]
def text(self, txt, x, y=None): """ Draw a text at a provided position. .. showcode:: /../examples/text.py """ if isinstance(txt, (str, unicode)): try: txt = txt.decode("utf-8") except UnicodeEncodeError: pass if y is None: x, y = x else: warnings.warn("position must a tuple: text('%s', (%s, %s))" % (txt, x, y)) attrString = self._dummyContext.attributedString(txt) w, h = attrString.size() setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(x, y, w * 2, h)) box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(box) origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) if origins: x -= origins[-1][0] y -= origins[-1][1] self.textBox(txt, (x, y - h, w * 2, h * 2))
def _getPathForFrameSetter(self, box): if isinstance(box, BezierPath): path = box._getCGPath() (x, y), (w, h) = CoreText.CGPathGetPathBoundingBox(path) else: x, y, w, h = box path = CoreText.CGPathCreateMutable() CoreText.CGPathAddRect(path, None, CoreText.CGRectMake(x, y, w, h)) return path, (x, y)
def testFunctions10_8(self): astr = CoreText.CFAttributedStringCreate(None, "-", None) self.assertTrue(astr is not None) token = CoreText.CTLineCreateWithAttributedString(astr) self.assertIsInstance(token, CoreText.CTLineRef) r = CoreText.CTLineGetBoundsWithOptions( token, CoreText.kCTLineBoundsExcludeTypographicLeading) self.assertIsInstance(r, Quartz.CGRect)
def testFunctions10_6_crash(self): descr = CoreText.CTFontDescriptorCreateWithNameAndSize("Courier", 14.0) self.assertNotEqual(descr, None) self.assertResultIsCFRetained( CoreText.CTFontCreateWithFontDescriptorAndOptions) v = CoreText.CTFontCreateWithFontDescriptorAndOptions( descr, 14.0, None, 0) self.assertIsInstance(v, CoreText.CTFontRef)
def text(self, txt, font=_FALLBACKFONT, fontSize=10, offset=None): """ Draws a `txt` with a `font` and `fontSize` at an `offset` in the bezier path. Optionally `txt` can be a `FormattedString`. """ if isinstance(txt, FormattedString): attributedString = txt.getNSObject() else: fontName = font font = AppKit.NSFont.fontWithName_size_(font, fontSize) if font is None: warnings.warn( "font: %s is not installed, back to the fallback font: %s" % (fontName, _FALLBACKFONT)) font = AppKit.NSFont.fontWithName_size_( _FALLBACKFONT, fontSize) attributes = {AppKit.NSFontAttributeName: font} attributedString = AppKit.NSAttributedString.alloc( ).initWithString_attributes_(txt, attributes) w, h = attributedString.size() setter = CoreText.CTFramesetterCreateWithAttributedString( attributedString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(0, -h, w * 2, h * 2)) box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(box) origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) if offset: x, y = offset else: x = y = 0 if origins: x -= origins[-1][0] y -= origins[-1][1] for i, (originX, originY) in enumerate(origins): ctLine = ctLines[i] # path around a bug somewhere # create a new CTLine from a substring with the same range... rng = CoreText.CTLineGetStringRange(ctLine) txtLine = attributedString.attributedSubstringFromRange_(rng) ctLine = CoreText.CTLineCreateWithAttributedString(txtLine) ctRuns = CoreText.CTLineGetGlyphRuns(ctLine) self._path.moveToPoint_((x + originX, y + originY)) for ctRun in ctRuns: glyphs = CoreText.CTRunGetGlyphs( ctRun, CoreText.CTRunGetStringRange(ctRun), None) attributes = CoreText.CTRunGetAttributes(ctRun) font = attributes.get(AppKit.NSFontAttributeName) glyphs = [g for g in glyphs if g != 0] self._path.appendBezierPathWithGlyphs_count_inFont_( glyphs, len(glyphs), font)
def ctRunThing(fs, x, y): ly = y w, h = textSize(fs) attrString = fs.getNSObject() setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(0, 0, w, h)) ctBox = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(ctBox) for ctLine in ctLines: #print('---', ctLine) ctRuns = CoreText.CTLineGetGlyphRuns(ctLine) # loop over all runs for ctRun in ctRuns: # get all positions pos = CoreText.CTRunGetPositions( ctRun, (0, CoreText.CTRunGetGlyphCount(ctRun)), None) # get all glyphs glyphs = CoreText.CTRunGetGlyphs( ctRun, (0, CoreText.CTRunGetGlyphCount(ctRun)), None) #print(y, ly, pos) # enumerate over all pos for i, (gx, gy) in enumerate(pos): # draw a line context.stroke(0) context.line((x + gx, ly + gy), (x + gx, ly + gy + 100)) context.stroke(None) # get the glyph name from the glyph order #glyphName = glyphOrder[glyphs[i]] # get the shift to center the name of the glyph centerShift = 0 if i < len(pos) - 1: centerShift = (pos[i + 1][0] - gx) else: # last one centerShift = w - gx centerShift *= .5 #tx, _ = textSize(glyphName) leadingMax = CoreText.CTRunGetAttributes( ctRun)['NSParagraphStyle'].maximumLineHeight() leadingMin = CoreText.CTRunGetAttributes( ctRun)['NSParagraphStyle'].minimumLineHeight() print(leadingMax, leadingMin) fill(None) stroke(1, 0, 0) S = 8 rect(x - S, ly - S, 2 * S, 2 * S) ly -= leadingMax
def ctRunThing(fs): w, h = textSize(fs) box = 0, 0, w, h attrString = fs.getNSObject() setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(*box)) ctBox = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(ctBox) ctRuns = CoreText.CTLineGetGlyphRuns(ctLines[0]) stringIndices = CoreText.CTRunGetStringIndicesPtr(ctRuns[0]) return stringIndices
def __init__(self, ctLine, p, lineIndex): self._ctLine = ctLine self.x, self.y = p # Relative position from top of TextBox self.lineIndex = lineIndex # Vertical line index in TextBox. self.glyphCount = CoreText.CTLineGetGlyphCount(ctLine) self.string = '' self.runs = [] for runIndex, ctRun in enumerate(CoreText.CTLineGetGlyphRuns(ctLine)): textRun = TextRun(ctRun, runIndex) self.runs.append(textRun) self.string += textRun.string
def testFunctions(self): v = CoreText.CTFramesetterGetTypeID() self.assertIsInstance(v, int) setter = CoreText.CTFramesetterCreateWithAttributedString( CoreText.CFAttributedStringCreate(None, "hello", None)) self.assertIsInstance(setter, CoreText.CTFramesetterRef) # CTFramesetterCreateFrame: tested in test_ctframe.py v = CoreText.CTFramesetterGetTypesetter(setter) self.assertIsInstance(v, CoreText.CTTypesetterRef)
def getBaseLines(txt, box): u"""Answer a list of (x,y) positions of all line starts in the box. This function may become part of standard DrawBot in the near future.""" x, y, w, h = box attrString = txt.getNSObject() setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(*box)) box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(box) origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) return [(x + o.x, y + o.y) for o in origins]
def fontPath(fontName): font = CoreText.CTFontDescriptorCreateWithNameAndSize(fontName, 10) if font: url = CoreText.CTFontDescriptorCopyAttribute( font, CoreText.kCTFontURLAttribute) if url: return url.path() else: # warn if font doest not exists pass return None
def text(self, txt, offset=None, font=_FALLBACKFONT, fontSize=10, align=None): """Draws a `txt` with a `font` and `fontSize` at an `offset` in the Bézier path. If a font path is given the font will be installed and used directly. - Optionally an alignment can be set. - Possible `align` values are: `"left"`, `"center"` and `"right"`. - The default alignment is `left`. - Optionally `txt` can be a `FormattedString`. """ context = BaseContext() if align and align not in self._textAlignMap.keys(): raise PageBotError("align must be %s" % (", ".join(self._textAlignMap.keys()))) context.font(font, fontSize) attributedString = context.attributedString(txt, align) w, h = attributedString.size() w *= 2 if offset: x, y = offset else: x = y = 0 if align == "right": x -= w elif align == "center": x -= w * .5 setter = CoreText.CTFramesetterCreateWithAttributedString( attributedString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(x, y, w, h * 2)) frame = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(frame) origins = CoreText.CTFrameGetLineOrigins(frame, (0, len(ctLines)), None) if origins: y -= origins[0][1] self.textBox(txt, box=(x, y, w, h * 2), font=font, fontSize=fontSize, align=align)
def textBox(self, txt, box, font=_FALLBACKFONT, fontSize=10, align=None, hyphenation=None): """Draws a `txt` with a `font` and `fontSize` in a `box` in the Bézier path. If a font path is given the font will be installed and used directly. - Optionally an alignment can be set. - Possible `align` values are: `"left"`, `"center"` and `"right"`. - The default alignment is `left`. - Optionally `hyphenation` can be provided. - Optionally `txt` can be a `FormattedString`. - Optionally `box` can be a `BezierPath`. """ if align and align not in self._textAlignMap.keys(): raise PageBotError("align must be %s" % (", ".join(self._textAlignMap.keys()))) context = BaseContext() context.font(font, fontSize) context.hyphenation(hyphenation) path, (x, y) = context._getPathForFrameSetter(box) attributedString = context.attributedString(txt, align) setter = CoreText.CTFramesetterCreateWithAttributedString( attributedString) frame = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(frame) origins = CoreText.CTFrameGetLineOrigins(frame, (0, len(ctLines)), None) for i, (originX, originY) in enumerate(origins): ctLine = ctLines[i] ctRuns = CoreText.CTLineGetGlyphRuns(ctLine) for ctRun in ctRuns: attributes = CoreText.CTRunGetAttributes(ctRun) font = attributes.get(AppKit.NSFontAttributeName) baselineShift = attributes.get( AppKit.NSBaselineOffsetAttributeName, 0) glyphCount = CoreText.CTRunGetGlyphCount(ctRun) for i in range(glyphCount): glyph = CoreText.CTRunGetGlyphs(ctRun, (i, 1), None)[0] ax, ay = CoreText.CTRunGetPositions(ctRun, (i, 1), None)[0] if glyph: self._path.moveToPoint_( (x + originX + ax, y + originY + ay + baselineShift)) self._path.appendBezierPathWithGlyph_inFont_( glyph, font) self.optimizePath() return context.clippedText(txt, box, align)
def hyphenateAttributedString(self, attrString, width): attrString = attrString.mutableCopy() mutString = attrString.mutableString() wordRange = AppKit.NSMakeRange(mutString.length(), 0) while wordRange.location > 2: wordRange = attrString.doubleClickAtIndex_(wordRange.location - 2) hyphenIndex = AppKit.NSMaxRange(wordRange) while hyphenIndex != AppKit.NSNotFound: hyphenIndex = attrString.lineBreakByHyphenatingBeforeIndex_withinRange_( hyphenIndex, wordRange) if hyphenIndex != AppKit.NSNotFound: mutString.insertString_atIndex_(unichr(self._softHypen), hyphenIndex) textLength = attrString.length() setter = CoreText.CTTypesetterCreateWithAttributedString(attrString) location = 0 while location < textLength: breakIndex = CoreText.CTTypesetterSuggestLineBreak( setter, location, width) sub = attrString.attributedSubstringFromRange_( (location, breakIndex)) location += breakIndex subString = sub.string() if breakIndex == 0: break subString = sub.string() if subString[-1] == unichr(self._softHypen): subAttr, _ = sub.attributesAtIndex_effectiveRange_(0, None) hyphenAttrString = AppKit.NSAttributedString.alloc( ).initWithString_attributes_("-", subAttr) hyphenWidth = hyphenAttrString.size().width if sub.size().width + hyphenWidth < width: mutString.insertString_atIndex_("-", location) setter = CoreText.CTTypesetterCreateWithAttributedString( attrString) location += 1 else: attrString.deleteCharactersInRange_((location - 1, 1)) setter = CoreText.CTTypesetterCreateWithAttributedString( attrString) location -= breakIndex mutString.replaceOccurrencesOfString_withString_options_range_( unichr(self._softHypen), "", AppKit.NSLiteralSearch, (0, mutString.length())) return attrString
def getTextLines(fs, w, h): """Answer an ordered list of all baseline position, starting at the top.""" box = 0, 0, w, h attrString = fs.getNSObject() setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) path = Quartz.CGPathCreateMutable() Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(*box)) box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(box) textLines = [] for ctLine in ctLines: tl = TextLine(ctLine) textLines.append(tl) origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) return textLines, origins
def getImageOfGlyph(glyphAttributedString, backingColor): line = CoreText.CTLineCreateWithAttributedString(glyphAttributedString) # Get a rough size of our glyph. We'll use this to make the NSImage, and get a more accurate # frame once we have a context to call CTLineGetImageBounds. typographicWidth, ascent, descent, leading = CoreText.CTLineGetTypographicBounds( line, None, None, None) img = Foundation.NSImage.alloc().initWithSize_( Foundation.NSMakeSize(ceil(typographicWidth), ceil(ascent + descent))) img.lockFocus() context = AppKit.NSGraphicsContext.currentContext().graphicsPort() bounds = CoreText.CTLineGetImageBounds(line, context) Quartz.CGContextTranslateCTM(context, 0, ceil( descent)) # Shift everything up so the descender is inside our image if backingColor: # Draw a circle behind the glyph with the ratio to the size of the glyph bgCircleDiameterRatio = 0.9 bgCircleOffsetRatio = (1.0 - bgCircleDiameterRatio) / 2.0 bgCircleRect = Foundation.NSMakeRect( bounds.origin.x + bounds.size.width * bgCircleOffsetRatio, bounds.origin.y + bounds.size.height * bgCircleOffsetRatio, bounds.size.width * bgCircleDiameterRatio, bounds.size.height * bgCircleDiameterRatio) backgroundCirclePath = Foundation.NSBezierPath.bezierPathWithOvalInRect_( bgCircleRect) backingColor.setFill() backgroundCirclePath.fill() CoreText.CTLineDraw(line, context) bitmapRep = Foundation.NSBitmapImageRep.alloc().initWithFocusedViewRect_( Foundation.NSIntegralRect(bounds)) img.unlockFocus() finalImage = Foundation.NSImage.alloc().initWithSize_( Foundation.NSIntegralRect(bounds).size) finalImage.addRepresentation_(bitmapRep) return finalImage
def getVariationAxesForFont(font): """ Return a dictionary { axis tag: { name: , minValue: , maxValue: } } """ axes = OrderedDict() variationAxesDescriptions = CoreText.CTFontCopyVariationAxes(font) if variationAxesDescriptions is None: # non-variable fonts have no axes descriptions return axes for variationAxesDescription in variationAxesDescriptions: tag = convertIntToVariationTag(variationAxesDescription[ CoreText.kCTFontVariationAxisIdentifierKey]) name = variationAxesDescription[CoreText.kCTFontVariationAxisNameKey] minValue = variationAxesDescription[ CoreText.kCTFontVariationAxisMinimumValueKey] maxValue = variationAxesDescription[ CoreText.kCTFontVariationAxisMaximumValueKey] defaultValue = variationAxesDescription[ CoreText.kCTFontVariationAxisDefaultValueKey] data = dict(name=name, minValue=minValue, maxValue=maxValue, defaultValue=defaultValue) axes[tag] = data return axes
def __init__(self, ctLine): self._ctLine = ctLine self.glyphCount = CoreText.CTLineGetGlyphCount(ctLine) # Hack for now to find the string. s = [] for index, part in enumerate(repr(self._ctLine).split('"')[1].split('\\u')): if index == 0: s.append(part) elif len(part) >= 4: s.append(chr(int(part[0:4], 16))) s.append(part[4:]) self.string = ''.join(s) self.runs = [] for ctRun in CoreText.CTLineGetGlyphRuns(ctLine): self.runs.append(TextRun(ctRun, self.string))
def stringWidth(string, ctFont): """\ Returns the width of the given string rendered in the given CoreText font. """ # pylint: disable=no-member; pylint can’t see imports from PyObjC modules. drawable = _drawableString(string, ctFont) line = CoreText.CTLineCreateWithAttributedString(drawable) # The PyObjC adaptation of CTLineGetTypographicBounds returns a tuple (width, ascender, descender, linegap). (width, _, _, _) = CoreText.CTLineGetTypographicBounds(line, None, None, None) return width
def textSize(self, txt, align, width, height): attrString = self.attributedString(txt, align) if width is None: w, h = attrString.size() else: if width is None: width = CoreText.CGFLOAT_MAX if height is None: height = CoreText.CGFLOAT_MAX if self._state.hyphenation: path = CoreText.CGPathCreateMutable() CoreText.CGPathAddRect(path, None, CoreText.CGRectMake(0, 0, width, height)) attrString = self.hyphenateAttributedString(attrString, path) setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) (w, h), _ = CoreText.CTFramesetterSuggestFrameSizeWithConstraints(setter, (0, 0), None, (width, height), None) return w, h
def ctFont(fontName, fontSize): """\ Returns the CoreText font instance for the specified font. """ # pylint: disable=no-member; pylint can’t see imports from PyObjC modules. return CoreText.CTFontCreateWithName(fontName, fontSize, None)
def testMethods10_5(self): setter = CoreText.CTFramesetterCreateWithAttributedString( CoreText.CFAttributedStringCreate(None, "hello", None)) self.assertIsInstance(setter, CoreText.CTFramesetterRef) self.assertArgIsOut( CoreText.CTFramesetterSuggestFrameSizeWithConstraints, 4) r = CoreText.CTFramesetterSuggestFrameSizeWithConstraints( setter, CoreText.CFRange(0, 2), None, CGSize(100, 500), None) self.assertIsInstance(r, tuple) self.assertEqual(len(r), 2) size, a_range = r self.assertIsInstance(size, CGSize) self.assertIsInstance(a_range, CoreText.CFRange)
def mergeUnicodeStack(glyphNames, stack, cmap, glyphOrder, direction): if not stack: return if len(stack) > 1: # cache this... data, ftFont = fontData(cmap, glyphOrder) fontProvider = CoreText.CGDataProviderCreateWithCFData(data) cgFont = CoreText.CGFontCreateWithDataProvider(fontProvider) ctFont = CoreText.CTFontCreateWithGraphicsFont(cgFont, 0, None, None) attributes = { AppKit.NSFontAttributeName: ctFont } if direction == RTL: attributes[AppKit.NSWritingDirectionAttributeName] = [AppKit.NSWritingDirectionRightToLeft | AppKit.NSTextWritingDirectionEmbedding] attr = AppKit.NSAttributedString.alloc().initWithString_attributes_("".join(stack), attributes) ctLine = CoreText.CTLineCreateWithAttributedString(attr) ctRuns = CoreText.CTLineGetGlyphRuns(ctLine) newGlyphNames = [] for ctRun in ctRuns: glyphCount = CoreText.CTRunGetGlyphCount(ctRun) indexes = CoreText.CTRunGetGlyphs(ctRun, (0, glyphCount), None) for index in indexes: glyphName = ftFont.getGlyphName(index) newGlyphNames.append(glyphName) if direction == RTL: newGlyphNames.reverse() glyphNames.extend(newGlyphNames) else: glyphNames.extend([characterToGlyphName(c, cmap, fallback=c) for c in stack])
def uninstallFontFile(path, scope="process"): assert scope in _installScopes, ("scope must be one of %s" % sorted(_installScopes.keys())) scope = _installScopes[scope] fontURL = _makeURL(path) res, error = CoreText.CTFontManagerUnregisterFontsForURL( fontURL, CoreText.kCTFontManagerScopeProcess, None) if error: raise FontInstallError(error)
def fontFilePath(self): """Returns the path to the file of the current font.""" font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize) if font is not None: url = CoreText.CTFontDescriptorCopyAttribute(font.fontDescriptor(), CoreText.kCTFontURLAttribute) if url: return url.path() logger.warning("Cannot find the path to the font '%s'.", self._font) return None
def fontContainsCharacters(self, characters): """Returns a Boolean if the current font contains the provided `characters`. Characters is a string containing one or more characters.""" font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize) if font is None: return False result, glyphs = CoreText.CTFontGetGlyphsForCharacters(font, characters, None, len(characters)) return result