diff --git a/libs/pyglet/font/quartz.py b/libs/pyglet/font/quartz.py index cf0cefa..fdc5dcc 100644 --- a/libs/pyglet/font/quartz.py +++ b/libs/pyglet/font/quartz.py @@ -7,7 +7,7 @@ from ctypes import c_void_p, c_int32, byref, c_byte from pyglet.font import base import pyglet.image -from pyglet.libs.darwin import cocoapy, kCTFontURLAttribute +from pyglet.libs.darwin import cocoapy, kCTFontURLAttribute, CGFloat cf = cocoapy.cf ct = cocoapy.ct @@ -38,26 +38,39 @@ class QuartzGlyphRenderer(base.GlyphRenderer): cf.CFRelease(string) cf.CFRelease(attributes) - # Get a bounding rectangle for glyphs in string. + # Determine the glyphs involved for the text (if any) 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) + # If a glyph is returned as 0, it does not exist in the current font. + if glyphs[0] == 0: + # Use the typographic bounds instead for the placements. + # This seems to have some sort of fallback information in the bounds. + ascent, descent = CGFloat(), CGFloat() + advance = width = int(ct.CTLineGetTypographicBounds(line, byref(ascent), byref(descent), None)) + height = int(ascent.value + descent.value) + lsb = 0 + baseline = descent.value + else: + # Get a bounding rectangle for glyphs in string. + rect = ct.CTFontGetBoundingRectsForGlyphs(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)) + # 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.ceil(rect.origin.x)) - 1 + advance = int(round(advance)) # Create bitmap context. bitsPerComponent = 8 diff --git a/libs/pyglet/libs/darwin/cocoapy/cocoalibs.py b/libs/pyglet/libs/darwin/cocoapy/cocoalibs.py index a8c7477..ad4fb26 100644 --- a/libs/pyglet/libs/darwin/cocoapy/cocoalibs.py +++ b/libs/pyglet/libs/darwin/cocoapy/cocoalibs.py @@ -543,6 +543,9 @@ kCTFontBoldTrait = (1 << 1) ct.CTLineCreateWithAttributedString.restype = c_void_p ct.CTLineCreateWithAttributedString.argtypes = [c_void_p] +ct.CTLineGetTypographicBounds.restype = c_double +ct.CTLineGetTypographicBounds.argtypes = [c_void_p, POINTER(CGFloat), POINTER(CGFloat), POINTER(CGFloat)] + ct.CTLineDraw.restype = None ct.CTLineDraw.argtypes = [c_void_p, c_void_p] diff --git a/libs/pyglet/media/mediathreads.py b/libs/pyglet/media/mediathreads.py index 130868b..067c1dd 100644 --- a/libs/pyglet/media/mediathreads.py +++ b/libs/pyglet/media/mediathreads.py @@ -56,7 +56,11 @@ class MediaThread: with self._condition: self._stopped = True self._condition.notify() - self._thread.join() + try: + self._thread.join() + except RuntimeError: + # Ignore on unclean shutdown + pass def sleep(self, timeout): """Wait for some amount of time, or until notified. diff --git a/libs/pyglet/window/cocoa/pyglet_textview.py b/libs/pyglet/window/cocoa/pyglet_textview.py index 39f1146..5f9c1f0 100644 --- a/libs/pyglet/window/cocoa/pyglet_textview.py +++ b/libs/pyglet/window/cocoa/pyglet_textview.py @@ -40,8 +40,9 @@ class PygletTextView_Implementation: text = cfstring_to_string(text) self.setString_(self.empty_string) # Don't send control characters (tab, newline) as on_text events. - if unicodedata.category(text[0]) != 'Cc': - self._window.dispatch_event("on_text", text) + if text: + if unicodedata.category(text[0]) != 'Cc': + self._window.dispatch_event("on_text", text) @PygletTextView.method('v@') def insertNewline_(self, sender): diff --git a/libs/pyglet/window/cocoa/pyglet_view.py b/libs/pyglet/window/cocoa/pyglet_view.py index 0c85e89..a66921c 100644 --- a/libs/pyglet/window/cocoa/pyglet_view.py +++ b/libs/pyglet/window/cocoa/pyglet_view.py @@ -139,10 +139,6 @@ class PygletView_Implementation: self.addTrackingArea_(self._tracking_area) - @PygletView.method('B') - def acceptsFirstResponder (self): - return True - @PygletView.method('B') def canBecomeKeyView(self): return True