racket/gui Cocoa: repairs for Cairo and Pango
* Fix a clipped-rendering problem for text in Cairo. * Fix Pango's CoreText back-end to support non-BMP characters. Note that Emoji characters still do not render. Cairo uses CGContextShowGlyphsWithAdvances() to draw glyphs, but it would need to use CTFontDrawGlyphs() to make Emoji work. (Mozilla has a patch to do that for some older version of Cairo, so look there if it seems worth doing one day.) * Disable Pango's CoreText font fallbacks in favor of the Racket-implemented fallback. This is not obviously a good idea, but it restore the `racket/draw` hack of prefering "Arial Unicode MS". Otherwise, various symbol glyphs are chosen badly, such as #\u273A, at least on my machine. * Drop the clusters argument to `pango_cairo_show_glyph_string`, which turns out to be unnecessary.
This commit is contained in:
parent
7b26260d99
commit
69984fb231
|
@ -1 +1 @@
|
||||||
Subproject commit 61d502ecff8b298dc0908876ee91fc8acbfe4e3e
|
Subproject commit a32d6b2b4cbdc9ff184d53144157035b0eec98b4
|
|
@ -1316,7 +1316,7 @@
|
||||||
|
|
||||||
(define/private (do-text cr draw-mode s x y font combine? offset angle)
|
(define/private (do-text cr draw-mode s x y font combine? offset angle)
|
||||||
(let* ([s (if (zero? offset)
|
(let* ([s (if (zero? offset)
|
||||||
s
|
s
|
||||||
(substring s offset))]
|
(substring s offset))]
|
||||||
[blank? (string=? s "")]
|
[blank? (string=? s "")]
|
||||||
[s (if (and (not draw-mode) blank?) " " s)]
|
[s (if (and (not draw-mode) blank?) " " s)]
|
||||||
|
@ -1372,7 +1372,7 @@
|
||||||
(let ([layout (pango_layout_new context)]
|
(let ([layout (pango_layout_new context)]
|
||||||
[next-s #f])
|
[next-s #f])
|
||||||
(pango_layout_set_font_description layout desc)
|
(pango_layout_set_font_description layout desc)
|
||||||
(when attrs (pango_layout_set_attributes layout attrs))
|
(install-attributes! layout attrs)
|
||||||
(pango_layout_set_text layout s)
|
(pango_layout_set_text layout s)
|
||||||
(let ([next-s
|
(let ([next-s
|
||||||
(if (or (not substitute-fonts?)
|
(if (or (not substitute-fonts?)
|
||||||
|
@ -1460,7 +1460,7 @@
|
||||||
(or (hash-ref layouts (char->integer ch) #f)
|
(or (hash-ref layouts (char->integer ch) #f)
|
||||||
(let ([layout (pango_layout_new context)])
|
(let ([layout (pango_layout_new context)])
|
||||||
(pango_layout_set_font_description layout desc)
|
(pango_layout_set_font_description layout desc)
|
||||||
(when attrs (pango_layout_set_attributes layout attrs))
|
(install-attributes! layout attrs)
|
||||||
(pango_layout_set_text layout (string ch))
|
(pango_layout_set_text layout (string ch))
|
||||||
(unless (or (not substitute-fonts?)
|
(unless (or (not substitute-fonts?)
|
||||||
(zero? (pango_layout_get_unknown_glyphs_count layout)))
|
(zero? (pango_layout_get_unknown_glyphs_count layout)))
|
||||||
|
@ -1497,7 +1497,6 @@
|
||||||
;; loop directly affects the responsiveness of the DrRacket
|
;; loop directly affects the responsiveness of the DrRacket
|
||||||
;; editor.
|
;; editor.
|
||||||
(let ([glyph-infos (malloc len _PangoGlyphInfo 'raw)] ;; assuming atomic until `free' below
|
(let ([glyph-infos (malloc len _PangoGlyphInfo 'raw)] ;; assuming atomic until `free' below
|
||||||
[log-clusters (malloc len _int 'raw)]
|
|
||||||
[first-font (vector-ref (hash-ref layouts (char->integer (string-ref s 0))) 3)]
|
[first-font (vector-ref (hash-ref layouts (char->integer (string-ref s 0))) 3)]
|
||||||
[first-ascent (and first-v (fl- (vector-ref first-v 1) (vector-ref first-v 2)))])
|
[first-ascent (and first-v (fl- (vector-ref first-v 1) (vector-ref first-v 2)))])
|
||||||
(and
|
(and
|
||||||
|
@ -1520,8 +1519,6 @@
|
||||||
;; Assume that the rect of the characters will pan out,
|
;; Assume that the rect of the characters will pan out,
|
||||||
;; and start filling in the glyph-info array:
|
;; and start filling in the glyph-info array:
|
||||||
(memcpy glyph-infos i glyphs 1 _PangoGlyphInfo)
|
(memcpy glyph-infos i glyphs 1 _PangoGlyphInfo)
|
||||||
;; Every glyph is is own cluster:
|
|
||||||
(ptr-set! log-clusters _int i i)
|
|
||||||
;; Adjust width to be consistent with measured widths
|
;; Adjust width to be consistent with measured widths
|
||||||
;; used when drawing individual characters.
|
;; used when drawing individual characters.
|
||||||
;; This is `set-PangoGlyphInfo-width!', but without
|
;; This is `set-PangoGlyphInfo-width!', but without
|
||||||
|
@ -1531,7 +1528,7 @@
|
||||||
;; If we get here, we can use the fast way:
|
;; If we get here, we can use the fast way:
|
||||||
(let ([glyph-string (make-PangoGlyphString len
|
(let ([glyph-string (make-PangoGlyphString len
|
||||||
glyph-infos
|
glyph-infos
|
||||||
log-clusters)])
|
#f)])
|
||||||
;; Move into position (based on the recorded Pango-units baseline)
|
;; Move into position (based on the recorded Pango-units baseline)
|
||||||
;; and draw the glyphs
|
;; and draw the glyphs
|
||||||
(cairo_move_to cr
|
(cairo_move_to cr
|
||||||
|
@ -1539,7 +1536,6 @@
|
||||||
(text-align-y/delta (+ y (/ (vector-ref first-v 4) (->fl PANGO_SCALE))) 0))
|
(text-align-y/delta (+ y (/ (vector-ref first-v 4) (->fl PANGO_SCALE))) 0))
|
||||||
(pango_cairo_show_glyph_string cr first-font glyph-string)
|
(pango_cairo_show_glyph_string cr first-font glyph-string)
|
||||||
(free glyph-infos)
|
(free glyph-infos)
|
||||||
(free log-clusters)
|
|
||||||
#t)))))
|
#t)))))
|
||||||
;; We use the slower, per-layout way:
|
;; We use the slower, per-layout way:
|
||||||
(let* ([query-and-cache
|
(let* ([query-and-cache
|
||||||
|
|
|
@ -19,21 +19,31 @@
|
||||||
(protect-out substitute-fonts?
|
(protect-out substitute-fonts?
|
||||||
install-alternate-face
|
install-alternate-face
|
||||||
font->pango-attrs
|
font->pango-attrs
|
||||||
font->hinting))
|
font->hinting
|
||||||
|
install-attributes!))
|
||||||
|
|
||||||
(define-local-member-name
|
(define-local-member-name
|
||||||
get-pango-attrs
|
get-pango-attrs
|
||||||
s-pango-attrs
|
s-pango-attrs
|
||||||
s-hinting)
|
s-hinting)
|
||||||
|
|
||||||
(define underlined-attrs (let ([l (pango_attr_list_new)])
|
(define fallback-attrs (and (or xp? (eq? 'macosx (system-type)))
|
||||||
(pango_attr_list_insert l (pango_attr_underline_new
|
|
||||||
PANGO_UNDERLINE_SINGLE))
|
|
||||||
l))
|
|
||||||
(define fallback-attrs (and xp?
|
|
||||||
(let ([l (pango_attr_list_new)])
|
(let ([l (pango_attr_list_new)])
|
||||||
(pango_attr_list_insert l (pango_attr_fallback_new #f))
|
(pango_attr_list_insert l (pango_attr_fallback_new #f))
|
||||||
l)))
|
l)))
|
||||||
|
(define underlined-attrs (let ([l (pango_attr_list_new)])
|
||||||
|
(pango_attr_list_insert l (pango_attr_underline_new
|
||||||
|
PANGO_UNDERLINE_SINGLE))
|
||||||
|
(when (eq? 'macosx (system-type))
|
||||||
|
(pango_attr_list_insert l (pango_attr_fallback_new #f)))
|
||||||
|
l))
|
||||||
|
|
||||||
|
(define always-attrs (and (eq? 'macosx (system-type)) fallback-attrs))
|
||||||
|
|
||||||
|
(define (install-attributes! layout attrs)
|
||||||
|
(cond
|
||||||
|
[attrs (pango_layout_set_attributes layout attrs)]
|
||||||
|
[always-attrs (pango_layout_set_attributes layout always-attrs)]))
|
||||||
|
|
||||||
(define (size? v) (and (exact-positive-integer? v)
|
(define (size? v) (and (exact-positive-integer? v)
|
||||||
(v . <= . 1024)))
|
(v . <= . 1024)))
|
||||||
|
@ -74,7 +84,7 @@
|
||||||
(and desc
|
(and desc
|
||||||
(let ([attrs (send font get-pango-attrs)])
|
(let ([attrs (send font get-pango-attrs)])
|
||||||
(pango_layout_set_font_description layout desc)
|
(pango_layout_set_font_description layout desc)
|
||||||
(when attrs (pango_layout_set_attributes layout attrs))
|
(install-attributes! layout attrs)
|
||||||
(and (zero? (pango_layout_get_unknown_glyphs_count layout))
|
(and (zero? (pango_layout_get_unknown_glyphs_count layout))
|
||||||
(begin
|
(begin
|
||||||
(hash-set! substitute-mapping (char->integer ch) face)
|
(hash-set! substitute-mapping (char->integer ch) face)
|
||||||
|
@ -83,7 +93,7 @@
|
||||||
(hash-set! substitute-mapping (char->integer ch) #t)
|
(hash-set! substitute-mapping (char->integer ch) #t)
|
||||||
;; put old desc & attrs back
|
;; put old desc & attrs back
|
||||||
(pango_layout_set_font_description layout desc)
|
(pango_layout_set_font_description layout desc)
|
||||||
(when attrs (pango_layout_set_attributes layout attrs)))))
|
(install-attributes! layout attrs))))
|
||||||
|
|
||||||
(define (has-screen-glyph? c font desc for-label?)
|
(define (has-screen-glyph? c font desc for-label?)
|
||||||
(let* ([s (cairo_image_surface_create CAIRO_FORMAT_ARGB32 1 1)]
|
(let* ([s (cairo_image_surface_create CAIRO_FORMAT_ARGB32 1 1)]
|
||||||
|
|
|
@ -107,6 +107,9 @@
|
||||||
;; --------------------------------------------------
|
;; --------------------------------------------------
|
||||||
;; Patches:
|
;; Patches:
|
||||||
|
|
||||||
|
;; Fix a problem with glyph extents and clipped rendering:
|
||||||
|
(define-runtime-path cairo-coretext-patch "patches/cairo-coretext.patch")
|
||||||
|
|
||||||
;; Enable kerning and set DPI to 72:
|
;; Enable kerning and set DPI to 72:
|
||||||
(define-runtime-path coretext-patch "patches/coretext.patch")
|
(define-runtime-path coretext-patch "patches/coretext.patch")
|
||||||
|
|
||||||
|
@ -304,7 +307,8 @@
|
||||||
null))]
|
null))]
|
||||||
[("cairo") (config #:depends '("pixman" "fontconfig" "freetype" "libpng")
|
[("cairo") (config #:depends '("pixman" "fontconfig" "freetype" "libpng")
|
||||||
#:env path-flags
|
#:env path-flags
|
||||||
#:configure '("--enable-xlib=no"))]
|
#:configure '("--enable-xlib=no")
|
||||||
|
#:patches (list cairo-coretext-patch))]
|
||||||
[("harfbuzz") (config #:depends '("fontconfig" "freetype" "cairo")
|
[("harfbuzz") (config #:depends '("fontconfig" "freetype" "cairo")
|
||||||
#:configure '("--without-icu")
|
#:configure '("--without-icu")
|
||||||
#:patches (if win?
|
#:patches (if win?
|
||||||
|
|
21
racket/src/native-libs/patches/cairo-coretext.patch
Normal file
21
racket/src/native-libs/patches/cairo-coretext.patch
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
diff -r -u old/cairo-1.12.16/src/cairo-quartz-font.c new/cairo-1.12.16/src/cairo-quartz-font.c
|
||||||
|
--- old/cairo-1.12.16/src/cairo-quartz-font.c 2014-04-15 11:04:35.000000000 -0600
|
||||||
|
+++ new/cairo-1.12.16/src/cairo-quartz-font.c 2014-04-15 11:05:43.000000000 -0600
|
||||||
|
@@ -461,10 +461,12 @@
|
||||||
|
bbox.size.width / emscale, bbox.size.height / emscale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- xmin = CGRectGetMinX(bbox);
|
||||||
|
- ymin = CGRectGetMinY(bbox);
|
||||||
|
- xmax = CGRectGetMaxX(bbox);
|
||||||
|
- ymax = CGRectGetMaxY(bbox);
|
||||||
|
+ /* add 1 to bounds to avoid round-off error that happens somewhere
|
||||||
|
+ in the path of rendering text (e.g., "-" vs. "-d" with 12-point Menlo) */
|
||||||
|
+ xmin = CGRectGetMinX(bbox)-1;
|
||||||
|
+ ymin = CGRectGetMinY(bbox)-1;
|
||||||
|
+ xmax = CGRectGetMaxX(bbox)+1;
|
||||||
|
+ ymax = CGRectGetMaxY(bbox)+1;
|
||||||
|
|
||||||
|
extents.x_bearing = xmin;
|
||||||
|
extents.y_bearing = - ymax;
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
|
diff -r -u old/pango-1.36.3/pango/pangocoretext.c new/pango-1.36.3/pango/pangocoretext.c
|
||||||
|
--- old/pango-1.36.3/pango/pangocoretext.c 2014-03-05 21:33:55.000000000 -0700
|
||||||
|
+++ new/pango-1.36.3/pango/pangocoretext.c 2014-04-14 18:25:38.000000000 -0600
|
||||||
|
@@ -97,8 +97,7 @@
|
||||||
|
bitmap = CFCharacterSetCreateBitmapRepresentation (kCFAllocatorDefault,
|
||||||
|
charset);
|
||||||
|
|
||||||
|
- /* We only handle the BMP plane */
|
||||||
|
- length = MIN (CFDataGetLength (bitmap), 8192);
|
||||||
|
+ length = CFDataGetLength (bitmap);
|
||||||
|
ptr = CFDataGetBytePtr (bitmap);
|
||||||
|
|
||||||
|
/* FIXME: can and should this be done more efficiently? */
|
||||||
diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modules/basic/basic-coretext.c
|
diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modules/basic/basic-coretext.c
|
||||||
--- old/pango-1.36.3/modules/basic/basic-coretext.c 2014-03-05 21:33:55.000000000 -0700
|
--- old/pango-1.36.3/modules/basic/basic-coretext.c 2014-03-05 21:33:55.000000000 -0700
|
||||||
+++ new/pango-1.36.3/modules/basic/basic-coretext.c 2014-03-30 09:52:46.000000000 -0600
|
+++ new/pango-1.36.3/modules/basic/basic-coretext.c 2014-04-14 17:50:38.000000000 -0600
|
||||||
@@ -55,7 +55,8 @@
|
@@ -55,7 +55,8 @@
|
||||||
PangoGlyphString *glyphs,
|
PangoGlyphString *glyphs,
|
||||||
int i,
|
int i,
|
||||||
|
@ -43,7 +56,26 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
|
|
||||||
ct_glyph_count = CTRunGetGlyphCount (iter->current_run);
|
ct_glyph_count = CTRunGetGlyphCount (iter->current_run);
|
||||||
iter->current_indices = malloc (sizeof (CFIndex *) * ct_glyph_count);
|
iter->current_indices = malloc (sizeof (CFIndex *) * ct_glyph_count);
|
||||||
@@ -175,6 +183,12 @@
|
@@ -166,7 +174,17 @@
|
||||||
|
static gunichar
|
||||||
|
run_iterator_get_character (struct RunIterator *iter)
|
||||||
|
{
|
||||||
|
- return CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]);
|
||||||
|
+ gunichar c;
|
||||||
|
+
|
||||||
|
+ c = CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]);
|
||||||
|
+ if (c & 0xD800) {
|
||||||
|
+ /* surrogate pair */
|
||||||
|
+ gunichar c2;
|
||||||
|
+ c2 = CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]+1);
|
||||||
|
+ c = 0x10000 + (((c & 0x3FF) << 10) | (c2 & 0x3FF));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGGlyph
|
||||||
|
@@ -175,6 +193,12 @@
|
||||||
return iter->current_cgglyphs[iter->ct_i];
|
return iter->current_cgglyphs[iter->ct_i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +88,7 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
static CFIndex
|
static CFIndex
|
||||||
run_iterator_get_index (struct RunIterator *iter)
|
run_iterator_get_index (struct RunIterator *iter)
|
||||||
{
|
{
|
||||||
@@ -297,6 +311,7 @@
|
@@ -297,6 +321,7 @@
|
||||||
{
|
{
|
||||||
CFIndex index;
|
CFIndex index;
|
||||||
CGGlyph cgglyph;
|
CGGlyph cgglyph;
|
||||||
|
@ -64,7 +96,7 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
gunichar wc;
|
gunichar wc;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -338,6 +353,7 @@
|
@@ -338,6 +363,7 @@
|
||||||
gi = g_slice_new (struct GlyphInfo);
|
gi = g_slice_new (struct GlyphInfo);
|
||||||
gi->index = run_iterator_get_index (&riter);
|
gi->index = run_iterator_get_index (&riter);
|
||||||
gi->cgglyph = run_iterator_get_cgglyph (&riter);
|
gi->cgglyph = run_iterator_get_cgglyph (&riter);
|
||||||
|
@ -72,7 +104,7 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
gi->wc = run_iterator_get_character (&riter);
|
gi->wc = run_iterator_get_character (&riter);
|
||||||
|
|
||||||
glyph_list = g_slist_prepend (glyph_list, gi);
|
glyph_list = g_slist_prepend (glyph_list, gi);
|
||||||
@@ -426,7 +442,7 @@
|
@@ -426,7 +452,7 @@
|
||||||
if (gi == NULL || gi->index > gs_i)
|
if (gi == NULL || gi->index > gs_i)
|
||||||
{
|
{
|
||||||
/* gs_i is behind, insert empty glyph */
|
/* gs_i is behind, insert empty glyph */
|
||||||
|
@ -81,7 +113,7 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (gi->index < gs_i)
|
else if (gi->index < gs_i)
|
||||||
@@ -457,7 +473,7 @@
|
@@ -457,7 +483,7 @@
|
||||||
|
|
||||||
if (result != PANGO_COVERAGE_NONE)
|
if (result != PANGO_COVERAGE_NONE)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +122,7 @@ diff -r -u old/pango-1.36.3/modules/basic/basic-coretext.c new/pango-1.36.3/modu
|
||||||
|
|
||||||
if (g_unichar_type (gi->wc) == G_UNICODE_NON_SPACING_MARK)
|
if (g_unichar_type (gi->wc) == G_UNICODE_NON_SPACING_MARK)
|
||||||
{
|
{
|
||||||
@@ -480,7 +496,7 @@
|
@@ -480,7 +506,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -125,3 +157,25 @@ diff -r -u old/pango-1.36.3/pango/pangocairo-coretextfontmap.c new/pango-1.36.3/
|
||||||
- cafontmap->dpi = 96.;
|
- cafontmap->dpi = 96.;
|
||||||
+ cafontmap->dpi = 72.;
|
+ cafontmap->dpi = 72.;
|
||||||
}
|
}
|
||||||
|
diff -r -u old/pango-1.36.3/pango/pangocoretext-fontmap.c new/pango-1.36.3/pango/pangocoretext-fontmap.c
|
||||||
|
--- old/pango-1.36.3/pango/pangocoretext-fontmap.c 2014-04-14 10:56:38.000000000 -0600
|
||||||
|
+++ new/pango-1.36.3/pango/pangocoretext-fontmap.c 2014-04-14 11:01:45.000000000 -0600
|
||||||
|
@@ -297,7 +297,8 @@
|
||||||
|
cf_number = (CFNumberRef)CFDictionaryGetValue (dict,
|
||||||
|
kCTFontWeightTrait);
|
||||||
|
|
||||||
|
- if (CFNumberGetValue (cf_number, kCFNumberCGFloatType, &value))
|
||||||
|
+ weight = PANGO_WEIGHT_NORMAL;
|
||||||
|
+ if (cf_number && CFNumberGetValue (cf_number, kCFNumberCGFloatType, &value))
|
||||||
|
{
|
||||||
|
if (value < ct_weight_min || value > ct_weight_max)
|
||||||
|
{
|
||||||
|
@@ -315,8 +316,6 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- weight = PANGO_WEIGHT_NORMAL;
|
||||||
|
|
||||||
|
CFRelease (dict);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user