diff options
author | Behdad Esfahbod <behdad@gnome.org> | 2007-12-10 08:31:33 +0000 |
---|---|---|
committer | Behdad Esfahbod <behdad@src.gnome.org> | 2007-12-10 08:31:33 +0000 |
commit | f4fad0c741636d017aefd76d58e271466696cc6f (patch) | |
tree | 2e77cb9df99173cd841609f5ccdb4a40136dcd21 /pango/pangocairo-render.c | |
parent | ed7f7ab40893d20bab5a221cc95cfcba965cd93e (diff) | |
download | pango-f4fad0c741636d017aefd76d58e271466696cc6f.tar.gz |
Bug 478914 – Use something invalid instead of '?' when validating input
2007-12-10 Behdad Esfahbod <behdad@gnome.org>
Bug 478914 – Use something invalid instead of '?' when validating
input text
* pango/pango-layout.c (pango_layout_set_text): Set invalid input
bytes to -1, which gives a unichar value of -1, and eventually a
glyph value of -1, aka PANGO_GLYPH_INVALID_INPUT.
* pango/fonts.c (pango_font_get_glyph_extents),
(pango_font_get_metrics), (pango_font_get_font_map):
* pango/modules.c (build_map):
* pango/pango-context.c (get_script), (get_shaper_and_font),
(string_from_script), (itemize_state_process_run):
* pango/pango-coverage.c (pango_coverage_get):
* pango/pango-impl-utils.h:
* pango/pango-utils.c:
* pango/pangocairo-font.c (pango_cairo_font_get_scaled_font),
(_pango_cairo_font_private_get_hex_box_info),
(_pango_cairo_font_private_get_glyph_extents_missing):
* pango/pangocairo-private.h:
* pango/pangocairo-render.c (_pango_cairo_renderer_draw_frame),
(_pango_cairo_renderer_draw_box_glyph),
(_pango_cairo_renderer_draw_unknown_glyph):
* pango/pangofc-fontmap.c (pango_fc_font_map_get_patterns):
* pango/pangoft2-private.h:
* pango/pangoft2-render.c (pango_ft2_font_render_box_glyph),
(pango_ft2_font_render_glyph), (pango_ft2_renderer_draw_glyph):
* pango/pangoft2.c (pango_ft2_font_get_face),
(pango_ft2_font_get_glyph_extents):
* pango/pangox.c (pango_x_find_subfont), (pango_x_render):
* pango/pangoxft-font.c (_pango_xft_font_get_mini_font),
(get_glyph_extents_missing), (pango_xft_font_get_font):
* pango/pangoxft-private.h:
* pango/pangoxft-render.c (get_total_matrix), (draw_box),
(_pango_xft_renderer_draw_box_glyph),
(_pango_xft_renderer_draw_unknown_glyph),
(pango_xft_renderer_draw_glyphs):
* pango/shape.c (pango_shape):
Render PANGO_GLYPH_INVALID_INPUT to a single-width box with a cross
inside. Also cleanup spewed warnings and warn at the source, where
we fail to find a shaper, instead of at every location that we see
a NULL font.
* pango/pango-font.h:
* docs/pango-sections.txt:
* docs/tmpl/glyphs.sgml:
New public macro:
PANGO_GLYPH_INVALID_INPUT
svn path=/trunk/; revision=2519
Diffstat (limited to 'pango/pangocairo-render.c')
-rw-r--r-- | pango/pangocairo-render.c | 129 |
1 files changed, 112 insertions, 17 deletions
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c index 21792cb1..17bf976f 100644 --- a/pango/pangocairo-render.c +++ b/pango/pangocairo-render.c @@ -21,6 +21,8 @@ #include <config.h> +#include <math.h> + #include "pangocairo-private.h" typedef struct _PangoCairoRendererClass PangoCairoRendererClass; @@ -58,15 +60,18 @@ set_color (PangoCairoRenderer *crenderer, color->blue / 65535.); } -/* modifies cairo_set_line_width() without doing cairo_save/restore() */ +/* note: modifies crenderer->cr 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) + double line_width, + gboolean invalid) { + cairo_t *cr = crenderer->cr; + if (crenderer->do_path) { double d2 = line_width * .5, d = line_width; @@ -74,19 +79,95 @@ _pango_cairo_renderer_draw_frame (PangoCairoRenderer *crenderer, /* 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(). + * what we really want is cairo_stroke_to_path(), but that's not + * implemented in cairo yet. */ /* outer */ - cairo_rectangle (crenderer->cr, x-d2, y-d2, width+d, height+d); + cairo_rectangle (cr, x-d2, y-d2, width+d, height+d); + /* inner */ - cairo_rectangle (crenderer->cr, x+d2 + (width-d), y+d2, - (width-d), height-d); + if (invalid) + { + /* delicacies of computing the joint... this is REALLY slow */ + + double alpha, tan_alpha2, cos_alpha; + double sx, sy; + + alpha = atan2 (height, width); + + tan_alpha2 = tan (alpha * .5); + if (tan_alpha2 < 1e-5 || (sx = d2 / tan_alpha2, 2. * sx > width - d)) + sx = (width - d) * .5; + + cos_alpha = cos (alpha); + if (cos_alpha < 1e-5 || (sy = d2 / cos_alpha, 2. * sy > height - d)) + sy = (height - d) * .5; + + /* top triangle */ + cairo_new_sub_path (cr); + cairo_line_to (cr, x+width-sx, y+d2); + cairo_line_to (cr, x+sx, y+d2); + cairo_line_to (cr, x+.5*width, y+.5*height-sy); + cairo_close_path (cr); + + /* bottom triangle */ + cairo_new_sub_path (cr); + cairo_line_to (cr, x+width-sx, y+height-d2); + cairo_line_to (cr, x+.5*width, y+.5*height+sy); + cairo_line_to (cr, x+sx, y+height-d2); + cairo_close_path (cr); + + + alpha = G_PI_2 - alpha; + tan_alpha2 = tan (alpha * .5); + if (tan_alpha2 < 1e-5 || (sy = d2 / tan_alpha2, 2. * sy > height - d)) + sy = (width - d) * .5; + + cos_alpha = cos (alpha); + if (cos_alpha < 1e-5 || (sx = d2 / cos_alpha, 2. * sx > width - d)) + sx = (width - d) * .5; + + /* left triangle */ + cairo_new_sub_path (cr); + cairo_line_to (cr, x+d2, y+sy); + cairo_line_to (cr, x+d2, y+height-sy); + cairo_line_to (cr, x+.5*width-sx, y+.5*height); + cairo_close_path (cr); + + /* right triangle */ + cairo_new_sub_path (cr); + cairo_line_to (cr, x+width-d2, y+sy); + cairo_line_to (cr, x+.5*width+sx, y+.5*height); + cairo_line_to (cr, x+width-d2, y+height-sy); + cairo_close_path (cr); + } + else + cairo_rectangle (cr, x+width-d2, 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); + cairo_rectangle (cr, x, y, width, height); + + if (invalid) + { + /* draw an X */ + + cairo_new_sub_path (cr); + cairo_move_to (cr, x, y); + cairo_rel_line_to (cr, width, height); + + cairo_new_sub_path (cr); + cairo_move_to (cr, x + width, y); + cairo_rel_line_to (cr, -width, height); + + cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT); + } + + cairo_set_line_width (cr, line_width); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); + cairo_set_miter_limit (cr, 2.); + cairo_stroke (cr); } } @@ -94,7 +175,8 @@ static void _pango_cairo_renderer_draw_box_glyph (PangoCairoRenderer *crenderer, PangoGlyphInfo *gi, double cx, - double cy) + double cy, + gboolean invalid) { double temp_x, temp_y; @@ -107,7 +189,8 @@ _pango_cairo_renderer_draw_box_glyph (PangoCairoRenderer *crenderer, cy + 1.5 - PANGO_UNKNOWN_GLYPH_HEIGHT, (double)gi->geometry.width / PANGO_SCALE - 3.0, PANGO_UNKNOWN_GLYPH_HEIGHT - 3.0, - 1.0); + 1.0, + invalid); cairo_move_to (crenderer->cr, temp_x, temp_y); cairo_restore (crenderer->cr); @@ -128,30 +211,42 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer, double temp_x, temp_y; PangoCairoFontHexBoxInfo *hbi; gunichar ch; + gboolean invalid_input; cairo_save (crenderer->cr); cairo_get_current_point (crenderer->cr, &temp_x, &temp_y); - hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font); + ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG; + invalid_input = G_UNLIKELY (gi->glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF); + hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font); if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr)) { - _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy); + _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy, invalid_input); 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); + if (G_UNLIKELY (invalid_input)) + { + cols = 1; + } + else + { + 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); + hbi->line_width, + invalid_input); + + if (invalid_input) + goto done; x0 = cx + hbi->pad_x * 3.0; y0 = cy + hbi->box_descent - hbi->pad_y * 2; |