1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
5
* Copyright (C) 2002-2003 Sven Neumann <sven@gimp.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
#include <glib-object.h>
25
#include <pango/pangoft2.h>
27
#include "text-types.h"
29
#include "core/gimpimage.h"
30
#include "core/gimpunit.h"
33
#include "gimptext-private.h"
34
#include "gimptextlayout.h"
37
static void gimp_text_layout_class_init (GimpTextLayoutClass *klass);
38
static void gimp_text_layout_init (GimpTextLayout *layout);
39
static void gimp_text_layout_finalize (GObject *object);
41
static void gimp_text_layout_position (GimpTextLayout *layout);
43
static PangoContext * gimp_text_get_pango_context (GimpText *text,
47
static gint gimp_text_layout_pixel_size (Gimp *gimp,
51
static gint gimp_text_layout_point_size (Gimp *gimp,
57
static GObjectClass * parent_class = NULL;
61
gimp_text_layout_get_type (void)
63
static GType layout_type = 0;
67
static const GTypeInfo layout_info =
69
sizeof (GimpTextLayoutClass),
71
(GBaseFinalizeFunc) NULL,
72
(GClassInitFunc) gimp_text_layout_class_init,
73
NULL, /* class_finalize */
74
NULL, /* class_data */
75
sizeof (GimpTextLayout),
77
(GInstanceInitFunc) gimp_text_layout_init,
80
layout_type = g_type_register_static (G_TYPE_OBJECT,
89
gimp_text_layout_class_init (GimpTextLayoutClass *klass)
91
GObjectClass *object_class;
93
object_class = G_OBJECT_CLASS (klass);
95
parent_class = g_type_class_peek_parent (klass);
97
object_class->finalize = gimp_text_layout_finalize;
101
gimp_text_layout_init (GimpTextLayout *layout)
104
layout->layout = NULL;
108
gimp_text_layout_finalize (GObject *object)
110
GimpTextLayout *layout;
112
layout = GIMP_TEXT_LAYOUT (object);
116
g_object_unref (layout->text);
121
g_object_unref (layout->layout);
122
layout->layout = NULL;
125
G_OBJECT_CLASS (parent_class)->finalize (object);
130
gimp_text_layout_new (GimpText *text,
133
GimpTextLayout *layout;
134
PangoContext *context;
135
PangoFontDescription *font_desc;
136
PangoAlignment alignment = PANGO_ALIGN_LEFT;
140
g_return_val_if_fail (GIMP_IS_TEXT (text), NULL);
141
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
143
font_desc = pango_font_description_from_string (text->font);
144
g_return_val_if_fail (font_desc != NULL, NULL);
148
gimp_image_get_resolution (image, &xres, &yres);
150
size = gimp_text_layout_point_size (image->gimp,
155
pango_font_description_set_size (font_desc, MAX (1, size));
157
context = gimp_text_get_pango_context (text, xres, yres);
159
layout = g_object_new (GIMP_TYPE_TEXT_LAYOUT, NULL);
160
layout->text = g_object_ref (text);
161
layout->layout = pango_layout_new (context);
163
g_object_unref (context);
165
pango_layout_set_font_description (layout->layout, font_desc);
166
pango_font_description_free (font_desc);
169
pango_layout_set_text (layout->layout, text->text, -1);
171
pango_layout_set_text (layout->layout, NULL, 0);
173
switch (text->justify)
175
case GIMP_TEXT_JUSTIFY_LEFT:
176
alignment = PANGO_ALIGN_LEFT;
178
case GIMP_TEXT_JUSTIFY_RIGHT:
179
alignment = PANGO_ALIGN_RIGHT;
181
case GIMP_TEXT_JUSTIFY_CENTER:
182
alignment = PANGO_ALIGN_CENTER;
184
case GIMP_TEXT_JUSTIFY_FILL:
185
/* FIXME: This doesn't work since the implementation is missing
188
alignment = PANGO_ALIGN_LEFT;
189
pango_layout_set_justify (layout->layout, TRUE);
193
pango_layout_set_alignment (layout->layout, alignment);
195
switch (text->box_mode)
197
case GIMP_TEXT_BOX_DYNAMIC:
199
case GIMP_TEXT_BOX_FIXED:
200
pango_layout_set_width (layout->layout,
201
gimp_text_layout_pixel_size (image->gimp,
208
pango_layout_set_indent (layout->layout,
209
gimp_text_layout_pixel_size (image->gimp,
213
pango_layout_set_spacing (layout->layout,
214
gimp_text_layout_pixel_size (image->gimp,
218
gimp_text_layout_position (layout);
220
switch (text->box_mode)
222
case GIMP_TEXT_BOX_DYNAMIC:
224
case GIMP_TEXT_BOX_FIXED:
225
layout->extents.height =
226
PANGO_PIXELS (gimp_text_layout_pixel_size (image->gimp,
237
gimp_text_layout_get_size (GimpTextLayout *layout,
241
g_return_val_if_fail (GIMP_IS_TEXT_LAYOUT (layout), FALSE);
244
*width = layout->extents.width;
246
*height = layout->extents.height;
248
return (layout->extents.width > 0 && layout->extents.height > 0);
252
gimp_text_layout_get_offsets (GimpTextLayout *layout,
256
g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout));
259
*x = layout->extents.x;
261
*y = layout->extents.y;
265
gimp_text_layout_position (GimpTextLayout *layout)
268
PangoRectangle logical;
272
layout->extents.x = 0;
273
layout->extents.x = 0;
274
layout->extents.width = 0;
275
layout->extents.height = 0;
277
pango_layout_get_pixel_extents (layout->layout, &ink, &logical);
280
g_print ("ink rect: %d x %d @ %d, %d\n",
281
ink.width, ink.height, ink.x, ink.y);
282
g_print ("logical rect: %d x %d @ %d, %d\n",
283
logical.width, logical.height, logical.x, logical.y);
286
if (ink.width < 1 || ink.height < 1)
289
x1 = MIN (ink.x, logical.x);
290
y1 = MIN (ink.y, logical.y);
291
x2 = MAX (ink.x + ink.width, logical.x + logical.width);
292
y2 = MAX (ink.y + ink.height, logical.y + logical.height);
294
layout->extents.x = - x1;
295
layout->extents.y = - y1;
296
layout->extents.width = x2 - x1;
297
layout->extents.height = y2 - y1;
299
if (layout->text->border > 0)
301
gint border = layout->text->border;
303
layout->extents.x += border;
304
layout->extents.y += border;
305
layout->extents.width += 2 * border;
306
layout->extents.height += 2 * border;
310
g_print ("layout extents: %d x %d @ %d, %d\n",
311
layout->extents.width, layout->extents.height,
312
layout->extents.x, layout->extents.y);
318
gimp_text_ft2_subst_func (FcPattern *pattern,
321
GimpText *text = GIMP_TEXT (data);
323
FcPatternAddBool (pattern, FC_HINTING, text->hinting);
324
FcPatternAddBool (pattern, FC_AUTOHINT, text->autohint);
325
FcPatternAddBool (pattern, FC_ANTIALIAS, text->antialias);
328
static PangoContext *
329
gimp_text_get_pango_context (GimpText *text,
333
PangoContext *context;
334
PangoFT2FontMap *fontmap;
336
fontmap = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
338
pango_ft2_font_map_set_resolution (fontmap, xres, yres);
340
pango_ft2_font_map_set_default_substitute (fontmap,
341
gimp_text_ft2_subst_func,
343
(GDestroyNotify) g_object_unref);
345
context = pango_ft2_font_map_create_context (fontmap);
346
g_object_unref (fontmap);
348
/* Workaround for bug #143542 (PangoFT2Fontmap leak),
349
* see also bug #148997 (Text layer rendering leaks font file descriptor):
351
* Calling pango_ft2_font_map_substitute_changed() causes the
352
* font_map cache to be flushed, thereby removing the circular
353
* reference that causes the leak.
355
g_object_weak_ref (G_OBJECT (context),
356
(GWeakNotify) pango_ft2_font_map_substitute_changed,
360
pango_context_set_language (context,
361
pango_language_from_string (text->language));
363
switch (text->base_dir)
365
case GIMP_TEXT_DIRECTION_LTR:
366
pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
368
case GIMP_TEXT_DIRECTION_RTL:
369
pango_context_set_base_dir (context, PANGO_DIRECTION_RTL);
377
gimp_text_layout_pixel_size (Gimp *gimp,
386
case GIMP_UNIT_PIXEL:
387
return PANGO_SCALE * value;
390
factor = _gimp_unit_get_factor (gimp, unit);
391
g_return_val_if_fail (factor > 0.0, 0);
393
return PANGO_SCALE * value * res / factor;
398
gimp_text_layout_point_size (Gimp *gimp,
407
case GIMP_UNIT_POINT:
408
return PANGO_SCALE * value;
410
case GIMP_UNIT_PIXEL:
411
g_return_val_if_fail (res > 0.0, 0);
412
return (PANGO_SCALE * value *
413
_gimp_unit_get_factor (gimp, GIMP_UNIT_POINT) / res);
416
factor = _gimp_unit_get_factor (gimp, unit);
417
g_return_val_if_fail (factor > 0.0, 0);
419
return (PANGO_SCALE * value *
420
_gimp_unit_get_factor (gimp, GIMP_UNIT_POINT) / factor);