summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c b/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c
new file mode 100644
index 0000000000..b5431a53e7
--- /dev/null
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-hebrew.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "harfbuzz-shaper.h"
+#include "harfbuzz-shaper-private.h"
+#include <assert.h>
+
+/*
+// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly
+// ligatures one does not want in modern Hebrew (as lam-alef ligatures).
+*/
+#ifndef NO_OPENTYPE
+static const HB_OpenTypeFeature hebrew_features[] = {
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
+ {0, 0}
+};
+#endif
+
+/* Hebrew shaping. In the non opentype case we try to use the
+ presentation forms specified for Hebrew. Especially for the
+ ligatures with Dagesh this gives much better results than we could
+ achieve manually.
+*/
+HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item)
+{
+ enum {
+ Dagesh = 0x5bc,
+ ShinDot = 0x5c1,
+ SinDot = 0x5c2,
+ Patah = 0x5b7,
+ Qamats = 0x5b8,
+ Holam = 0x5b9,
+ Rafe = 0x5bf
+ };
+
+ assert(shaper_item->item.script == HB_Script_Hebrew);
+
+#ifndef NO_OPENTYPE
+ if (HB_SelectScript(shaper_item, hebrew_features)) {
+
+ const int availableGlyphs = shaper_item->num_glyphs;
+ if (!HB_ConvertStringToGlyphIndices(shaper_item))
+ return FALSE;
+
+ HB_HeuristicSetGlyphAttributes(shaper_item);
+ HB_OpenTypeShape(shaper_item, /*properties*/0);
+ return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
+ }
+#endif
+
+ {
+ const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
+ unsigned short *logClusters = shaper_item->log_clusters;
+ HB_GlyphAttributes *attributes = shaper_item->attributes;
+
+ HB_Bool haveGlyphs;
+ int slen = 1;
+ int cluster_start = 0;
+ hb_uint32 i;
+
+ HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
+ *shapedChars = *uc;
+ logClusters[0] = 0;
+
+ for (i = 1; i < shaper_item->item.length; ++i) {
+ hb_uint16 base = shapedChars[cluster_start];
+ hb_uint16 shaped = 0;
+ HB_Bool invalid = FALSE;
+ if (uc[i] == Dagesh) {
+ if (base >= 0x5d0
+ && base <= 0x5ea
+ && base != 0x5d7
+ && base != 0x5dd
+ && base != 0x5df
+ && base != 0x5e2
+ && base != 0x5e5) {
+ shaped = base - 0x5d0 + 0xfb30;
+ } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) {
+ shaped = base + 2;
+ } else {
+ invalid = TRUE;
+ }
+ } else if (uc[i] == ShinDot) {
+ if (base == 0x05e9)
+ shaped = 0xfb2a;
+ else if (base == 0xfb49)
+ shaped = 0xfb2c;
+ else
+ invalid = TRUE;
+ } else if (uc[i] == SinDot) {
+ if (base == 0x05e9)
+ shaped = 0xfb2b;
+ else if (base == 0xfb49)
+ shaped = 0xfb2d;
+ else
+ invalid = TRUE;
+ } else if (uc[i] == Patah) {
+ if (base == 0x5d0)
+ shaped = 0xfb2e;
+ } else if (uc[i] == Qamats) {
+ if (base == 0x5d0)
+ shaped = 0xfb2f;
+ } else if (uc[i] == Holam) {
+ if (base == 0x5d5)
+ shaped = 0xfb4b;
+ } else if (uc[i] == Rafe) {
+ if (base == 0x5d1)
+ shaped = 0xfb4c;
+ else if (base == 0x5db)
+ shaped = 0xfb4d;
+ else if (base == 0x5e4)
+ shaped = 0xfb4e;
+ }
+
+ if (invalid) {
+ shapedChars[slen] = 0x25cc;
+ attributes[slen].clusterStart = TRUE;
+ attributes[slen].mark = FALSE;
+ attributes[slen].combiningClass = 0;
+ cluster_start = slen;
+ ++slen;
+ }
+ if (shaped) {
+ if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
+ shapedChars[cluster_start] = shaped;
+ } else
+ shaped = 0;
+ }
+ if (!shaped) {
+ HB_CharCategory category;
+ int cmb;
+ shapedChars[slen] = uc[i];
+ HB_GetUnicodeCharProperties(uc[i], &category, &cmb);
+ if (category != HB_Mark_NonSpacing) {
+ attributes[slen].clusterStart = TRUE;
+ attributes[slen].mark = FALSE;
+ attributes[slen].combiningClass = 0;
+ attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
+ cluster_start = slen;
+ } else {
+ attributes[slen].clusterStart = FALSE;
+ attributes[slen].mark = TRUE;
+ attributes[slen].combiningClass = cmb;
+ }
+ ++slen;
+ }
+ logClusters[i] = cluster_start;
+ }
+
+ haveGlyphs = shaper_item->font->klass
+ ->convertStringToGlyphIndices(shaper_item->font,
+ shapedChars, slen,
+ shaper_item->glyphs, &shaper_item->num_glyphs,
+ shaper_item->item.bidiLevel % 2);
+
+ HB_FREE_STACKARRAY(shapedChars);
+
+ if (!haveGlyphs)
+ return FALSE;
+
+ HB_HeuristicPosition(shaper_item);
+ }
+
+ return TRUE;
+}
+