📄 pangowin32.c
字号:
table = g_malloc (ENCODING_TABLE_SIZE*n_tables); res = GetFontData (hdc, CMAP, CMAP_HEADER_SIZE, table, ENCODING_TABLE_SIZE*n_tables); if (res != ENCODING_TABLE_SIZE*n_tables) return 0; for (i = 0; i < n_tables; i++) { if (table[i].platform_id == GUINT16_TO_BE (MICROSOFT_PLATFORM_ID) && table[i].encoding_id == GUINT16_TO_BE (encoding_id)) { offset = GUINT32_FROM_BE (table[i].offset); g_free (table); return offset; } } g_free (table); return 0;}static gpointerget_format_4_cmap (HDC hdc){ guint32 offset; guint32 res; guint16 length; guint16 *tbl, *tbl_end; struct format_4_cmap *table; /* FIXME: Could look here at the CRC for the font in the DC and return a cached copy if the same */ offset = get_cmap_offset (hdc, UNICODE_ENCODING_ID); if (offset == 0) return NULL; res = GetFontData (hdc, CMAP, offset + 2, &length, 2); if (res != 2) return NULL; length = GUINT16_FROM_BE (length); table = g_malloc (length); res = GetFontData (hdc, CMAP, offset, table, length); if (res != length || GUINT16_FROM_BE (table->format) != 4 || (GUINT16_FROM_BE (table->length) % 2) != 0) { g_free (table); return NULL; } table->format = GUINT16_FROM_BE (table->format); table->length = GUINT16_FROM_BE (table->length); table->language = GUINT16_FROM_BE (table->language); table->seg_count_x_2 = GUINT16_FROM_BE (table->seg_count_x_2); table->search_range = GUINT16_FROM_BE (table->search_range); table->entry_selector = GUINT16_FROM_BE (table->entry_selector); table->range_shift = GUINT16_FROM_BE (table->range_shift); tbl_end = (guint16 *)((char *)table + length); tbl = &table->reserved; while (tbl < tbl_end) { *tbl = GUINT16_FROM_BE (*tbl); tbl++; } return table;}static guint16 *get_id_range_offset (struct format_4_cmap *table){ gint32 seg_count = table->seg_count_x_2/2; return &table->arrays[seg_count*3];}static guint16 *get_id_delta (struct format_4_cmap *table){ gint32 seg_count = table->seg_count_x_2/2; return &table->arrays[seg_count*2];}static guint16 *get_start_count (struct format_4_cmap *table){ gint32 seg_count = table->seg_count_x_2/2; return &table->arrays[seg_count*1];}static guint16 *get_end_count (struct format_4_cmap *table){ gint32 seg_count = table->seg_count_x_2/2; /* Apparently the reseved spot is not reserved for the end_count array!? */ return (&table->arrays[seg_count*0])-1;}static gbooleanfind_segment (struct format_4_cmap *table, guint16 wc, guint16 *segment){ guint16 start, end, i; guint16 seg_count = table->seg_count_x_2/2; guint16 *end_count = get_end_count (table); guint16 *start_count = get_start_count (table); static guint last = 0; /* Cache of one */ if (last < seg_count && wc >= start_count[last] && wc <= end_count[last]) { *segment = last; return TRUE; } /* Binary search for the segment */ start = 0; /* inclusive */ end = seg_count; /* not inclusive */ while (start < end) { /* Look at middle pos */ i = (start + end)/2; if (i == start) { /* We made no progress. Look if this is the one. */ if (wc >= start_count[i] && wc <= end_count[i]) { *segment = i; last = i; return TRUE; } else return FALSE; } else if (wc < start_count[i]) { end = i; } else if (wc > end_count[i]) { start = i; } else { /* Found it! */ *segment = i; last = i; return TRUE; } } return FALSE;}static gpointerget_format_12_cmap (HDC hdc){ guint32 offset; guint32 res; guint32 length; guint32 *tbl, *tbl_end; struct format_12_cmap *table; offset = get_cmap_offset (hdc, UCS4_ENCODING_ID); if (offset == 0) 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;}/** * 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; /* Do GetFontData magic on font->hfont here. */ cmap = font_get_cmap (font); if (cmap == NULL) return 0; 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;}gbooleanpango_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;}gbooleanpango_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_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))); 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; } /* Do GetFontData magic on font->hfont here. */ cmap = font_get_cmap (font); if (cmap == NULL) { PING(("no table")); return; } 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 + -