📄 pangowin32.c
字号:
return NULL; res = GetFontData (hdc, CMAP, offset + 4, &length, 4); if (res != 4) return NULL; length = GUINT32_FROM_BE (length); table = g_malloc (length); res = GetFontData (hdc, CMAP, offset, table, length); if (res != length) { g_free (table); return NULL; } table->format = GUINT16_FROM_BE (table->format); table->length = GUINT32_FROM_BE (table->length); table->language = GUINT32_FROM_BE (table->language); table->count = GUINT32_FROM_BE (table->count); if (table->format != 12 || (table->length % 4) != 0 || table->length > length || table->length < 16 + table->count * 12) { g_free (table); return NULL; } tbl_end = (guint32 *) ((char *) table + length); tbl = table->groups; while (tbl < tbl_end) { *tbl = GUINT32_FROM_BE (*tbl); tbl++; } return table;}static gpointerfont_get_cmap (PangoFont *font){ PangoWin32Font *win32font = (PangoWin32Font *)font; gpointer cmap; if (win32font->win32face->cmap) return win32font->win32face->cmap; pango_win32_font_select_font (font, _pango_win32_hdc); /* Prefer the format 12 cmap */ if ((cmap = get_format_12_cmap (_pango_win32_hdc)) != NULL) { win32font->win32face->cmap_format = 12; win32font->win32face->cmap = cmap; } else if ((cmap = get_format_4_cmap (_pango_win32_hdc)) != NULL) { win32font->win32face->cmap_format = 4; win32font->win32face->cmap = cmap; } pango_win32_font_done_font (font); return cmap;}static gintpango_win32_font_get_type1_glyph_index (PangoFont *font, gunichar wc){ wchar_t unicode[2]; WORD glyph_index; gint32 res; unicode[0] = wc; unicode[1] = 0; pango_win32_font_select_font (font, _pango_win32_hdc); res = GetGlyphIndicesW (_pango_win32_hdc, unicode, 1, &glyph_index, 0); pango_win32_font_done_font (font); if (res == 1) return glyph_index; else return 0;}/** * pango_win32_font_get_glyph_index: * @font: a #PangoFont. * @wc: a Unicode character. * * Obtains the index of the glyph for @wc in @font, or 0, if not * covered. * * Return value: the glyph index for @wc. **/gintpango_win32_font_get_glyph_index (PangoFont *font, gunichar wc){ PangoWin32Font *win32font = (PangoWin32Font *)font; gpointer cmap; guint16 glyph; if (win32font->win32face->has_cmap) { /* Do GetFontData magic on font->hfont here. */ cmap = font_get_cmap (font); if (cmap == NULL) win32font->win32face->has_cmap = FALSE; } if (!win32font->win32face->has_cmap) return pango_win32_font_get_type1_glyph_index (font, wc); if (win32font->win32face->cmap_format == 4) { struct format_4_cmap *cmap4 = cmap; guint16 *id_range_offset; guint16 *id_delta; guint16 *start_count; guint16 segment; guint16 id; guint16 ch = wc; if (wc > 0xFFFF) return 0; if (!find_segment (cmap4, ch, &segment)) return 0; id_range_offset = get_id_range_offset (cmap4); id_delta = get_id_delta (cmap4); start_count = get_start_count (cmap4); if (id_range_offset[segment] == 0) glyph = (id_delta[segment] + ch) % 65536; else { id = *(id_range_offset[segment]/2 + (ch - start_count[segment]) + &id_range_offset[segment]); if (id) glyph = (id_delta[segment] + id) %65536; else glyph = 0; } } else if (win32font->win32face->cmap_format == 12) { struct format_12_cmap *cmap12 = cmap; guint32 i; glyph = 0; for (i = 0; i < cmap12->count; i++) { if (cmap12->groups[i*3+0] <= wc && wc <= cmap12->groups[i*3+1]) { glyph = cmap12->groups[i*3+2] + (wc - cmap12->groups[i*3+0]); break; } } } else g_assert_not_reached (); return glyph;}gboolean_pango_win32_get_name_header (HDC hdc, struct name_header *header){ if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header)) return FALSE; header->num_records = GUINT16_FROM_BE (header->num_records); header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset); return TRUE;}gboolean_pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record){ if (GetFontData (hdc, NAME, 6 + i * sizeof (*record), record, sizeof (*record)) != sizeof (*record)) return FALSE; record->platform_id = GUINT16_FROM_BE (record->platform_id); record->encoding_id = GUINT16_FROM_BE (record->encoding_id); record->language_id = GUINT16_FROM_BE (record->language_id); record->name_id = GUINT16_FROM_BE (record->name_id); record->string_length = GUINT16_FROM_BE (record->string_length); record->string_offset = GUINT16_FROM_BE (record->string_offset); return TRUE;}static gbooleanfont_has_name_in (PangoFont *font, PangoWin32CoverageLanguageClass cjkv){ HFONT hfont, oldhfont; struct name_header header; struct name_record record; gint i; gboolean retval = FALSE; if (cjkv == PANGO_WIN32_COVERAGE_UNSPEC) return TRUE; hfont = pango_win32_get_hfont (font); oldhfont = SelectObject (_pango_win32_hdc, hfont); if (!_pango_win32_get_name_header (_pango_win32_hdc, &header)) { SelectObject (_pango_win32_hdc, oldhfont); return FALSE; } for (i = 0; i < header.num_records; i++) { if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record)) { SelectObject (_pango_win32_hdc, oldhfont); return FALSE; } if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0) continue; PING(("platform:%d encoding:%d language:%04x name_id:%d", record.platform_id, record.encoding_id, record.language_id, record.name_id)); if (record.platform_id == MICROSOFT_PLATFORM_ID) if ((cjkv == PANGO_WIN32_COVERAGE_ZH_TW && record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)) || (cjkv == PANGO_WIN32_COVERAGE_ZH_CN && record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) || (cjkv == PANGO_WIN32_COVERAGE_JA && PRIMARYLANGID (record.language_id) == LANG_JAPANESE) || (cjkv == PANGO_WIN32_COVERAGE_KO && PRIMARYLANGID (record.language_id) == LANG_KOREAN) || (cjkv == PANGO_WIN32_COVERAGE_VI && PRIMARYLANGID (record.language_id) == LANG_VIETNAMESE)) { PING (("yep:%d:%04x", cjkv, record.language_id)); retval = TRUE; break; } } SelectObject (_pango_win32_hdc, oldhfont); return retval;}static voidpango_win32_font_calc_type1_coverage (PangoFont *font, PangoCoverage *coverage, PangoLanguage *lang){ GLYPHSET *glyph_set; gint32 res; guint32 ch; guint32 i; pango_win32_font_select_font (font, _pango_win32_hdc); res = GetFontUnicodeRanges(_pango_win32_hdc, NULL); if (res == 0) goto fail1; glyph_set = g_malloc (res); res = GetFontUnicodeRanges(_pango_win32_hdc, glyph_set); if (res == 0) goto fail2; for (i = 0; i < glyph_set->cRanges; i++) { guint32 end = glyph_set->ranges[i].wcLow + glyph_set->ranges[i].cGlyphs; for (ch = glyph_set->ranges[i].wcLow; ch < end; ch++) if (CH_IS_UNIHAN_BMP (ch)) pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE); else pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT); } fail2: g_free (glyph_set); fail1: pango_win32_font_done_font (font);}static voidpango_win32_font_calc_coverage (PangoFont *font, PangoCoverage *coverage, PangoLanguage *lang){ PangoWin32Font *win32font = (PangoWin32Font *)font; gpointer cmap; guint32 ch; guint32 i; PangoWin32CoverageLanguageClass cjkv; gboolean hide_unihan = FALSE; PING(("font:%s lang:%s", pango_font_description_to_string (pango_font_describe (font)), pango_language_to_string (lang))); if (win32font->win32face->has_cmap) { /* Do GetFontData magic on font->hfont here. */ cmap = font_get_cmap (font); if (cmap == NULL) win32font->win32face->has_cmap = FALSE; } if (!win32font->win32face->has_cmap) { pango_win32_font_calc_type1_coverage (font, coverage, lang); return; } cjkv = pango_win32_coverage_language_classify (lang); if (cjkv != PANGO_WIN32_COVERAGE_UNSPEC && !font_has_name_in (font, cjkv)) { PING(("hiding UniHan chars")); hide_unihan = TRUE; } PING (("coverage:")); if (win32font->win32face->cmap_format == 4) { struct format_4_cmap *cmap4 = cmap; guint16 *id_range_offset; guint16 *start_count; guint16 *end_count; guint16 seg_count; guint16 id; seg_count = cmap4->seg_count_x_2/2; end_count = get_end_count (cmap4); start_count = get_start_count (cmap4); id_range_offset = get_id_range_offset (cmap4); for (i = 0; i < seg_count; i++) { if (id_range_offset[i] == 0) {#ifdef PANGO_WIN32_DEBUGGING if (_pango_win32_debug) { if (end_count[i] == start_count[i]) g_print ("%04x ", start_count[i]); else g_print ("%04x:%04x ", start_count[i], end_count[i]); }#endif for (ch = start_count[i]; ch <= end_count[i]; ch++) if (hide_unihan && CH_IS_UNIHAN_BMP (ch)) pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE); else pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT); } else {#ifdef PANGO_WIN32_DEBUGGING guint32 ch0 = G_MAXUINT;#endif for (ch = start_count[i]; ch <= end_count[i]; ch++) { if (ch == 0xFFFF) break; id = *(id_range_offset[i]/2 + (ch - start_count[i]) + &id_range_offset[i]); if (id) {#ifdef PANGO_WIN32_DEBUGGING if (ch0 == G_MAXUINT) ch0 = ch;#endif if (hide_unihan && CH_IS_UNIHAN_BMP (ch)) pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE); else pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT); }#ifdef PANGO_WIN32_DEBUGGING else if (ch0 < G_MAXUINT) { if (_pango_win32_debug) { if (ch > ch0 + 2) g_print ("%04x:%04x ", ch0, ch - 1); else g_print ("%04x ", ch0); } ch0 = G_MAXUINT; }#endif }#ifdef PANGO_WIN32_DEBUGGING if (ch0 < G_MAXUINT) { if (_pango_win32_debug) { if (ch > ch0 + 2) g_print ("%04x:%04x ", ch0, ch - 1); else g_print ("%04x ", ch0); } }#endif } } } else if (win32font->win32face->cmap_format == 12) { struct format_12_cmap *cmap12 = cmap; for (i = 0; i < cmap12->count; i++) {#ifdef PANGO_WIN32_DEBUGGING if (_pango_win32_debug) { if (cmap12->groups[i*3+0] == cmap12->groups[i*3+1]) g_print ("%04x ", cmap12->groups[i*3+0]); else g_print ("%04x:%04x ", cmap12->groups[i*3+0], cmap12->groups[i*3+1]); }#endif for (ch = cmap12->groups[i*3+0]; ch <= cmap12->groups[i*3+1]; ch++) { if (hide_unihan && CH_IS_UNIHAN (ch)) pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE); else pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT); } } } else g_assert_not_reached ();#ifdef PANGO_WIN32_DEBUGGING if (_pango_win32_debug) g_print ("\n");#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -