[hb-old] Start adding HarfBuzz-old as a new backend
diff --git a/src/hb-old/harfbuzz-hebrew.c b/src/hb-old/harfbuzz-hebrew.c
new file mode 100644
index 0000000..b5431a5
--- /dev/null
+++ b/src/hb-old/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;
+}
+