1/* Pango
2 * pango-impl-utils.h: Macros for get_type() functions
3 * Inspired by Jody Goldberg's gsf-impl-utils.h
4 *
5 * Copyright (C) 2003 Red Hat Software
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#ifndef __PANGO_IMPL_UTILS_H__
24#define __PANGO_IMPL_UTILS_H__
25
26#include <glib.h>
27#include <glib-object.h>
28#include <pango/pango.h>
29
30G_BEGIN_DECLS
31
32
33/* String interning for static strings */
34#define I_(string) g_intern_static_string (string)
35
36
37/* Some functions for handling PANGO_ATTR_SHAPE */
38void _pango_shape_shape (const char *text,
39 unsigned int n_chars,
40 PangoRectangle *shape_ink,
41 PangoRectangle *shape_logical,
42 PangoGlyphString *glyphs);
43
44void _pango_shape_get_extents (gint n_chars,
45 PangoRectangle *shape_ink,
46 PangoRectangle *shape_logical,
47 PangoRectangle *ink_rect,
48 PangoRectangle *logical_rect);
49
50
51/* We define these functions static here because we don't want to add public API
52 * for them (if anything, it belongs to glib, but glib found it trivial enough
53 * not to add API for). At some point metrics calculations will be
54 * centralized and this mess can be minimized. Or so I hope.
55 */
56
57static inline G_GNUC_UNUSED int
58pango_unichar_width (gunichar c)
59{
60 return G_UNLIKELY (g_unichar_iszerowidth (c)) ? 0 :
61 G_UNLIKELY (g_unichar_iswide (c)) ? 2 : 1;
62}
63
64static G_GNUC_UNUSED glong
65pango_utf8_strwidth (const gchar *p)
66{
67 glong len = 0;
68 g_return_val_if_fail (p != NULL, 0);
69
70 while (*p)
71 {
72 len += pango_unichar_width (c: g_utf8_get_char (p));
73 p = g_utf8_next_char (p);
74 }
75
76 return len;
77}
78
79/* Glib's g_utf8_strlen() is broken and stops at embedded NUL's.
80 * Wrap it here. */
81static G_GNUC_UNUSED glong
82pango_utf8_strlen (const gchar *p, gssize max)
83{
84 glong len = 0;
85 const gchar *start = p;
86 g_return_val_if_fail (p != NULL || max == 0, 0);
87
88 if (max <= 0)
89 return g_utf8_strlen (p, max);
90
91 p = g_utf8_next_char (p);
92 while (p - start < max)
93 {
94 ++len;
95 p = g_utf8_next_char (p);
96 }
97
98 /* only do the last len increment if we got a complete
99 * char (don't count partial chars)
100 */
101 if (p - start <= max)
102 ++len;
103
104 return len;
105}
106
107
108/* To be made public at some point */
109
110static G_GNUC_UNUSED void
111pango_glyph_string_reverse_range (PangoGlyphString *glyphs,
112 int start, int end)
113{
114 int i, j;
115
116 for (i = start, j = end - 1; i < j; i++, j--)
117 {
118 PangoGlyphInfo glyph_info;
119 gint log_cluster;
120
121 glyph_info = glyphs->glyphs[i];
122 glyphs->glyphs[i] = glyphs->glyphs[j];
123 glyphs->glyphs[j] = glyph_info;
124
125 log_cluster = glyphs->log_clusters[i];
126 glyphs->log_clusters[i] = glyphs->log_clusters[j];
127 glyphs->log_clusters[j] = log_cluster;
128 }
129}
130
131static inline gboolean
132pango_is_default_ignorable (gunichar ch)
133{
134 int plane = ch >> 16;
135
136 if (G_LIKELY (plane == 0))
137 {
138 int page = ch >> 8;
139 switch (page)
140 {
141 case 0x00: return ch == 0x00ad;
142 case 0x03: return ch == 0x034f;
143 case 0x06: return ch == 0x061c;
144 case 0x17: return (0x17b4 <= ch && ch <= 0x17b5);
145 case 0x18: return (0x180b <= ch && ch <= 0x180e);
146 case 0x20: return (0x200b <= ch && ch <= 0x200f) ||
147 (0x202a <= ch && ch <= 0x202e) ||
148 (0x2060 <= ch && ch <= 0x206f);
149 case 0xfe: return (0xfe00 <= ch && ch <= 0xfe0f) || ch == 0xfeff;
150 case 0xff: return (0xfff0 <= ch && ch <= 0xfff8);
151 default: return FALSE;
152 }
153 }
154 else
155 {
156 /* Other planes */
157 switch (plane)
158 {
159 case 0x01: return (0x1d173 <= ch && ch <= 0x1d17a);
160 case 0x0e: return (0xe0000 <= ch && ch <= 0xe0fff);
161 default: return FALSE;
162 }
163 }
164}
165
166/* These are the default ignorables that we render as hexboxes
167 * with nicks if PANGO_SHOW_IGNORABLES is used.
168 *
169 * The cairo hexbox drawing code assumes that these nicks are
170 * 1-6 ASCII chars
171 */
172static struct {
173 gunichar ch;
174 const char *nick;
175} ignorables[] = {
176 { 0x00ad, "SHY" }, /* SOFT HYPHEN */
177 { 0x034f, "CGJ" }, /* COMBINING GRAPHEME JOINER */
178 { 0x061c, "ALM" }, /* ARABIC LETTER MARK */
179 { 0x200b, "ZWS" }, /* ZERO WIDTH SPACE */
180 { 0x200c, "ZWNJ" }, /* ZERO WIDTH NON-JOINER */
181 { 0x200d, "ZWJ" }, /* ZERO WIDTH JOINER */
182 { 0x200e, "LRM" }, /* LEFT-TO-RIGHT MARK */
183 { 0x200f, "RLM" }, /* RIGHT-TO-LEFT MARK */
184 { 0x2028, "LS" }, /* LINE SEPARATOR */
185 { 0x2029, "PS" }, /* PARAGRAPH SEPARATOR */
186 { 0x202a, "LRE" }, /* LEFT-TO-RIGHT EMBEDDING */
187 { 0x202b, "RLE" }, /* RIGHT-TO-LEFT EMBEDDING */
188 { 0x202c, "PDF" }, /* POP DIRECTIONAL FORMATTING */
189 { 0x202d, "LRO" }, /* LEFT-TO-RIGHT OVERRIDE */
190 { 0x202e, "RLO" }, /* RIGHT-TO-LEFT OVERRIDE */
191 { 0x2060, "WJ" }, /* WORD JOINER */
192 { 0x2061, "FA" }, /* FUNCTION APPLICATION */
193 { 0x2062, "IT" }, /* INVISIBLE TIMES */
194 { 0x2063, "IS" }, /* INVISIBLE SEPARATOR */
195 { 0x2066, "LRI" }, /* LEFT-TO-RIGHT ISOLATE */
196 { 0x2067, "RLI" }, /* RIGHT-TO-LEFT ISOLATE */
197 { 0x2068, "FSI" }, /* FIRST STRONG ISOLATE */
198 { 0x2069, "PDI" }, /* POP DIRECTIONAL ISOLATE */
199 { 0xfeff, "ZWNBS" }, /* ZERO WIDTH NO-BREAK SPACE */
200};
201
202static inline G_GNUC_UNUSED const char *
203pango_get_ignorable (gunichar ch)
204{
205 int i;
206
207 for (i = 0; i < G_N_ELEMENTS (ignorables); i++)
208 {
209 if (ch < ignorables[i].ch)
210 return NULL;
211
212 if (ch == ignorables[i].ch)
213 return ignorables[i].nick;
214 }
215 return NULL;
216}
217
218static inline G_GNUC_UNUSED const char *
219pango_get_ignorable_size (gunichar ch,
220 int *rows,
221 int *cols)
222{
223 const char *nick;
224 int len;
225
226 nick = pango_get_ignorable (ch);
227 if (nick)
228 {
229 len = strlen (s: nick);
230 if (len < 4)
231 {
232 *rows = 1;
233 *cols = len;
234 }
235 else if (len > 4)
236 {
237 *rows = 2;
238 *cols = 3;
239 }
240 else
241 {
242 *rows = 2;
243 *cols = 2;
244 }
245 }
246
247 return nick;
248}
249
250/* Backward compatibility shim, to avoid bumping up the minimum
251 * required version of GLib; most of our uses of g_memdup() are
252 * safe, and those that aren't have been fixed
253 */
254#if !GLIB_CHECK_VERSION (2, 67, 3)
255# define g_memdup2(mem,size) g_memdup((mem),(size))
256#endif
257
258G_END_DECLS
259
260#endif /* __PANGO_IMPL_UTILS_H__ */
261

source code of gtk/subprojects/pango/pango/pango-impl-utils.h