~ubuntu-branches/ubuntu/karmic/pango1.0/karmic-security

« back to all changes in this revision

Viewing changes to pango/pangocairo-render.c

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier
  • Date: 2007-12-18 21:11:37 UTC
  • mfrom: (1.2.44 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218211137-0ibmwreimvxf3cp1
Tags: 1.19.2-1ubuntu1
* Sync with Debian; Ubuntu changes are:
  - Add patch 30_anymetrics, turns on FC_ANY_METRICS whenever looking up
    fonts with fontconfig; lets fontconfig's configuration know that we
    don't care about getting a font with exactly the same shape as the
    family we asked for and fixes (eg) a firefox vs. evince font metrics
    ugliness issue.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
#include <config.h>
23
23
 
 
24
#include <math.h>
 
25
 
24
26
#include "pangocairo-private.h"
25
27
 
26
28
typedef struct _PangoCairoRendererClass PangoCairoRendererClass;
58
60
                          color->blue / 65535.);
59
61
}
60
62
 
61
 
/* modifies cairo_set_line_width() without doing cairo_save/restore() */
 
63
/* note: modifies crenderer->cr without doing cairo_save/restore() */
62
64
static void
63
65
_pango_cairo_renderer_draw_frame (PangoCairoRenderer *crenderer,
64
66
                                  double              x,
65
67
                                  double              y,
66
68
                                  double              width,
67
69
                                  double              height,
68
 
                                  double              line_width)
 
70
                                  double              line_width,
 
71
                                  gboolean            invalid)
69
72
{
 
73
  cairo_t *cr = crenderer->cr;
 
74
 
70
75
  if (crenderer->do_path)
71
76
    {
72
77
      double d2 = line_width * .5, d = line_width;
74
79
      /* we draw an outer box in one winding direction and an inner one in the
75
80
       * opposite direction.  This works for both cairo windings rules.
76
81
       *
77
 
       * what we really want is cairo_stroke_to_path().
 
82
       * what we really want is cairo_stroke_to_path(), but that's not
 
83
       * implemented in cairo yet.
78
84
       */
79
85
 
80
86
      /* outer */
81
 
      cairo_rectangle (crenderer->cr, x-d2, y-d2, width+d, height+d);
 
87
      cairo_rectangle (cr, x-d2, y-d2, width+d, height+d);
 
88
 
82
89
      /* inner */
83
 
      cairo_rectangle (crenderer->cr, x+d2 + (width-d), y+d2, - (width-d), height-d);
 
90
      if (invalid)
 
91
        {
 
92
          /* delicacies of computing the joint... this is REALLY slow */
 
93
 
 
94
          double alpha, tan_alpha2, cos_alpha;
 
95
          double sx, sy;
 
96
 
 
97
          alpha = atan2 (height, width);
 
98
 
 
99
          tan_alpha2 = tan (alpha * .5);
 
100
          if (tan_alpha2 < 1e-5 || (sx = d2 / tan_alpha2, 2. * sx > width - d))
 
101
            sx = (width - d) * .5;
 
102
 
 
103
          cos_alpha = cos (alpha);
 
104
          if (cos_alpha < 1e-5 || (sy = d2 / cos_alpha, 2. * sy > height - d))
 
105
            sy = (height - d) * .5;
 
106
 
 
107
          /* top triangle */
 
108
          cairo_new_sub_path (cr);
 
109
          cairo_line_to (cr, x+width-sx, y+d2);
 
110
          cairo_line_to (cr, x+sx, y+d2);
 
111
          cairo_line_to (cr, x+.5*width, y+.5*height-sy);
 
112
          cairo_close_path (cr);
 
113
 
 
114
          /* bottom triangle */
 
115
          cairo_new_sub_path (cr);
 
116
          cairo_line_to (cr, x+width-sx, y+height-d2);
 
117
          cairo_line_to (cr, x+.5*width, y+.5*height+sy);
 
118
          cairo_line_to (cr, x+sx, y+height-d2);
 
119
          cairo_close_path (cr);
 
120
 
 
121
 
 
122
          alpha = G_PI_2 - alpha;
 
123
          tan_alpha2 = tan (alpha * .5);
 
124
          if (tan_alpha2 < 1e-5 || (sy = d2 / tan_alpha2, 2. * sy > height - d))
 
125
            sy = (width - d) * .5;
 
126
 
 
127
          cos_alpha = cos (alpha);
 
128
          if (cos_alpha < 1e-5 || (sx = d2 / cos_alpha, 2. * sx > width - d))
 
129
            sx = (width - d) * .5;
 
130
 
 
131
          /* left triangle */
 
132
          cairo_new_sub_path (cr);
 
133
          cairo_line_to (cr, x+d2, y+sy);
 
134
          cairo_line_to (cr, x+d2, y+height-sy);
 
135
          cairo_line_to (cr, x+.5*width-sx, y+.5*height);
 
136
          cairo_close_path (cr);
 
137
 
 
138
          /* right triangle */
 
139
          cairo_new_sub_path (cr);
 
140
          cairo_line_to (cr, x+width-d2, y+sy);
 
141
          cairo_line_to (cr, x+.5*width+sx, y+.5*height);
 
142
          cairo_line_to (cr, x+width-d2, y+height-sy);
 
143
          cairo_close_path (cr);
 
144
        }
 
145
      else
 
146
        cairo_rectangle (cr, x+width-d2, y+d2, - (width-d), height-d);
84
147
    }
85
148
  else
86
149
    {
87
 
      cairo_rectangle (crenderer->cr, x, y, width, height);
88
 
      cairo_set_line_width (crenderer->cr, line_width);
89
 
      cairo_stroke (crenderer->cr);
 
150
      cairo_rectangle (cr, x, y, width, height);
 
151
 
 
152
      if (invalid)
 
153
        {
 
154
          /* draw an X */
 
155
 
 
156
          cairo_new_sub_path (cr);
 
157
          cairo_move_to (cr, x, y);
 
158
          cairo_rel_line_to (cr, width, height);
 
159
 
 
160
          cairo_new_sub_path (cr);
 
161
          cairo_move_to (cr, x + width, y);
 
162
          cairo_rel_line_to (cr, -width, height);
 
163
 
 
164
          cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
 
165
        }
 
166
 
 
167
      cairo_set_line_width (cr, line_width);
 
168
      cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
 
169
      cairo_set_miter_limit (cr, 2.);
 
170
      cairo_stroke (cr);
90
171
    }
91
172
}
92
173
 
