diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-04-08 18:48:12 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-04-08 18:48:12 +0000 |
commit | 5469607a00d84a07dc638eda46a87fc90142d64b (patch) | |
tree | cce121bf02e868c5a711d63e58a43288c461c8c3 /third_party/harfbuzz/src/harfbuzz-hebrew.c | |
parent | a4e5ed854acf0cc707d8768420ce9fb9313ba60a (diff) |
add
git-svn-id: http://skia.googlecode.com/svn/trunk@536 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'third_party/harfbuzz/src/harfbuzz-hebrew.c')
-rw-r--r-- | third_party/harfbuzz/src/harfbuzz-hebrew.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/third_party/harfbuzz/src/harfbuzz-hebrew.c b/third_party/harfbuzz/src/harfbuzz-hebrew.c new file mode 100644 index 0000000000..d2664deefa --- /dev/null +++ b/third_party/harfbuzz/src/harfbuzz-hebrew.c @@ -0,0 +1,189 @@ +/* + * 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); + + HB_HeuristicSetGlyphAttributes(shaper_item); + +#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_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; +} + |