⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pangowin32.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Pango * pangowin32.c: Routines for handling Windows fonts * * Copyright (C) 1999 Red Hat Software * Copyright (C) 2000 Tor Lillqvist * Copyright (C) 2001 Alexander Larsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <config.h>#include <string.h>#include <stdlib.h>#include <glib.h>#include "pango-impl-utils.h"#include "pangowin32.h"#include "pangowin32-private.h"#define CH_IS_UNIHAN_BMP(ch) ((ch) >= 0x3400 && (ch) <= 0x9FFF)#define CH_IS_UNIHAN(ch) (CH_IS_UNIHAN_BMP (ch) || \			  ((ch) >= 0x20000 && (ch) <= 0x2A6DF) ||	\			  ((ch) >= 0x2F800 && (ch) <= 0x2FA1F))HDC pango_win32_hdc;OSVERSIONINFO pango_win32_os_version_info;gboolean pango_win32_debug = FALSE;static void pango_win32_font_dispose    (GObject             *object);static void pango_win32_font_finalize   (GObject             *object);static gboolean pango_win32_font_real_select_font        (PangoFont *font,							  HDC        hdc);static void     pango_win32_font_real_done_font          (PangoFont *font);static double   pango_win32_font_real_get_metrics_factor (PangoFont *font);static PangoFontDescription *pango_win32_font_describe          (PangoFont        *font);static PangoFontDescription *pango_win32_font_describe_absolute (PangoFont        *font);static PangoCoverage        *pango_win32_font_get_coverage      (PangoFont        *font,								 PangoLanguage    *lang);static void                  pango_win32_font_calc_coverage     (PangoFont        *font,								 PangoCoverage    *coverage,								 PangoLanguage    *lang);static PangoEngineShape     *pango_win32_font_find_shaper       (PangoFont        *font,								 PangoLanguage    *lang,								 guint32           ch);static void                  pango_win32_font_get_glyph_extents (PangoFont        *font,								 PangoGlyph        glyph,								 PangoRectangle   *ink_rect,								 PangoRectangle   *logical_rect);static PangoFontMetrics *    pango_win32_font_get_metrics       (PangoFont        *font,								 PangoLanguage    *lang);static PangoFontMap *        pango_win32_font_get_font_map      (PangoFont        *font);static gboolean pango_win32_font_real_select_font      (PangoFont *font,							HDC        hdc);static void     pango_win32_font_real_done_font        (PangoFont *font);static double   pango_win32_font_real_get_metrics_factor (PangoFont *font);static HFONT                 pango_win32_get_hfont              (PangoFont        *font);static void                  pango_win32_get_item_properties    (PangoItem        *item,								 PangoUnderline   *uline,								 PangoAttrColor   *fg_color,								 gboolean         *fg_set,								 PangoAttrColor   *bg_color,								 gboolean         *bg_set);static HFONTpango_win32_get_hfont (PangoFont *font){  PangoWin32Font *win32font = (PangoWin32Font *)font;  PangoWin32FontCache *cache;  TEXTMETRIC tm;  if (!win32font)    return NULL;  if (!win32font->hfont)    {      cache = pango_win32_font_map_get_font_cache (win32font->fontmap);      win32font->hfont = pango_win32_font_cache_load (cache, &win32font->logfont);      if (!win32font->hfont)	{	  gchar *face_utf8 = g_locale_to_utf8 (win32font->logfont.lfFaceName,					       -1, NULL, NULL, NULL);	  g_warning ("Cannot load font '%s\n", face_utf8);	  g_free (face_utf8);	  return NULL;	}      SelectObject (pango_win32_hdc, win32font->hfont);      GetTextMetrics (pango_win32_hdc, &tm);      win32font->tm_overhang = tm.tmOverhang;      win32font->tm_descent = tm.tmDescent;      win32font->tm_ascent = tm.tmAscent;    }  return win32font->hfont;}/** * pango_win32_get_context: * * Retrieves a #PangoContext appropriate for rendering with Windows fonts.  * * Return value: the new #PangoContext **/PangoContext *pango_win32_get_context (void){  PangoContext *result;  result = pango_context_new ();  pango_context_set_font_map (result, pango_win32_font_map_for_display ());  return result;}G_DEFINE_TYPE (PangoWin32Font, pango_win32_font, PANGO_TYPE_FONT)static voidpango_win32_font_init (PangoWin32Font *win32font){  win32font->size = -1;  win32font->metrics_by_lang = NULL;  win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);}/** * pango_win32_get_dc: * * Obtains a handle to the Windows device context that is used by Pango. * * Return value: A handle to the Windows device context that is used by Pango. **/HDCpango_win32_get_dc (void){  if (pango_win32_hdc == NULL)    {      pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);      memset (&pango_win32_os_version_info, 0,	      sizeof (pango_win32_os_version_info));      pango_win32_os_version_info.dwOSVersionInfoSize =	sizeof (OSVERSIONINFO);      GetVersionEx (&pango_win32_os_version_info);      /* Also do some generic pangowin32 initialisations... this function       * is a suitable place for those as it is called from a couple       * of class_init functions.       */#ifdef PANGO_WIN32_DEBUGGING      if (getenv ("PANGO_WIN32_DEBUG") != NULL)	pango_win32_debug = TRUE;#endif    }  return pango_win32_hdc;}/** * pango_win32_get_debug_flag: * * Returns whether debugging is turned on. * * Return value: %TRUE if debugging is turned on. * * Since: 1.2 */gbooleanpango_win32_get_debug_flag (void){  return pango_win32_debug;}static voidpango_win32_font_class_init (PangoWin32FontClass *class){  GObjectClass *object_class = G_OBJECT_CLASS (class);  PangoFontClass *font_class = PANGO_FONT_CLASS (class);  object_class->finalize = pango_win32_font_finalize;  object_class->dispose = pango_win32_font_dispose;  font_class->describe = pango_win32_font_describe;  font_class->describe_absolute = pango_win32_font_describe_absolute;  font_class->get_coverage = pango_win32_font_get_coverage;  font_class->find_shaper = pango_win32_font_find_shaper;  font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;  font_class->get_metrics = pango_win32_font_get_metrics;  font_class->get_font_map = pango_win32_font_get_font_map;  class->select_font = pango_win32_font_real_select_font;  class->done_font = pango_win32_font_real_done_font;  class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;  pango_win32_get_dc ();}PangoWin32Font *pango_win32_font_new (PangoFontMap  *fontmap,		      const LOGFONT *lfp,		      int	     size){  PangoWin32Font *result;  g_return_val_if_fail (fontmap != NULL, NULL);  g_return_val_if_fail (lfp != NULL, NULL);  result = (PangoWin32Font *)g_object_new (PANGO_TYPE_WIN32_FONT, NULL);  result->fontmap = fontmap;  g_object_ref (fontmap);  result->size = size;  pango_win32_make_matching_logfont (fontmap, lfp, size,				     &result->logfont);  return result;}/** * pango_win32_render: * @hdc:     the device context * @font:    the font in which to draw the string * @glyphs:  the glyph string to draw * @x:       the x position of start of string (in pixels) * @y:       the y position of baseline (in pixels) * * Render a #PangoGlyphString onto a Windows DC */voidpango_win32_render (HDC               hdc,		    PangoFont        *font,		    PangoGlyphString *glyphs,		    int               x,		    int               y){  HFONT hfont, old_hfont = NULL;  int i, j, num_valid_glyphs;  guint16 *glyph_indexes;  gint *dX;  gint this_x;  PangoGlyphUnit start_x_offset, x_offset, next_x_offset, cur_y_offset;  g_return_if_fail (glyphs != NULL);#ifdef PANGO_WIN32_DEBUGGING  if (pango_win32_debug)    {      PING (("num_glyphs:%d", glyphs->num_glyphs));      for (i = 0; i < glyphs->num_glyphs; i++)	{	  g_print (" %d:%d", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);	  if (glyphs->glyphs[i].geometry.x_offset != 0 ||	      glyphs->glyphs[i].geometry.y_offset != 0)	    g_print (":%d,%d", glyphs->glyphs[i].geometry.x_offset,		     glyphs->glyphs[i].geometry.y_offset);	}      g_print ("\n");    }#endif  if (glyphs->num_glyphs == 0)    return;  hfont = pango_win32_get_hfont (font);  if (!hfont)    return;  old_hfont = SelectObject (hdc, hfont);  glyph_indexes = g_new (guint16, glyphs->num_glyphs);  dX = g_new (INT, glyphs->num_glyphs);  /* Render glyphs using one ExtTextOutW() call for each run of glyphs   * that have the same y offset. The big majoroty of glyphs will have   * y offset of zero, so in general, the whole glyph string will be   * rendered by one call to ExtTextOutW().   *   * In order to minimize buildup of rounding errors, we keep track of   * where the glyphs should be rendered in PangoGlyphUnits, and round   * to pixels separately for each glyph,   */  i = 0;  /* Outer loop through all glyphs in string */  while (i < glyphs->num_glyphs)    {      cur_y_offset = glyphs->glyphs[i].geometry.y_offset;      num_valid_glyphs = 0;      x_offset = 0;      start_x_offset = glyphs->glyphs[i].geometry.x_offset;      this_x = PANGO_PIXELS (start_x_offset);      /* Inner loop through glyphs with the same y offset, or code       * point zero (just spacing).       */      while (i < glyphs->num_glyphs &&	     (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY ||	      cur_y_offset == glyphs->glyphs[i].geometry.y_offset))	{	  if (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY)	    {	      /* PANGO_GLYPH_EMPTY glyphs should not be rendered, but their	       * indicated width (set up by PangoLayout) should be taken	       * into account.	       */	      /* If the string starts with spacing, must shift the	       * starting point for the glyphs actually rendered.  For	       * spacing in the middle of the glyph string, add to the dX	       * of the previous glyph to be rendered.	       */	      if (num_valid_glyphs == 0)		start_x_offset += glyphs->glyphs[i].geometry.width;	      else		{		  x_offset += glyphs->glyphs[i].geometry.width;		  dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - this_x;		}	    }	  else	    {	      if (glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)		{		  /* Glyph index is actually the char value that doesn't		   * have any glyph (ORed with the flag). We should really		   * do the same that pango_xft_real_render() does: render		   * a box with the char value in hex inside it in a tiny		   * font. Later. For now, use the TrueType invalid glyph		   * at 0.		   */		  glyph_indexes[num_valid_glyphs] = 0;		}	      else		glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;	      x_offset += glyphs->glyphs[i].geometry.width;	      /* If the next glyph has an X offset, take that into consideration now */	      if (i < glyphs->num_glyphs - 1)		next_x_offset = glyphs->glyphs[i+1].geometry.x_offset;	      else		next_x_offset = 0;	      dX[num_valid_glyphs] = PANGO_PIXELS (x_offset + next_x_offset) - this_x;	      /* Prepare for next glyph */	      this_x += dX[num_valid_glyphs];	      num_valid_glyphs++;	    }	  i++;	}#ifdef PANGO_WIN32_DEBUGGING      if (pango_win32_debug)	{	  g_print ("ExtTextOutW at %d,%d deltas:",		   x + PANGO_PIXELS (start_x_offset),		   y + PANGO_PIXELS (cur_y_offset));	  for (j = 0; j < num_valid_glyphs; j++)	    g_print (" %d", dX[j]);	  g_print ("\n");	}#endif      ExtTextOutW (hdc,		   x + PANGO_PIXELS (start_x_offset),		   y + PANGO_PIXELS (cur_y_offset),		   ETO_GLYPH_INDEX,		   NULL,		   glyph_indexes, num_valid_glyphs,		   dX);      x += this_x;    }  SelectObject (hdc, old_hfont); /* restore */  g_free (glyph_indexes);  g_free (dX);}/** * pango_win32_render_transformed: * @hdc:     a windows device context * @matrix:  a #PangoMatrix, or %NULL to use an identity transformation * @font:    the font in which to draw the string * @glyphs:  the glyph string to draw * @x:       the x position of the start of the string (in Pango *           units in user space coordinates) * @y:       the y position of the baseline (in Pango units *           in user space coordinates) * * Renders a #PangoGlyphString onto a windows DC, possibly * transforming the layed-out coordinates through a transformation * matrix. Note that the transformation matrix for @font is not * changed, so to produce correct rendering results, the @font * must have been loaded using a #PangoContext with an identical * transformation matrix to that passed in to this function. **/voidpango_win32_render_transformed (HDC                hdc,				const PangoMatrix *matrix,				PangoFont         *font,				PangoGlyphString  *glyphs,				int                x,				int                y){  XFORM xForm;  XFORM xFormPrev = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};  int   mode = GetGraphicsMode (hdc);  if (!SetGraphicsMode (hdc, GM_ADVANCED))    g_warning ("SetGraphicsMode() failed");  else if (!GetWorldTransform (hdc, &xFormPrev))    g_warning ("GetWorldTransform() failed");  else if (matrix)    {      xForm.eM11 = matrix->xx;      xForm.eM12 = matrix->yx;      xForm.eM21 = matrix->xy;      xForm.eM22 = matrix->yy;      xForm.eDx = matrix->x0;      xForm.eDy = matrix->y0;      if (!SetWorldTransform (hdc, &xForm))	g_warning ("GetWorldTransform() failed");    }  pango_win32_render (hdc, font, glyphs, x/PANGO_SCALE, y/PANGO_SCALE);  /* restore */  SetWorldTransform (hdc, &xFormPrev);  SetGraphicsMode (hdc, mode);}static voidpango_win32_font_get_glyph_extents (PangoFont      *font,				    PangoGlyph      glyph,				    PangoRectangle *ink_rect,				    PangoRectangle *logical_rect){  PangoWin32Font *win32font = (PangoWin32Font *)font;  guint16 glyph_index = glyph;  GLYPHMETRICS gm;  guint32 res;  HFONT hfont;  MAT2 m = {{0,1}, {0,0}, {0,0}, {0,1}};  PangoWin32GlyphInfo *info;  if (glyph == PANGO_GLYPH_EMPTY)    {      if (ink_rect)	ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;      if (logical_rect)	logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;      return;    }  if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)    glyph_index = glyph = 0;  info = g_hash_table_lookup (win32font->glyph_info, GUINT_TO_POINTER (glyph));  if (!info)    {      info = g_new0 (PangoWin32GlyphInfo, 1);      memset (&gm, 0, sizeof (gm));      hfont = pango_win32_get_hfont (font);      SelectObject (pango_win32_hdc, hfont);      /* FIXME: (Alex) This constant reuse of pango_win32_hdc is	 not thread-safe */      res = GetGlyphOutlineA (pango_win32_hdc,			      glyph_index,			      GGO_METRICS | GGO_GLYPH_INDEX,			      &gm,			      0, NULL,			      &m);      if (res == GDI_ERROR)	{	  gchar *error = g_win32_error_message (GetLastError ());	  g_warning ("GetGlyphOutline(%04X) failed: %s\n",		     glyph_index, error);	  g_free (error);	  /* Don't just return now, use the still zeroed out gm */	}      info->ink_rect.x = PANGO_SCALE * gm.gmptGlyphOrigin.x;      info->ink_rect.width = PANGO_SCALE * gm.gmBlackBoxX;      info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y;      info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY;      info->logical_rect.x = 0;      info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX;      info->logical_rect.y = - PANGO_SCALE * win32font->tm_ascent;      info->logical_rect.height = PANGO_SCALE * (win32font->tm_ascent + win32font->tm_descent);      g_hash_table_insert (win32font->glyph_info, GUINT_TO_POINTER(glyph), info);    }  if (ink_rect)    *ink_rect = info->ink_rect;  if (logical_rect)    *logical_rect = info->logical_rect;}static intmax_glyph_width (PangoLayout *layout){  int max_width = 0;  GSList *l, *r;  for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)    {      PangoLayoutLine *line = l->data;      for (r = line->runs; r; r = r->next)	{	  PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;	  int i;	  for (i = 0; i < glyphs->num_glyphs; i++)	    if (glyphs->glyphs[i].geometry.width > max_width)	      max_width = glyphs->glyphs[i].geometry.width;	}    }  return max_width;}static PangoFontMetrics *pango_win32_font_get_metrics (PangoFont     *font,			      PangoLanguage *language){  PangoWin32MetricsInfo *info = NULL; /* Quiet gcc */  PangoWin32Font *win32font = (PangoWin32Font *)font;  GSList *tmp_list;  const char *sample_str = pango_language_get_sample_string (language);  tmp_list = win32font->metrics_by_lang;  while (tmp_list)    {      info = tmp_list->data;      if (info->sample_str == sample_str)    /* We _don't_ need strcmp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -