diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:16:05 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:17:21 -0400 |
commit | bcdce34c8ac0adffd589e9fb68b62ff09368bb0f (patch) | |
tree | 7b92ba875b22212d15ffb9d9620d517cfa427a1e /pango2/pango-impl-utils.h | |
parent | b197cc08b18bc44a3e93f859ca7e61dfe335bbc5 (diff) | |
download | pango-bcdce34c8ac0adffd589e9fb68b62ff09368bb0f.tar.gz |
Move the code from pango/ to pango2/
Life is easier if the src path matches the installed
header path prefix, so make them match. Update all
users.
Diffstat (limited to 'pango2/pango-impl-utils.h')
-rw-r--r-- | pango2/pango-impl-utils.h | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/pango2/pango-impl-utils.h b/pango2/pango-impl-utils.h new file mode 100644 index 00000000..cc21bc0b --- /dev/null +++ b/pango2/pango-impl-utils.h @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2003 Red Hat Software + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib.h> +#include <glib-object.h> +#include <pango2/pango.h> + +G_BEGIN_DECLS + + +/* String interning for static strings */ +#define I_(string) g_intern_static_string (string) + +/* We define these functions static here because we don't want to add public API + * for them (if anything, it belongs to glib, but glib found it trivial enough + * not to add API for). At some point metrics calculations will be + * centralized and this mess can be minimized. Or so I hope. + */ + +static inline G_GNUC_UNUSED int +pango2_unichar_width (gunichar c) +{ + return G_UNLIKELY (g_unichar_iszerowidth (c)) ? 0 : + G_UNLIKELY (g_unichar_iswide (c)) ? 2 : 1; +} + +static G_GNUC_UNUSED glong +pango2_utf8_strwidth (const char *p) +{ + glong len = 0; + g_return_val_if_fail (p != NULL, 0); + + while (*p) + { + len += pango2_unichar_width (g_utf8_get_char (p)); + p = g_utf8_next_char (p); + } + + return len; +} + +/* Glib's g_utf8_strlen() is broken and stops at embedded NUL's. + * Wrap it here. */ +static G_GNUC_UNUSED glong +pango2_utf8_strlen (const char *p, + gssize max) +{ + glong len = 0; + const char *start = p; + g_return_val_if_fail (p != NULL || max == 0, 0); + + if (max <= 0) + return g_utf8_strlen (p, max); + + p = g_utf8_next_char (p); + while (p - start < max) + { + ++len; + p = g_utf8_next_char (p); + } + + /* only do the last len increment if we got a complete + * char (don't count partial chars) + */ + if (p - start <= max) + ++len; + + return len; +} + + +/* To be made public at some point */ + +static G_GNUC_UNUSED void +pango2_glyph_string_reverse_range (Pango2GlyphString *glyphs, + int start, + int end) +{ + int i, j; + + for (i = start, j = end - 1; i < j; i++, j--) + { + Pango2GlyphInfo glyph_info; + int log_cluster; + + glyph_info = glyphs->glyphs[i]; + glyphs->glyphs[i] = glyphs->glyphs[j]; + glyphs->glyphs[j] = glyph_info; + + log_cluster = glyphs->log_clusters[i]; + glyphs->log_clusters[i] = glyphs->log_clusters[j]; + glyphs->log_clusters[j] = log_cluster; + } +} + +static inline gboolean +pango2_is_default_ignorable (gunichar ch) +{ + int plane = ch >> 16; + + if (G_LIKELY (plane == 0)) + { + int page = ch >> 8; + switch (page) + { + case 0x00: return ch == 0x00ad; + case 0x03: return ch == 0x034f; + case 0x06: return ch == 0x061c; + case 0x17: return (0x17b4 <= ch && ch <= 0x17b5); + case 0x18: return (0x180b <= ch && ch <= 0x180e); + case 0x20: return (0x200b <= ch && ch <= 0x200f) || + (0x202a <= ch && ch <= 0x202e) || + (0x2060 <= ch && ch <= 0x206f); + case 0xfe: return (0xfe00 <= ch && ch <= 0xfe0f) || ch == 0xfeff; + case 0xff: return (0xfff0 <= ch && ch <= 0xfff8); + default: return FALSE; + } + } + else + { + /* Other planes */ + switch (plane) + { + case 0x01: return (0x1d173 <= ch && ch <= 0x1d17a); + case 0x0e: return (0xe0000 <= ch && ch <= 0xe0fff); + default: return FALSE; + } + } +} + +/* These are the default ignorables that we render as hexboxes + * with nicks if PANGO2_SHOW_IGNORABLES is used. + * + * The cairo hexbox drawing code assumes that these nicks are + * 1-6 ASCII chars + */ +static struct { + gunichar ch; + const char *nick; +} ignorables[] = { + { 0x00ad, "SHY" }, /* SOFT HYPHEN */ + { 0x034f, "CGJ" }, /* COMBINING GRAPHEME JOINER */ + { 0x061c, "ALM" }, /* ARABIC LETTER MARK */ + { 0x200b, "ZWS" }, /* ZERO WIDTH SPACE */ + { 0x200c, "ZWNJ" }, /* ZERO WIDTH NON-JOINER */ + { 0x200d, "ZWJ" }, /* ZERO WIDTH JOINER */ + { 0x200e, "LRM" }, /* LEFT-TO-RIGHT MARK */ + { 0x200f, "RLM" }, /* RIGHT-TO-LEFT MARK */ + { 0x2028, "LS" }, /* LINE SEPARATOR */ + { 0x2029, "PS" }, /* PARAGRAPH SEPARATOR */ + { 0x202a, "LRE" }, /* LEFT-TO-RIGHT EMBEDDING */ + { 0x202b, "RLE" }, /* RIGHT-TO-LEFT EMBEDDING */ + { 0x202c, "PDF" }, /* POP DIRECTIONAL FORMATTING */ + { 0x202d, "LRO" }, /* LEFT-TO-RIGHT OVERRIDE */ + { 0x202e, "RLO" }, /* RIGHT-TO-LEFT OVERRIDE */ + { 0x2060, "WJ" }, /* WORD JOINER */ + { 0x2061, "FA" }, /* FUNCTION APPLICATION */ + { 0x2062, "IT" }, /* INVISIBLE TIMES */ + { 0x2063, "IS" }, /* INVISIBLE SEPARATOR */ + { 0x2066, "LRI" }, /* LEFT-TO-RIGHT ISOLATE */ + { 0x2067, "RLI" }, /* RIGHT-TO-LEFT ISOLATE */ + { 0x2068, "FSI" }, /* FIRST STRONG ISOLATE */ + { 0x2069, "PDI" }, /* POP DIRECTIONAL ISOLATE */ + { 0xfeff, "ZWNBS" }, /* ZERO WIDTH NO-BREAK SPACE */ +}; + +static inline G_GNUC_UNUSED const char * +pango2_get_ignorable (gunichar ch) +{ + for (guint i = 0; i < G_N_ELEMENTS (ignorables); i++) + { + if (ch < ignorables[i].ch) + return NULL; + + if (ch == ignorables[i].ch) + return ignorables[i].nick; + } + + return NULL; +} + +static inline G_GNUC_UNUSED const char * +pango2_get_ignorable_size (gunichar ch, + int *rows, + int *cols) +{ + const char *nick; + int len; + + nick = pango2_get_ignorable (ch); + if (nick) + { + len = strlen (nick); + if (len < 4) + { + *rows = 1; + *cols = len; + } + else if (len > 4) + { + *rows = 2; + *cols = 3; + } + else + { + *rows = 2; + *cols = 2; + } + } + + return nick; +} + +/* Backward compatibility shim, to avoid bumping up the minimum + * required version of GLib; most of our uses of g_memdup() are + * safe, and those that aren't have been fixed + */ +#if !GLIB_CHECK_VERSION (2, 67, 3) +# define g_memdup2(mem,size) g_memdup((mem),(size)) +#endif + +G_END_DECLS |