94
175
_pango_cairo_renderer_draw_box_glyph (PangoCairoRenderer *crenderer,
95
176
                                      PangoGlyphInfo     *gi,
96
177
                                      double              cx,
97
 
                                      double              cy)
 
178
                                      double              cy,
 
179
                                      gboolean            invalid)
98
180
{
99
181
  double temp_x, temp_y;
100
182
 
107
189
                                    cy + 1.5 - PANGO_UNKNOWN_GLYPH_HEIGHT,
108
190
                                    (double)gi->geometry.width / PANGO_SCALE - 3.0,
109
191
                                    PANGO_UNKNOWN_GLYPH_HEIGHT - 3.0,
110
 
                                    1.0);
 
192
                                    1.0,
 
193
                                    invalid);
111
194
 
112
195
  cairo_move_to (crenderer->cr, temp_x, temp_y);
113
196
  cairo_restore (crenderer->cr);
128
211
  double temp_x, temp_y;
129
212
  PangoCairoFontHexBoxInfo *hbi;
130
213
  gunichar ch;
 
214
  gboolean invalid_input;
131
215
 
132
216
  cairo_save (crenderer->cr);
133
217
  cairo_get_current_point (crenderer->cr, &temp_x, &temp_y);
134
218
 
 
219
  ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
 
220
  invalid_input = G_UNLIKELY (gi->glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF);
 
221
 
135
222
  hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);
136
 
 
137
223
  if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr))
138
224
    {
139
 
      _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy);
 
225
      _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy, invalid_input);
140
226
      goto done;
141
227
    }
142
228
 
143
 
  ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
144
 
 
145
229
  rows = hbi->rows;
146
 
  cols = (ch > 0xffff ? 6 : 4) / rows;
147
 
  g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);
 
230
  if (G_UNLIKELY (invalid_input))
 
231
    {
 
232
      cols = 1;
 
233
    }
 
234
  else
 
235
    {
 
236
      cols = (ch > 0xffff ? 6 : 4) / rows;
 
237
      g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);
 
238
    }
148
239
 
149
240
  _pango_cairo_renderer_draw_frame (crenderer,
150
241
                                    cx + hbi->pad_x * 1.5,
151
242
                                    cy + hbi->box_descent - hbi->box_height + hbi->pad_y * 0.5,
152
243
                                    (double)gi->geometry.width / PANGO_SCALE - 3 * hbi->pad_x,
153
244
                                    (hbi->box_height - hbi->pad_y),
154
 
                                    hbi->line_width);
 
245
                                    hbi->line_width,
 
246
                                    invalid_input);
 
247
 
 
248
  if (invalid_input)
 
249
    goto done;
155
250
 
156
251
  x0 = cx + hbi->pad_x * 3.0;
157
252
  y0 = cy + hbi->box_descent - hbi->pad_y * 2;