4
* Copyright (C) 1999 Red Hat Software
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public
17
* License along with this library; if not, write to the
18
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
* Boston, MA 02111-1307, USA.
24
#include "pango-glyph.h"
25
#include "pango-font.h"
26
#include "pango-impl-utils.h"
29
* pango_glyph_string_new:
31
* Create a new #PangoGlyphString.
33
* Return value: the newly allocated #PangoGlyphString, which
34
* should be freed with pango_glyph_string_free().
37
pango_glyph_string_new (void)
39
PangoGlyphString *string = g_slice_new (PangoGlyphString);
41
string->num_glyphs = 0;
43
string->glyphs = NULL;
44
string->log_clusters = NULL;
50
* pango_glyph_string_set_size:
51
* @string: a #PangoGlyphString.
52
* @new_len: the new length of the string.
54
* Resize a glyph string to the given length.
57
pango_glyph_string_set_size (PangoGlyphString *string, gint new_len)
59
g_return_if_fail (new_len >= 0);
61
while (new_len > string->space)
63
if (string->space == 0)
68
if (string->space < 0)
70
g_warning ("glyph string length overflows maximum integer size, truncated");
71
new_len = string->space = G_MAXINT - 8;
75
string->glyphs = g_realloc (string->glyphs, string->space * sizeof (PangoGlyphInfo));
76
string->log_clusters = g_realloc (string->log_clusters, string->space * sizeof (gint));
77
string->num_glyphs = new_len;
81
pango_glyph_string_get_type (void)
83
static GType our_type = 0;
86
our_type = g_boxed_type_register_static (I_("PangoGlyphString"),
87
(GBoxedCopyFunc)pango_glyph_string_copy,
88
(GBoxedFreeFunc)pango_glyph_string_free);
94
* pango_glyph_string_copy:
95
* @string: a #PangoGlyphString.
97
* Copy a glyph string and associated storage.
99
* Return value: the newly allocated #PangoGlyphString, which
100
* should be freed with pango_glyph_string_free().
103
pango_glyph_string_copy (PangoGlyphString *string)
105
PangoGlyphString *new_string = g_slice_new (PangoGlyphString);
107
*new_string = *string;
109
new_string->glyphs = g_memdup (string->glyphs,
110
string->space * sizeof (PangoGlyphInfo));
111
new_string->log_clusters = g_memdup (string->log_clusters,
112
string->space * sizeof (gint));
118
* pango_glyph_string_free:
119
* @string: a #PangoGlyphString.
121
* Free a glyph string and associated storage.
124
pango_glyph_string_free (PangoGlyphString *string)
126
g_free (string->glyphs);
127
g_free (string->log_clusters);
128
g_slice_free (PangoGlyphString, string);
132
* pango_glyph_string_extents_range:
133
* @glyphs: a #PangoGlyphString
134
* @start: start index
135
* @end: end index (the range is the set of bytes with
136
indices such that start <= index < end)
137
* @font: a #PangoFont
138
* @ink_rect: rectangle used to store the extents of the glyph string range as drawn
139
* or %NULL to indicate that the result is not needed.
140
* @logical_rect: rectangle used to store the logical extents of the glyph string range
141
* or %NULL to indicate that the result is not needed.
143
* Computes the extents of a sub-portion of a glyph string. The extents are
144
* relative to the start of the glyph string range (the origin of their
145
* coordinate system is at the start of the range, not at the start of the entire
149
pango_glyph_string_extents_range (PangoGlyphString *glyphs,
153
PangoRectangle *ink_rect,
154
PangoRectangle *logical_rect)
159
/* Note that the handling of empty rectangles for ink
160
* and logical rectangles is different. A zero-height ink
161
* rectangle makes no contribution to the overall ink rect,
162
* while a zero-height logical rect still reserves horizontal
163
* width. Also, we may return zero-width, positive height
164
* logical rectangles, while we'll never do that for the
167
g_return_if_fail (start <= end);
169
if (G_UNLIKELY (!ink_rect && !logical_rect))
177
ink_rect->height = 0;
184
logical_rect->width = 0;
185
logical_rect->height = 0;
188
for (i = start; i < end; i++)
190
PangoRectangle glyph_ink;
191
PangoRectangle glyph_logical;
193
PangoGlyphGeometry *geometry = &glyphs->glyphs[i].geometry;
195
pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph,
196
ink_rect ? &glyph_ink : NULL,
197
logical_rect ? &glyph_logical : NULL);
199
if (ink_rect && glyph_ink.width != 0 && glyph_ink.height != 0)
201
if (ink_rect->width == 0 || ink_rect->height == 0)
203
ink_rect->x = x_pos + glyph_ink.x + geometry->x_offset;
204
ink_rect->width = glyph_ink.width;
205
ink_rect->y = glyph_ink.y + geometry->y_offset;
206
ink_rect->height = glyph_ink.height;
212
new_x = MIN (ink_rect->x, x_pos + glyph_ink.x + geometry->x_offset);
213
ink_rect->width = MAX (ink_rect->x + ink_rect->width,
214
x_pos + glyph_ink.x + glyph_ink.width + geometry->x_offset) - new_x;
217
new_y = MIN (ink_rect->y, glyph_ink.y + geometry->y_offset);
218
ink_rect->height = MAX (ink_rect->y + ink_rect->height,
219
glyph_ink.y + glyph_ink.height + geometry->y_offset) - new_y;
226
logical_rect->width += geometry->width;
230
logical_rect->y = glyph_logical.y;
231
logical_rect->height = glyph_logical.height;
235
int new_y = MIN (logical_rect->y, glyph_logical.y);
236
logical_rect->height = MAX (logical_rect->y + logical_rect->height,
237
glyph_logical.y + glyph_logical.height) - new_y;
238
logical_rect->y = new_y;
242
x_pos += geometry->width;
247
* pango_glyph_string_extents:
248
* @glyphs: a #PangoGlyphString
249
* @font: a #PangoFont
250
* @ink_rect: rectangle used to store the extents of the glyph string as drawn
251
* or %NULL to indicate that the result is not needed.
252
* @logical_rect: rectangle used to store the logical extents of the glyph string
253
* or %NULL to indicate that the result is not needed.
255
* Compute the logical and ink extents of a glyph string. See the documentation
256
* for pango_font_get_glyph_extents() for details about the interpretation
260
pango_glyph_string_extents (PangoGlyphString *glyphs,
262
PangoRectangle *ink_rect,
263
PangoRectangle *logical_rect)
265
pango_glyph_string_extents_range (glyphs, 0, glyphs->num_glyphs,
266
font, ink_rect, logical_rect);
270
* pango_glyph_string_get_width:
271
* @glyphs: a #PangoGlyphString
273
* Computes the logical width of the glyph string as can also be computed
274
* using pango_glyph_string_extents(). However, since this only computes the
275
* width, it's much faster. This is in fact only a convenience function that
276
* computes the sum of geometry.width for each glyph in the @glyphs.
278
* Return value: the logical width of the glyph string.
283
pango_glyph_string_get_width (PangoGlyphString *glyphs)
288
for (i = 0; i < glyphs->num_glyphs; i++)
289
width += glyphs->glyphs[i].geometry.width;
295
* pango_glyph_string_get_logical_widths:
296
* @glyphs: a #PangoGlyphString
297
* @text: the text corresponding to the glyphs
298
* @length: the length of @text, in bytes
299
* @embedding_level: the embedding level of the string
300
* @logical_widths: an array whose length is g_utf8_strlen (text, length)
301
* to be filled in with the resulting character widths.
303
* Given a #PangoGlyphString resulting from pango_shape() and the corresponding
304
* text, determine the screen width corresponding to each character. When
305
* multiple characters compose a single cluster, the width of the entire
306
* cluster is divided equally among the characters.
309
pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
316
int last_cluster = 0;
318
int last_cluster_width = 0;
319
const char *p = text; /* Points to start of current cluster */
321
for (i=0; i<=glyphs->num_glyphs; i++)
323
int glyph_index = (embedding_level % 2 == 0) ? i : glyphs->num_glyphs - i - 1;
325
/* If this glyph belongs to a new cluster, or we're at the end, find
326
* the start of the next cluster, and assign the widths for this cluster.
328
if (i == glyphs->num_glyphs || p != text + glyphs->log_clusters[glyph_index])
330
int next_cluster = last_cluster;
332
if (i < glyphs->num_glyphs)
334
while (p < text + glyphs->log_clusters[glyph_index])
337
p = g_utf8_next_char (p);
342
while (p < text + length)
345
p = g_utf8_next_char (p);
349
for (j = last_cluster; j < next_cluster; j++)
350
logical_widths[j] = (width - last_cluster_width) / (next_cluster - last_cluster);
352
last_cluster = next_cluster;
353
last_cluster_width = width;
356
if (i < glyphs->num_glyphs)
357
width += glyphs->glyphs[glyph_index].geometry.width;