summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2007-01-16 09:52:02 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2007-01-16 09:52:02 +0000
commit56e7902a63f2036ea46a386c9d80827d6420f143 (patch)
tree6363106a16cc800436c945d09d88bbad951b5997
parent7a102793913cb7a1a0eefbbfc9d5c0d04c9eb868 (diff)
downloadpango-56e7902a63f2036ea46a386c9d80827d6420f143.tar.gz
New attribute types PANGO_ATTR_GRAVITY and PANGO_ATTR_GRAVITY_HINT. New
2007-01-16 Behdad Esfahbod <behdad@gnome.org> * pango/pango-attributes.h: * pango/pango-attributes.c: New attribute types PANGO_ATTR_GRAVITY and PANGO_ATTR_GRAVITY_HINT. New public functions: pango_attr_gravity_new() pango_attr_gravity_hint_new() * pango/pango-context.c (update_attr_iterator), (itemize_state_init), (itemize_state_add_character), (get_shaper_and_font), (itemize_state_update_for_new_run): Handle gravity and gravity_hint attributes. * pango/pango-utils.h: * pango/pango-utils.c: New public function: pango_parse_enum() * pango/pango-markup.c (span_parse_func): Parse gravity and gravity_hint attributes for <span>. Optimize a bit. * pango/pango-markup.c (parse_absolute_size), (attr_strcmp), (span_parse_int), (span_parse_boolean), (span_parse_color), (span_parse_enum), (span_parse_func): Use pango_scan_int(), pango_color_parse(), and pango_parse_enum(). Also, ignore '-' and '_' differences when matching attribute names for <span>. * examples/renderdemo.c (parse_enum), (parse_ellipsis), (parse_gravity), (parse_gravity_hint), (parse_hinting), (parse_wrap): Use a generic parse_enum() that uses pango_parse_enum(). * modules/basic/basic-fc.c (basic_engine_shape): * pango/pangofc-fontmap.c (pango_fc_make_pattern): Use PANGO_GRAVITY_IS_VERTICAL(). * pango/pango.def: * docs/pango-sections.txt: * docs/tmpl/text-attributes.sgml: * docs/tmpl/utils.sgml: Update. svn path=/trunk/; revision=2145
-rw-r--r--ChangeLog44
-rw-r--r--docs/pango-sections.txt5
-rw-r--r--docs/tmpl/text-attributes.sgml38
-rw-r--r--docs/tmpl/utils.sgml13
-rw-r--r--examples/renderdemo.c122
-rw-r--r--modules/basic/basic-fc.c13
-rw-r--r--pango/pango-attributes.c55
-rw-r--r--pango/pango-attributes.h11
-rw-r--r--pango/pango-context.c60
-rw-r--r--pango/pango-markup.c527
-rw-r--r--pango/pango-utils.c78
-rw-r--r--pango/pango-utils.h6
-rw-r--r--pango/pango.def3
-rw-r--r--pango/pangofc-fontmap.c13
14 files changed, 587 insertions, 401 deletions
diff --git a/ChangeLog b/ChangeLog
index 32f4602b..180abbb3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+2007-01-16 Behdad Esfahbod <behdad@gnome.org>
+
+ * pango/pango-attributes.h:
+ * pango/pango-attributes.c:
+ New attribute types PANGO_ATTR_GRAVITY and PANGO_ATTR_GRAVITY_HINT.
+ New public functions:
+
+ pango_attr_gravity_new()
+ pango_attr_gravity_hint_new()
+
+ * pango/pango-context.c (update_attr_iterator),
+ (itemize_state_init), (itemize_state_add_character),
+ (get_shaper_and_font), (itemize_state_update_for_new_run):
+ Handle gravity and gravity_hint attributes.
+
+ * pango/pango-utils.h:
+ * pango/pango-utils.c:
+ New public function:
+
+ pango_parse_enum()
+
+ * pango/pango-markup.c (span_parse_func): Parse gravity and
+ gravity_hint attributes for <span>. Optimize a bit.
+
+ * pango/pango-markup.c (parse_absolute_size), (attr_strcmp),
+ (span_parse_int), (span_parse_boolean), (span_parse_color),
+ (span_parse_enum), (span_parse_func): Use pango_scan_int(),
+ pango_color_parse(), and pango_parse_enum(). Also, ignore '-' and
+ '_' differences when matching attribute names for <span>.
+
+ * examples/renderdemo.c (parse_enum), (parse_ellipsis),
+ (parse_gravity), (parse_gravity_hint), (parse_hinting),
+ (parse_wrap): Use a generic parse_enum() that uses pango_parse_enum().
+
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * pango/pangofc-fontmap.c (pango_fc_make_pattern):
+ Use PANGO_GRAVITY_IS_VERTICAL().
+
+ * pango/pango.def:
+ * docs/pango-sections.txt:
+ * docs/tmpl/text-attributes.sgml:
+ * docs/tmpl/utils.sgml:
+ Update.
+
2007-01-15 Behdad Esfahbod <behdad@gnome.org>
Bug 323173 – Add layout of mixed direction text for vertical layout
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 64da609e..d9d68e9c 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -345,7 +345,6 @@ pango_attr_shape_new
pango_attr_shape_new_with_data
PangoAttrDataCopyFunc
pango_attr_scale_new
-pango_attr_fallback_new
PANGO_SCALE_XX_SMALL
PANGO_SCALE_X_SMALL
PANGO_SCALE_SMALL
@@ -355,6 +354,9 @@ PANGO_SCALE_X_LARGE
PANGO_SCALE_XX_LARGE
pango_attr_rise_new
pango_attr_letter_spacing_new
+pango_attr_fallback_new
+pango_attr_gravity_new
+pango_attr_gravity_hint_new
PangoColor
PANGO_TYPE_COLOR
pango_color_parse
@@ -964,6 +966,7 @@ pango_scan_string
pango_scan_int
pango_config_key_get
pango_lookup_aliases
+pango_parse_enum
pango_parse_style
pango_parse_variant
pango_parse_weight
diff --git a/docs/tmpl/text-attributes.sgml b/docs/tmpl/text-attributes.sgml
index bcb109c6..79f9ac94 100644
--- a/docs/tmpl/text-attributes.sgml
+++ b/docs/tmpl/text-attributes.sgml
@@ -52,6 +52,8 @@ attribute is listed in parentheses after the description.
@PANGO_ATTR_UNDERLINE_COLOR: underline color (#PangoAttrColor)
@PANGO_ATTR_STRIKETHROUGH_COLOR: strikethrough color (#PangoAttrColor)
@PANGO_ATTR_ABSOLUTE_SIZE: font size in pixels scaled by %PANGO_SCALE (#PangoAttrInt)
+@PANGO_ATTR_GRAVITY: base text gravity (#PangoAttrInt)
+@PANGO_ATTR_GRAVITY_HINT: gravity hint (#PangoAttrInt)
<!-- ##### MACRO PANGO_TYPE_ATTR_TYPE ##### -->
<para>
@@ -434,15 +436,6 @@ user data.
@Returns:
-<!-- ##### FUNCTION pango_attr_fallback_new ##### -->
-<para>
-
-</para>
-
-@enable_fallback:
-@Returns:
-
-
<!-- ##### MACRO PANGO_SCALE_XX_SMALL ##### -->
<para>
The scale factor for three shrinking steps (1 / (1.2 * 1.2 * 1.2)).
@@ -510,6 +503,33 @@ The scale factor for three magnification steps (1.2 * 1.2 * 1.2).
@Returns:
+<!-- ##### FUNCTION pango_attr_fallback_new ##### -->
+<para>
+
+</para>
+
+@enable_fallback:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_gravity_new ##### -->
+<para>
+
+</para>
+
+@gravity:
+@Returns:
+
+
+<!-- ##### FUNCTION pango_attr_gravity_hint_new ##### -->
+<para>
+
+</para>
+
+@hint:
+@Returns:
+
+
<!-- ##### STRUCT PangoColor ##### -->
<para>
The #PangoColor structure is used to
diff --git a/docs/tmpl/utils.sgml b/docs/tmpl/utils.sgml
index d836f661..f53c776f 100644
--- a/docs/tmpl/utils.sgml
+++ b/docs/tmpl/utils.sgml
@@ -104,6 +104,19 @@ backends and modules, but may be useful for other purposes too.
@n_families:
+<!-- ##### FUNCTION pango_parse_enum ##### -->
+<para>
+
+</para>
+
+@type:
+@str:
+@value:
+@warn:
+@possible_values:
+@Returns:
+
+
<!-- ##### FUNCTION pango_parse_style ##### -->
<para>
diff --git a/examples/renderdemo.c b/examples/renderdemo.c
index 21773e4e..75a5ca4a 100644
--- a/examples/renderdemo.c
+++ b/examples/renderdemo.c
@@ -333,61 +333,57 @@ do_output (PangoContext *context,
pango_matrix_free (orig_matrix);
}
-
static gboolean
-parse_ellipsis (const char *name,
- const char *arg,
- gpointer data,
- GError **error)
+parse_enum (GType *type,
+ int *value,
+ const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
{
- static GEnumClass *class = NULL;
- gboolean ret = TRUE;
- GEnumValue *value;
+ char *possible_values = NULL;
+ gboolean ret;
- if (!class)
- class = g_type_class_ref (PANGO_TYPE_ELLIPSIZE_MODE);
+ ret = pango_parse_enum (type,
+ arg,
+ value,
+ FALSE,
+ &possible_values);
- value = g_enum_get_value_by_nick (class, arg);
- if (value)
- opt_ellipsize = value->value;
- else
+ if (!ret && error)
{
- g_set_error(error,
- G_OPTION_ERROR,
- G_OPTION_ERROR_BAD_VALUE,
- "Argument for --ellipsize must be one of none/start/middle/end");
- ret = FALSE;
+ g_set_error(error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ "Argument for %s must be one of %s",
+ name,
+ possible_values);
+ ret = FALSE;
}
+ g_free (possible_values);
+
return ret;
}
static gboolean
+parse_ellipsis (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ return parse_enum (PANGO_TYPE_ELLIPSIZE_MODE, &opt_ellipsize,
+ name, arg, data, error);
+}
+
+static gboolean
parse_gravity (const char *name,
const char *arg,
gpointer data,
GError **error)
{
- static GEnumClass *class = NULL;
- gboolean ret = TRUE;
- GEnumValue *value;
-
- if (!class)
- class = g_type_class_ref (PANGO_TYPE_GRAVITY);
-
- value = g_enum_get_value_by_nick (class, arg);
- if (value)
- opt_gravity = value->value;
- else
- {
- g_set_error(error,
- G_OPTION_ERROR,
- G_OPTION_ERROR_BAD_VALUE,
- "Argument for --gravity must be one of south/east/north/west/auto");
- ret = FALSE;
- }
-
- return ret;
+ return parse_enum (PANGO_TYPE_GRAVITY, &opt_gravity,
+ name, arg, data, error);
}
static gboolean
@@ -396,26 +392,8 @@ parse_gravity_hint (const char *name,
gpointer data,
GError **error)
{
- static GEnumClass *class = NULL;
- gboolean ret = TRUE;
- GEnumValue *value;
-
- if (!class)
- class = g_type_class_ref (PANGO_TYPE_GRAVITY_HINT);
-
- value = g_enum_get_value_by_nick (class, arg);
- if (value)
- opt_gravity_hint = value->value;
- else
- {
- g_set_error(error,
- G_OPTION_ERROR,
- G_OPTION_ERROR_BAD_VALUE,
- "Argument for --gravity-hint must be one of natural/strong/line");
- ret = FALSE;
- }
-
- return ret;
+ return parse_enum (PANGO_TYPE_GRAVITY_HINT, &opt_gravity_hint,
+ name, arg, data, error);
}
static gboolean
@@ -424,12 +402,8 @@ parse_hinting (const char *name,
gpointer data,
GError **error)
{
- static GEnumClass *class = NULL;
gboolean ret = TRUE;
- if (!class)
- class = g_type_class_ref (PANGO_TYPE_ELLIPSIZE_MODE);
-
if (strcmp (arg, "none") == 0)
opt_hinting = HINT_NONE;
else if (strcmp (arg, "auto") == 0)
@@ -454,28 +428,12 @@ parse_wrap (const char *name,
gpointer data,
GError **error)
{
- static GEnumClass *class = NULL;
- gboolean ret = TRUE;
- GEnumValue *value;
-
- if (!class)
- class = g_type_class_ref (PANGO_TYPE_WRAP_MODE);
-
- value = g_enum_get_value_by_nick (class, arg);
- if (value)
+ gboolean ret;
+ if ((ret = parse_enum (PANGO_TYPE_WRAP_MODE, &opt_wrap,
+ name, arg, data, error)))
{
- opt_wrap = value->value;
opt_wrap_set = TRUE;
}
- else
- {
- g_set_error(error,
- G_OPTION_ERROR,
- G_OPTION_ERROR_BAD_VALUE,
- "Argument for --wrap must be one of word/char/word-char");
- ret = FALSE;
- }
-
return ret;
}
diff --git a/modules/basic/basic-fc.c b/modules/basic/basic-fc.c
index 3551e282..81a90360 100644
--- a/modules/basic/basic-fc.c
+++ b/modules/basic/basic-fc.c
@@ -332,18 +332,7 @@ basic_engine_shape (PangoEngineShape *engine,
if (!face)
return;
- switch (analysis->gravity)
- {
- case PANGO_GRAVITY_SOUTH:
- case PANGO_GRAVITY_NORTH:
- default:
- vertical = FALSE;
- break;
- case PANGO_GRAVITY_EAST:
- case PANGO_GRAVITY_WEST:
- vertical = TRUE;
- break;
- }
+ vertical = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity);
if (vertical)
{
fallback_shape (engine, font, text, length, analysis, glyphs);
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 7f997461..ea46dd6a 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -968,6 +968,61 @@ pango_attr_shape_new (const PangoRectangle *ink_rect,
NULL, NULL, NULL);
}
+/**
+ * pango_attr_gravity_new:
+ * @gravity: the gravity value; should not be %PANGO_GRAVITY_AUTO.
+ *
+ * Create a new gravity attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.16
+ **/
+PangoAttribute *
+pango_attr_gravity_new (PangoGravity gravity)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_GRAVITY,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, NULL);
+
+ return pango_attr_int_new (&klass, (int)gravity);
+}
+
+/**
+ * pango_attr_gravity_hint_new:
+ * @hint: the gravity hint value.
+ *
+ * Create a new gravity hint attribute.
+ *
+ * Return value: the newly allocated #PangoAttribute, which should be
+ * freed with pango_attribute_destroy().
+ *
+ * Since: 1.16
+ **/
+PangoAttribute *
+pango_attr_gravity_hint_new (PangoGravityHint hint)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_GRAVITY_HINT,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, (int)hint);
+}
+
+
+/*
+ * Attribute List
+ */
+
GType
pango_attr_list_get_type (void)
{
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 4dc31af6..3c07275e 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -86,9 +86,11 @@ typedef enum
PANGO_ATTR_SCALE, /* PangoAttrFloat */
PANGO_ATTR_FALLBACK, /* PangoAttrInt */
PANGO_ATTR_LETTER_SPACING, /* PangoAttrInt */
- PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */
- PANGO_ATTR_STRIKETHROUGH_COLOR, /* PangoAttrColor */
- PANGO_ATTR_ABSOLUTE_SIZE /* PangoAttrSize */
+ PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */
+ PANGO_ATTR_STRIKETHROUGH_COLOR,/* PangoAttrColor */
+ PANGO_ATTR_ABSOLUTE_SIZE, /* PangoAttrSize */
+ PANGO_ATTR_GRAVITY, /* PangoAttrInt */
+ PANGO_ATTR_GRAVITY_HINT /* PangoAttrInt */
} PangoAttrType;
typedef enum {
@@ -219,6 +221,9 @@ PangoAttribute *pango_attr_shape_new_with_data (const PangoRectangle *ink_
PangoAttrDataCopyFunc copy_func,
GDestroyNotify destroy_func);
+PangoAttribute *pango_attr_gravity_new (PangoGravity gravity);
+PangoAttribute *pango_attr_gravity_hint_new (PangoGravityHint hint);
+
GType pango_attr_list_get_type (void) G_GNUC_CONST;
PangoAttrList * pango_attr_list_new (void);
PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 32197e5f..53b86302 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -663,6 +663,8 @@ struct _ItemizeState
guint8 embedding;
PangoGravity gravity;
+ PangoGravityHint gravity_hint;
+ PangoGravity resolved_gravity;
PangoGravity font_desc_gravity;
gboolean centered_baseline;
@@ -723,7 +725,7 @@ static void
update_attr_iterator (ItemizeState *state)
{
PangoLanguage *old_lang;
- PangoAttribute *fallback;
+ PangoAttribute *attr;
int end_index;
pango_attr_iterator_range (state->attr_iter, NULL, &end_index);
@@ -748,8 +750,14 @@ update_attr_iterator (ItemizeState *state)
if (!state->lang)
state->lang = state->context->language;
- fallback = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK);
- state->enable_fallback = (fallback == NULL || ((PangoAttrInt *)fallback)->value);
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK);
+ state->enable_fallback = (attr == NULL || ((PangoAttrInt *)attr)->value);
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY);
+ state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : ((PangoAttrInt *)attr)->value;
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY_HINT);
+ state->gravity_hint = attr == NULL ? state->context->gravity_hint : ((PangoAttrInt *)attr)->value;
state->changed |= FONT_CHANGED;
if (state->lang != old_lang)
@@ -850,6 +858,8 @@ itemize_state_init (ItemizeState *state,
state->font_desc_gravity = PANGO_GRAVITY_AUTO;
state->gravity = PANGO_GRAVITY_AUTO;
+ state->gravity_hint = state->context->gravity_hint;
+ state->resolved_gravity = PANGO_GRAVITY_AUTO;
state->derived_lang = NULL;
state->lang_engine = NULL;
state->current_fonts = NULL;
@@ -970,7 +980,7 @@ itemize_state_add_character (ItemizeState *state,
state->item->analysis.font = font;
state->item->analysis.level = state->embedding;
- state->item->analysis.gravity = state->gravity;
+ state->item->analysis.gravity = state->resolved_gravity;
/* The level vs. gravity dance:
* - If gravity is SOUTH, leave level untouched.
@@ -1099,19 +1109,10 @@ get_shaper_and_font (ItemizeState *state,
*/
PangoScript script;
- switch (state->gravity)
- {
- case PANGO_GRAVITY_SOUTH:
- case PANGO_GRAVITY_NORTH:
- case PANGO_GRAVITY_AUTO:
- default:
- script = state->script;
- break;
- case PANGO_GRAVITY_EAST:
- case PANGO_GRAVITY_WEST:
- script = PANGO_SCRIPT_COMMON;
- break;
- }
+ 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);
@@ -1212,25 +1213,34 @@ get_lang_map (PangoLanguage *lang)
static void
itemize_state_update_for_new_run (ItemizeState *state)
{
+ /* This block should be moved to update_attr_iterator, but I'm too lazy to
+ * do it right now */
if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED))
{
- PangoGravity old_gravity = state->gravity;
+ PangoGravity old_gravity = state->resolved_gravity;
if (state->font_desc_gravity != PANGO_GRAVITY_AUTO)
- state->gravity = state->font_desc_gravity;
+ state->resolved_gravity = state->font_desc_gravity;
else
{
- PangoGravity gravity = state->context->resolved_gravity;
+ PangoGravity gravity;
+ PangoGravityHint gravity_hint;
+
+ gravity = state->gravity;
+ if (G_LIKELY (gravity == PANGO_GRAVITY_AUTO))
+ gravity = state->context->resolved_gravity;
+
+ gravity_hint = state->gravity_hint;
gravity = pango_gravity_get_for_script (state->script,
- state->context->resolved_gravity,
- state->context->gravity_hint);
- state->gravity = gravity;
+ gravity,
+ gravity_hint);
+ state->resolved_gravity = gravity;
}
- if (old_gravity != state->gravity)
+ if (old_gravity != state->resolved_gravity)
{
- pango_font_description_set_gravity (state->font_desc, state->gravity);
+ pango_font_description_set_gravity (state->font_desc, state->resolved_gravity);
state->changed |= FONT_CHANGED;
}
}
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index 8f925830..e53bb592 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -26,6 +26,7 @@
#include "pango-attributes.h"
#include "pango-font.h"
+#include "pango-enum-types.h"
#include "pango-impl-utils.h"
/* FIXME */
@@ -783,33 +784,19 @@ parse_absolute_size (OpenTag *tag,
double factor;
if (strcmp (size, "xx-small") == 0)
- {
- level = XXSmall;
- }
+ level = XXSmall;
else if (strcmp (size, "x-small") == 0)
- {
- level = XSmall;
- }
+ level = XSmall;
else if (strcmp (size, "small") == 0)
- {
- level = Small;
- }
+ level = Small;
else if (strcmp (size, "medium") == 0)
- {
- level = Medium;
- }
+ level = Medium;
else if (strcmp (size, "large") == 0)
- {
- level = Large;
- }
+ level = Large;
else if (strcmp (size, "x-large") == 0)
- {
- level = XLarge;
- }
+ level = XLarge;
else if (strcmp (size, "xx-large") == 0)
- {
- level = XXLarge;
- }
+ level = XXLarge;
else
return FALSE;
@@ -824,15 +811,143 @@ parse_absolute_size (OpenTag *tag,
return TRUE;
}
-#define CHECK_DUPLICATE(var) G_STMT_START{ \
- if ((var) != NULL) { \
- g_set_error (error, G_MARKUP_ERROR, \
- G_MARKUP_ERROR_INVALID_CONTENT, \
- _("Attribute '%s' occurs twice on <span> tag " \
- "on line %d char %d, may only occur once"), \
- names[i], line_number, char_number); \
- return FALSE; \
- }}G_STMT_END
+/* a string compare func that ignores '-' vs '_' differences */
+static gint
+attr_strcmp (gconstpointer pa,
+ gconstpointer pb)
+{
+ const char *a = pa;
+ const char *b = pb;
+
+ int ca;
+ int cb;
+
+ while (*a && *b)
+ {
+ ca = *a++;
+ cb = *b++;
+
+ if (ca == cb)
+ continue;
+
+ ca = ca == '_' ? '-' : ca;
+ cb = cb == '_' ? '-' : cb;
+
+ if (ca != cb)
+ return cb - ca;
+ }
+
+ ca = *a;
+ cb = *b;
+
+ return cb - ca;
+}
+
+static gboolean
+span_parse_int (const char *attr_name,
+ const char *attr_val,
+ int *val,
+ int line_number,
+ GError **error)
+{
+ const char *end = attr_val;
+
+ if (!pango_scan_int (&end, val) || *end != '\0')
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "on line %d could not be parsed; "
+ "should be an integer, not '%s'"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_boolean (const char *attr_name,
+ const char *attr_val,
+ gboolean *val,
+ int line_number,
+ GError **error)
+{
+ const char *end = attr_val;
+
+ if (strcmp (attr_val, "true") == 0 ||
+ strcmp (attr_val, "yes") == 0 ||
+ strcmp (attr_val, "t") == 0 ||
+ strcmp (attr_val, "y") == 0)
+ *val = TRUE;
+ else if (strcmp (attr_val, "false") == 0 ||
+ strcmp (attr_val, "no") == 0 ||
+ strcmp (attr_val, "f") == 0 ||
+ strcmp (attr_val, "n") == 0)
+ *val = FALSE;
+ else
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "line %d should have one of "
+ "'true/yes/t/y' or 'false/no/f/n': '%s' is not valid"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_color (const char *attr_name,
+ const char *attr_val,
+ PangoColor *color,
+ int line_number,
+ GError **error)
+{
+ if (!pango_color_parse (color, attr_val))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Value of '%s' attribute on <span> tag "
+ "on line %d could not be parsed; "
+ "should be a color specification, not '%s'"),
+ attr_name, line_number, attr_val);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+span_parse_enum (const char *attr_name,
+ const char *attr_val,
+ GType type,
+ int *val,
+ int line_number,
+ GError **error)
+{
+ char *possible_values = NULL;
+
+ if (!pango_parse_enum (type, attr_val, val, FALSE, &possible_values))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ _("'%s' is not a valid value for the '%s' "
+ "attribute on <span> tag, line %d; valid "
+ "values are %s"),
+ attr_val, attr_name, line_number, possible_values);
+ g_free (possible_values);
+ return FALSE;
+ }
+
+ return TRUE;
+}
static gboolean
span_parse_func (MarkupData *md,
@@ -844,6 +959,7 @@ span_parse_func (MarkupData *md,
{
int line_number, char_number;
int i;
+
const char *family = NULL;
const char *size = NULL;
const char *style = NULL;
@@ -861,101 +977,72 @@ span_parse_func (MarkupData *md,
const char *letter_spacing = NULL;
const char *lang = NULL;
const char *fallback = NULL;
+ const char *gravity = NULL;
+ const char *gravity_hint = NULL;
g_markup_parse_context_get_position (context,
&line_number, &char_number);
+#define CHECK_DUPLICATE(var) G_STMT_START{ \
+ if ((var) != NULL) { \
+ g_set_error (error, G_MARKUP_ERROR, \
+ G_MARKUP_ERROR_INVALID_CONTENT, \
+ _("Attribute '%s' occurs twice on <span> tag " \
+ "on line %d char %d, may only occur once"), \
+ names[i], line_number, char_number); \
+ return FALSE; \
+ }}G_STMT_END
+#define CHECK_ATTRIBUTE2(var, name) \
+ if (attr_strcmp (names[i], (name)) == 0) { \
+ CHECK_DUPLICATE (var); \
+ (var) = values[i]; \
+ found = TRUE; \
+ break; \
+ }
+#define CHECK_ATTRIBUTE(var) CHECK_ATTRIBUTE2 (var, G_STRINGIFY (var))
+
i = 0;
while (names[i])
{
- if (strcmp (names[i], "font_family") == 0 ||
- strcmp (names[i], "face") == 0)
- {
- CHECK_DUPLICATE (family);
- family = values[i];
- }
- else if (strcmp (names[i], "size") == 0)
- {
- CHECK_DUPLICATE (size);
- size = values[i];
- }
- else if (strcmp (names[i], "style") == 0)
- {
- CHECK_DUPLICATE (style);
- style = values[i];
- }
- else if (strcmp (names[i], "weight") == 0)
- {
- CHECK_DUPLICATE (weight);
- weight = values[i];
- }
- else if (strcmp (names[i], "variant") == 0)
- {
- CHECK_DUPLICATE (variant);
- variant = values[i];
- }
- else if (strcmp (names[i], "stretch") == 0)
- {
- CHECK_DUPLICATE (stretch);
- stretch = values[i];
- }
- else if (strcmp (names[i], "font_desc") == 0)
- {
- CHECK_DUPLICATE (desc);
- desc = values[i];
- }
- else if (strcmp (names[i], "foreground") == 0 ||
- strcmp (names[i], "color") == 0)
- {
- CHECK_DUPLICATE (foreground);
- foreground = values[i];
- }
- else if (strcmp (names[i], "background") == 0)
- {
- CHECK_DUPLICATE (background);
- background = values[i];
- }
- else if (strcmp (names[i], "underline") == 0)
- {
- CHECK_DUPLICATE (underline);
- underline = values[i];
- }
- else if (strcmp (names[i], "underline_color") == 0)
- {
- CHECK_DUPLICATE (underline_color);
- underline_color = values[i];
- }
- else if (strcmp (names[i], "strikethrough") == 0)
- {
- CHECK_DUPLICATE (strikethrough);
- strikethrough = values[i];
- }
- else if (strcmp (names[i], "strikethrough_color") == 0)
- {
- CHECK_DUPLICATE (strikethrough_color);
- strikethrough_color = values[i];
- }
- else if (strcmp (names[i], "rise") == 0)
- {
- CHECK_DUPLICATE (rise);
- rise = values[i];
- }
- else if (strcmp (names[i], "letter_spacing") == 0)
- {
- CHECK_DUPLICATE (letter_spacing);
- letter_spacing = values[i];
- }
- else if (strcmp (names[i], "lang") == 0)
- {
- CHECK_DUPLICATE (lang);
- lang = values[i];
- }
- else if (strcmp (names[i], "fallback") == 0)
- {
- CHECK_DUPLICATE (fallback);
- fallback = values[i];
- }
- else
+ gboolean found = FALSE;
+
+ switch (names[i][0]) {
+ case 'f':
+ CHECK_ATTRIBUTE2(family, "face");
+ CHECK_ATTRIBUTE (fallback);
+ CHECK_ATTRIBUTE2(desc, "font_desc");
+ CHECK_ATTRIBUTE2(family, "font_family");
+ CHECK_ATTRIBUTE (foreground);
+ break;
+ case 's':
+ CHECK_ATTRIBUTE (size);
+ CHECK_ATTRIBUTE (stretch);
+ CHECK_ATTRIBUTE (strikethrough);
+ CHECK_ATTRIBUTE (strikethrough_color);
+ CHECK_ATTRIBUTE (style);
+ break;
+ case 'g':
+ CHECK_ATTRIBUTE (gravity);
+ CHECK_ATTRIBUTE (gravity_hint);
+ break;
+ case 'l':
+ CHECK_ATTRIBUTE (lang);
+ CHECK_ATTRIBUTE (letter_spacing);
+ break;
+ case 'u':
+ CHECK_ATTRIBUTE (underline);
+ CHECK_ATTRIBUTE (underline_color);
+ break;
+ default:
+ CHECK_ATTRIBUTE (background);
+ CHECK_ATTRIBUTE2(foreground, "color");
+ CHECK_ATTRIBUTE (rise);
+ CHECK_ATTRIBUTE (variant);
+ CHECK_ATTRIBUTE (weight);
+ break;
+ }
+
+ if (!found)
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
@@ -969,7 +1056,7 @@ span_parse_func (MarkupData *md,
}
/* Parse desc first, then modify it with other font-related attributes. */
- if (desc)
+ if (G_UNLIKELY (desc))
{
PangoFontDescription *parsed;
@@ -983,12 +1070,12 @@ span_parse_func (MarkupData *md,
}
}
- if (family)
+ if (G_UNLIKELY (family))
{
add_attribute (tag, pango_attr_family_new (family));
}
- if (size)
+ if (G_UNLIKELY (size))
{
if (g_ascii_isdigit (*size))
{
@@ -1044,7 +1131,7 @@ span_parse_func (MarkupData *md,
}
}
- if (style)
+ if (G_UNLIKELY (style))
{
PangoStyle pango_style;
@@ -1063,7 +1150,7 @@ span_parse_func (MarkupData *md,
}
}
- if (weight)
+ if (G_UNLIKELY (weight))
{
PangoWeight pango_weight;
@@ -1083,7 +1170,7 @@ span_parse_func (MarkupData *md,
}
}
- if (variant)
+ if (G_UNLIKELY (variant))
{
PangoVariant pango_variant;
@@ -1102,7 +1189,7 @@ span_parse_func (MarkupData *md,
}
}
- if (stretch)
+ if (G_UNLIKELY (stretch))
{
PangoStretch pango_stretch;
@@ -1122,191 +1209,117 @@ span_parse_func (MarkupData *md,
}
}
- if (foreground)
+ if (G_UNLIKELY (foreground))
{
PangoColor color;
- if (!pango_color_parse (&color, foreground))
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Could not parse foreground color specification "
- "'%s' on line %d"),
- foreground, line_number);
- goto error;
- }
+ if (!span_parse_color ("foreground", foreground, &color, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_foreground_new (color.red, color.green, color.blue));
}
- if (background)
+ if (G_UNLIKELY (background))
{
PangoColor color;
- if (!pango_color_parse (&color, background))
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Could not parse background color specification "
- "'%s' on line %d"),
- background, line_number);
- goto error;
- }
+ if (!span_parse_color ("background", background, &color, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_background_new (color.red, color.green, color.blue));
}
- if (underline)
+ if (G_UNLIKELY (underline))
{
PangoUnderline ul = PANGO_UNDERLINE_NONE;
- if (strcmp (underline, "single") == 0)
- ul = PANGO_UNDERLINE_SINGLE;
- else if (strcmp (underline, "double") == 0)
- ul = PANGO_UNDERLINE_DOUBLE;
- else if (strcmp (underline, "low") == 0)
- ul = PANGO_UNDERLINE_LOW;
- else if (strcmp (underline, "error") == 0)
- ul = PANGO_UNDERLINE_ERROR;
- else if (strcmp (underline, "none") == 0)
- ul = PANGO_UNDERLINE_NONE;
- else
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("'%s' is not a valid value for the 'underline' "
- "attribute on <span> tag, line %d; valid "
- "values are for example 'single', "
- "'double', 'low', 'none'"),
- underline, line_number);
- goto error;
- }
+ if (!span_parse_enum ("underline", underline, PANGO_TYPE_UNDERLINE, &ul, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_underline_new (ul));
}
- if (underline_color)
+ if (G_UNLIKELY (underline_color))
{
PangoColor color;
- if (!pango_color_parse (&color, underline_color))
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Could not parse underline_color color specification "
- "'%s' on line %d"),
- underline_color, line_number);
- goto error;
- }
+ if (!span_parse_color ("underline_color", underline_color, &color, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_underline_color_new (color.red, color.green, color.blue));
}
- if (strikethrough)
+ if (G_UNLIKELY (gravity))
{
- if (strcmp (strikethrough, "true") == 0)
- add_attribute (tag, pango_attr_strikethrough_new (TRUE));
- else if (strcmp (strikethrough, "false") == 0)
- add_attribute (tag, pango_attr_strikethrough_new (FALSE));
- else
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("'strikethrough' attribute on <span> tag "
- "line %d should have one of the values "
- "'true' or 'false': '%s' is not valid"),
- line_number, strikethrough);
- goto error;
- }
+ PangoGravity gr = PANGO_GRAVITY_SOUTH;
+
+ if (!span_parse_enum ("gravity", gravity, PANGO_TYPE_GRAVITY, &gr, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_gravity_new (gr));
+ }
+
+ if (G_UNLIKELY (gravity_hint))
+ {
+ PangoGravityHint hint = PANGO_GRAVITY_HINT_NATURAL;
+
+ if (!span_parse_enum ("gravity_hint", gravity_hint, PANGO_TYPE_GRAVITY_HINT, &hint, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_gravity_hint_new (hint));
+ }
+
+ if (G_UNLIKELY (strikethrough))
+ {
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_strikethrough_new (b));
}
- if (strikethrough_color)
+ if (G_UNLIKELY (strikethrough_color))
{
PangoColor color;
- if (!pango_color_parse (&color, strikethrough_color))
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Could not parse strikethrough_color color specification "
- "'%s' on line %d"),
- strikethrough_color, line_number);
- goto error;
- }
+ if (!span_parse_color ("strikethrough_color", strikethrough_color, &color, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_strikethrough_color_new (color.red, color.green, color.blue));
}
- if (fallback)
+ if (G_UNLIKELY (fallback))
{
- if (strcmp (fallback, "true") == 0)
- add_attribute (tag, pango_attr_fallback_new (TRUE));
- else if (strcmp (fallback, "false") == 0)
- add_attribute (tag, pango_attr_fallback_new (FALSE));
- else
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("'fallback' attribute on <span> tag "
- "line %d should have one of the values "
- "'true' or 'false': '%s' is not valid"),
- line_number, fallback);
- goto error;
- }
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("fallback", fallback, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_fallback_new (b));
}
- if (rise)
+ if (G_UNLIKELY (rise))
{
- char *end = NULL;
- glong n;
-
- n = strtol (rise, &end, 10);
+ gint n = 0;
- if (*end != '\0')
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Value of 'rise' attribute on <span> tag "
- "on line %d could not be parsed; "
- "should be an integer, not '%s'"),
- line_number, rise);
- goto error;
- }
+ if (!span_parse_int ("rise", rise, &n, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_rise_new (n));
}
- if (letter_spacing)
+ if (G_UNLIKELY (letter_spacing))
{
- char *end = NULL;
- glong n;
+ gint n = 0;
- n = strtol (letter_spacing, &end, 10);
-
- if (*end != '\0')
- {
- g_set_error (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Value of 'letter_spacing' attribute on <span> tag "
- "on line %d could not be parsed; "
- "should be an integer, not '%s'"),
- line_number, letter_spacing);
- goto error;
- }
+ if (!span_parse_int ("letter_spacing", letter_spacing, &n, line_number, error))
+ goto error;
add_attribute (tag, pango_attr_letter_spacing_new (n));
}
- if (lang)
+ if (G_UNLIKELY (lang))
{
add_attribute (tag,
pango_attr_language_new (pango_language_from_string (lang)));
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index ce778a8f..01e20403 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -454,6 +454,8 @@ pango_scan_string (const char **pos, GString *out)
case 't':
c = '\t';
break;
+ default:
+ break;
}
quoted = FALSE;
@@ -720,6 +722,82 @@ pango_get_lib_subdirectory (void)
#endif
}
+
+/**
+ * pango_parse_enum:
+ * @type: enum type to parse, eg. %PANGO_TYPE_ELLIPSIZE_MODE.
+ * @str: string to parse. May be %NULL.
+ * @value: integer to store the result in, or %NULL.
+ * @warn: if %TRUE, issue a g_warning() on bad input.
+ * @possible_values: place to store list of possible values on failure, or %NULL.
+ *
+ * Parses an enum type and stored the result in @value.
+ *
+ * If @str does not match the nick name of any of the possible values for the
+ * enum, %FALSE is returned, a warning is issued if @warn is %TRUE, and a
+ * string representing the list of possible values is stored in
+ * @possible_values. The list is slash-separated, eg.
+ * "none/start/middle/end". If failed and @possible_values is not %NULL,
+ * returned string should be freed using g_free().
+ *
+ * Return value: %TRUE if @str was successfully parsed.
+ *
+ * Since: 1.16
+ **/
+gboolean
+pango_parse_enum (GType type,
+ const char *str,
+ int *value,
+ gboolean warn,
+ char **possible_values)
+{
+ GEnumClass *class = NULL;
+ gboolean ret = TRUE;
+ GEnumValue *v = NULL;
+
+ class = g_type_class_ref (type);
+
+ if (G_LIKELY (str))
+ v = g_enum_get_value_by_nick (class, str);
+
+ if (v)
+ {
+ if (G_LIKELY (value))
+ *value = v->value;
+ }
+ else
+ {
+ ret = FALSE;
+ if (warn || possible_values)
+ {
+ int i;
+ GString *s = g_string_new (NULL);
+
+ for (i = 0, v = g_enum_get_value (class, i); v;
+ i++ , v = g_enum_get_value (class, i))
+ {
+ if (i)
+ g_string_append_c (s, '/');
+ g_string_append (s, v->value_nick);
+ }
+
+ if (warn)
+ g_warning ("%s must be one of %s",
+ G_ENUM_CLASS_TYPE_NAME(class),
+ s->str);
+
+ if (possible_values)
+ *possible_values = s->str;
+
+ g_string_free (s, possible_values ? FALSE : TRUE);
+ }
+ }
+
+ g_type_class_unref (class);
+
+ return ret;
+}
+
/**
* pango_parse_style:
* @str: a string to parse.
diff --git a/pango/pango-utils.h b/pango/pango-utils.h
index 2d409c05..7756f093 100644
--- a/pango/pango-utils.h
+++ b/pango/pango-utils.h
@@ -48,6 +48,12 @@ void pango_lookup_aliases (const char *fontname,
int *n_families);
#endif /* PANGO_ENABLE_BACKEND */
+gboolean pango_parse_enum (GType type,
+ const char *str,
+ int *value,
+ gboolean warn,
+ char **possible_values);
+
/* Functions for parsing textual representations
* of PangoFontDescription fields. They return TRUE if the input string
* contains a valid value, which then has been assigned to the corresponding
diff --git a/pango/pango.def b/pango/pango.def
index dd37bf94..7b3aa3ec 100644
--- a/pango/pango.def
+++ b/pango/pango.def
@@ -5,6 +5,8 @@ EXPORTS
pango_attr_family_new
pango_attr_font_desc_new
pango_attr_foreground_new
+ pango_attr_gravity_hint_new
+ pango_attr_gravity_new
pango_attr_iterator_copy
pango_attr_iterator_destroy
pango_attr_iterator_get
@@ -298,6 +300,7 @@ EXPORTS
pango_matrix_transform_rectangle
pango_matrix_translate
pango_module_register
+ pango_parse_enum
pango_parse_markup
pango_parse_stretch
pango_parse_style
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index a1e4ee35..e901f07a 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -823,18 +823,7 @@ pango_fc_make_pattern (const PangoFontDescription *description,
#endif
gravity = pango_font_description_get_gravity (description);
- switch (gravity)
- {
- case PANGO_GRAVITY_SOUTH:
- case PANGO_GRAVITY_NORTH:
- default:
- vertical = FcFalse;
- break;
- case PANGO_GRAVITY_EAST:
- case PANGO_GRAVITY_WEST:
- vertical = FcTrue;
- break;
- }
+ vertical = PANGO_GRAVITY_IS_VERTICAL (gravity) ? FcTrue : FcFalse;
/* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is
* to work around a bug in libgnomeprint where it doesn't look