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

📄 pangocairo-render.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Pango * pangocairo-render.c: Rendering routines to Cairo surfaces * * Copyright (C) 2004 Red Hat, Inc. * * 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 "pangocairo-private.h"typedef struct _PangoCairoRendererClass PangoCairoRendererClass;#define PANGO_CAIRO_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))#define PANGO_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_RENDERER))#define PANGO_CAIRO_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))struct _PangoCairoRenderer{  PangoRenderer parent_instance;  cairo_t *cr;  gboolean do_path;  double x_offset, y_offset;};struct _PangoCairoRendererClass{  PangoRendererClass parent_class;};G_DEFINE_TYPE (PangoCairoRenderer, pango_cairo_renderer, PANGO_TYPE_RENDERER)static voidset_color (PangoCairoRenderer *crenderer,	   PangoRenderPart     part){  PangoColor *color = pango_renderer_get_color ((PangoRenderer *) (crenderer), part);  if (color)    cairo_set_source_rgb (crenderer->cr,			  color->red / 65535.,			  color->green / 65535.,			  color->blue / 65535.);}/* modifies cairo_set_line_width() without doing cairo_save/restore() */static void_pango_cairo_renderer_draw_frame (PangoCairoRenderer *crenderer,				  double              x,				  double              y,				  double              width,				  double              height,				  double              line_width){  if (crenderer->do_path)    {      cairo_t *cr = crenderer->cr;      double d2 = line_width * .5, d = line_width;      /* we draw an outer box in one winding direction and an inner one in the       * opposite direction.  This works for both cairo windings rules.       *       * what we really want is cairo_stroke_to_path().       */      /* outer */      cairo_rectangle (crenderer->cr, x-d2, y-d2, width+d, height+d);      /* inner */      cairo_rectangle (crenderer->cr, x+d2 + (width-d), y+d2, - (width-d), height-d);    }  else    {      cairo_rectangle (crenderer->cr, x, y, width, height);      cairo_set_line_width (crenderer->cr, line_width);      cairo_stroke (crenderer->cr);    }}static void_pango_cairo_renderer_draw_box_glyph (PangoCairoRenderer *crenderer,				      PangoGlyphInfo     *gi,				      double              cx,				      double              cy){  double temp_x, temp_y;  cairo_save (crenderer->cr);  cairo_get_current_point (crenderer->cr, &temp_x, &temp_y);  _pango_cairo_renderer_draw_frame (crenderer,				    cx + 1.5,				    cy + 1.5 - PANGO_UNKNOWN_GLYPH_HEIGHT,				    (double)gi->geometry.width / PANGO_SCALE - 3.0,				    PANGO_UNKNOWN_GLYPH_HEIGHT - 3.0,				    1.0);  cairo_move_to (crenderer->cr, temp_x, temp_y);  cairo_restore (crenderer->cr);}static void_pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,					  PangoFont          *font,					  PangoGlyphInfo     *gi,					  double              cx,					  double              cy){  char buf[7];  double x0, y0;  int row, col;  int rows, cols;  char hexbox_string[2] = {0, 0};  double temp_x, temp_y;  PangoCairoHexBoxInfo *hbi;  gunichar ch;  cairo_save (crenderer->cr);  cairo_get_current_point (crenderer->cr, &temp_x, &temp_y);  hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);  if (!hbi || !_pango_cairo_font_install ((PangoCairoFont *) (hbi->font), crenderer->cr))    {      _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy);      goto done;    }  ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;  rows = hbi->rows;  cols = (ch > 0xffff ? 6 : 4) / rows;  g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);  _pango_cairo_renderer_draw_frame (crenderer,				    cx + hbi->pad_x * 1.5,				    cy + hbi->box_descent - hbi->box_height + hbi->pad_y * 0.5,				    (double)gi->geometry.width / PANGO_SCALE - 3 * hbi->pad_x,				    (hbi->box_height - hbi->pad_y),				    hbi->line_width);  x0 = cx + hbi->pad_x * 3.0;  y0 = cy + hbi->box_descent - hbi->pad_y * 2;  for (row = 0; row < rows; row++)    {      double y = y0 - (rows - 1 - row) * (hbi->digit_height + hbi->pad_y);      for (col = 0; col < cols; col++)	{	  double x = x0 + col * (hbi->digit_width + hbi->pad_x);	  cairo_move_to (crenderer->cr, x, y);	  hexbox_string[0] = buf[row * cols + col];	  if (crenderer->do_path)	      cairo_text_path (crenderer->cr, hexbox_string);	  else	      cairo_show_text (crenderer->cr, hexbox_string);	}    }done:  cairo_move_to (crenderer->cr, temp_x, temp_y);  cairo_restore (crenderer->cr);}static voidpango_cairo_renderer_draw_glyphs (PangoRenderer     *renderer,				  PangoFont         *font,				  PangoGlyphString  *glyphs,				  int                x,				  int                y){  PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);  /* cairo_glyph_t is 24 bytes */#define MAX_STACK 40  int i, count;  int x_position = 0;  cairo_glyph_t *cairo_glyphs;  cairo_glyph_t stack_glyphs[MAX_STACK];  double base_x = crenderer->x_offset + (double)x / PANGO_SCALE;  double base_y = crenderer->y_offset + (double)y / PANGO_SCALE;  cairo_save (crenderer->cr);  if (!crenderer->do_path)    set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);  if (!_pango_cairo_font_install ((PangoCairoFont *) (font), crenderer->cr))    {      for (i = 0; i < glyphs->num_glyphs; i++)	{	  PangoGlyphInfo *gi = &glyphs->glyphs[i];	  if (gi->glyph != PANGO_GLYPH_EMPTY)	    {	      double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;	      double cy = gi->geometry.y_offset == 0 ?			  base_y :			  base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;	      _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);	    }	  x_position += gi->geometry.width;	}      goto done;    }  if (glyphs->num_glyphs > MAX_STACK)    cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);  else    cairo_glyphs = stack_glyphs;  count = 0;  for (i = 0; i < glyphs->num_glyphs; i++)    {      PangoGlyphInfo *gi = &glyphs->glyphs[i];      if (gi->glyph != PANGO_GLYPH_EMPTY)	{	  double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;	  double cy = gi->geometry.y_offset == 0 ?		      base_y :		      base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;	  if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)	    _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);	  else	    {	      cairo_glyphs[count].index = gi->glyph;	      cairo_glyphs[count].x = cx;	      cairo_glyphs[count].y = cy;	      count++;	    }	}      x_position += gi->geometry.width;    }  if (crenderer->do_path)    cairo_glyph_path (crenderer->cr, cairo_glyphs, count);  else    cairo_show_glyphs (crenderer->cr, cairo_glyphs, count);  if (glyphs->num_glyphs > MAX_STACK)    g_free (cairo_glyphs);done:  cairo_restore (crenderer->cr);#undef MAX_STACK}static voidpango_cairo_renderer_draw_rectangle (PangoRenderer     *renderer,				     PangoRenderPart    part,				     int                x,				     int                y,				     int                width,				     int                height){  PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);  if (!crenderer->do_path)    {      cairo_save (crenderer->cr);      set_color (crenderer, part);    }  cairo_rectangle (crenderer->cr,		   crenderer->x_offset + (double)x / PANGO_SCALE,		   crenderer->y_offset + (double)y / PANGO_SCALE,		   (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);  if (!crenderer->do_path)    {      cairo_fill (crenderer->cr);      cairo_restore (crenderer->cr);    }}/* Draws an error underline that looks like one of: *              H       E                H *     /\      /\      /\        /\      /\               - *   A/  \    /  \    /  \     A/  \    /  \              | *    \   \  /    \  /   /D     \   \  /    \             | *     \   \/  C   \/   /        \   \/   C  \            | height = HEIGHT_SQUARES * square *      \      /\  F   /          \  F   /\   \           | *       \    /  \    /            \    /  \   \G         | *        \  /    \  /              \  /    \  /          | *         \/      \/                \/      \/           - *         B                         B *         |---| *       unit_width = (HEIGHT_SQUARES - 1) * square * * The x, y, width, height passed in give the desired bounding box; * x/width are adjusted to make the underline a integer number of units * wide. */#define HEIGHT_SQUARES 2.5static voiddraw_error_underline (cairo_t *cr,		      double   x,		      double   y,		      double   width,		      double   height){  double square = height / HEIGHT_SQUARES;  double unit_width = (HEIGHT_SQUARES - 1) * square;  int width_units = (width + unit_width / 2) / unit_width;  double y_top, y_bottom;  int i;  x += (width - width_units * unit_width) / 2;  width = width_units * unit_width;  y_top = y;  y_bottom = y + height;  /* Bottom of squiggle */  cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */  for (i = 0; i < width_units; i += 2)    {      double x_middle = x + (i + 1) * unit_width;      double x_right = x + (i + 2) * unit_width;      cairo_line_to (cr, x_middle, y_bottom); /* B */      if (i + 1 == width_units)	/* Nothing */;      else if (i + 2 == width_units)	cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */      else	cairo_line_to (cr, x_right, y_top + square); /* C */    }  /* Top of squiggle */  for (i -= 2; i >= 0; i -= 2)    {      double x_left = x + i * unit_width;      double x_middle = x + (i + 1) * unit_width;      double x_right = x + (i + 2) * unit_width;      if (i + 1 == width_units)	cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */      else {	if (i + 2 == width_units)	  cairo_line_to (cr, x_right, y_top); /* E */	cairo_line_to (cr, x_middle, y_bottom - square); /* F */      }      cairo_line_to (cr, x_left, y_top);   /* H */    }}static voidpango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,					   int            x,					   int            y,

⌨️ 快捷键说明

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