static cairo_font_face_t * pango_cairo_core_text_font_create_font_face (PangoCairoFont *font) { PangoCoreTextFont *ctfont = (PangoCoreTextFont *) (font); CTFontRef font_id; CGFontRef cgfont; cairo_font_face_t *cairo_face; font_id = pango_core_text_font_get_ctfont (ctfont); cgfont = CTFontCopyGraphicsFont (font_id, NULL); cairo_face = cairo_quartz_font_face_create_for_cgfont (cgfont); CFRelease (cgfont); return cairo_face; }
static PangoFontMetrics * pango_cairo_core_text_font_create_base_metrics_for_context (PangoCairoFont *font, PangoContext *context) { PangoCoreTextFont *cfont = (PangoCoreTextFont *) font; PangoFontMetrics *metrics; PangoFontDescription *font_desc; PangoLayout *layout; PangoRectangle extents; PangoLanguage *language = pango_context_get_language (context); const char *sample_str = pango_language_get_sample_string (language); CTFontRef ctfont; metrics = pango_font_metrics_new (); ctfont = pango_core_text_font_get_ctfont (cfont); metrics->ascent = CTFontGetAscent (ctfont) * PANGO_SCALE; metrics->descent = CTFontGetDescent (ctfont) * PANGO_SCALE; metrics->underline_position = CTFontGetUnderlinePosition (ctfont) * PANGO_SCALE; metrics->underline_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; metrics->strikethrough_position = metrics->ascent / 3; metrics->strikethrough_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; layout = pango_layout_new (context); font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font); pango_layout_set_font_description (layout, font_desc); pango_layout_set_text (layout, sample_str, -1); pango_layout_get_extents (layout, NULL, &extents); metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str); pango_layout_set_text (layout, "0123456789", -1); metrics->approximate_digit_width = max_glyph_width (layout); pango_font_description_free (font_desc); g_object_unref (layout); return metrics; }
* * FIXME items for future fixing: * # CoreText strings are UTF16, and the indices *often* refer to characters, * but not *always*. Notable exception is when a character is encoded using * two UTF16 code points. This are two characters in a CFString. At this point * advancing a single character in the CFString and advancing a single character * using g_utf8_next_char in the const char string goes out of sync. * # We currently don't bother about LTR, Pango core appears to fix this up for us. * (Even when we cared warnings were generated that strings were in the wrong * order, this should be investigated). * # When CoreText generates two glyphs for one character, only one is stored. * This breaks the example strings for e.g. Georgian and Gothic. */ glyph_list = create_core_text_glyph_list (text, length, pango_core_text_font_get_ctfont (cfont)); if (!glyph_list) return; /* Translate the glyph list to a PangoGlyphString */ n_chars = g_utf8_strlen (text, length); pango_glyph_string_set_size (glyphs, n_chars); glyph_iter = glyph_list; coverage = pango_font_get_coverage (PANGO_FONT (cfont), analysis->language); for (gs_prev_i = -1, gs_i = 0, p = text; gs_i < n_chars; gs_prev_i = gs_i, gs_i++, p = g_utf8_next_char (p)) {
static void basic_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, gint length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { const char *p; char *copy; CTLineRef line; CFStringRef cstr; CFDictionaryRef attributes; CFAttributedStringRef attstr; PangoCoreTextFont *cfont = PANGO_CORE_TEXT_FONT (font); PangoCoverage *coverage; CFArrayRef runs; CTRunRef run; CTRunStatus run_status; CFIndex i, glyph_count; const CGGlyph *cgglyphs; CFTypeRef keys[] = { (CFTypeRef) kCTFontAttributeName }; CFTypeRef values[] = { pango_core_text_font_get_ctfont (cfont) }; attributes = CFDictionaryCreate (kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); copy = g_strndup (text, length + 1); copy[length] = 0; cstr = CFStringCreateWithCString (kCFAllocatorDefault, copy, kCFStringEncodingUTF8); g_free (copy); attstr = CFAttributedStringCreate (kCFAllocatorDefault, cstr, attributes); line = CTLineCreateWithAttributedString (attstr); runs = CTLineGetGlyphRuns (line); /* Since Pango divides things into runs already, we assume there is * only a single run in this line. */ run = CFArrayGetValueAtIndex (runs, 0); run_status = CTRunGetStatus (run); glyph_count = CTRunGetGlyphCount (run); cgglyphs = CTRunGetGlyphsPtr (run); p = text; pango_glyph_string_set_size (glyphs, glyph_count); coverage = pango_font_get_coverage (PANGO_FONT (cfont), analysis->language); for (i = 0; i < glyph_count; i++) { CFIndex real_i, prev_i; gunichar wc; gunichar mirrored_ch; wc = g_utf8_get_char (p); if (analysis->level % 2) if (pango_get_mirror_char (wc, &mirrored_ch)) wc = mirrored_ch; if (run_status & kCTRunStatusRightToLeft) { real_i = glyph_count - i - 1; prev_i = real_i + 1; } else { real_i = i; prev_i = real_i - 1; } if (wc == 0xa0) /* non-break-space */ wc = 0x20; if (pango_is_zero_width (wc)) { set_glyph (font, glyphs, real_i, p - text, PANGO_GLYPH_EMPTY); } else { PangoCoverageLevel result; result = pango_coverage_get (coverage, wc); if (result != PANGO_COVERAGE_NONE) { set_glyph (font, glyphs, real_i, p - text, cgglyphs[real_i]); if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK) { if (i > 0) { PangoRectangle logical_rect, ink_rect; glyphs->glyphs[real_i].geometry.width = MAX (glyphs->glyphs[prev_i].geometry.width, glyphs->glyphs[prev_i].geometry.width); glyphs->glyphs[prev_i].geometry.width = 0; glyphs->log_clusters[real_i] = glyphs->log_clusters[prev_i]; /* Some heuristics to try to guess how overstrike glyphs are * done and compensate */ pango_font_get_glyph_extents (font, glyphs->glyphs[real_i].glyph, &ink_rect, &logical_rect); if (logical_rect.width == 0 && ink_rect.x == 0) glyphs->glyphs[real_i].geometry.x_offset = (glyphs->glyphs[real_i].geometry.width - ink_rect.width) / 2; } } } else { set_glyph (font, glyphs, real_i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc)); } } p = g_utf8_next_char (p); } CFRelease (line); CFRelease (attstr); CFRelease (cstr); CFRelease (attributes); pango_coverage_unref (coverage); }