/* static */ int FontUtils::FontScore(const unordered_map<char32, inT64>& ch_map, const string& fontname, int* raw_score, vector<bool>* ch_flags) { PangoFontInfo font_info; if (!font_info.ParseFontDescriptionName(fontname)) { tprintf("ERROR: Could not parse %s\n", fontname.c_str()); } PangoFont* font = font_info.ToPangoFont(); PangoCoverage* coverage = pango_font_get_coverage(font, NULL); if (ch_flags) { ch_flags->clear(); ch_flags->reserve(ch_map.size()); } *raw_score = 0; int ok_chars = 0; for (unordered_map<char32, inT64>::const_iterator it = ch_map.begin(); it != ch_map.end(); ++it) { bool covered = (IsWhitespace(it->first) || (pango_coverage_get(coverage, it->first) == PANGO_COVERAGE_EXACT)); if (covered) { ++(*raw_score); ok_chars += it->second; } if (ch_flags) { ch_flags->push_back(covered); } } return ok_chars; }
/* static */ void FontUtils::GetAllRenderableCharacters(const string& font_name, vector<bool>* unichar_bitmap) { PangoFontInfo font_info(font_name); PangoCoverage* coverage = pango_font_get_coverage( font_info.ToPangoFont(), NULL); CharCoverageMapToBitmap(coverage, unichar_bitmap); }
int PangoFontInfo::DropUncoveredChars(string* utf8_text) const { PangoFont* font = ToPangoFont(); PangoCoverage* coverage = pango_font_get_coverage(font, NULL); int num_dropped_chars = 0; // Maintain two iterators that point into the string. For space efficiency, we // will repeatedly copy one covered UTF8 character from one to the other, and // at the end resize the string to the right length. char* out = const_cast<char*>(utf8_text->c_str()); const UNICHAR::const_iterator it_begin = UNICHAR::begin(utf8_text->c_str(), utf8_text->length()); const UNICHAR::const_iterator it_end = UNICHAR::end(utf8_text->c_str(), utf8_text->length()); for (UNICHAR::const_iterator it = it_begin; it != it_end; ++it) { // Skip bad utf-8. if (!it.is_legal()) continue; // One suitable error message will still be issued. if (!IsWhitespace(*it) && !pango_is_zero_width(*it) && pango_coverage_get(coverage, *it) != PANGO_COVERAGE_EXACT) { if (TLOG_IS_ON(2)) { char tmp[5]; int len = it.get_utf8(tmp); tmp[len] = '\0'; tlog(2, "'%s' (U+%x) not covered by font\n", tmp, *it); } ++num_dropped_chars; continue; } strncpy(out, it.utf8_data(), it.utf8_len()); out += it.utf8_len(); } utf8_text->resize(out - utf8_text->c_str()); return num_dropped_chars; }
static VALUE rg_get_coverage(VALUE self, VALUE language) { PangoCoverage* c = pango_font_get_coverage(_SELF(self), RVAL2PANGOLANGUAGE(language)); return PANGOCOVERAGE2RVAL(c); }
static PangoCoverageLevel pango_engine_shape_real_covers (PangoEngineShape *engine, PangoFont *font, PangoLanguage *language, gunichar wc) { PangoCoverage *coverage = pango_font_get_coverage (font, language); PangoCoverageLevel result = pango_coverage_get (coverage, wc); pango_coverage_unref (coverage); return result; }
/* static */ void FontUtils::GetAllRenderableCharacters(const vector<string>& fonts, vector<bool>* unichar_bitmap) { // Form the union of coverage maps from the fonts PangoCoverage* all_coverage = pango_coverage_new(); tlog(1, "Processing %d fonts\n", fonts.size()); for (int i = 0; i < fonts.size(); ++i) { PangoFontInfo font_info(fonts[i]); PangoCoverage* coverage = pango_font_get_coverage( font_info.ToPangoFont(), NULL); // Mark off characters that any font can render. pango_coverage_max(all_coverage, coverage); } CharCoverageMapToBitmap(all_coverage, unichar_bitmap); pango_coverage_unref(all_coverage); }
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { bool result = true; PangoCoverage* coverage = pango_font_get_coverage(m_platformData.m_font, pango_language_get_default()); for (int i = 0; i < length; i++) { if (PANGO_COVERAGE_NONE == pango_coverage_get(coverage, characters[i])) { result = false; break; } } pango_coverage_unref(coverage); return result; }
bool PangoFontInfo::CoversUTF8Text(const char* utf8_text, int byte_length) const { PangoFont* font = ToPangoFont(); PangoCoverage* coverage = pango_font_get_coverage(font, NULL); for (UNICHAR::const_iterator it = UNICHAR::begin(utf8_text, byte_length); it != UNICHAR::end(utf8_text, byte_length); ++it) { if (IsWhitespace(*it) || pango_is_zero_width(*it)) continue; if (pango_coverage_get(coverage, *it) != PANGO_COVERAGE_EXACT) { char tmp[5]; int len = it.get_utf8(tmp); tmp[len] = '\0'; tlog(2, "'%s' (U+%x) not covered by font\n", tmp, *it); return false; } } return true; }
{ } static void pango_engine_lang_class_init (PangoEngineLangClass *klass) { } static PangoCoverageLevel pango_engine_shape_real_covers (PangoEngineShape *engine G_GNUC_UNUSED, PangoFont *font, PangoLanguage *language, gunichar wc) { PangoCoverage *coverage = pango_font_get_coverage (font, language); PangoCoverageLevel result = pango_coverage_get (coverage, wc); pango_coverage_unref (coverage); return result; } G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_DEFINE_ABSTRACT_TYPE (PangoEngineShape, pango_engine_shape, PANGO_TYPE_ENGINE); G_GNUC_END_IGNORE_DEPRECATIONS static void pango_engine_shape_init (PangoEngineShape *klass) { }
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); }