2 * Copyright (C) 1999 Red Hat Software
5 * Copyright (C) 2001 Hans Breuer
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
29 #include "pango-impl-utils.h"
30 #include "pangowin32.h"
43 static HDC pre_render (int width, int height);
44 static void post_render (HDC hdc, const char* sFile);
47 calc_duration (GTimeVal *tv1, GTimeVal *tv0)
49 return ( ((float)tv1->tv_sec - tv0->tv_sec)
50 + (tv1->tv_usec - tv0->tv_usec) / 1000000.0);
54 compare_font_family (PangoFontFamily** a,
57 return strcmp (pango_font_family_get_name (*a), pango_font_family_get_name (*b));
60 int main (int argc, char **argv)
62 PangoFontMap *fontmap = pango_win32_font_map_for_display();
63 PangoContext *context;
64 PangoCoverage * coverage = NULL;
65 PangoFont* font = NULL;
66 PangoFontFamily** families = NULL;
67 PangoFontFace** faces = NULL;
69 gchar* family_name = NULL;
70 PangoLanguage *lang = pango_language_from_string (g_win32_getlocale ());
74 int my_font_size = 12;
76 printf ("# Pango Font Test\n"
78 "#\n", pango_language_to_string (lang));
80 /* this wasn't necessary with previous version
82 * force initialization of built-in engines, otherwise
83 * the rendering get's really fast - too fast to work :-(
85 context = pango_win32_get_context ();
87 if (argc == 1) /* No arguments given */
89 char *std_fonts[] = {"Sans 12", "Serif 12", "Monospace 12"};
91 /* try to load some fonts often hardcoded */
92 for (i = 0; i < G_N_ELEMENTS (std_fonts); i++)
94 PangoFontDescription *desc = pango_font_description_from_string(std_fonts[i]);
96 /* spits warnings if font cannot be loaded */
97 font = pango_font_map_load_font (fontmap, context, desc);
99 g_object_unref (font);
104 PangoFontDescription *desc = NULL;
107 s = g_string_new (argv[1]);
108 for (i = 2; i < argc; i++)
110 s = g_string_append_c (s, ' ');
111 s = g_string_append (s, argv[i]);
113 if (0 != atoi (argv[i]))
114 my_font_size = atoi (argv[i]);
117 desc = pango_font_description_from_string(s->str);
118 family_name = g_strdup (pango_font_description_get_family (desc));
120 font = pango_font_map_load_font (fontmap, context, desc);
122 coverage = pango_font_get_coverage (font, lang);
126 pango_coverage_unref (coverage);
127 pango_font_description_free (desc);
128 g_object_unref (font);
131 pango_font_map_list_families (fontmap, &families, &nb);
135 qsort (families, nb, sizeof (PangoFontFamily*), compare_font_family);
139 /* Get on the family faces. No simple way ? */
140 for (i = 0; i < nb; i++)
142 if (0 == g_ascii_strcasecmp (pango_font_family_get_name (families[i]), family_name))
144 pango_font_family_list_faces (families[i], &faces, &nb);
145 /* now nb is the number of faces */
151 g_free (family_name);
155 hdc = pre_render(my_font_size * 64, 3 * my_font_size * nb / 2);
157 for (i = 0; i < nb; i++)
159 PangoFontDescription *desc;
166 desc = pango_font_description_new ();
168 f_name = pango_font_family_get_name (families[i]);
169 pango_font_description_set_family (desc, f_name);
173 desc = pango_font_face_describe (faces[i]);
174 /* this is _not_ the family name from above */
175 f_name = pango_font_description_get_family (desc);
177 weight = pango_font_description_get_weight (desc);
178 style = pango_font_description_get_style (desc);
180 g_print ("%s; Style: %d; Weight: %d\n",
181 f_name, style, weight);
183 /* give it an arbitray size to load it */
184 pango_font_description_set_size (desc, my_font_size * PANGO_SCALE);
186 g_get_current_time (&tv0);
187 font = pango_font_map_load_font (fontmap, context, desc);
188 g_get_current_time (&tv1);
189 g_print ("\tpango_font_map_load_font took %.3f sec\n", calc_duration (&tv1, &tv0));
194 PangoGlyphString * glyphs;
195 char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
196 "abcdefghijklmnopqrstuvwxyz"
197 "1234567890 -+*/!\xc2\xa7$%&()[]{}<>|#=?@";
199 g_get_current_time (&tv0);
200 coverage = pango_font_get_coverage (font, lang);
201 g_get_current_time (&tv1);
202 g_print ("\tpango_font_get_coverage took %.3f sec\n", calc_duration (&tv1, &tv0));
205 pango_context_set_language (context, lang);
206 pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
207 pango_context_set_font_description (context, desc);
209 glyphs = pango_glyph_string_new ();
210 item = pango_item_new ();
212 item->analysis.shape_engine = pango_font_find_shaper (font, lang, s[0]);
213 item->analysis.font = g_object_ref (font);
214 pango_shape ( s, sizeof(s), &(item->analysis), glyphs);
218 /* the positioning isn't correct */
219 char* name = g_strdup_printf ("%s (%s%s)",
221 weight == PANGO_WEIGHT_NORMAL ? "n" :
222 (weight == PANGO_WEIGHT_HEAVY ? "h" :
223 (weight > PANGO_WEIGHT_NORMAL ? "b" : "l")),
224 style == PANGO_STYLE_OBLIQUE ? "o" :
225 (style == PANGO_STYLE_ITALIC ? "i" : "n"));
227 TextOut (hdc, 0, line, name, strlen(name));
228 g_get_current_time (&tv0);
229 pango_win32_render (hdc, font, glyphs, 200, line);
230 g_get_current_time (&tv1);
231 g_print ("\tpango_win32_render took %.3f sec\n",
232 calc_duration (&tv1, &tv0));
233 line += (3 * my_font_size / 2);
237 /* free glyphs, ... */
238 pango_glyph_string_free (glyphs);
239 pango_item_free (item);
241 pango_coverage_unref (coverage);
242 g_object_unref (font);
244 pango_font_description_free (desc);
248 post_render (hdc, "pango-fonts.bmp");
257 * Real Win32 specific render support
259 static HBITMAP hbmpold = NULL;
260 static HWND hwndRender = NULL;
263 SaveBitmap (HBITMAP hBmp, const char* pszFile);
266 pre_render (int width, int height)
272 r.top = 0; r.left = 0;
276 hwndRender = CreateWindow ("EDIT",
277 "pango-render-window",
282 GetModuleHandle(NULL),
285 if (hwndRender == NULL)
286 fprintf (stderr, "Couldn't create window\n"), exit (1);
288 hdc = GetDC(hwndRender);
289 hmemdc = CreateCompatibleDC (hdc);
291 fprintf (stderr, "CreateCompatibleDC failed\n"), exit (1);
293 hbmp = CreateCompatibleBitmap (hdc, width, height);
295 fprintf (stderr, "CreateCompatibleBitmap failed\n"), exit (1);
297 hbmpold = SelectObject(hmemdc, hbmp);
299 FillRect (hmemdc, &r, GetStockObject(WHITE_BRUSH));
300 SetTextColor (hmemdc, RGB (0,0,0));
301 SetBkMode (hmemdc, TRANSPARENT);
306 post_render (HDC hdc, const char* sFile)
308 HBITMAP hbmp = SelectObject(hdc, hbmpold);
310 SaveBitmap (hbmp, sFile);
313 ReleaseDC(hwndRender, GetDC(hwndRender));
314 DestroyWindow (hwndRender);
318 SaveBitmap (HBITMAP hBmp, const char* pszFile)
323 /* Retrieve the bitmap's color format, width, and height. */
324 if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
326 /* Convert the color format to a count of bits. */
327 cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
330 else if (cClrBits <= 4)
332 else if (cClrBits <= 8)
334 else if (cClrBits <= 16)
336 else if (cClrBits <= 24)
342 * Allocate memory for the BITMAPINFO structure. (This structure
343 * contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
346 pbmi = (PBITMAPINFO) GlobalAlloc(LPTR,
347 sizeof(BITMAPINFOHEADER) +
348 sizeof(RGBQUAD) * (1 << cClrBits));
350 * There is no RGBQUAD array for the 24-bit-per-pixel format. */
352 pbmi = (PBITMAPINFO) GlobalAlloc(LPTR,
353 sizeof(BITMAPINFOHEADER));
354 /* Initialize the fields in the BITMAPINFO structure. */
355 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
356 pbmi->bmiHeader.biWidth = bmp.bmWidth;
357 pbmi->bmiHeader.biHeight = bmp.bmHeight;
358 pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
359 pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
361 pbmi->bmiHeader.biClrUsed = (1 << cClrBits);
363 pbmi->bmiHeader.biClrUsed = 0;
364 /* If the bitmap is not compressed, set the BI_RGB flag. */
365 pbmi->bmiHeader.biCompression = BI_RGB;
367 * Compute the number of bytes in the array of color
368 * indices and store the result in biSizeImage.
370 pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
371 * pbmi->bmiHeader.biHeight
374 * Set biClrImportant to 0, indicating that all of the
375 * device colors are important.
377 pbmi->bmiHeader.biClrImportant = 0;
380 HANDLE hf; /* file handle */
381 BITMAPFILEHEADER hdr; /* bitmap file-header */
382 PBITMAPINFOHEADER pbih; /* bitmap info-header */
383 LPBYTE lpBits; /* memory pointer */
384 DWORD dwTotal; /* total count of bytes */
385 DWORD cb; /* incremental count of bytes */
389 pbih = (PBITMAPINFOHEADER) pbmi;
390 lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
394 * Retrieve the color table (RGBQUAD array) and the bits
395 * (array of palette indices) from the DIB.
397 hDC = CreateCompatibleDC(NULL);
398 if (!GetDIBits(hDC, hBmp, 0, (WORD) pbih->biHeight,
399 lpBits, pbmi, DIB_RGB_COLORS))
401 /* Create the .BMP file. */
402 hf = CreateFile (pszFile,
403 GENERIC_READ | GENERIC_WRITE,
405 (LPSECURITY_ATTRIBUTES) NULL,
407 FILE_ATTRIBUTE_NORMAL,
410 if (hf == INVALID_HANDLE_VALUE)
412 hdr.bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
413 /* Compute the size of the entire file. */
414 hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER)
415 + pbih->biSize + pbih->biClrUsed
416 * sizeof(RGBQUAD) + pbih->biSizeImage);
419 /* Compute the offset to the array of color indices. */
420 hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER)
421 + pbih->biSize + pbih->biClrUsed
423 /* Copy the BITMAPFILEHEADER into the .BMP file. */
424 if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
425 (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
427 /* Copy the BITMAPINFOHEADER and RGBQUAD array into the file. */
428 if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
429 + pbih->biClrUsed * sizeof (RGBQUAD),
430 (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
432 /* Copy the array of color indices into the .BMP file. */
433 dwTotal = cb = pbih->biSizeImage;
435 if (!WriteFile(hf, (LPSTR) lpBits, (int) cb,
436 (LPDWORD) &dwTotal, (LPOVERLAPPED) NULL))
439 /* Close the .BMP file. */
440 if (!CloseHandle(hf))
444 GlobalFree((HGLOBAL)lpBits);
445 GlobalFree((HGLOBAL)pbmi);