def add_menu_item(menu, title, action, key): with AutoReleasePool(): title = cocoapy.CFSTR(title) action = cocoapy.get_selector(action) key = cocoapy.CFSTR(key) menuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_( title, action, key) menu.addItem_(menuItem) # cleanup title.release() key.release() menuItem.release()
def have_font(cls, name): name = str(name) if name in cls._loaded_CGFont_table: return True # Try to create the font to see if it exists. # TODO: Find a better way to check. cfstring = cocoapy.CFSTR(name) cgfont = c_void_p(quartz.CGFontCreateWithFontName(cfstring)) cf.CFRelease(cfstring) if cgfont: cf.CFRelease(cgfont) return True return False
def __init__(self): super(CocoaEventLoop, self).__init__() with AutoReleasePool(): # Prepare the default application. self.NSApp = NSApplication.sharedApplication() if self.NSApp.isRunning(): # Application was already started by GUI library (e.g. wxPython). return if not self.NSApp.mainMenu(): create_menu() self.NSApp.setActivationPolicy_( cocoapy.NSApplicationActivationPolicyRegular) # Prevent Lion / Mountain Lion from automatically saving application state. # If we don't do this, new windows will not display on 10.8 after finishLaunching # has been called. defaults = NSUserDefaults.standardUserDefaults() ignoreState = cocoapy.CFSTR("ApplePersistenceIgnoreState") if not defaults.objectForKey_(ignoreState): defaults.setBool_forKey_(True, ignoreState) self._finished_launching = False
def _create_font_descriptor(self, family_name, traits): # Create an attribute dictionary. attributes = c_void_p( cf.CFDictionaryCreateMutable(None, 0, cf.kCFTypeDictionaryKeyCallBacks, cf.kCFTypeDictionaryValueCallBacks)) # Add family name to attributes. cfname = cocoapy.CFSTR(family_name) cf.CFDictionaryAddValue(attributes, cocoapy.kCTFontFamilyNameAttribute, cfname) cf.CFRelease(cfname) # Construct a CFNumber to represent the traits. itraits = c_int32(traits) symTraits = c_void_p( cf.CFNumberCreate(None, cocoapy.kCFNumberSInt32Type, byref(itraits))) if symTraits: # Construct a dictionary to hold the traits values. traitsDict = c_void_p( cf.CFDictionaryCreateMutable( None, 0, cf.kCFTypeDictionaryKeyCallBacks, cf.kCFTypeDictionaryValueCallBacks)) if traitsDict: # Add CFNumber traits to traits dictionary. cf.CFDictionaryAddValue(traitsDict, cocoapy.kCTFontSymbolicTrait, symTraits) # Add traits dictionary to attributes. cf.CFDictionaryAddValue(attributes, cocoapy.kCTFontTraitsAttribute, traitsDict) cf.CFRelease(traitsDict) cf.CFRelease(symTraits) # Create font descriptor with attributes. descriptor = c_void_p( ct.CTFontDescriptorCreateWithAttributes(attributes)) cf.CFRelease(attributes) return descriptor
def render(self, text): # Using CTLineDraw seems to be the only way to make sure that the text # is drawn with the specified font when that font is a graphics font loaded from # memory. For whatever reason, [NSAttributedString drawAtPoint:] ignores # the graphics font if it not registered with the font manager. # So we just use CTLineDraw for both graphics fonts and installed fonts. ctFont = self.font.ctFont # Create an attributed string using text and font. attributes = c_void_p( cf.CFDictionaryCreateMutable(None, 1, cf.kCFTypeDictionaryKeyCallBacks, cf.kCFTypeDictionaryValueCallBacks)) cf.CFDictionaryAddValue(attributes, cocoapy.kCTFontAttributeName, ctFont) string = c_void_p( cf.CFAttributedStringCreate(None, cocoapy.CFSTR(text), attributes)) # Create a CTLine object to render the string. line = c_void_p(ct.CTLineCreateWithAttributedString(string)) cf.CFRelease(string) cf.CFRelease(attributes) # Get a bounding rectangle for glyphs in string. count = len(text) chars = (cocoapy.UniChar * count)(*list(map(ord, str(text)))) glyphs = (cocoapy.CGGlyph * count)() ct.CTFontGetGlyphsForCharacters(ctFont, chars, glyphs, count) rect = ct.CTFontGetBoundingRectsForGlyphs(ctFont, 0, glyphs, None, count) # Get advance for all glyphs in string. advance = ct.CTFontGetAdvancesForGlyphs(ctFont, 0, glyphs, None, count) # Set image parameters: # We add 2 pixels to the bitmap width and height so that there will be a 1-pixel border # around the glyph image when it is placed in the texture atlas. This prevents # weird artifacts from showing up around the edges of the rendered glyph textures. # We adjust the baseline and lsb of the glyph by 1 pixel accordingly. width = max(int(math.ceil(rect.size.width) + 2), 1) height = max(int(math.ceil(rect.size.height) + 2), 1) baseline = -int(math.floor(rect.origin.y)) + 1 lsb = int(math.floor(rect.origin.x)) - 1 advance = int(round(advance)) # Create bitmap context. bitsPerComponent = 8 bytesPerRow = 4 * width colorSpace = c_void_p(quartz.CGColorSpaceCreateDeviceRGB()) bitmap = c_void_p( quartz.CGBitmapContextCreate( None, width, height, bitsPerComponent, bytesPerRow, colorSpace, cocoapy.kCGImageAlphaPremultipliedLast)) # Draw text to bitmap context. quartz.CGContextSetShouldAntialias(bitmap, True) quartz.CGContextSetTextPosition(bitmap, -lsb, baseline) ct.CTLineDraw(line, bitmap) cf.CFRelease(line) # Create an image to get the data out. imageRef = c_void_p(quartz.CGBitmapContextCreateImage(bitmap)) bytesPerRow = quartz.CGImageGetBytesPerRow(imageRef) dataProvider = c_void_p(quartz.CGImageGetDataProvider(imageRef)) imageData = c_void_p(quartz.CGDataProviderCopyData(dataProvider)) buffersize = cf.CFDataGetLength(imageData) buffer = (c_byte * buffersize)() byteRange = cocoapy.CFRange(0, buffersize) cf.CFDataGetBytes(imageData, byteRange, buffer) quartz.CGImageRelease(imageRef) quartz.CGDataProviderRelease(imageData) cf.CFRelease(bitmap) cf.CFRelease(colorSpace) glyph_image = pyglet.image.ImageData(width, height, 'RGBA', buffer, bytesPerRow) glyph = self.font.create_glyph(glyph_image) glyph.set_bearings(baseline, lsb, advance) t = list(glyph.tex_coords) glyph.tex_coords = t[9:12] + t[6:9] + t[3:6] + t[:3] return glyph