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
30 G_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 */
38 void _pango_shape_shape (const char *text,
39 unsigned int n_chars,
40 PangoRectangle *shape_ink,
41 PangoRectangle *shape_logical,
42 PangoGlyphString *glyphs);
43
44 void _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
57 static inline G_GNUC_UNUSED int
pango_unichar_width(gunichar c)58 pango_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
64 static G_GNUC_UNUSED glong
pango_utf8_strwidth(const gchar * p)65 pango_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 (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. */
81 static G_GNUC_UNUSED glong
pango_utf8_strlen(const gchar * p,gssize max)82 pango_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
110 static G_GNUC_UNUSED void
pango_glyph_string_reverse_range(PangoGlyphString * glyphs,int start,int end)111 pango_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
131 /* The cairo hexbox drawing code assumes
132 * that these nicks are 1-6 ASCII chars
133 */
134 static struct {
135 gunichar ch;
136 const char *nick;
137 } ignorables[] = {
138 { 0x00ad, "SHY" }, /* SOFT HYPHEN */
139 { 0x034f, "CGJ" }, /* COMBINING GRAPHEME JOINER */
140 { 0x200b, "ZWS" }, /* ZERO WIDTH SPACE */
141 { 0x200c, "ZWNJ" }, /* ZERO WIDTH NON-JOINER */
142 { 0x200d, "ZWJ" }, /* ZERO WIDTH JOINER */
143 { 0x200e, "LRM" }, /* LEFT-TO-RIGHT MARK */
144 { 0x200f, "RLM" }, /* RIGHT-TO-LEFT MARK */
145 { 0x2028, "LS" }, /* LINE SEPARATOR */
146 { 0x2029, "PS" }, /* PARAGRAPH SEPARATOR */
147 { 0x202a, "LRE" }, /* LEFT-TO-RIGHT EMBEDDING */
148 { 0x202b, "RLE" }, /* RIGHT-TO-LEFT EMBEDDING */
149 { 0x202c, "PDF" }, /* POP DIRECTIONAL FORMATTING */
150 { 0x202d, "LRO" }, /* LEFT-TO-RIGHT OVERRIDE */
151 { 0x202e, "RLO" }, /* RIGHT-TO-LEFT OVERRIDE */
152 { 0x2060, "WJ" }, /* WORD JOINER */
153 { 0x2061, "FA" }, /* FUNCTION APPLICATION */
154 { 0x2062, "IT" }, /* INVISIBLE TIMES */
155 { 0x2063, "IS" }, /* INVISIBLE SEPARATOR */
156 { 0xfeff, "ZWNBS" }, /* ZERO WIDTH NO-BREAK SPACE */
157 };
158
159 static inline G_GNUC_UNUSED const char *
pango_get_ignorable(gunichar ch)160 pango_get_ignorable (gunichar ch)
161 {
162 int i;
163
164 for (i = 0; i < G_N_ELEMENTS (ignorables); i++)
165 {
166 if (ch < ignorables[i].ch)
167 return NULL;
168
169 if (ch == ignorables[i].ch)
170 return ignorables[i].nick;
171 }
172 return NULL;
173 }
174
175 static inline G_GNUC_UNUSED const char *
pango_get_ignorable_size(gunichar ch,int * rows,int * cols)176 pango_get_ignorable_size (gunichar ch,
177 int *rows,
178 int *cols)
179 {
180 const char *nick;
181 int len;
182
183 nick = pango_get_ignorable (ch);
184 if (nick)
185 {
186 len = strlen (nick);
187 if (len < 4)
188 {
189 *rows = 1;
190 *cols = len;
191 }
192 else if (len > 4)
193 {
194 *rows = 2;
195 *cols = 3;
196 }
197 else
198 {
199 *rows = 2;
200 *cols = 2;
201 }
202 }
203
204 return nick;
205 }
206
207 /* Backward compatibility shim, to avoid bumping up the minimum
208 * required version of GLib; most of our uses of g_memdup() are
209 * safe, and those that aren't have been fixed
210 */
211 #if !GLIB_CHECK_VERSION (2, 67, 3)
212 # define g_memdup2(mem,size) g_memdup((mem),(size))
213 #endif
214
215 G_END_DECLS
216
217 #endif /* __PANGO_IMPL_UTILS_H__ */
218