harfbuzz-hebrew.c revision 5569331642446be05292e3e1f8a51218827168cd
15569331642446be05292e3e1f8a51218827168cdclaireho/* 25569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 35569331642446be05292e3e1f8a51218827168cdclaireho * 45569331642446be05292e3e1f8a51218827168cdclaireho * This is part of HarfBuzz, an OpenType Layout engine library. 55569331642446be05292e3e1f8a51218827168cdclaireho * 65569331642446be05292e3e1f8a51218827168cdclaireho * Permission is hereby granted, without written agreement and without 75569331642446be05292e3e1f8a51218827168cdclaireho * license or royalty fees, to use, copy, modify, and distribute this 85569331642446be05292e3e1f8a51218827168cdclaireho * software and its documentation for any purpose, provided that the 95569331642446be05292e3e1f8a51218827168cdclaireho * above copyright notice and the following two paragraphs appear in 105569331642446be05292e3e1f8a51218827168cdclaireho * all copies of this software. 115569331642446be05292e3e1f8a51218827168cdclaireho * 125569331642446be05292e3e1f8a51218827168cdclaireho * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 135569331642446be05292e3e1f8a51218827168cdclaireho * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 145569331642446be05292e3e1f8a51218827168cdclaireho * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 155569331642446be05292e3e1f8a51218827168cdclaireho * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 165569331642446be05292e3e1f8a51218827168cdclaireho * DAMAGE. 175569331642446be05292e3e1f8a51218827168cdclaireho * 185569331642446be05292e3e1f8a51218827168cdclaireho * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 195569331642446be05292e3e1f8a51218827168cdclaireho * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 205569331642446be05292e3e1f8a51218827168cdclaireho * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 215569331642446be05292e3e1f8a51218827168cdclaireho * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 225569331642446be05292e3e1f8a51218827168cdclaireho * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 235569331642446be05292e3e1f8a51218827168cdclaireho */ 245569331642446be05292e3e1f8a51218827168cdclaireho 255569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-shaper.h" 265569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-shaper-private.h" 275569331642446be05292e3e1f8a51218827168cdclaireho#include <assert.h> 285569331642446be05292e3e1f8a51218827168cdclaireho 295569331642446be05292e3e1f8a51218827168cdclaireho/* 305569331642446be05292e3e1f8a51218827168cdclaireho// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly 315569331642446be05292e3e1f8a51218827168cdclaireho// ligatures one does not want in modern Hebrew (as lam-alef ligatures). 325569331642446be05292e3e1f8a51218827168cdclaireho*/ 335569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE 345569331642446be05292e3e1f8a51218827168cdclairehostatic const HB_OpenTypeFeature hebrew_features[] = { 355569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, 365569331642446be05292e3e1f8a51218827168cdclaireho {0, 0} 375569331642446be05292e3e1f8a51218827168cdclaireho}; 385569331642446be05292e3e1f8a51218827168cdclaireho#endif 395569331642446be05292e3e1f8a51218827168cdclaireho 405569331642446be05292e3e1f8a51218827168cdclaireho/* Hebrew shaping. In the non opentype case we try to use the 415569331642446be05292e3e1f8a51218827168cdclaireho presentation forms specified for Hebrew. Especially for the 425569331642446be05292e3e1f8a51218827168cdclaireho ligatures with Dagesh this gives much better results than we could 435569331642446be05292e3e1f8a51218827168cdclaireho achieve manually. 445569331642446be05292e3e1f8a51218827168cdclaireho*/ 455569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item) 465569331642446be05292e3e1f8a51218827168cdclaireho{ 475569331642446be05292e3e1f8a51218827168cdclaireho enum { 485569331642446be05292e3e1f8a51218827168cdclaireho Dagesh = 0x5bc, 495569331642446be05292e3e1f8a51218827168cdclaireho ShinDot = 0x5c1, 505569331642446be05292e3e1f8a51218827168cdclaireho SinDot = 0x5c2, 515569331642446be05292e3e1f8a51218827168cdclaireho Patah = 0x5b7, 525569331642446be05292e3e1f8a51218827168cdclaireho Qamats = 0x5b8, 535569331642446be05292e3e1f8a51218827168cdclaireho Holam = 0x5b9, 545569331642446be05292e3e1f8a51218827168cdclaireho Rafe = 0x5bf 555569331642446be05292e3e1f8a51218827168cdclaireho }; 565569331642446be05292e3e1f8a51218827168cdclaireho 575569331642446be05292e3e1f8a51218827168cdclaireho assert(shaper_item->item.script == HB_Script_Hebrew); 585569331642446be05292e3e1f8a51218827168cdclaireho 595569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicSetGlyphAttributes(shaper_item); 605569331642446be05292e3e1f8a51218827168cdclaireho 615569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE 625569331642446be05292e3e1f8a51218827168cdclaireho if (HB_SelectScript(shaper_item, hebrew_features)) { 635569331642446be05292e3e1f8a51218827168cdclaireho 645569331642446be05292e3e1f8a51218827168cdclaireho const int availableGlyphs = shaper_item->num_glyphs; 655569331642446be05292e3e1f8a51218827168cdclaireho if (!HB_ConvertStringToGlyphIndices(shaper_item)) 665569331642446be05292e3e1f8a51218827168cdclaireho return FALSE; 675569331642446be05292e3e1f8a51218827168cdclaireho 685569331642446be05292e3e1f8a51218827168cdclaireho 695569331642446be05292e3e1f8a51218827168cdclaireho HB_OpenTypeShape(shaper_item, /*properties*/0); 705569331642446be05292e3e1f8a51218827168cdclaireho return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE); 715569331642446be05292e3e1f8a51218827168cdclaireho } 725569331642446be05292e3e1f8a51218827168cdclaireho#endif 735569331642446be05292e3e1f8a51218827168cdclaireho 745569331642446be05292e3e1f8a51218827168cdclaireho { 755569331642446be05292e3e1f8a51218827168cdclaireho const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos; 765569331642446be05292e3e1f8a51218827168cdclaireho unsigned short *logClusters = shaper_item->log_clusters; 775569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = shaper_item->attributes; 785569331642446be05292e3e1f8a51218827168cdclaireho 795569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool haveGlyphs; 805569331642446be05292e3e1f8a51218827168cdclaireho int slen = 1; 815569331642446be05292e3e1f8a51218827168cdclaireho int cluster_start = 0; 825569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 i; 835569331642446be05292e3e1f8a51218827168cdclaireho 845569331642446be05292e3e1f8a51218827168cdclaireho HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length); 855569331642446be05292e3e1f8a51218827168cdclaireho *shapedChars = *uc; 865569331642446be05292e3e1f8a51218827168cdclaireho logClusters[0] = 0; 875569331642446be05292e3e1f8a51218827168cdclaireho 885569331642446be05292e3e1f8a51218827168cdclaireho for (i = 1; i < shaper_item->item.length; ++i) { 895569331642446be05292e3e1f8a51218827168cdclaireho hb_uint16 base = shapedChars[cluster_start]; 905569331642446be05292e3e1f8a51218827168cdclaireho hb_uint16 shaped = 0; 915569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool invalid = FALSE; 925569331642446be05292e3e1f8a51218827168cdclaireho if (uc[i] == Dagesh) { 935569331642446be05292e3e1f8a51218827168cdclaireho if (base >= 0x5d0 945569331642446be05292e3e1f8a51218827168cdclaireho && base <= 0x5ea 955569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5d7 965569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5dd 975569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5df 985569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5e2 995569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5e5) { 1005569331642446be05292e3e1f8a51218827168cdclaireho shaped = base - 0x5d0 + 0xfb30; 1015569331642446be05292e3e1f8a51218827168cdclaireho } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) { 1025569331642446be05292e3e1f8a51218827168cdclaireho shaped = base + 2; 1035569331642446be05292e3e1f8a51218827168cdclaireho } else { 1045569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1055569331642446be05292e3e1f8a51218827168cdclaireho } 1065569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == ShinDot) { 1075569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x05e9) 1085569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2a; 1095569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0xfb49) 1105569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2c; 1115569331642446be05292e3e1f8a51218827168cdclaireho else 1125569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1135569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == SinDot) { 1145569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x05e9) 1155569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2b; 1165569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0xfb49) 1175569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2d; 1185569331642446be05292e3e1f8a51218827168cdclaireho else 1195569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1205569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Patah) { 1215569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d0) 1225569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2e; 1235569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Qamats) { 1245569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d0) 1255569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2f; 1265569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Holam) { 1275569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d5) 1285569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4b; 1295569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Rafe) { 1305569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d1) 1315569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4c; 1325569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0x5db) 1335569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4d; 1345569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0x5e4) 1355569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4e; 1365569331642446be05292e3e1f8a51218827168cdclaireho } 1375569331642446be05292e3e1f8a51218827168cdclaireho 1385569331642446be05292e3e1f8a51218827168cdclaireho if (invalid) { 1395569331642446be05292e3e1f8a51218827168cdclaireho shapedChars[slen] = 0x25cc; 1405569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = TRUE; 1415569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = FALSE; 1425569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = 0; 1435569331642446be05292e3e1f8a51218827168cdclaireho cluster_start = slen; 1445569331642446be05292e3e1f8a51218827168cdclaireho ++slen; 1455569331642446be05292e3e1f8a51218827168cdclaireho } 1465569331642446be05292e3e1f8a51218827168cdclaireho if (shaped) { 1475569331642446be05292e3e1f8a51218827168cdclaireho if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) { 1485569331642446be05292e3e1f8a51218827168cdclaireho shapedChars[cluster_start] = shaped; 1495569331642446be05292e3e1f8a51218827168cdclaireho } else 1505569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0; 1515569331642446be05292e3e1f8a51218827168cdclaireho } 1525569331642446be05292e3e1f8a51218827168cdclaireho if (!shaped) { 1535569331642446be05292e3e1f8a51218827168cdclaireho HB_CharCategory category; 1545569331642446be05292e3e1f8a51218827168cdclaireho int cmb; 1555569331642446be05292e3e1f8a51218827168cdclaireho shapedChars[slen] = uc[i]; 1565569331642446be05292e3e1f8a51218827168cdclaireho HB_GetUnicodeCharProperties(uc[i], &category, &cmb); 1575569331642446be05292e3e1f8a51218827168cdclaireho if (category != HB_Mark_NonSpacing) { 1585569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = TRUE; 1595569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = FALSE; 1605569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = 0; 1615569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].dontPrint = HB_IsControlChar(uc[i]); 1625569331642446be05292e3e1f8a51218827168cdclaireho cluster_start = slen; 1635569331642446be05292e3e1f8a51218827168cdclaireho } else { 1645569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = FALSE; 1655569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = TRUE; 1665569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = cmb; 1675569331642446be05292e3e1f8a51218827168cdclaireho } 1685569331642446be05292e3e1f8a51218827168cdclaireho ++slen; 1695569331642446be05292e3e1f8a51218827168cdclaireho } 1705569331642446be05292e3e1f8a51218827168cdclaireho logClusters[i] = cluster_start; 1715569331642446be05292e3e1f8a51218827168cdclaireho } 1725569331642446be05292e3e1f8a51218827168cdclaireho 1735569331642446be05292e3e1f8a51218827168cdclaireho haveGlyphs = shaper_item->font->klass 1745569331642446be05292e3e1f8a51218827168cdclaireho ->convertStringToGlyphIndices(shaper_item->font, 1755569331642446be05292e3e1f8a51218827168cdclaireho shapedChars, slen, 1765569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphs, &shaper_item->num_glyphs, 1775569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->item.bidiLevel % 2); 1785569331642446be05292e3e1f8a51218827168cdclaireho 1795569331642446be05292e3e1f8a51218827168cdclaireho HB_FREE_STACKARRAY(shapedChars); 1805569331642446be05292e3e1f8a51218827168cdclaireho 1815569331642446be05292e3e1f8a51218827168cdclaireho if (!haveGlyphs) 1825569331642446be05292e3e1f8a51218827168cdclaireho return FALSE; 1835569331642446be05292e3e1f8a51218827168cdclaireho 1845569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicPosition(shaper_item); 1855569331642446be05292e3e1f8a51218827168cdclaireho } 1865569331642446be05292e3e1f8a51218827168cdclaireho 1875569331642446be05292e3e1f8a51218827168cdclaireho return TRUE; 1885569331642446be05292e3e1f8a51218827168cdclaireho} 1895569331642446be05292e3e1f8a51218827168cdclaireho 190