2 * pangowin32.c: Routines for handling Windows fonts
4 * Copyright (C) 1999 Red Hat Software
5 * Copyright (C) 2000 Tor Lillqvist
6 * Copyright (C) 2001 Alexander Larsson
7 * Copyright (C) 2007 Novell, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
31 #include "pango-impl-utils.h"
32 #include "pangowin32.h"
33 #include "pangowin32-private.h"
35 #define MAX_FREED_FONTS 16
37 #define CH_IS_UNIHAN_BMP(ch) ((ch) >= 0x3400 && (ch) <= 0x9FFF)
38 #define CH_IS_UNIHAN(ch) (CH_IS_UNIHAN_BMP (ch) || \
39 ((ch) >= 0x20000 && (ch) <= 0x2A6DF) || \
40 ((ch) >= 0x2F800 && (ch) <= 0x2FA1F))
43 OSVERSIONINFO _pango_win32_os_version_info;
44 gboolean _pango_win32_debug = FALSE;
46 static void pango_win32_font_dispose (GObject *object);
47 static void pango_win32_font_finalize (GObject *object);
49 static gboolean pango_win32_font_real_select_font (PangoFont *font,
51 static void pango_win32_font_real_done_font (PangoFont *font);
52 static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
54 static PangoFontDescription *pango_win32_font_describe (PangoFont *font);
55 static PangoFontDescription *pango_win32_font_describe_absolute (PangoFont *font);
56 static PangoCoverage *pango_win32_font_get_coverage (PangoFont *font,
58 static void pango_win32_font_calc_coverage (PangoFont *font,
59 PangoCoverage *coverage,
61 static PangoEngineShape *pango_win32_font_find_shaper (PangoFont *font,
64 static void pango_win32_font_get_glyph_extents (PangoFont *font,
66 PangoRectangle *ink_rect,
67 PangoRectangle *logical_rect);
68 static PangoFontMetrics * pango_win32_font_get_metrics (PangoFont *font,
70 static PangoFontMap * pango_win32_font_get_font_map (PangoFont *font);
72 static gboolean pango_win32_font_real_select_font (PangoFont *font,
74 static void pango_win32_font_real_done_font (PangoFont *font);
75 static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
77 static HFONT pango_win32_get_hfont (PangoFont *font);
78 static void pango_win32_get_item_properties (PangoItem *item,
79 PangoUnderline *uline,
80 PangoAttrColor *fg_color,
82 PangoAttrColor *bg_color,
86 pango_win32_get_hfont (PangoFont *font)
88 PangoWin32Font *win32font = (PangoWin32Font *)font;
89 PangoWin32FontCache *cache;
95 if (!win32font->hfont)
97 cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
99 win32font->hfont = pango_win32_font_cache_loadw (cache, &win32font->logfontw);
100 if (!win32font->hfont)
102 gchar *face_utf8 = g_utf16_to_utf8 (win32font->logfontw.lfFaceName,
103 -1, NULL, NULL, NULL);
104 g_warning ("Cannot load font '%s\n", face_utf8);
109 SelectObject (_pango_win32_hdc, win32font->hfont);
110 GetTextMetrics (_pango_win32_hdc, &tm);
112 win32font->tm_overhang = tm.tmOverhang;
113 win32font->tm_descent = tm.tmDescent;
114 win32font->tm_ascent = tm.tmAscent;
117 return win32font->hfont;
121 * pango_win32_get_context:
123 * Retrieves a #PangoContext appropriate for rendering with Windows fonts.
125 * Return value: the new #PangoContext
127 * Deprecated: 1.22: Use pango_win32_font_map_for_display() followed by
128 * pango_font_map_create_context() instead.
131 pango_win32_get_context (void)
133 return pango_font_map_create_context (pango_win32_font_map_for_display ());
136 G_DEFINE_TYPE (PangoWin32Font, _pango_win32_font, PANGO_TYPE_FONT)
139 _pango_win32_font_init (PangoWin32Font *win32font)
141 win32font->size = -1;
143 win32font->metrics_by_lang = NULL;
145 win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);
149 * pango_win32_get_dc:
151 * Obtains a handle to the Windows device context that is used by Pango.
153 * Return value: A handle to the Windows device context that is used by Pango.
156 pango_win32_get_dc (void)
158 if (_pango_win32_hdc == NULL)
160 _pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
161 memset (&_pango_win32_os_version_info, 0,
162 sizeof (_pango_win32_os_version_info));
163 _pango_win32_os_version_info.dwOSVersionInfoSize =
164 sizeof (OSVERSIONINFO);
165 GetVersionEx (&_pango_win32_os_version_info);
167 /* Also do some generic pangowin32 initialisations... this function
168 * is a suitable place for those as it is called from a couple
169 * of class_init functions.
171 #ifdef PANGO_WIN32_DEBUGGING
172 if (getenv ("PANGO_WIN32_DEBUG") != NULL)
173 _pango_win32_debug = TRUE;
177 return _pango_win32_hdc;
181 * pango_win32_get_debug_flag:
183 * Returns whether debugging is turned on.
185 * Return value: %TRUE if debugging is turned on.
190 pango_win32_get_debug_flag (void)
192 return _pango_win32_debug;
196 _pango_win32_font_class_init (PangoWin32FontClass *class)
198 GObjectClass *object_class = G_OBJECT_CLASS (class);
199 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
201 object_class->finalize = pango_win32_font_finalize;
202 object_class->dispose = pango_win32_font_dispose;
204 font_class->describe = pango_win32_font_describe;
205 font_class->describe_absolute = pango_win32_font_describe_absolute;
206 font_class->get_coverage = pango_win32_font_get_coverage;
207 font_class->find_shaper = pango_win32_font_find_shaper;
208 font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;
209 font_class->get_metrics = pango_win32_font_get_metrics;
210 font_class->get_font_map = pango_win32_font_get_font_map;
212 class->select_font = pango_win32_font_real_select_font;
213 class->done_font = pango_win32_font_real_done_font;
214 class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
216 pango_win32_get_dc ();
220 * pango_win32_render:
221 * @hdc: the device context
222 * @font: the font in which to draw the string
223 * @glyphs: the glyph string to draw
224 * @x: the x position of start of string (in pixels)
225 * @y: the y position of baseline (in pixels)
227 * Render a #PangoGlyphString onto a Windows DC
230 pango_win32_render (HDC hdc,
232 PangoGlyphString *glyphs,
236 HFONT hfont, old_hfont = NULL;
237 int i, j, num_valid_glyphs;
238 guint16 *glyph_indexes;
241 gint start_x_offset, x_offset, next_x_offset, cur_y_offset; /* in Pango units */
243 g_return_if_fail (glyphs != NULL);
245 #ifdef PANGO_WIN32_DEBUGGING
246 if (_pango_win32_debug)
248 PING (("num_glyphs:%d", glyphs->num_glyphs));
249 for (i = 0; i < glyphs->num_glyphs; i++)
251 g_print (" %d:%d", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);
252 if (glyphs->glyphs[i].geometry.x_offset != 0 ||
253 glyphs->glyphs[i].geometry.y_offset != 0)
254 g_print (":%d,%d", glyphs->glyphs[i].geometry.x_offset,
255 glyphs->glyphs[i].geometry.y_offset);
261 if (glyphs->num_glyphs == 0)
264 hfont = pango_win32_get_hfont (font);
268 old_hfont = SelectObject (hdc, hfont);
270 glyph_indexes = g_new (guint16, glyphs->num_glyphs);
271 dX = g_new (INT, glyphs->num_glyphs);
273 /* Render glyphs using one ExtTextOutW() call for each run of glyphs
274 * that have the same y offset. The big majoroty of glyphs will have
275 * y offset of zero, so in general, the whole glyph string will be
276 * rendered by one call to ExtTextOutW().
278 * In order to minimize buildup of rounding errors, we keep track of
279 * where the glyphs should be rendered in Pango units, and round
280 * to pixels separately for each glyph,
285 /* Outer loop through all glyphs in string */
286 while (i < glyphs->num_glyphs)
288 cur_y_offset = glyphs->glyphs[i].geometry.y_offset;
289 num_valid_glyphs = 0;
291 start_x_offset = glyphs->glyphs[i].geometry.x_offset;
292 this_x = PANGO_PIXELS (start_x_offset);
294 /* Inner loop through glyphs with the same y offset, or code
295 * point zero (just spacing).
297 while (i < glyphs->num_glyphs &&
298 (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY ||
299 cur_y_offset == glyphs->glyphs[i].geometry.y_offset))
301 if (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY)
303 /* PANGO_GLYPH_EMPTY glyphs should not be rendered, but their
304 * indicated width (set up by PangoLayout) should be taken
308 /* If the string starts with spacing, must shift the
309 * starting point for the glyphs actually rendered. For
310 * spacing in the middle of the glyph string, add to the dX
311 * of the previous glyph to be rendered.
313 if (num_valid_glyphs == 0)
314 start_x_offset += glyphs->glyphs[i].geometry.width;
317 x_offset += glyphs->glyphs[i].geometry.width;
318 dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - this_x;
323 if (glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
325 /* Glyph index is actually the char value that doesn't
326 * have any glyph (ORed with the flag). We should really
327 * do the same that pango_xft_real_render() does: render
328 * a box with the char value in hex inside it in a tiny
329 * font. Later. For now, use the TrueType invalid glyph
332 glyph_indexes[num_valid_glyphs] = 0;
335 glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;
337 x_offset += glyphs->glyphs[i].geometry.width;
339 /* If the next glyph has an X offset, take that into consideration now */
340 if (i < glyphs->num_glyphs - 1)
341 next_x_offset = glyphs->glyphs[i+1].geometry.x_offset;
345 dX[num_valid_glyphs] = PANGO_PIXELS (x_offset + next_x_offset) - this_x;
347 /* Prepare for next glyph */
348 this_x += dX[num_valid_glyphs];
353 #ifdef PANGO_WIN32_DEBUGGING
354 if (_pango_win32_debug)
356 g_print ("ExtTextOutW at %d,%d deltas:",
357 x + PANGO_PIXELS (start_x_offset),
358 y + PANGO_PIXELS (cur_y_offset));
359 for (j = 0; j < num_valid_glyphs; j++)
360 g_print (" %d", dX[j]);
366 x + PANGO_PIXELS (start_x_offset),
367 y + PANGO_PIXELS (cur_y_offset),
370 glyph_indexes, num_valid_glyphs,
376 SelectObject (hdc, old_hfont); /* restore */
377 g_free (glyph_indexes);
382 * pango_win32_render_transformed:
383 * @hdc: a windows device context
384 * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
385 * @font: the font in which to draw the string
386 * @glyphs: the glyph string to draw
387 * @x: the x position of the start of the string (in Pango
388 * units in user space coordinates)
389 * @y: the y position of the baseline (in Pango units
390 * in user space coordinates)
392 * Renders a #PangoGlyphString onto a windows DC, possibly
393 * transforming the layed-out coordinates through a transformation
394 * matrix. Note that the transformation matrix for @font is not
395 * changed, so to produce correct rendering results, the @font
396 * must have been loaded using a #PangoContext with an identical
397 * transformation matrix to that passed in to this function.
400 pango_win32_render_transformed (HDC hdc,
401 const PangoMatrix *matrix,
403 PangoGlyphString *glyphs,
408 XFORM xFormPrev = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
409 int mode = GetGraphicsMode (hdc);
411 if (!SetGraphicsMode (hdc, GM_ADVANCED))
412 g_warning ("SetGraphicsMode() failed");
413 else if (!GetWorldTransform (hdc, &xFormPrev))
414 g_warning ("GetWorldTransform() failed");
417 xForm.eM11 = matrix->xx;
418 xForm.eM12 = matrix->yx;
419 xForm.eM21 = matrix->xy;
420 xForm.eM22 = matrix->yy;
421 xForm.eDx = matrix->x0;
422 xForm.eDy = matrix->y0;
423 if (!SetWorldTransform (hdc, &xForm))
424 g_warning ("GetWorldTransform() failed");
427 pango_win32_render (hdc, font, glyphs, x/PANGO_SCALE, y/PANGO_SCALE);
430 SetWorldTransform (hdc, &xFormPrev);
431 SetGraphicsMode (hdc, mode);
435 pango_win32_font_get_glyph_extents (PangoFont *font,
437 PangoRectangle *ink_rect,
438 PangoRectangle *logical_rect)
440 PangoWin32Font *win32font = (PangoWin32Font *)font;
441 guint16 glyph_index = glyph;
445 MAT2 m = {{0,1}, {0,0}, {0,0}, {0,1}};
446 PangoWin32GlyphInfo *info;
448 if (glyph == PANGO_GLYPH_EMPTY)
451 ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
453 logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
457 if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
458 glyph_index = glyph = 0;
460 info = g_hash_table_lookup (win32font->glyph_info, GUINT_TO_POINTER (glyph));
464 info = g_new0 (PangoWin32GlyphInfo, 1);
466 memset (&gm, 0, sizeof (gm));
468 hfont = pango_win32_get_hfont (font);
469 SelectObject (_pango_win32_hdc, hfont);
470 /* FIXME: (Alex) This constant reuse of _pango_win32_hdc is
472 res = GetGlyphOutlineA (_pango_win32_hdc,
474 GGO_METRICS | GGO_GLYPH_INDEX,
479 if (res == GDI_ERROR)
481 gchar *error = g_win32_error_message (GetLastError ());
482 g_warning ("GetGlyphOutline(%04X) failed: %s\n",
486 /* Don't just return now, use the still zeroed out gm */
489 info->ink_rect.x = PANGO_SCALE * gm.gmptGlyphOrigin.x;
490 info->ink_rect.width = PANGO_SCALE * gm.gmBlackBoxX;
491 info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y;
492 info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY;
494 info->logical_rect.x = 0;
495 info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX;
496 info->logical_rect.y = - PANGO_SCALE * win32font->tm_ascent;
497 info->logical_rect.height = PANGO_SCALE * (win32font->tm_ascent + win32font->tm_descent);
499 g_hash_table_insert (win32font->glyph_info, GUINT_TO_POINTER(glyph), info);
503 *ink_rect = info->ink_rect;
506 *logical_rect = info->logical_rect;
510 max_glyph_width (PangoLayout *layout)
515 for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
517 PangoLayoutLine *line = l->data;
519 for (r = line->runs; r; r = r->next)
521 PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
524 for (i = 0; i < glyphs->num_glyphs; i++)
525 if (glyphs->glyphs[i].geometry.width > max_width)
526 max_width = glyphs->glyphs[i].geometry.width;
533 static PangoFontMetrics *
534 pango_win32_font_get_metrics (PangoFont *font,
535 PangoLanguage *language)
537 PangoWin32MetricsInfo *info = NULL; /* Quiet gcc */
538 PangoWin32Font *win32font = (PangoWin32Font *)font;
541 const char *sample_str = pango_language_get_sample_string (language);
543 tmp_list = win32font->metrics_by_lang;
546 info = tmp_list->data;
548 if (info->sample_str == sample_str) /* We _don't_ need strcmp */
551 tmp_list = tmp_list->next;
557 PangoFontMetrics *metrics;
559 info = g_new (PangoWin32MetricsInfo, 1);
560 win32font->metrics_by_lang = g_slist_prepend (win32font->metrics_by_lang, info);
562 info->sample_str = sample_str;
563 info->metrics = metrics = pango_font_metrics_new ();
565 hfont = pango_win32_get_hfont (font);
568 PangoCoverage *coverage;
571 SelectObject (_pango_win32_hdc, hfont);
572 GetTextMetrics (_pango_win32_hdc, &tm);
574 metrics->ascent = tm.tmAscent * PANGO_SCALE;
575 metrics->descent = tm.tmDescent * PANGO_SCALE;
576 metrics->approximate_char_width = tm.tmAveCharWidth * PANGO_SCALE;
578 coverage = pango_win32_font_get_coverage (font, language);
579 if (pango_coverage_get (coverage, '0') != PANGO_COVERAGE_NONE &&
580 pango_coverage_get (coverage, '9') != PANGO_COVERAGE_NONE)
582 PangoContext *context;
583 PangoFontDescription *font_desc;
586 /* Get the average width of the chars in "0123456789" */
587 context = pango_font_map_create_context (pango_win32_font_map_for_display ());
588 pango_context_set_language (context, language);
589 font_desc = pango_font_describe_with_absolute_size (font);
590 pango_context_set_font_description (context, font_desc);
591 layout = pango_layout_new (context);
592 pango_layout_set_text (layout, "0123456789", -1);
594 metrics->approximate_digit_width = max_glyph_width (layout);
596 pango_font_description_free (font_desc);
597 g_object_unref (layout);
598 g_object_unref (context);
601 metrics->approximate_digit_width = metrics->approximate_char_width;
603 pango_coverage_unref (coverage);
605 /* FIXME: Should get the real values from the TrueType font file */
606 metrics->underline_position = -2 * PANGO_SCALE;
607 metrics->underline_thickness = 1 * PANGO_SCALE;
608 metrics->strikethrough_thickness = metrics->underline_thickness;
609 /* Really really wild guess */
610 metrics->strikethrough_position = metrics->ascent / 3;
614 return pango_font_metrics_ref (info->metrics);
617 static PangoFontMap *
618 pango_win32_font_get_font_map (PangoFont *font)
620 PangoWin32Font *win32font = (PangoWin32Font *)font;
622 return win32font->fontmap;
626 pango_win32_font_real_select_font (PangoFont *font,
629 HFONT hfont = pango_win32_get_hfont (font);
634 if (!SelectObject (hdc, hfont))
636 g_warning ("pango_win32_font_real_select_font: Cannot select font\n");
644 pango_win32_font_real_done_font (PangoFont *font)
649 pango_win32_font_real_get_metrics_factor (PangoFont *font)
655 * pango_win32_font_logfont:
656 * @font: a #PangoFont which must be from the Win32 backend
658 * Determine the LOGFONTA struct for the specified font. Note that
659 * Pango internally uses LOGFONTW structs, so if converting the UTF-16
660 * face name in the LOGFONTW struct to system codepage fails, the
661 * returned LOGFONTA will have an emppty face name. To get the
662 * LOGFONTW of a PangoFont, use pango_win32_font_logfontw(). It
663 * is recommended to do that always even if you don't expect
664 * to come across fonts with odd names.
666 * Return value: A newly allocated LOGFONTA struct. It must be
667 * freed with g_free().
670 pango_win32_font_logfont (PangoFont *font)
672 PangoWin32Font *win32font = (PangoWin32Font *)font;
675 g_return_val_if_fail (font != NULL, NULL);
676 g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
678 lfp = g_new (LOGFONTA, 1);
680 *lfp = *(LOGFONTA*) &win32font->logfontw;
681 if (!WideCharToMultiByte (CP_ACP, 0,
682 win32font->logfontw.lfFaceName, -1,
683 lfp->lfFaceName, G_N_ELEMENTS (lfp->lfFaceName),
685 lfp->lfFaceName[0] = '\0';
691 * pango_win32_font_logfontw:
692 * @font: a #PangoFont which must be from the Win32 backend
694 * Determine the LOGFONTW struct for the specified font.
696 * Return value: A newly allocated LOGFONTW struct. It must be
697 * freed with g_free().
702 pango_win32_font_logfontw (PangoFont *font)
704 PangoWin32Font *win32font = (PangoWin32Font *)font;
707 g_return_val_if_fail (font != NULL, NULL);
708 g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
710 lfp = g_new (LOGFONTW, 1);
711 *lfp = win32font->logfontw;
717 * pango_win32_font_select_font:
718 * @font: a #PangoFont from the Win32 backend
719 * @hdc: a windows device context
721 * Selects the font into the specified DC and changes the mapping mode
722 * and world transformation of the DC appropriately for the font.
723 * You may want to surround the use of this function with calls
724 * to SaveDC() and RestoreDC(). Call pango_win32_font_done_font() when
725 * you are done using the DC to release allocated resources.
727 * See pango_win32_font_get_metrics_factor() for information about
728 * converting from the coordinate space used by this function
731 * Return value: %TRUE if the operation succeeded.
734 pango_win32_font_select_font (PangoFont *font,
737 g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), FALSE);
739 return PANGO_WIN32_FONT_GET_CLASS (font)->select_font (font, hdc);
743 * pango_win32_font_done_font:
744 * @font: a #PangoFont from the win32 backend
746 * Releases any resources allocated by pango_win32_font_done_font()
749 pango_win32_font_done_font (PangoFont *font)
751 g_return_if_fail (PANGO_WIN32_IS_FONT (font));
753 PANGO_WIN32_FONT_GET_CLASS (font)->done_font (font);
757 * pango_win32_font_get_metrics_factor:
758 * @font: a #PangoFont from the win32 backend
760 * Returns the scale factor from logical units in the coordinate
761 * space used by pango_win32_font_select_font() to Pango units
764 * Return value: factor to multiply logical units by to get Pango
768 pango_win32_font_get_metrics_factor (PangoFont *font)
770 g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), 1.);
772 return PANGO_WIN32_FONT_GET_CLASS (font)->get_metrics_factor (font);
776 pango_win32_fontmap_cache_add (PangoFontMap *fontmap,
777 PangoWin32Font *win32font)
779 PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
781 if (win32fontmap->freed_fonts->length == MAX_FREED_FONTS)
783 PangoWin32Font *old_font = g_queue_pop_tail (win32fontmap->freed_fonts);
784 g_object_unref (old_font);
787 g_object_ref (win32font);
788 g_queue_push_head (win32fontmap->freed_fonts, win32font);
789 win32font->in_cache = TRUE;
793 pango_win32_font_dispose (GObject *object)
795 PangoWin32Font *win32font = PANGO_WIN32_FONT (object);
797 /* If the font is not already in the freed-fonts cache, add it,
798 * if it is already there, do nothing and the font will be
801 if (!win32font->in_cache && win32font->fontmap)
802 pango_win32_fontmap_cache_add (win32font->fontmap, win32font);
804 G_OBJECT_CLASS (_pango_win32_font_parent_class)->dispose (object);
808 free_metrics_info (PangoWin32MetricsInfo *info)
810 pango_font_metrics_unref (info->metrics);
815 pango_win32_font_entry_remove (PangoWin32Face *face,
818 face->cached_fonts = g_slist_remove (face->cached_fonts, font);
822 pango_win32_font_finalize (GObject *object)
824 PangoWin32Font *win32font = (PangoWin32Font *)object;
825 PangoWin32FontCache *cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
827 if (win32font->hfont != NULL)
828 pango_win32_font_cache_unload (cache, win32font->hfont);
830 g_slist_foreach (win32font->metrics_by_lang, (GFunc)free_metrics_info, NULL);
831 g_slist_free (win32font->metrics_by_lang);
833 if (win32font->win32face)
834 pango_win32_font_entry_remove (win32font->win32face, PANGO_FONT (win32font));
836 g_hash_table_destroy (win32font->glyph_info);
838 g_assert (win32font->fontmap != NULL);
839 g_object_remove_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
840 win32font->fontmap = NULL;
842 G_OBJECT_CLASS (_pango_win32_font_parent_class)->finalize (object);
845 static PangoFontDescription *
846 pango_win32_font_describe (PangoFont *font)
848 PangoFontDescription *desc;
849 PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
851 desc = pango_font_description_copy (win32font->win32face->description);
852 pango_font_description_set_size (desc, win32font->size / (PANGO_SCALE / PANGO_WIN32_FONT_MAP (win32font->fontmap)->resolution));
857 static PangoFontDescription *
858 pango_win32_font_describe_absolute (PangoFont *font)
860 PangoFontDescription *desc;
861 PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
863 desc = pango_font_description_copy (win32font->win32face->description);
864 pango_font_description_set_absolute_size (desc, win32font->size);
870 pango_win32_get_shaper_map (PangoLanguage *lang)
872 static guint engine_type_id = 0;
873 static guint render_type_id = 0;
875 if (engine_type_id == 0)
877 engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
878 render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_WIN32);
881 return pango_find_map (lang, engine_type_id, render_type_id);
885 pango_win32_coverage_language_classify (PangoLanguage *lang)
887 if (pango_language_matches (lang, "zh-tw"))
888 return PANGO_WIN32_COVERAGE_ZH_TW;
889 else if (pango_language_matches (lang, "zh-cn"))
890 return PANGO_WIN32_COVERAGE_ZH_CN;
891 else if (pango_language_matches (lang, "ja"))
892 return PANGO_WIN32_COVERAGE_JA;
893 else if (pango_language_matches (lang, "ko"))
894 return PANGO_WIN32_COVERAGE_KO;
895 else if (pango_language_matches (lang, "vi"))
896 return PANGO_WIN32_COVERAGE_VI;
898 return PANGO_WIN32_COVERAGE_UNSPEC;
901 static PangoCoverage *
902 pango_win32_font_entry_get_coverage (PangoWin32Face *face,
905 gint i = pango_win32_coverage_language_classify (lang);
906 if (face->coverages[i])
908 pango_coverage_ref (face->coverages[i]);
909 return face->coverages[i];
916 pango_win32_font_entry_set_coverage (PangoWin32Face *face,
917 PangoCoverage *coverage,
920 face->coverages[pango_win32_coverage_language_classify (lang)] = pango_coverage_ref (coverage);
923 static PangoCoverage *
924 pango_win32_font_get_coverage (PangoFont *font,
927 PangoCoverage *coverage;
928 PangoWin32Font *win32font = (PangoWin32Font *)font;
930 coverage = pango_win32_font_entry_get_coverage (win32font->win32face, lang);
933 coverage = pango_coverage_new ();
934 pango_win32_font_calc_coverage (font, coverage, lang);
936 pango_win32_font_entry_set_coverage (win32font->win32face, coverage, lang);
942 static PangoEngineShape *
943 pango_win32_font_find_shaper (PangoFont *font,
947 PangoMap *shape_map = NULL;
950 shape_map = pango_win32_get_shaper_map (lang);
951 script = pango_script_for_unichar (ch);
952 return (PangoEngineShape *)pango_map_get_engine (shape_map, script);
955 /* Utility functions */
958 * pango_win32_get_unknown_glyph:
959 * @font: a #PangoFont
960 * @wc: the Unicode character for which a glyph is needed.
962 * Returns the index of a glyph suitable for drawing @wc as an
965 * Use PANGO_GET_UNKNOWN_GLYPH() instead.
967 * Return value: a glyph index into @font
970 pango_win32_get_unknown_glyph (PangoFont *font,
973 return PANGO_GET_UNKNOWN_GLYPH (wc);
977 * pango_win32_render_layout_line:
978 * @hdc: DC to use for uncolored drawing
979 * @line: a #PangoLayoutLine
980 * @x: the x position of start of string (in pixels)
981 * @y: the y position of baseline (in pixels)
983 * Render a #PangoLayoutLine onto a device context. For underlining to
984 * work property the text alignment of the DC should have TA_BASELINE
988 pango_win32_render_layout_line (HDC hdc,
989 PangoLayoutLine *line,
993 GSList *tmp_list = line->runs;
994 PangoRectangle overall_rect;
995 PangoRectangle logical_rect;
996 PangoRectangle ink_rect;
1000 pango_layout_line_get_extents (line,NULL, &overall_rect);
1004 HBRUSH oldfg = NULL;
1005 HBRUSH brush = NULL;
1007 PangoUnderline uline = PANGO_UNDERLINE_NONE;
1008 PangoLayoutRun *run = tmp_list->data;
1009 PangoAttrColor fg_color, bg_color;
1010 gboolean fg_set, bg_set;
1012 tmp_list = tmp_list->next;
1014 pango_win32_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set);
1016 if (uline == PANGO_UNDERLINE_NONE)
1017 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
1018 NULL, &logical_rect);
1020 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
1021 &ink_rect, &logical_rect);
1027 brush = CreateSolidBrush (RGB ((bg_color.color.red + 128) >> 8,
1028 (bg_color.color.green + 128) >> 8,
1029 (bg_color.color.blue + 128) >> 8));
1030 oldbrush = SelectObject (hdc, brush);
1031 Rectangle (hdc, x + PANGO_PIXELS (x_off + logical_rect.x),
1032 y + PANGO_PIXELS (overall_rect.y),
1033 PANGO_PIXELS (logical_rect.width),
1034 PANGO_PIXELS (overall_rect.height));
1035 SelectObject (hdc, oldbrush);
1036 DeleteObject (brush);
1041 brush = CreateSolidBrush (RGB ((fg_color.color.red + 128) >> 8,
1042 (fg_color.color.green + 128) >> 8,
1043 (fg_color.color.blue + 128) >> 8));
1044 oldfg = SelectObject (hdc, brush);
1047 pango_win32_render (hdc, run->item->analysis.font, run->glyphs,
1048 x + PANGO_PIXELS (x_off), y);
1052 case PANGO_UNDERLINE_NONE:
1054 case PANGO_UNDERLINE_DOUBLE:
1055 points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
1056 points[0].y = points[1].y = y + 4;
1057 points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
1058 Polyline (hdc, points, 2);
1059 points[0].y = points[1].y = y + 2;
1060 Polyline (hdc, points, 2);
1062 case PANGO_UNDERLINE_SINGLE:
1063 points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
1064 points[0].y = points[1].y = y + 2;
1065 points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
1066 Polyline (hdc, points, 2);
1068 case PANGO_UNDERLINE_ERROR:
1072 int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
1074 for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
1078 points[0].x = point_x;
1079 points[1].x = MAX (point_x + 1, end_x);
1082 points[0].y = points[1].y = y + 2;
1084 points[0].y = points[1].y = y + 3;
1086 Polyline (hdc, points, 2);
1087 counter = (counter + 1) % 2;
1091 case PANGO_UNDERLINE_LOW:
1092 points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
1093 points[0].y = points[1].y = y + PANGO_PIXELS (ink_rect.y + ink_rect.height) + 2;
1094 points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
1095 Polyline (hdc, points, 2);
1101 SelectObject (hdc, oldfg);
1102 DeleteObject (brush);
1105 x_off += logical_rect.width;
1110 * pango_win32_render_layout:
1111 * @hdc: HDC to use for uncolored drawing
1112 * @layout: a #PangoLayout
1113 * @x: the X position of the left of the layout (in pixels)
1114 * @y: the Y position of the top of the layout (in pixels)
1116 * Render a #PangoLayoutLine onto an X drawable
1119 pango_win32_render_layout (HDC hdc,
1120 PangoLayout *layout,
1124 PangoLayoutIter *iter;
1126 g_return_if_fail (hdc != NULL);
1127 g_return_if_fail (PANGO_IS_LAYOUT (layout));
1129 iter = pango_layout_get_iter (layout);
1133 PangoRectangle logical_rect;
1134 PangoLayoutLine *line;
1137 line = pango_layout_iter_get_line_readonly (iter);
1139 pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
1140 baseline = pango_layout_iter_get_baseline (iter);
1142 pango_win32_render_layout_line (hdc,
1144 x + PANGO_PIXELS (logical_rect.x),
1145 y + PANGO_PIXELS (baseline));
1147 while (pango_layout_iter_next_line (iter));
1149 pango_layout_iter_free (iter);
1152 /* This utility function is duplicated here and in pango-layout.c; should it be
1153 * public? Trouble is - what is the appropriate set of properties?
1156 pango_win32_get_item_properties (PangoItem *item,
1157 PangoUnderline *uline,
1158 PangoAttrColor *fg_color,
1160 PangoAttrColor *bg_color,
1163 GSList *tmp_list = item->analysis.extra_attrs;
1173 PangoAttribute *attr = tmp_list->data;
1175 switch (attr->klass->type)
1177 case PANGO_ATTR_UNDERLINE:
1179 *uline = ((PangoAttrInt *)attr)->value;
1182 case PANGO_ATTR_FOREGROUND:
1184 *fg_color = *((PangoAttrColor *)attr);
1190 case PANGO_ATTR_BACKGROUND:
1192 *bg_color = *((PangoAttrColor *)attr);
1201 tmp_list = tmp_list->next;
1206 get_cmap_offset (HDC hdc,
1207 guint16 encoding_id)
1210 struct cmap_encoding_subtable *table;
1215 /* Get The number of encoding tables, at offset 2 */
1216 res = GetFontData (hdc, CMAP, 2, &n_tables, 2);
1220 n_tables = GUINT16_FROM_BE (n_tables);
1222 table = g_malloc (ENCODING_TABLE_SIZE*n_tables);
1224 res = GetFontData (hdc, CMAP, CMAP_HEADER_SIZE, table, ENCODING_TABLE_SIZE*n_tables);
1225 if (res != ENCODING_TABLE_SIZE*n_tables)
1228 for (i = 0; i < n_tables; i++)
1230 if (table[i].platform_id == GUINT16_TO_BE (MICROSOFT_PLATFORM_ID) &&
1231 table[i].encoding_id == GUINT16_TO_BE (encoding_id))
1233 offset = GUINT32_FROM_BE (table[i].offset);
1243 get_format_4_cmap (HDC hdc)
1248 guint16 *tbl, *tbl_end;
1249 struct format_4_cmap *table;
1251 /* FIXME: Could look here at the CRC for the font in the DC
1252 and return a cached copy if the same */
1254 offset = get_cmap_offset (hdc, UNICODE_ENCODING_ID);
1258 res = GetFontData (hdc, CMAP, offset + 2, &length, 2);
1261 length = GUINT16_FROM_BE (length);
1263 table = g_malloc (length);
1265 res = GetFontData (hdc, CMAP, offset, table, length);
1266 if (res != length ||
1267 GUINT16_FROM_BE (table->format) != 4 ||
1268 (GUINT16_FROM_BE (table->length) % 2) != 0)
1274 table->format = GUINT16_FROM_BE (table->format);
1275 table->length = GUINT16_FROM_BE (table->length);
1276 table->language = GUINT16_FROM_BE (table->language);
1277 table->seg_count_x_2 = GUINT16_FROM_BE (table->seg_count_x_2);
1278 table->search_range = GUINT16_FROM_BE (table->search_range);
1279 table->entry_selector = GUINT16_FROM_BE (table->entry_selector);
1280 table->range_shift = GUINT16_FROM_BE (table->range_shift);
1282 tbl_end = (guint16 *)((char *)table + length);
1283 tbl = &table->reserved;
1285 while (tbl < tbl_end)
1287 *tbl = GUINT16_FROM_BE (*tbl);
1295 get_id_range_offset (struct format_4_cmap *table)
1297 gint32 seg_count = table->seg_count_x_2/2;
1298 return &table->arrays[seg_count*3];
1302 get_id_delta (struct format_4_cmap *table)
1304 gint32 seg_count = table->seg_count_x_2/2;
1305 return &table->arrays[seg_count*2];
1309 get_start_count (struct format_4_cmap *table)
1311 gint32 seg_count = table->seg_count_x_2/2;
1312 return &table->arrays[seg_count*1];
1316 get_end_count (struct format_4_cmap *table)
1318 gint32 seg_count = table->seg_count_x_2/2;
1319 /* Apparently the reseved spot is not reserved for
1320 the end_count array!? */
1321 return (&table->arrays[seg_count*0])-1;
1325 find_segment (struct format_4_cmap *table,
1329 guint16 start, end, i;
1330 guint16 seg_count = table->seg_count_x_2/2;
1331 guint16 *end_count = get_end_count (table);
1332 guint16 *start_count = get_start_count (table);
1333 static guint last = 0; /* Cache of one */
1335 if (last < seg_count &&
1336 wc >= start_count[last] &&
1337 wc <= end_count[last])
1344 /* Binary search for the segment */
1345 start = 0; /* inclusive */
1346 end = seg_count; /* not inclusive */
1349 /* Look at middle pos */
1350 i = (start + end)/2;
1354 /* We made no progress. Look if this is the one. */
1356 if (wc >= start_count[i] &&
1366 else if (wc < start_count[i])
1370 else if (wc > end_count[i])
1386 get_format_12_cmap (HDC hdc)
1391 guint32 *tbl, *tbl_end;
1392 struct format_12_cmap *table;
1394 offset = get_cmap_offset (hdc, UCS4_ENCODING_ID);
1398 res = GetFontData (hdc, CMAP, offset + 4, &length, 4);
1401 length = GUINT32_FROM_BE (length);
1403 table = g_malloc (length);
1405 res = GetFontData (hdc, CMAP, offset, table, length);
1412 table->format = GUINT16_FROM_BE (table->format);
1413 table->length = GUINT32_FROM_BE (table->length);
1414 table->language = GUINT32_FROM_BE (table->language);
1415 table->count = GUINT32_FROM_BE (table->count);
1417 if (table->format != 12 ||
1418 (table->length % 4) != 0 ||
1419 table->length > length ||
1420 table->length < 16 + table->count * 12)
1426 tbl_end = (guint32 *) ((char *) table + length);
1427 tbl = table->groups;
1429 while (tbl < tbl_end)
1431 *tbl = GUINT32_FROM_BE (*tbl);
1439 font_get_cmap (PangoFont *font)
1441 PangoWin32Font *win32font = (PangoWin32Font *)font;
1444 if (win32font->win32face->cmap)
1445 return win32font->win32face->cmap;
1447 pango_win32_font_select_font (font, _pango_win32_hdc);
1449 /* Prefer the format 12 cmap */
1450 if ((cmap = get_format_12_cmap (_pango_win32_hdc)) != NULL)
1452 win32font->win32face->cmap_format = 12;
1453 win32font->win32face->cmap = cmap;
1455 else if ((cmap = get_format_4_cmap (_pango_win32_hdc)) != NULL)
1457 win32font->win32face->cmap_format = 4;
1458 win32font->win32face->cmap = cmap;
1461 pango_win32_font_done_font (font);
1467 pango_win32_font_get_type1_glyph_index (PangoFont *font,
1476 pango_win32_font_select_font (font, _pango_win32_hdc);
1477 res = GetGlyphIndicesW (_pango_win32_hdc, unicode, 1, &glyph_index, 0);
1478 pango_win32_font_done_font (font);
1487 * pango_win32_font_get_glyph_index:
1488 * @font: a #PangoFont.
1489 * @wc: a Unicode character.
1491 * Obtains the index of the glyph for @wc in @font, or 0, if not
1494 * Return value: the glyph index for @wc.
1497 pango_win32_font_get_glyph_index (PangoFont *font,
1500 PangoWin32Font *win32font = (PangoWin32Font *)font;
1504 if (win32font->win32face->has_cmap)
1506 /* Do GetFontData magic on font->hfont here. */
1507 cmap = font_get_cmap (font);
1509 win32font->win32face->has_cmap = FALSE;
1512 if (!win32font->win32face->has_cmap)
1513 return pango_win32_font_get_type1_glyph_index (font, wc);
1515 if (win32font->win32face->cmap_format == 4)
1517 struct format_4_cmap *cmap4 = cmap;
1518 guint16 *id_range_offset;
1520 guint16 *start_count;
1528 if (!find_segment (cmap4, ch, &segment))
1531 id_range_offset = get_id_range_offset (cmap4);
1532 id_delta = get_id_delta (cmap4);
1533 start_count = get_start_count (cmap4);
1535 if (id_range_offset[segment] == 0)
1536 glyph = (id_delta[segment] + ch) % 65536;
1539 id = *(id_range_offset[segment]/2 +
1540 (ch - start_count[segment]) +
1541 &id_range_offset[segment]);
1543 glyph = (id_delta[segment] + id) %65536;
1548 else if (win32font->win32face->cmap_format == 12)
1550 struct format_12_cmap *cmap12 = cmap;
1554 for (i = 0; i < cmap12->count; i++)
1556 if (cmap12->groups[i*3+0] <= wc && wc <= cmap12->groups[i*3+1])
1558 glyph = cmap12->groups[i*3+2] + (wc - cmap12->groups[i*3+0]);
1564 g_assert_not_reached ();
1570 _pango_win32_get_name_header (HDC hdc,
1571 struct name_header *header)
1573 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
1576 header->num_records = GUINT16_FROM_BE (header->num_records);
1577 header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
1583 _pango_win32_get_name_record (HDC hdc,
1585 struct name_record *record)
1587 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
1588 record, sizeof (*record)) != sizeof (*record))
1591 record->platform_id = GUINT16_FROM_BE (record->platform_id);
1592 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
1593 record->language_id = GUINT16_FROM_BE (record->language_id);
1594 record->name_id = GUINT16_FROM_BE (record->name_id);
1595 record->string_length = GUINT16_FROM_BE (record->string_length);
1596 record->string_offset = GUINT16_FROM_BE (record->string_offset);
1602 font_has_name_in (PangoFont *font,
1603 PangoWin32CoverageLanguageClass cjkv)
1605 HFONT hfont, oldhfont;
1606 struct name_header header;
1607 struct name_record record;
1609 gboolean retval = FALSE;
1611 if (cjkv == PANGO_WIN32_COVERAGE_UNSPEC)
1614 hfont = pango_win32_get_hfont (font);
1615 oldhfont = SelectObject (_pango_win32_hdc, hfont);
1617 if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
1619 SelectObject (_pango_win32_hdc, oldhfont);
1623 for (i = 0; i < header.num_records; i++)
1625 if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
1627 SelectObject (_pango_win32_hdc, oldhfont);
1631 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
1634 PING (("platform:%d encoding:%d language:%04x name_id:%d",
1635 record.platform_id, record.encoding_id, record.language_id, record.name_id));
1637 if (record.platform_id == MICROSOFT_PLATFORM_ID)
1638 if ((cjkv == PANGO_WIN32_COVERAGE_ZH_TW &&
1639 record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL))
1641 (cjkv == PANGO_WIN32_COVERAGE_ZH_CN &&
1642 record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED))
1644 (cjkv == PANGO_WIN32_COVERAGE_JA &&
1645 PRIMARYLANGID (record.language_id) == LANG_JAPANESE)
1647 (cjkv == PANGO_WIN32_COVERAGE_KO &&
1648 PRIMARYLANGID (record.language_id) == LANG_KOREAN)
1650 (cjkv == PANGO_WIN32_COVERAGE_VI &&
1651 PRIMARYLANGID (record.language_id) == LANG_VIETNAMESE))
1653 PING (("yep:%d:%04x", cjkv, record.language_id));
1659 SelectObject (_pango_win32_hdc, oldhfont);
1664 pango_win32_font_calc_type1_coverage (PangoFont *font,
1665 PangoCoverage *coverage,
1666 PangoLanguage *lang)
1668 GLYPHSET *glyph_set;
1673 pango_win32_font_select_font (font, _pango_win32_hdc);
1674 res = GetFontUnicodeRanges(_pango_win32_hdc, NULL);
1678 glyph_set = g_malloc (res);
1679 res = GetFontUnicodeRanges(_pango_win32_hdc, glyph_set);
1683 for (i = 0; i < glyph_set->cRanges; i++)
1685 guint32 end = glyph_set->ranges[i].wcLow + glyph_set->ranges[i].cGlyphs;
1687 for (ch = glyph_set->ranges[i].wcLow; ch < end; ch++)
1688 if (CH_IS_UNIHAN_BMP (ch))
1689 pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
1691 pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
1698 pango_win32_font_done_font (font);
1702 pango_win32_font_calc_coverage (PangoFont *font,
1703 PangoCoverage *coverage,
1704 PangoLanguage *lang)
1706 PangoWin32Font *win32font = (PangoWin32Font *)font;
1710 PangoWin32CoverageLanguageClass cjkv;
1711 gboolean hide_unihan = FALSE;
1712 PangoFontDescription *desc;
1715 desc = pango_font_describe (font);
1716 name = pango_font_description_to_string (desc);
1717 PING (("font:%s lang:%s", name,
1718 pango_language_to_string (lang)));
1720 pango_font_description_free (desc);
1722 if (win32font->win32face->has_cmap)
1724 /* Do GetFontData magic on font->hfont here. */
1725 cmap = font_get_cmap (font);
1727 win32font->win32face->has_cmap = FALSE;
1730 if (!win32font->win32face->has_cmap)
1732 pango_win32_font_calc_type1_coverage (font, coverage, lang);
1736 cjkv = pango_win32_coverage_language_classify (lang);
1738 if (cjkv != PANGO_WIN32_COVERAGE_UNSPEC && !font_has_name_in (font, cjkv))
1740 PING (("hiding UniHan chars"));
1744 PING (("coverage:"));
1745 if (win32font->win32face->cmap_format == 4)
1747 struct format_4_cmap *cmap4 = cmap;
1748 guint16 *id_range_offset;
1749 guint16 *start_count;
1754 seg_count = cmap4->seg_count_x_2/2;
1755 end_count = get_end_count (cmap4);
1756 start_count = get_start_count (cmap4);
1757 id_range_offset = get_id_range_offset (cmap4);
1759 for (i = 0; i < seg_count; i++)
1761 if (id_range_offset[i] == 0)
1763 #ifdef PANGO_WIN32_DEBUGGING
1764 if (_pango_win32_debug)
1766 if (end_count[i] == start_count[i])
1767 g_print ("%04x ", start_count[i]);
1769 g_print ("%04x:%04x ", start_count[i], end_count[i]);
1772 for (ch = start_count[i]; ch <= end_count[i]; ch++)
1773 if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
1774 pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
1776 pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
1780 #ifdef PANGO_WIN32_DEBUGGING
1781 guint32 ch0 = G_MAXUINT;
1783 for (ch = start_count[i]; ch <= end_count[i]; ch++)
1788 id = *(id_range_offset[i]/2 +
1789 (ch - start_count[i]) +
1790 &id_range_offset[i]);
1793 #ifdef PANGO_WIN32_DEBUGGING
1794 if (ch0 == G_MAXUINT)
1797 if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
1798 pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
1800 pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
1802 #ifdef PANGO_WIN32_DEBUGGING
1803 else if (ch0 < G_MAXUINT)
1805 if (_pango_win32_debug)
1808 g_print ("%04x:%04x ", ch0, ch - 1);
1810 g_print ("%04x ", ch0);
1816 #ifdef PANGO_WIN32_DEBUGGING
1817 if (ch0 < G_MAXUINT)
1819 if (_pango_win32_debug)
1822 g_print ("%04x:%04x ", ch0, ch - 1);
1824 g_print ("%04x ", ch0);
1831 else if (win32font->win32face->cmap_format == 12)
1833 struct format_12_cmap *cmap12 = cmap;
1835 for (i = 0; i < cmap12->count; i++)
1837 #ifdef PANGO_WIN32_DEBUGGING
1838 if (_pango_win32_debug)
1840 if (cmap12->groups[i*3+0] == cmap12->groups[i*3+1])
1841 g_print ("%04x ", cmap12->groups[i*3+0]);
1843 g_print ("%04x:%04x ", cmap12->groups[i*3+0], cmap12->groups[i*3+1]);
1846 for (ch = cmap12->groups[i*3+0]; ch <= cmap12->groups[i*3+1]; ch++)
1848 if (hide_unihan && CH_IS_UNIHAN (ch))
1849 pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
1851 pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
1856 g_assert_not_reached ();
1857 #ifdef PANGO_WIN32_DEBUGGING
1858 if (_pango_win32_debug)