From 10faf8d5772c8737c8588d0baa7f05691df7bc0b Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Thu, 27 Mar 2003 17:24:53 +0000 Subject: [PATCH] added hinting and antialias properties. 2003-03-27 Sven Neumann * app/text/gimptext.[ch]: added hinting and antialias properties. * app/text/gimptextlayout.c: rewrote some parts using the PangoFontMap API. Respect hinting and antialias properties. (PangoFT2 does not allow to switch antialias off, so that has no effect yet.) * app/tools/gimptextoptions.c: added a check button that controls hinting. --- ChangeLog | 12 +++++ app/text/gimptext.c | 46 +++++++++++++----- app/text/gimptext.h | 4 +- app/text/gimptextlayout.c | 93 +++++++++++++++++++------------------ app/tools/gimptextoptions.c | 15 ++++-- 5 files changed, 108 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49d9484df2..9b34ffb7fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2003-03-27 Sven Neumann + + * app/text/gimptext.[ch]: added hinting and antialias properties. + + * app/text/gimptextlayout.c: rewrote some parts using the + PangoFontMap API. Respect hinting and antialias properties. + (PangoFT2 does not allow to switch antialias off, so that has no + effect yet.) + + * app/tools/gimptextoptions.c: added a check button that controls + hinting. + 2003-03-27 Sven Neumann * configure.in: require PangoFT2 >= 1.2.0. diff --git a/app/text/gimptext.c b/app/text/gimptext.c index cb5744a7e5..ae9f0002a5 100644 --- a/app/text/gimptext.c +++ b/app/text/gimptext.c @@ -48,13 +48,15 @@ enum PROP_FONT, PROP_FONT_SIZE, PROP_FONT_SIZE_UNIT, + PROP_HINTING, + PROP_ANTIALIAS, PROP_LANGUAGE, PROP_COLOR, - PROP_FIXED_WIDTH, PROP_JUSTIFICATION, PROP_INDENTATION, PROP_LINE_SPACING, PROP_LETTER_SPACING, + PROP_BOX_WIDTH, PROP_BORDER }; @@ -147,6 +149,16 @@ gimp_text_class_init (GimpTextClass *klass) "font-size-unit", NULL, TRUE, GIMP_UNIT_PIXEL, 0); + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_HINTING, + "hinting", + N_("Hinting alters the font outline to" + "produce a crisp bitmap at small sizes"), + TRUE, + 0); + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ANTIALIAS, + "antialias", NULL, + TRUE, + 0); GIMP_CONFIG_INSTALL_PROP_STRING (object_class, PROP_LANGUAGE, "language", NULL, language, @@ -155,10 +167,6 @@ gimp_text_class_init (GimpTextClass *klass) "color", NULL, &black, 0); - GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_FIXED_WIDTH, - "fixed-width", NULL, - 0, GIMP_MAX_IMAGE_SIZE, 0, - 0); GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_JUSTIFICATION, "justify", NULL, @@ -180,6 +188,10 @@ gimp_text_class_init (GimpTextClass *klass) "letter-spacing", NULL, -8192.0, 8192.0, 0.0, 0); + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_BOX_WIDTH, + "box-width", NULL, + 0, GIMP_MAX_IMAGE_SIZE, 0, + 0); /* border does only exist to implement the old text API */ param_spec = g_param_spec_int ("border", NULL, NULL, @@ -236,15 +248,18 @@ gimp_text_get_property (GObject *object, case PROP_FONT_SIZE_UNIT: g_value_set_int (value, text->font_size_unit); break; + case PROP_HINTING: + g_value_set_boolean (value, text->hinting); + break; + case PROP_ANTIALIAS: + g_value_set_boolean (value, text->antialias); + break; case PROP_LANGUAGE: g_value_set_string (value, text->language); break; case PROP_COLOR: g_value_set_boxed (value, &text->color); break; - case PROP_FIXED_WIDTH: - g_value_set_int (value, text->fixed_width); - break; case PROP_JUSTIFICATION: g_value_set_enum (value, text->justify); break; @@ -257,6 +272,9 @@ gimp_text_get_property (GObject *object, case PROP_LETTER_SPACING: g_value_set_double (value, text->letter_spacing); break; + case PROP_BOX_WIDTH: + g_value_set_int (value, text->box_width); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -288,6 +306,12 @@ gimp_text_set_property (GObject *object, case PROP_FONT_SIZE_UNIT: text->font_size_unit = g_value_get_int (value); break; + case PROP_HINTING: + text->hinting = g_value_get_boolean (value); + break; + case PROP_ANTIALIAS: + text->antialias = g_value_get_boolean (value); + break; case PROP_LANGUAGE: g_free (text->language); text->language = g_value_dup_string (value); @@ -296,9 +320,6 @@ gimp_text_set_property (GObject *object, color = g_value_get_boxed (value); text->color = *color; break; - case PROP_FIXED_WIDTH: - text->fixed_width = g_value_get_int (value); - break; case PROP_JUSTIFICATION: text->justify = g_value_get_enum (value); break; @@ -311,6 +332,9 @@ gimp_text_set_property (GObject *object, case PROP_LETTER_SPACING: text->letter_spacing = g_value_get_double (value); break; + case PROP_BOX_WIDTH: + text->box_width = g_value_get_int (value); + break; case PROP_BORDER: text->border = g_value_get_int (value); break; diff --git a/app/text/gimptext.h b/app/text/gimptext.h index c767e6c717..0ebf63b8ca 100644 --- a/app/text/gimptext.h +++ b/app/text/gimptext.h @@ -40,13 +40,15 @@ struct _GimpText gchar *font; gdouble font_size; GimpUnit font_size_unit; + gboolean hinting; + gboolean antialias; gchar *language; GimpRGB color; GimpTextJustification justify; gdouble indent; gdouble line_spacing; gdouble letter_spacing; - gint fixed_width; + gint box_width; /* for historical reasons, don't use */ gint border; diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c index c833091fd2..c417db8e33 100644 --- a/app/text/gimptextlayout.c +++ b/app/text/gimptextlayout.c @@ -52,17 +52,18 @@ struct _GimpTextLayoutClass }; -static void gimp_text_layout_class_init (GimpTextLayoutClass *klass); -static void gimp_text_layout_init (GimpTextLayout *layout); -static void gimp_text_layout_finalize (GObject *object); +static void gimp_text_layout_class_init (GimpTextLayoutClass *klass); +static void gimp_text_layout_init (GimpTextLayout *layout); +static void gimp_text_layout_finalize (GObject *object); -static void gimp_text_layout_position (GimpTextLayout *layout); +static void gimp_text_layout_position (GimpTextLayout *layout); -static PangoContext * gimp_image_get_pango_context (GimpImage *image); +static PangoContext * gimp_text_get_pango_context (GimpText *text, + gdouble xres, + gdouble yres); -static GQuark gimp_text_context_quark = 0; -static GObjectClass * parent_class = NULL; +static GObjectClass * parent_class = NULL; GType @@ -142,6 +143,7 @@ gimp_text_layout_new (GimpText *text, PangoContext *context; PangoFontDescription *font_desc; PangoAlignment alignment = PANGO_ALIGN_LEFT; + gdouble xres, yres; gint size; g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); @@ -152,6 +154,8 @@ gimp_text_layout_new (GimpText *text, if (!font_desc) return NULL; + gimp_image_get_resolution (image, &xres, &yres); + switch (text->font_size_unit) { case GIMP_UNIT_PIXEL: @@ -160,14 +164,11 @@ gimp_text_layout_new (GimpText *text, default: { - gdouble xres, yres; gdouble factor; factor = gimp_unit_get_factor (text->font_size_unit); g_return_val_if_fail (factor > 0.0, NULL); - gimp_image_get_resolution (image, &xres, &yres); - size = (gdouble) PANGO_SCALE * text->font_size * yres / factor; } break; @@ -175,11 +176,7 @@ gimp_text_layout_new (GimpText *text, pango_font_description_set_size (font_desc, MAX (1, size)); - context = gimp_image_get_pango_context (image); - - if (text->language) - pango_context_set_language (context, - pango_language_from_string (text->language)); + context = gimp_text_get_pango_context (text, xres, yres); layout = g_object_new (GIMP_TYPE_TEXT_LAYOUT, NULL); layout->text = g_object_ref (text); @@ -215,8 +212,8 @@ gimp_text_layout_new (GimpText *text, pango_layout_set_alignment (layout->layout, alignment); pango_layout_set_width (layout->layout, - text->fixed_width > 0 ? - text->fixed_width * PANGO_SCALE : -1); + text->box_width > 0 ? + text->box_width * PANGO_SCALE : -1); pango_layout_set_indent (layout->layout, text->indent * PANGO_SCALE); pango_layout_set_spacing (layout->layout, text->line_spacing * PANGO_SCALE); @@ -294,10 +291,10 @@ gimp_text_layout_render (GimpTextLayout *layout, static void gimp_text_layout_position (GimpTextLayout *layout) { - PangoRectangle ink; - PangoRectangle logical; - gint x1, y1; - gint x2, y2; + PangoRectangle ink; + PangoRectangle logical; + gint x1, y1; + gint x2, y2; layout->extents.x = 0; layout->extents.x = 0; @@ -344,38 +341,44 @@ gimp_text_layout_position (GimpTextLayout *layout) static void -detach_pango_context (GObject *image) +gimp_text_ft2_subst_func (FcPattern *pattern, + gpointer data) { - g_object_set_qdata (image, gimp_text_context_quark, NULL); + gboolean hinting; + gboolean antialias; + + g_object_get (data, + "hinting", &hinting, + "antialias", &antialias, + NULL); + + FcPatternAddBool (pattern, FC_HINTING, hinting); + FcPatternAddBool (pattern, FC_ANTIALIAS, antialias); } static PangoContext * -gimp_image_get_pango_context (GimpImage *image) +gimp_text_get_pango_context (GimpText *text, + gdouble xres, + gdouble yres) { - PangoContext *context; + PangoContext *context; + PangoFT2FontMap *fontmap; - if (!gimp_text_context_quark) - gimp_text_context_quark = g_quark_from_static_string ("pango-context"); + fontmap = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); + + pango_ft2_font_map_set_resolution (fontmap, xres, yres); - context = (PangoContext *) g_object_get_qdata (G_OBJECT (image), - gimp_text_context_quark); + pango_ft2_font_map_set_default_substitute (fontmap, + gimp_text_ft2_subst_func, + g_object_ref (text), + (GDestroyNotify) g_object_unref); - if (!context) - { - gdouble xres, yres; - - gimp_image_get_resolution (image, &xres, &yres); + context = pango_ft2_font_map_create_context (fontmap); + g_object_unref (fontmap); - context = pango_ft2_get_context (xres, yres); + if (text->language) + pango_context_set_language (context, + pango_language_from_string (text->language)); - g_signal_connect_object (image, "resolution_changed", - G_CALLBACK (detach_pango_context), - context, 0); - - g_object_set_qdata_full (G_OBJECT (image), - gimp_text_context_quark, context, - (GDestroyNotify) g_object_unref); - } - - return g_object_ref (context); + return context; } diff --git a/app/tools/gimptextoptions.c b/app/tools/gimptextoptions.c index c3cbd72210..22b8bb33d2 100644 --- a/app/tools/gimptextoptions.c +++ b/app/tools/gimptextoptions.c @@ -230,7 +230,7 @@ gimp_text_options_gui (GimpToolOptions *tool_options) vbox = gimp_tool_options_gui (tool_options); - table = gtk_table_new (7, 3, FALSE); + table = gtk_table_new (8, 3, FALSE); gtk_table_set_col_spacings (GTK_TABLE (table), 2); gtk_table_set_row_spacings (GTK_TABLE (table), 2); gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); @@ -267,29 +267,34 @@ gimp_text_options_gui (GimpToolOptions *tool_options) GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); gtk_widget_show (menu); + button = gimp_prop_check_button_new (config, "hinting", _("_Hinting")); + gtk_table_attach (GTK_TABLE (table), button, 1, 3, 3, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (button); + button = gimp_prop_color_button_new (config, "color", _("Text Color"), -1, 24, GIMP_COLOR_AREA_FLAT); gimp_color_panel_set_context (GIMP_COLOR_PANEL (button), GIMP_CONTEXT (options)); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 3, + gimp_table_attach_aligned (GTK_TABLE (table), 0, 4, _("Color:"), 1.0, 0.5, button, 1, FALSE); box = gimp_prop_enum_stock_box_new (config, "justify", "gtk-justify", 0, 0); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 4, + gimp_table_attach_aligned (GTK_TABLE (table), 0, 5, _("Justify:"), 1.0, 0.5, box, 2, TRUE); spinbutton = gimp_prop_spin_button_new (config, "indent", 1.0, 10.0, 1); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 5); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 5, + gimp_table_attach_aligned (GTK_TABLE (table), 0, 6, _("Indent:"), 1.0, 0.5, spinbutton, 1, FALSE); spinbutton = gimp_prop_spin_button_new (config, "line-spacing", 1.0, 10.0, 1); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 5); - gimp_table_attach_stock (GTK_TABLE (table), 6, + gimp_table_attach_stock (GTK_TABLE (table), 7, _("Line\nSpacing:"), 0.0, spinbutton, 1, GIMP_STOCK_LINE_SPACING);