summaryrefslogtreecommitdiff
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
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
-rw-r--r--ChangeLog51
-rw-r--r--docs/pango-sections.txt1
-rw-r--r--docs/tmpl/glyphs.sgml14
-rw-r--r--pango/fonts.c35
-rw-r--r--pango/modules.c13
-rw-r--r--pango/pango-context.c70
-rw-r--r--pango/pango-coverage.c7
-rw-r--r--pango/pango-font.h1
-rw-r--r--pango/pango-impl-utils.h15
-rw-r--r--pango/pango-layout.c7
-rw-r--r--pango/pango-utils.c9
-rw-r--r--pango/pangocairo-font.c26
-rw-r--r--pango/pangocairo-private.h8
-rw-r--r--pango/pangocairo-render.c129
-rw-r--r--pango/pangofc-fontmap.c12
-rw-r--r--pango/pangoft2-private.h8
-rw-r--r--pango/pangoft2-render.c58
-rw-r--r--pango/pangoft2.c67
-rw-r--r--pango/pangox.c24
-rw-r--r--pango/pangoxft-font.c31
-rw-r--r--pango/pangoxft-private.h14
-rw-r--r--pango/pangoxft-render.c111
-rw-r--r--pango/shape.c19
23 files changed, 478 insertions, 252 deletions
diff --git a/ChangeLog b/ChangeLog
index 40e3b3fe..d17108ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+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
+
2007-12-05 Behdad Esfahbod <behdad@gnome.org>
* examples/cairotwisted.c (point_on_path): Optimize double math.
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 7571eea1..af8ce234 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -97,6 +97,7 @@ pango_matrix_transform_pixel_rectangle
pango_matrix_get_font_scale_factor
PangoGlyph
PANGO_GLYPH_EMPTY
+PANGO_GLYPH_INVALID_INPUT
PANGO_GLYPH_UNKNOWN_FLAG
PANGO_GET_UNKNOWN_GLYPH
PangoGlyphInfo
diff --git a/docs/tmpl/glyphs.sgml b/docs/tmpl/glyphs.sgml
index 46a2b2f0..5f019c1c 100644
--- a/docs/tmpl/glyphs.sgml
+++ b/docs/tmpl/glyphs.sgml
@@ -304,6 +304,20 @@ Unicode characters (those passing pango_is_zero_width()).
+<!-- ##### MACRO PANGO_GLYPH_INVALID_INPUT ##### -->
+<para>
+The %PANGO_GLYPH_EMPTY macro represents a #PangoGlyph value that has a
+special meaning of invalid input. #PangoLayout produces one such glyph
+per invalid input UTF-8 byte and such a glyph is rendered as a crossed
+box.
+
+Note that this value is defined such that it has the %PANGO_GLYPH_UNKNOWN_FLAG
+on.
+</para>
+
+@Since: 1.20
+
+
<!-- ##### MACRO PANGO_GLYPH_UNKNOWN_FLAG ##### -->
<para>
The %PANGO_GLYPH_UNKNOWN_FLAG macro is a flag value that can be added to
diff --git a/pango/fonts.c b/pango/fonts.c
index c60c602d..56dc4177 100644
--- a/pango/fonts.c
+++ b/pango/fonts.c
@@ -29,8 +29,6 @@
#include "pango-fontmap.h"
#include "pango-impl-utils.h"
-static const char bad_font_warning[] = "%s called with null font argument, expect ugly output";
-
struct _PangoFontDescription
{
char *family_name;
@@ -1314,6 +1312,9 @@ pango_font_find_shaper (PangoFont *font,
* PANGO_DESCENT(), PANGO_LBEARING(), and PANGO_RBEARING() can be used to convert
* from the extents rectangle to more traditional font metrics. The units
* of the rectangles are in 1/PANGO_SCALE of a device unit.
+ *
+ * If @font is %NULL, this function gracefully sets some sane values in the
+ * output variables and returns.
**/
void
pango_font_get_glyph_extents (PangoFont *font,
@@ -1323,12 +1324,6 @@ pango_font_get_glyph_extents (PangoFont *font,
{
if (G_UNLIKELY (!font))
{
-
- if (!_pango_warning_history.get_glyph_extents)
- {
- _pango_warning_history.get_glyph_extents = TRUE;
- g_warning (bad_font_warning, "pango_font_get_glyph_extents");
- }
if (ink_rect)
{
ink_rect->x = PANGO_SCALE;
@@ -1361,6 +1356,9 @@ pango_font_get_glyph_extents (PangoFont *font,
* be provided to indicate that the metrics should be retrieved that
* correspond to the script(s) used by that language.
*
+ * If @font is %NULL, this function gracefully sets some sane values in the
+ * output variables and returns.
+ *
* Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref()
* when finished using the object.
**/
@@ -1370,14 +1368,7 @@ pango_font_get_metrics (PangoFont *font,
{
if (G_UNLIKELY (!font))
{
- PangoFontMetrics *metrics;
-
- if (!_pango_warning_history.get_metrics)
- {
- _pango_warning_history.get_metrics = TRUE;
- g_warning (bad_font_warning, "pango_font_get_metrics");
- }
- metrics = pango_font_metrics_new ();
+ PangoFontMetrics *metrics = pango_font_metrics_new ();
metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT;
metrics->descent = 0;
@@ -1400,7 +1391,7 @@ pango_font_get_metrics (PangoFont *font,
*
* Gets the font map for which the font was created.
*
- * Return value: the #PangoFontMap for the font
+ * Return value: the #PangoFontMap for the font, or %NULL if @font is %NULL.
*
* Since: 1.10
**/
@@ -1408,15 +1399,7 @@ PangoFontMap *
pango_font_get_font_map (PangoFont *font)
{
if (G_UNLIKELY (!font))
- {
-
- if (!_pango_warning_history.get_font_map)
- {
- _pango_warning_history.get_font_map = TRUE;
- g_warning (bad_font_warning, "pango_font_get_font_map");
- }
- return NULL;
- }
+ return NULL;
if (PANGO_FONT_GET_CLASS (font)->get_font_map)
return PANGO_FONT_GET_CLASS (font)->get_font_map (font);
diff --git a/pango/modules.c b/pango/modules.c
index 5a9d6883..8fad375e 100644
--- a/pango/modules.c
+++ b/pango/modules.c
@@ -621,11 +621,14 @@ build_map (PangoMapInfo *info)
gchar *filename = g_build_filename (pango_get_sysconf_subdirectory (),
"pango.modules",
NULL);
- g_warning ("No builtin or dynamically\n"
- "loaded modules were found. Pango will not work correctly.\n"
- "This probably means there was an error in the creation of:\n"
- " '%s'\n"
- "You should create this file by running pango-querymodules.",
+ g_critical ("No modules found:\n"
+ "No builtin or dynamically loaded modules were found.\n"
+ "PangoFc will not work correctly.\n"
+ "This probably means there was an error in the creation of:\n"
+ " '%s'\n"
+ "You should create this file by running:\n"
+ " pango-querymodules > '%s'",
+ filename,
filename);
g_free (filename);
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 6f588191..1da56fd2 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -1094,6 +1094,21 @@ get_base_font (ItemizeState *state)
return state->base_font;
}
+static PangoScript
+get_script (ItemizeState *state)
+{
+ /* Always use a basic shaper for vertical layout (ie, east/west gravity)
+ * as none of our script shapers support vertical shaping right now.
+ *
+ * XXX Should move the knowledge into the shaper interface.
+ */
+
+ if (PANGO_GRAVITY_IS_VERTICAL (state->resolved_gravity))
+ return PANGO_SCRIPT_COMMON;
+ else
+ return state->script;
+}
+
static gboolean
get_shaper_and_font (ItemizeState *state,
gunichar wc,
@@ -1108,20 +1123,8 @@ get_shaper_and_font (ItemizeState *state,
return *shape_engine != NULL;
if (!state->exact_engines && !state->fallback_engines)
- {
- /* Always use a basic shaper for vertical layout (ie, east/west gravity)
- * as we do not support vertical shaping as of now.
- */
- PangoScript script;
-
- if (PANGO_GRAVITY_IS_VERTICAL (state->resolved_gravity))
- script = PANGO_SCRIPT_COMMON;
- else
- script = state->script;
-
- get_engines (state->context, state->derived_lang, script,
- &state->exact_engines, &state->fallback_engines);
- }
+ get_engines (state->context, state->derived_lang, get_script (state),
+ &state->exact_engines, &state->fallback_engines);
info.lang = state->derived_lang;
info.wc = wc;
@@ -1289,6 +1292,21 @@ itemize_state_update_for_new_run (ItemizeState *state)
}
}
+static const char *
+string_from_script (PangoScript script)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value (class, script);
+ if (!value)
+ return string_from_script (PANGO_SCRIPT_INVALID_CODE);
+
+ return value->value_nick;
+}
+
static void
itemize_state_process_run (ItemizeState *state)
{
@@ -1351,8 +1369,30 @@ itemize_state_process_run (ItemizeState *state)
PangoEngineShape *shape_engine;
PangoFont *font;
- if (!get_shaper_and_font (state, ' ', &shape_engine, &font))
+ if (G_UNLIKELY (!get_shaper_and_font (state, ' ', &shape_engine, &font)))
{
+ /* If no shaper was found, warn only once per fontmap/script pair */
+ PangoFontMap *fontmap = state->context->font_map;
+ const char *script_name = string_from_script (get_script (state));
+
+ if (!g_object_get_data (G_OBJECT (fontmap), script_name))
+ {
+ const char *what;
+ if (shape_engine == NULL)
+ what = "shape engine";
+ else if (font == NULL)
+ what = "font";
+ else
+ what = "nothing (oops!)";
+
+ g_warning ("failed to find shape engine, expect ugly output. engine-type='%s', script='%s'",
+ pango_font_map_get_shape_engine_type (fontmap),
+ script_name);
+
+ g_object_set_data_full (G_OBJECT (fontmap), script_name,
+ GINT_TO_POINTER (1), NULL);
+ }
+
shape_engine = _pango_get_fallback_shaper ();
font = NULL;
}
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c
index 340ccf7c..4ecdaf78 100644
--- a/pango/pango-coverage.c
+++ b/pango/pango-coverage.c
@@ -170,7 +170,12 @@ pango_coverage_get (PangoCoverage *coverage,
int block_index;
g_return_val_if_fail (coverage != NULL, PANGO_COVERAGE_NONE);
- g_return_val_if_fail (index >= 0, PANGO_COVERAGE_NONE);
+
+ /* index should really have been defined unsigned. Work around
+ * it by just returning NONE.
+ */
+ if (G_UNLIKELY (index < 0))
+ return PANGO_COVERAGE_NONE;
block_index = index / 256;
diff --git a/pango/pango-font.h b/pango/pango-font.h
index 1309c557..66e68aa8 100644
--- a/pango/pango-font.h
+++ b/pango/pango-font.h
@@ -372,6 +372,7 @@ struct _PangoFontClass
#endif /* PANGO_ENABLE_BACKEND */
#define PANGO_GLYPH_EMPTY ((PangoGlyph)0x0FFFFFFF)
+#define PANGO_GLYPH_INVALID_INPUT ((PangoGlyph)0xFFFFFFFF)
#define PANGO_GLYPH_UNKNOWN_FLAG ((PangoGlyph)0x10000000)
#define PANGO_GET_UNKNOWN_GLYPH(wc) ((PangoGlyph)(wc)|PANGO_GLYPH_UNKNOWN_FLAG)
diff --git a/pango/pango-impl-utils.h b/pango/pango-impl-utils.h
index 1f60d84f..e21988f1 100644
--- a/pango/pango-impl-utils.h
+++ b/pango/pango-impl-utils.h
@@ -75,21 +75,6 @@ prefix ## _get_type (void) \
parent_type, G_TYPE_FLAG_ABSTRACT)
-
-/* Warning history. Used to not spew some warnings more than once. */
-typedef struct _PangoWarningHistory PangoWarningHistory;
-
-struct _PangoWarningHistory {
- guint shape_font : 1;
- guint shape_shape_engine : 1;
- guint get_glyph_extents : 1;
- guint get_metrics : 1;
- guint get_font_map : 1;
-};
-
-extern PangoWarningHistory _pango_warning_history;
-
-
/* String interning for static strings */
#define I_(string) g_intern_static_string (string)
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 4ddb4b7c..55c8a1e1 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -961,8 +961,13 @@ pango_layout_set_text (PangoLayout *layout,
if (!*end)
break;
+ /* Replace invalid bytes with -1. The -1 will be converted to
+ * ((gunichar) -1) by glib, and that in turn yields a glyph value of
+ * ((PangoGlyph) -1) by PANGO_GET_UNKNOWN_GLYPH(-1),
+ * and that's PANGO_GLYPH_INVALID_INPUT.
+ */
if (!valid)
- *end++ = '?';
+ *end++ = -1;
start = end;
}
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index 0975af94..f4b52d71 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -59,8 +59,6 @@ struct PangoAlias
static GHashTable *pango_aliases_ht = NULL;
-PangoWarningHistory _pango_warning_history = { FALSE, FALSE, FALSE };
-
/**
* pango_version:
*
@@ -1585,7 +1583,7 @@ pango_is_zero_width (gunichar ch)
/**
* pango_quantize_line_geometry:
- * @thickness: pointer to the thickness of a line, in Pango scaled units
+ * @thickness: pointer to the thickness of a line, in Pango units
* @position: corresponding position
*
* Quantizes the thickness and position of a line, typically an
@@ -1593,8 +1591,9 @@ pango_is_zero_width (gunichar ch)
* multiples of %PANGO_SCALE. The purpose of this function is to avoid
* such lines looking blurry.
*
- * Care is taken to make sure @thickness is at least 1 when this function
- * returns, but returned @position may become zero as a result of rounding.
+ * Care is taken to make sure @thickness is at least one pixel when this
+ * function returns, but returned @position may become zero as a result
+ * of rounding.
*
* Since: 1.12
*/
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index c33d3fde..09255862 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -27,8 +27,6 @@
#include "pangocairo-private.h"
#include "pango-impl-utils.h"
-PangoCairoWarningHistory _pango_cairo_warning_history = { FALSE };
-
#define PANGO_CAIRO_FONT_PRIVATE(font) \
((PangoCairoFontPrivate *) \
(font == NULL ? NULL : \
@@ -151,7 +149,8 @@ done:
* The scaled font can be referenced and kept using
* cairo_scaled_font_reference().
*
- * Return value: the #cairo_scaled_font_t used by @font
+ * Return value: the #cairo_scaled_font_t used by @font,
+ * or %NULL if @font is %NULL.
*
* Since: 1.18
**/
@@ -160,15 +159,8 @@ pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
{
PangoCairoFontPrivate *cf_priv;
- if (G_UNLIKELY (!PANGO_IS_CAIRO_FONT (cfont)))
- {
- if (!_pango_cairo_warning_history.font_get_scaled_font)
- {
- _pango_cairo_warning_history.font_get_scaled_font = TRUE;
- g_warning ("pango_cairo_font_get_scaled_font called with bad font, expect ugly output");
- }
- return NULL;
- }
+ if (G_UNLIKELY (!cfont))
+ return NULL;
cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont);
@@ -408,7 +400,7 @@ _pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv)
cairo_font_options_destroy (font_options);
- scaled_mini_font = pango_cairo_font_get_scaled_font (mini_font);
+ scaled_mini_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *) mini_font);
for (i = 0 ; i < 16 ; i++)
{
@@ -576,6 +568,7 @@ _pango_cairo_font_private_get_glyph_extents_missing (PangoCairoFontPrivate *cf_p
PangoRectangle *logical_rect)
{
PangoCairoFontHexBoxInfo *hbi;
+ gunichar ch;
gint rows, cols;
hbi = _pango_cairo_font_private_get_hex_box_info (cf_priv);
@@ -585,8 +578,13 @@ _pango_cairo_font_private_get_glyph_extents_missing (PangoCairoFontPrivate *cf_p
return;
}
+ ch = glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
+
rows = hbi->rows;
- cols = ((glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 6 : 4) / rows;
+ if (G_UNLIKELY (glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF))
+ cols = 1;
+ else
+ cols = ((glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 6 : 4) / rows;
if (ink_rect)
{
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index 05dbb5a2..bf53e1f9 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -132,14 +132,6 @@ GType pango_cairo_renderer_get_type (void) G_GNUC_CONST;
const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context);
-typedef struct _PangoCairoWarningHistory PangoCairoWarningHistory;
-
-struct _PangoCairoWarningHistory {
- guint font_get_scaled_font : 1;
-};
-
-extern PangoCairoWarningHistory _pango_cairo_warning_history;
-
G_END_DECLS
#endif /* __PANGOCAIRO_PRIVATE_H__ */
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;
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 4840a1f0..adc8c796 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -1072,18 +1072,14 @@ pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
if (!font_patterns)
{
- g_printerr ("No fonts found; this probably means that the fontconfig\n"
+ g_critical ("No fonts found:\n"
+ "This probably means that the fontconfig\n"
"library is not correctly configured. You may need to\n"
"edit the fonts.conf configuration file. More information\n"
"about fontconfig can be found in the fontconfig(3) manual\n"
- "page and on http://fontconfig.org\n");
+ "page and on http://fontconfig.org");
- /* There is no point in proceeding; we'll just get a segfault later
- * on, and a bunch more possibly confusing error messages in between.
- */
-
- /* return NULL; */
- exit (1);
+ font_patterns = FcFontSetCreate ();
}
patterns = g_slice_new (PangoFcPatternSet);
diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h
index 8388ec9f..cf00d38e 100644
--- a/pango/pangoft2-private.h
+++ b/pango/pangoft2-private.h
@@ -115,12 +115,4 @@ GType pango_ft2_renderer_get_type (void) G_GNUC_CONST;
PangoRenderer *_pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap);
-typedef struct _PangoFT2WarningHistory PangoFT2WarningHistory;
-
-struct _PangoFT2WarningHistory {
- guint get_face : 1;
-};
-
-extern PangoFT2WarningHistory _pango_ft2_warning_history;
-
#endif /* __PANGOFT2_PRIVATE_H__ */
diff --git a/pango/pangoft2-render.c b/pango/pangoft2-render.c
index ef052efa..5bf98a20 100644
--- a/pango/pangoft2-render.c
+++ b/pango/pangoft2-render.c
@@ -100,9 +100,10 @@ pango_ft2_free_rendered_glyph (PangoFT2RenderedGlyph *rendered)
}
static PangoFT2RenderedGlyph *
-pango_ft2_font_render_box_glyph (int width,
- int height,
- int top)
+pango_ft2_font_render_box_glyph (int width,
+ int height,
+ int top,
+ gboolean invalid)
{
PangoFT2RenderedGlyph *box;
int i, j, offset1, offset2, line_width;
@@ -150,14 +151,38 @@ pango_ft2_font_render_box_glyph (int width,
}
}
+ if (invalid)
+ {
+ /* XXX This may scrabble memory. Didn't check close enough */
+ int inc = PANGO_SCALE * MAX (width - line_width, 0) / (height + 1);
+ offset1 = PANGO_SCALE;
+ offset2 = PANGO_SCALE * MAX (width - line_width - 1, 0) ;
+ for (i = box->bitmap.pitch;
+ i < (box->bitmap.rows - 1) * box->bitmap.pitch;
+ i += box->bitmap.pitch)
+ {
+ for (j = 0; j < line_width; j++)
+ {
+ box->bitmap.buffer[PANGO_PIXELS (offset1) + i + j] = 0xff;
+ box->bitmap.buffer[PANGO_PIXELS (offset2) + i + j] = 0xff;
+ }
+ offset1 += inc;
+ offset2 -= inc;
+ }
+
+ }
+
return box;
}
static PangoFT2RenderedGlyph *
pango_ft2_font_render_glyph (PangoFont *font,
- int glyph_index)
+ PangoGlyph glyph_index)
{
FT_Face face;
+ gboolean invalid_input;
+
+ invalid_input = glyph_index == PANGO_GLYPH_INVALID_INPUT || (glyph_index & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0x10FFFF;
if (glyph_index & PANGO_GLYPH_UNKNOWN_FLAG)
{
@@ -173,7 +198,8 @@ pango_ft2_font_render_glyph (PangoFont *font,
box = pango_ft2_font_render_box_glyph (PANGO_PIXELS (metrics->approximate_char_width),
PANGO_PIXELS (metrics->ascent + metrics->descent),
- PANGO_PIXELS (metrics->ascent));
+ PANGO_PIXELS (metrics->ascent),
+ invalid_input);
pango_font_metrics_unref (metrics);
return box;
@@ -207,7 +233,8 @@ pango_ft2_font_render_glyph (PangoFont *font,
generic_box:
return pango_ft2_font_render_box_glyph (PANGO_UNKNOWN_GLYPH_WIDTH,
PANGO_UNKNOWN_GLYPH_HEIGHT,
- PANGO_UNKNOWN_GLYPH_HEIGHT);
+ PANGO_UNKNOWN_GLYPH_HEIGHT,
+ invalid_input);
}
}
@@ -231,16 +258,17 @@ pango_ft2_renderer_draw_glyph (PangoRenderer *renderer,
if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
{
- glyph = pango_ft2_get_unknown_glyph (font);
- if (glyph == PANGO_GLYPH_EMPTY)
- {
- /* No unknown glyph found for the font, draw a box */
+ /* Since we don't draw hexbox for FT2 renderer,
+ * unifiy the rendered bitmap in the cache by converting
+ * all missing glyphs to either INVALID_INPUT or UNKNOWN_FLAG.
+ */
- /* Since we only draw an empty box for FT2 renderer,
- * we unify the rendered bitmaps in the cache.
- */
- glyph = PANGO_GLYPH_UNKNOWN_FLAG;
- }
+ gunichar wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG);
+
+ if (G_UNLIKELY (glyph == PANGO_GLYPH_INVALID_INPUT || wc > 0x10FFFF))
+ glyph = PANGO_GLYPH_INVALID_INPUT;
+ else
+ glyph = PANGO_GLYPH_UNKNOWN_FLAG;
}
rendered_glyph = _pango_ft2_font_get_cache_glyph_data (font, glyph);
diff --git a/pango/pangoft2.c b/pango/pangoft2.c
index f2d85af9..ff3ca319 100644
--- a/pango/pangoft2.c
+++ b/pango/pangoft2.c
@@ -33,8 +33,6 @@
#include "pangofc-fontmap.h"
#include "pangofc-private.h"
-PangoFT2WarningHistory _pango_ft2_warning_history = { FALSE };
-
/* for compatibility with older freetype versions */
#ifndef FT_LOAD_TARGET_MONO
#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
@@ -161,7 +159,8 @@ set_transform (PangoFT2Font *ft2font)
* face from pango_fc_font_lock_face() you must call
* pango_fc_font_unlock_face().
*
- * Return value: a pointer to a <type>FT_Face</type> structure, with the size set correctly
+ * Return value: a pointer to a <type>FT_Face</type> structure, with the size set correctly,
+ * or %NULL if @font is %NULL.
**/
FT_Face
pango_ft2_font_get_face (PangoFont *font)
@@ -175,15 +174,8 @@ pango_ft2_font_get_face (PangoFont *font)
int hintstyle;
int id;
- if (G_UNLIKELY (!PANGO_FT2_IS_FONT (font)))
- {
- if (!_pango_ft2_warning_history.get_face)
- {
- _pango_ft2_warning_history.get_face = TRUE;
- g_warning ("pango_ft2_font_get_face called with bad font, expect ugly output");
- }
- return NULL;
- }
+ if (G_UNLIKELY (!font))
+ return NULL;
pattern = fcfont->font_pattern;
@@ -336,40 +328,35 @@ pango_ft2_font_get_glyph_extents (PangoFont *font,
if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
{
- glyph = pango_ft2_get_unknown_glyph (font);
- if (glyph == PANGO_GLYPH_EMPTY)
- {
- /* No unknown glyph found for the font, draw a box */
- PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
+ PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
- if (metrics)
+ if (metrics)
+ {
+ if (ink_rect)
{
- if (ink_rect)
- {
- ink_rect->x = PANGO_SCALE;
- ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
- ink_rect->y = - (metrics->ascent - PANGO_SCALE);
- ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
- }
- if (logical_rect)
- {
- logical_rect->x = 0;
- logical_rect->width = metrics->approximate_char_width;
- logical_rect->y = -metrics->ascent;
- logical_rect->height = metrics->ascent + metrics->descent;
- }
-
- pango_font_metrics_unref (metrics);
+ ink_rect->x = PANGO_SCALE;
+ ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
+ ink_rect->y = - (metrics->ascent - PANGO_SCALE);
+ ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
}
- else
+ if (logical_rect)
{
- if (ink_rect)
- ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
- if (logical_rect)
- logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
+ logical_rect->x = 0;
+ logical_rect->width = metrics->approximate_char_width;
+ logical_rect->y = -metrics->ascent;
+ logical_rect->height = metrics->ascent + metrics->descent;
}
- return;
+
+ pango_font_metrics_unref (metrics);
+ }
+ else
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
+ if (logical_rect)
+ logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
}
+ return;
}
info = pango_ft2_font_get_glyph_info (font, glyph, TRUE);
diff --git a/pango/pangox.c b/pango/pangox.c
index 924164d3..bf2f12cd 100644
--- a/pango/pangox.c
+++ b/pango/pangox.c
@@ -117,10 +117,7 @@ pango_x_find_subfont (PangoFont *font,
PangoXFont *xfont = (PangoXFont *)font;
if (subfont_index < 1 || subfont_index > xfont->n_subfonts)
- {
- g_warning ("Invalid subfont %d", subfont_index);
- return NULL;
- }
+ return NULL;
return xfont->subfonts[subfont_index-1];
}
@@ -411,7 +408,7 @@ pango_x_render (Display *display,
glyph_y >= -16384 && glyph_y <= 32767))
goto next_glyph;
- if ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0)
+ if (G_LIKELY ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0))
{
guint16 index = PANGO_X_GLYPH_INDEX (glyph);
guint16 subfont_index = PANGO_X_GLYPH_SUBFONT (glyph);
@@ -455,6 +452,7 @@ pango_x_render (Display *display,
int baseline;
int stroke_thick;
gunichar wc;
+ gboolean invalid_input;
unknown_glyph:
FLUSH;
@@ -479,12 +477,13 @@ pango_x_render (Display *display,
x2 = x1 + PANGO_PIXELS (glyphs->glyphs[i].geometry.width);
baseline = glyph_y;
- stroke_thick = MAX ((int) (0.5 + 0.075 * (y2 - y1)), 1);
+ stroke_thick = MAX ((int) (0.5 + 0.025 * (y2 - y1)), 1);
if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG);
+ wc = glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
else
wc = 0;
+ invalid_input = glyph == PANGO_GLYPH_INVALID_INPUT || wc > 0x10FFFF;
switch (wc)
{
@@ -544,7 +543,7 @@ pango_x_render (Display *display,
default:
{
/* Perhaps we should draw the box-with-numbers as in the
- * Xft backend, though we have no guarantee of having
+ * other backends, though we have no guarantee of having
* an appropriate size of font. Right now, we just
* draw an empty box. (To draw the box-with-numbers.
* the backends would have to be changed to use
@@ -572,6 +571,15 @@ pango_x_render (Display *display,
XFillRectangle (display, d, gc,
x1, y2 - stroke_thick,
x2 - x1, stroke_thick);
+ if (invalid_input)
+ {
+ XDrawLine (display, d, gc,
+ x1, y1,
+ x2-1, y2-1);
+ XDrawLine (display, d, gc,
+ x2-1, y1,
+ x1, y2-1);
+ }
break;
}
diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c
index 73e87104..2dc14452 100644
--- a/pango/pangoxft-font.c
+++ b/pango/pangoxft-font.c
@@ -27,8 +27,6 @@
#include "pangoxft-private.h"
#include "pangofc-private.h"
-PangoXftWarningHistory _pango_xft_warning_history = { FALSE };
-
#define PANGO_XFT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
#define PANGO_XFT_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT))
#define PANGO_XFT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
@@ -153,12 +151,12 @@ _pango_xft_font_get_mini_font (PangoXftFont *xfont)
pango_font_description_set_size (desc, new_size);
xfont->mini_font = pango_font_map_load_font (fcfont->fontmap, context, desc);
- if (!xfont->mini_font)
- return NULL;
-
pango_font_description_free (desc);
g_object_unref (context);
+ if (!xfont->mini_font)
+ return NULL;
+
mini_xft = xft_font_get_font (xfont->mini_font);
for (i = 0 ; i < 16 ; i++)
@@ -169,7 +167,6 @@ _pango_xft_font_get_mini_font (PangoXftFont *xfont)
height = MAX (height, extents.height);
}
-
xfont->mini_width = PANGO_SCALE * width;
xfont->mini_height = PANGO_SCALE * height;
xfont->mini_pad = PANGO_SCALE * MIN (height / 2, MAX ((int)(2.2 * height + 27) / 28, 1));
@@ -210,8 +207,15 @@ get_glyph_extents_missing (PangoXftFont *xfont,
{
PangoFont *font = PANGO_FONT (xfont);
XftFont *xft_font = xft_font_get_font (font);
+ gunichar ch;
+ gint cols;
+
+ ch = glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
- gint cols = (glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 3 : 2;
+ if (G_UNLIKELY (glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF))
+ cols = 1;
+ else
+ cols = ch > 0xffff ? 3 : 2;
_pango_xft_font_get_mini_font (xfont);
@@ -463,20 +467,13 @@ pango_xft_font_real_shutdown (PangoFcFont *fcfont)
*
* Returns the XftFont of a font.
*
- * Return value: the XftFont associated to @font.
+ * Return value: the XftFont associated to @font, or %NULL if @font is %NULL.
**/
XftFont *
pango_xft_font_get_font (PangoFont *font)
{
- if (G_UNLIKELY (!PANGO_XFT_IS_FONT (font)))
- {
- if (!_pango_xft_warning_history.get_font)
- {
- _pango_xft_warning_history.get_font = TRUE;
- g_warning ("pango_xft_font_get_font called with bad font, expect ugly output");
- }
- return NULL;
- }
+ if (G_UNLIKELY (!font))
+ return NULL;
return xft_font_get_font (font);
}
diff --git a/pango/pangoxft-private.h b/pango/pangoxft-private.h
index 1ee2da68..fb1c2444 100644
--- a/pango/pangoxft-private.h
+++ b/pango/pangoxft-private.h
@@ -34,9 +34,9 @@ struct _PangoXftFont
XftFont *xft_font; /* created on demand */
PangoFont *mini_font; /* font used to display missing glyphs */
- guint16 mini_width; /* metrics for missing glyph drawing */
- guint16 mini_height;
- guint16 mini_pad;
+ guint mini_width; /* metrics for missing glyph drawing */
+ guint mini_height;
+ guint mini_pad;
GHashTable *glyph_info; /* Used only when we can't get
* glyph extents out of Xft because
@@ -55,14 +55,6 @@ PangoRenderer *_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap);
PangoFont *_pango_xft_font_get_mini_font (PangoXftFont *xfont);
-typedef struct _PangoXftWarningHistory PangoXftWarningHistory;
-
-struct _PangoXftWarningHistory {
- guint get_font : 1;
-};
-
-extern PangoXftWarningHistory _pango_xft_warning_history;
-
G_END_DECLS
#endif /* __PANGOXFT_PRIVATE_H__ */
diff --git a/pango/pangoxft-render.c b/pango/pangoxft-render.c
index efaae64e..5505ba5c 100644
--- a/pango/pangoxft-render.c
+++ b/pango/pangoxft-render.c
@@ -290,12 +290,31 @@ box_in_bounds (PangoRenderer *renderer,
}
static void
+get_total_matrix (PangoMatrix *total,
+ const PangoMatrix *global,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ PangoMatrix local = PANGO_MATRIX_INIT;
+ gdouble angle = atan2 (height, width);
+
+ pango_matrix_translate (&local, x, y);
+ pango_matrix_rotate (&local, -angle * (180. / G_PI));
+
+ *total = *global;
+ pango_matrix_concat (total, &local);
+}
+
+static void
draw_box (PangoRenderer *renderer,
gint line_width,
gint x,
gint y,
gint width,
- gint height)
+ gint height,
+ gboolean invalid)
{
pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
x, y, width, line_width);
@@ -305,13 +324,49 @@ draw_box (PangoRenderer *renderer,
x + width - line_width, y + line_width, line_width, height - line_width * 2);
pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
x, y + height - line_width, width, line_width);
+
+ if (invalid)
+ {
+ int length;
+ double in_width, in_height;
+ PangoMatrix orig_matrix = PANGO_MATRIX_INIT, new_matrix;
+ const PangoMatrix *porig_matrix;
+
+ in_width = pango_units_to_double (width - 2 * line_width);
+ in_height = pango_units_to_double (height - 2 * line_width);
+ length = PANGO_SCALE * sqrt (in_width*in_width + in_height*in_height);
+
+ porig_matrix = pango_renderer_get_matrix (renderer);
+ if (porig_matrix)
+ {
+ orig_matrix = *porig_matrix;
+ porig_matrix = &orig_matrix;
+ }
+
+ get_total_matrix (&new_matrix, &orig_matrix,
+ pango_units_to_double (x + line_width), pango_units_to_double (y + line_width),
+ in_width, in_height);
+ pango_renderer_set_matrix (renderer, &new_matrix);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ 0, -line_width / 2, length, line_width);
+
+ get_total_matrix (&new_matrix, &orig_matrix,
+ pango_units_to_double (x + line_width), pango_units_to_double (y + height - line_width),
+ in_width, -in_height);
+ pango_renderer_set_matrix (renderer, &new_matrix);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ 0, -line_width / 2, length, line_width);
+
+ pango_renderer_set_matrix (renderer, porig_matrix);
+ }
}
static void
_pango_xft_renderer_draw_box_glyph (PangoRenderer *renderer,
PangoGlyphInfo *gi,
int glyph_x,
- int glyph_y)
+ int glyph_y,
+ gboolean invalid)
{
int x = glyph_x + PANGO_SCALE;
int y = glyph_y - PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT - 1);
@@ -319,7 +374,7 @@ _pango_xft_renderer_draw_box_glyph (PangoRenderer *renderer,
int height = PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT - 2);
if (box_in_bounds (renderer, x, y, width, height))
- draw_box (renderer, PANGO_SCALE, x, y, width, height);
+ draw_box (renderer, PANGO_SCALE, x, y, width, height, invalid);
}
static void
@@ -335,17 +390,33 @@ _pango_xft_renderer_draw_unknown_glyph (PangoRenderer *renderer,
int xs[4];
int row, col;
int cols;
- PangoGlyph glyph;
+ gunichar ch;
+ gboolean invalid_input;
+
+ PangoFont *mini_font;
+ XftFont *mini_xft_font;
- PangoFont *mini_font = _pango_xft_font_get_mini_font (xfont);
- XftFont *mini_xft_font = pango_xft_font_get_font (mini_font);
+ ch = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
+ if (G_UNLIKELY (gi->glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF))
+ {
+ invalid_input = TRUE;
+ cols = 1;
+ }
+ else
+ {
+ invalid_input = FALSE;
+ cols = ch > 0xffff ? 3 : 2;
+ g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);
+ }
+
+ mini_font = _pango_xft_font_get_mini_font (xfont);
+ mini_xft_font = pango_xft_font_get_font (mini_font);
if (!mini_xft_font)
{
- _pango_xft_renderer_draw_box_glyph (renderer, gi, glyph_x, glyph_y);
+ _pango_xft_renderer_draw_box_glyph (renderer, gi, glyph_x, glyph_y, invalid_input);
return;
}
- glyph = gi->glyph & ~PANGO_GLYPH_UNKNOWN_FLAG;
ys[0] = glyph_y - PANGO_SCALE * xft_font->ascent + PANGO_SCALE * (((xft_font->ascent + xft_font->descent) - (xfont->mini_height * 2 + xfont->mini_pad * 5 + PANGO_SCALE / 2) / PANGO_SCALE) / 2);
ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
@@ -356,17 +427,6 @@ _pango_xft_renderer_draw_unknown_glyph (PangoRenderer *renderer,
xs[2] = xs[1] + xfont->mini_width + xfont->mini_pad;
xs[3] = xs[2] + xfont->mini_width + xfont->mini_pad;
- if (glyph > 0xffff)
- {
- cols = 3;
- g_snprintf (buf, sizeof(buf), "%06X", glyph);
- }
- else
- {
- cols = 2;
- g_snprintf (buf, sizeof(buf), "%04X", glyph);
- }
-
if (box_in_bounds (renderer,
xs[0], ys[0],
xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
@@ -376,7 +436,11 @@ _pango_xft_renderer_draw_unknown_glyph (PangoRenderer *renderer,
draw_box (renderer, xfont->mini_pad,
xs[0], ys[0],
xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
- xfont->mini_height * 2 + xfont->mini_pad * 5);
+ xfont->mini_height * 2 + xfont->mini_pad * 5,
+ invalid_input);
+
+ if (invalid_input)
+ return;
for (row = 0; row < 2; row++)
for (col = 0; col < cols; col++)
@@ -414,7 +478,12 @@ pango_xft_renderer_draw_glyphs (PangoRenderer *renderer,
int glyph_x = x + x_off + gi->geometry.x_offset;
int glyph_y = y + gi->geometry.y_offset;
- _pango_xft_renderer_draw_box_glyph (renderer, gi, glyph_x, glyph_y);
+ _pango_xft_renderer_draw_unknown_glyph (renderer,
+ xfont,
+ xft_font,
+ gi,
+ glyph_x,
+ glyph_y);
}
x_off += gi->geometry.width;
diff --git a/pango/shape.c b/pango/shape.c
index 1fd2d814..d0be6da5 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -50,7 +50,7 @@ pango_shape (const gchar *text,
glyphs->num_glyphs = 0;
- if (G_LIKELY (PANGO_IS_ENGINE_SHAPE (analysis->shape_engine) && PANGO_IS_FONT (analysis->font)))
+ if (G_LIKELY (analysis->shape_engine && analysis->font))
{
_pango_engine_shape_shape (analysis->shape_engine, analysis->font,
text, length, analysis, glyphs);
@@ -106,22 +106,7 @@ pango_shape (const gchar *text,
}
}
else
- {
- if (!PANGO_IS_ENGINE_SHAPE (analysis->shape_engine) &&
- !_pango_warning_history.shape_shape_engine)
- {
- _pango_warning_history.shape_shape_engine = TRUE;
- g_warning ("pango_shape called with bad shape_engine, expect ugly output");
- }
- if (!PANGO_IS_FONT (analysis->font) &&
- !_pango_warning_history.shape_font)
- {
- _pango_warning_history.shape_font = TRUE;
- g_warning ("pango_shape called with bad font, expect ugly output");
- }
-
- glyphs->num_glyphs = 0;
- }
+ glyphs->num_glyphs = 0;
if (!glyphs->num_glyphs)
{