summaryrefslogtreecommitdiff
path: root/pango/pangocairo-render.c
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2007-12-10 08:31:33 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2007-12-10 08:31:33 +0000
commitf4fad0c741636d017aefd76d58e271466696cc6f (patch)
tree2e77cb9df99173cd841609f5ccdb4a40136dcd21 /pango/pangocairo-render.c
parented7f7ab40893d20bab5a221cc95cfcba965cd93e (diff)
downloadpango-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.c129
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;