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#ifndef NO_OPENTYPE 605569331642446be05292e3e1f8a51218827168cdclaireho if (HB_SelectScript(shaper_item, hebrew_features)) { 615569331642446be05292e3e1f8a51218827168cdclaireho 625569331642446be05292e3e1f8a51218827168cdclaireho const int availableGlyphs = shaper_item->num_glyphs; 635569331642446be05292e3e1f8a51218827168cdclaireho if (!HB_ConvertStringToGlyphIndices(shaper_item)) 645569331642446be05292e3e1f8a51218827168cdclaireho return FALSE; 655569331642446be05292e3e1f8a51218827168cdclaireho 6657e6107a9d66a9a97b146def0ef38c010f954be6claireho HB_HeuristicSetGlyphAttributes(shaper_item); 675569331642446be05292e3e1f8a51218827168cdclaireho HB_OpenTypeShape(shaper_item, /*properties*/0); 685569331642446be05292e3e1f8a51218827168cdclaireho return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE); 695569331642446be05292e3e1f8a51218827168cdclaireho } 705569331642446be05292e3e1f8a51218827168cdclaireho#endif 715569331642446be05292e3e1f8a51218827168cdclaireho 725569331642446be05292e3e1f8a51218827168cdclaireho { 735569331642446be05292e3e1f8a51218827168cdclaireho const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos; 745569331642446be05292e3e1f8a51218827168cdclaireho unsigned short *logClusters = shaper_item->log_clusters; 755569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = shaper_item->attributes; 765569331642446be05292e3e1f8a51218827168cdclaireho 775569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool haveGlyphs; 785569331642446be05292e3e1f8a51218827168cdclaireho int slen = 1; 795569331642446be05292e3e1f8a51218827168cdclaireho int cluster_start = 0; 805569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 i; 815569331642446be05292e3e1f8a51218827168cdclaireho 825569331642446be05292e3e1f8a51218827168cdclaireho HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length); 835569331642446be05292e3e1f8a51218827168cdclaireho *shapedChars = *uc; 845569331642446be05292e3e1f8a51218827168cdclaireho logClusters[0] = 0; 855569331642446be05292e3e1f8a51218827168cdclaireho 865569331642446be05292e3e1f8a51218827168cdclaireho for (i = 1; i < shaper_item->item.length; ++i) { 87ca4c6948f69f807967f91d0e995716dd0f421dc5claireho hb_uint16 base = shapedChars[cluster_start]; 885569331642446be05292e3e1f8a51218827168cdclaireho hb_uint16 shaped = 0; 895569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool invalid = FALSE; 905569331642446be05292e3e1f8a51218827168cdclaireho if (uc[i] == Dagesh) { 915569331642446be05292e3e1f8a51218827168cdclaireho if (base >= 0x5d0 925569331642446be05292e3e1f8a51218827168cdclaireho && base <= 0x5ea 935569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5d7 945569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5dd 955569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5df 965569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5e2 975569331642446be05292e3e1f8a51218827168cdclaireho && base != 0x5e5) { 985569331642446be05292e3e1f8a51218827168cdclaireho shaped = base - 0x5d0 + 0xfb30; 995569331642446be05292e3e1f8a51218827168cdclaireho } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) { 1005569331642446be05292e3e1f8a51218827168cdclaireho shaped = base + 2; 1015569331642446be05292e3e1f8a51218827168cdclaireho } else { 1025569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1035569331642446be05292e3e1f8a51218827168cdclaireho } 1045569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == ShinDot) { 1055569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x05e9) 1065569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2a; 1075569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0xfb49) 1085569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2c; 1095569331642446be05292e3e1f8a51218827168cdclaireho else 1105569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1115569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == SinDot) { 1125569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x05e9) 1135569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2b; 1145569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0xfb49) 1155569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2d; 1165569331642446be05292e3e1f8a51218827168cdclaireho else 1175569331642446be05292e3e1f8a51218827168cdclaireho invalid = TRUE; 1185569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Patah) { 1195569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d0) 1205569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2e; 1215569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Qamats) { 1225569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d0) 1235569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb2f; 1245569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Holam) { 1255569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d5) 1265569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4b; 1275569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[i] == Rafe) { 1285569331642446be05292e3e1f8a51218827168cdclaireho if (base == 0x5d1) 1295569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4c; 1305569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0x5db) 1315569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4d; 1325569331642446be05292e3e1f8a51218827168cdclaireho else if (base == 0x5e4) 1335569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0xfb4e; 1345569331642446be05292e3e1f8a51218827168cdclaireho } 1355569331642446be05292e3e1f8a51218827168cdclaireho 1365569331642446be05292e3e1f8a51218827168cdclaireho if (invalid) { 1375569331642446be05292e3e1f8a51218827168cdclaireho shapedChars[slen] = 0x25cc; 1385569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = TRUE; 1395569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = FALSE; 1405569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = 0; 1415569331642446be05292e3e1f8a51218827168cdclaireho cluster_start = slen; 1425569331642446be05292e3e1f8a51218827168cdclaireho ++slen; 1435569331642446be05292e3e1f8a51218827168cdclaireho } 1445569331642446be05292e3e1f8a51218827168cdclaireho if (shaped) { 1455569331642446be05292e3e1f8a51218827168cdclaireho if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) { 146ca4c6948f69f807967f91d0e995716dd0f421dc5claireho shapedChars[cluster_start] = shaped; 1475569331642446be05292e3e1f8a51218827168cdclaireho } else 1485569331642446be05292e3e1f8a51218827168cdclaireho shaped = 0; 1495569331642446be05292e3e1f8a51218827168cdclaireho } 1505569331642446be05292e3e1f8a51218827168cdclaireho if (!shaped) { 1515569331642446be05292e3e1f8a51218827168cdclaireho HB_CharCategory category; 1525569331642446be05292e3e1f8a51218827168cdclaireho int cmb; 1535569331642446be05292e3e1f8a51218827168cdclaireho shapedChars[slen] = uc[i]; 1545569331642446be05292e3e1f8a51218827168cdclaireho HB_GetUnicodeCharProperties(uc[i], &category, &cmb); 1555569331642446be05292e3e1f8a51218827168cdclaireho if (category != HB_Mark_NonSpacing) { 1565569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = TRUE; 1575569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = FALSE; 1585569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = 0; 1595569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].dontPrint = HB_IsControlChar(uc[i]); 1605569331642446be05292e3e1f8a51218827168cdclaireho cluster_start = slen; 1615569331642446be05292e3e1f8a51218827168cdclaireho } else { 1625569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].clusterStart = FALSE; 1635569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].mark = TRUE; 1645569331642446be05292e3e1f8a51218827168cdclaireho attributes[slen].combiningClass = cmb; 1655569331642446be05292e3e1f8a51218827168cdclaireho } 1665569331642446be05292e3e1f8a51218827168cdclaireho ++slen; 1675569331642446be05292e3e1f8a51218827168cdclaireho } 1685569331642446be05292e3e1f8a51218827168cdclaireho logClusters[i] = cluster_start; 1695569331642446be05292e3e1f8a51218827168cdclaireho } 1705569331642446be05292e3e1f8a51218827168cdclaireho 1715569331642446be05292e3e1f8a51218827168cdclaireho haveGlyphs = shaper_item->font->klass 1725569331642446be05292e3e1f8a51218827168cdclaireho ->convertStringToGlyphIndices(shaper_item->font, 1735569331642446be05292e3e1f8a51218827168cdclaireho shapedChars, slen, 1745569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphs, &shaper_item->num_glyphs, 1755569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->item.bidiLevel % 2); 1765569331642446be05292e3e1f8a51218827168cdclaireho 1775569331642446be05292e3e1f8a51218827168cdclaireho HB_FREE_STACKARRAY(shapedChars); 1785569331642446be05292e3e1f8a51218827168cdclaireho 1795569331642446be05292e3e1f8a51218827168cdclaireho if (!haveGlyphs) 1805569331642446be05292e3e1f8a51218827168cdclaireho return FALSE; 1815569331642446be05292e3e1f8a51218827168cdclaireho 1825569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicPosition(shaper_item); 1835569331642446be05292e3e1f8a51218827168cdclaireho } 1845569331642446be05292e3e1f8a51218827168cdclaireho 1855569331642446be05292e3e1f8a51218827168cdclaireho return TRUE; 1865569331642446be05292e3e1f8a51218827168cdclaireho} 1875569331642446be05292e3e1f8a51218827168cdclaireho 188