harfbuzz-shaper.cpp 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 285569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-stream-private.h" 295569331642446be05292e3e1f8a51218827168cdclaireho#include <assert.h> 305569331642446be05292e3e1f8a51218827168cdclaireho#include <stdio.h> 315569331642446be05292e3e1f8a51218827168cdclaireho 325569331642446be05292e3e1f8a51218827168cdclaireho#define HB_MIN(a, b) ((a) < (b) ? (a) : (b)) 335569331642446be05292e3e1f8a51218827168cdclaireho#define HB_MAX(a, b) ((a) > (b) ? (a) : (b)) 345569331642446be05292e3e1f8a51218827168cdclaireho 355569331642446be05292e3e1f8a51218827168cdclaireho// ----------------------------------------------------------------------------------------------------- 365569331642446be05292e3e1f8a51218827168cdclaireho// 375569331642446be05292e3e1f8a51218827168cdclaireho// The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html 385569331642446be05292e3e1f8a51218827168cdclaireho// 395569331642446be05292e3e1f8a51218827168cdclaireho// ----------------------------------------------------------------------------------------------------- 405569331642446be05292e3e1f8a51218827168cdclaireho 415569331642446be05292e3e1f8a51218827168cdclaireho/* The Unicode algorithm does in our opinion allow line breaks at some 425569331642446be05292e3e1f8a51218827168cdclaireho places they shouldn't be allowed. The following changes were thus 435569331642446be05292e3e1f8a51218827168cdclaireho made in comparison to the Unicode reference: 445569331642446be05292e3e1f8a51218827168cdclaireho 455569331642446be05292e3e1f8a51218827168cdclaireho EX->AL from DB to IB 465569331642446be05292e3e1f8a51218827168cdclaireho SY->AL from DB to IB 475569331642446be05292e3e1f8a51218827168cdclaireho SY->PO from DB to IB 485569331642446be05292e3e1f8a51218827168cdclaireho SY->PR from DB to IB 495569331642446be05292e3e1f8a51218827168cdclaireho SY->OP from DB to IB 505569331642446be05292e3e1f8a51218827168cdclaireho AL->PR from DB to IB 515569331642446be05292e3e1f8a51218827168cdclaireho AL->PO from DB to IB 525569331642446be05292e3e1f8a51218827168cdclaireho PR->PR from DB to IB 535569331642446be05292e3e1f8a51218827168cdclaireho PO->PO from DB to IB 545569331642446be05292e3e1f8a51218827168cdclaireho PR->PO from DB to IB 555569331642446be05292e3e1f8a51218827168cdclaireho PO->PR from DB to IB 565569331642446be05292e3e1f8a51218827168cdclaireho HY->PO from DB to IB 575569331642446be05292e3e1f8a51218827168cdclaireho HY->PR from DB to IB 585569331642446be05292e3e1f8a51218827168cdclaireho HY->OP from DB to IB 595569331642446be05292e3e1f8a51218827168cdclaireho NU->EX from PB to IB 605569331642446be05292e3e1f8a51218827168cdclaireho EX->PO from DB to IB 615569331642446be05292e3e1f8a51218827168cdclaireho*/ 625569331642446be05292e3e1f8a51218827168cdclaireho 635569331642446be05292e3e1f8a51218827168cdclaireho// The following line break classes are not treated by the table: 645569331642446be05292e3e1f8a51218827168cdclaireho// AI, BK, CB, CR, LF, NL, SA, SG, SP, XX 655569331642446be05292e3e1f8a51218827168cdclaireho 665569331642446be05292e3e1f8a51218827168cdclairehoenum break_class { 675569331642446be05292e3e1f8a51218827168cdclaireho // the first 4 values have to agree with the enum in QCharAttributes 685569331642446be05292e3e1f8a51218827168cdclaireho ProhibitedBreak, // PB in table 695569331642446be05292e3e1f8a51218827168cdclaireho DirectBreak, // DB in table 705569331642446be05292e3e1f8a51218827168cdclaireho IndirectBreak, // IB in table 715569331642446be05292e3e1f8a51218827168cdclaireho CombiningIndirectBreak, // CI in table 725569331642446be05292e3e1f8a51218827168cdclaireho CombiningProhibitedBreak // CP in table 735569331642446be05292e3e1f8a51218827168cdclaireho}; 745569331642446be05292e3e1f8a51218827168cdclaireho#define DB DirectBreak 755569331642446be05292e3e1f8a51218827168cdclaireho#define IB IndirectBreak 765569331642446be05292e3e1f8a51218827168cdclaireho#define CI CombiningIndirectBreak 775569331642446be05292e3e1f8a51218827168cdclaireho#define CP CombiningProhibitedBreak 785569331642446be05292e3e1f8a51218827168cdclaireho#define PB ProhibitedBreak 795569331642446be05292e3e1f8a51218827168cdclaireho 805569331642446be05292e3e1f8a51218827168cdclairehostatic const hb_uint8 breakTable[HB_LineBreak_JT+1][HB_LineBreak_JT+1] = 815569331642446be05292e3e1f8a51218827168cdclaireho{ 825569331642446be05292e3e1f8a51218827168cdclaireho/* OP CL QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT */ 835569331642446be05292e3e1f8a51218827168cdclaireho/* OP */ { PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, CP, PB, PB, PB, PB, PB, PB }, 845569331642446be05292e3e1f8a51218827168cdclaireho/* CL */ { DB, PB, IB, IB, PB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 855569331642446be05292e3e1f8a51218827168cdclaireho/* QU */ { PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB }, 865569331642446be05292e3e1f8a51218827168cdclaireho/* GL */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB }, 875569331642446be05292e3e1f8a51218827168cdclaireho/* NS */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 885569331642446be05292e3e1f8a51218827168cdclaireho/* EX */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 895569331642446be05292e3e1f8a51218827168cdclaireho/* SY */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 905569331642446be05292e3e1f8a51218827168cdclaireho/* IS */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 915569331642446be05292e3e1f8a51218827168cdclaireho/* PR */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, IB }, 925569331642446be05292e3e1f8a51218827168cdclaireho/* PO */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 935569331642446be05292e3e1f8a51218827168cdclaireho/* NU */ { IB, PB, IB, IB, IB, IB, PB, PB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 945569331642446be05292e3e1f8a51218827168cdclaireho/* AL */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 955569331642446be05292e3e1f8a51218827168cdclaireho/* ID */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 965569331642446be05292e3e1f8a51218827168cdclaireho/* IN */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 975569331642446be05292e3e1f8a51218827168cdclaireho/* HY */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 985569331642446be05292e3e1f8a51218827168cdclaireho/* BA */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 995569331642446be05292e3e1f8a51218827168cdclaireho/* BB */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB }, 1005569331642446be05292e3e1f8a51218827168cdclaireho/* B2 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, PB, PB, CI, PB, DB, DB, DB, DB, DB }, 1015569331642446be05292e3e1f8a51218827168cdclaireho/* ZW */ { DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, DB, DB, DB, DB, DB, DB, DB }, 1025569331642446be05292e3e1f8a51218827168cdclaireho/* CM */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB }, 1035569331642446be05292e3e1f8a51218827168cdclaireho/* WJ */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB }, 1045569331642446be05292e3e1f8a51218827168cdclaireho/* H2 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB }, 1055569331642446be05292e3e1f8a51218827168cdclaireho/* H3 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB }, 1065569331642446be05292e3e1f8a51218827168cdclaireho/* JL */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, DB }, 1075569331642446be05292e3e1f8a51218827168cdclaireho/* JV */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB }, 1085569331642446be05292e3e1f8a51218827168cdclaireho/* JT */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB } 1095569331642446be05292e3e1f8a51218827168cdclaireho}; 1105569331642446be05292e3e1f8a51218827168cdclaireho#undef DB 1115569331642446be05292e3e1f8a51218827168cdclaireho#undef IB 1125569331642446be05292e3e1f8a51218827168cdclaireho#undef CI 1135569331642446be05292e3e1f8a51218827168cdclaireho#undef CP 1145569331642446be05292e3e1f8a51218827168cdclaireho#undef PB 1155569331642446be05292e3e1f8a51218827168cdclaireho 1165569331642446be05292e3e1f8a51218827168cdclairehostatic const hb_uint8 graphemeTable[HB_Grapheme_LVT + 1][HB_Grapheme_LVT + 1] = 1175569331642446be05292e3e1f8a51218827168cdclaireho{ 1185569331642446be05292e3e1f8a51218827168cdclaireho// Other, CR, LF, Control,Extend,L, V, T, LV, LVT 1195569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , true , true , true , true , true }, // Other, 1205569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , true , true , true , true , true }, // CR, 1215569331642446be05292e3e1f8a51218827168cdclaireho { true , false, true , true , true , true , true , true , true , true }, // LF, 1225569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , true , true , true , true , true }, // Control, 1235569331642446be05292e3e1f8a51218827168cdclaireho { false, true , true , true , false, false, false, false, false, false }, // Extend, 1245569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , false, true , true , true , true }, // L, 1255569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , false, false, true , false, true }, // V, 1265569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , true , false, false, false, false }, // T, 1275569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , false, true , true , true , true }, // LV, 1285569331642446be05292e3e1f8a51218827168cdclaireho { true , true , true , true , true , false, true , true , true , true }, // LVT 1295569331642446be05292e3e1f8a51218827168cdclaireho}; 1305569331642446be05292e3e1f8a51218827168cdclaireho 1315569331642446be05292e3e1f8a51218827168cdclairehostatic void calcLineBreaks(const HB_UChar16 *uc, hb_uint32 len, HB_CharAttributes *charAttributes) 1325569331642446be05292e3e1f8a51218827168cdclaireho{ 1335569331642446be05292e3e1f8a51218827168cdclaireho if (!len) 1345569331642446be05292e3e1f8a51218827168cdclaireho return; 1355569331642446be05292e3e1f8a51218827168cdclaireho 1365569331642446be05292e3e1f8a51218827168cdclaireho // ##### can this fail if the first char is a surrogate? 1375569331642446be05292e3e1f8a51218827168cdclaireho HB_LineBreakClass cls; 1385569331642446be05292e3e1f8a51218827168cdclaireho HB_GraphemeClass grapheme; 1395569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGraphemeAndLineBreakClass(*uc, &grapheme, &cls); 1405569331642446be05292e3e1f8a51218827168cdclaireho // handle case where input starts with an LF 1415569331642446be05292e3e1f8a51218827168cdclaireho if (cls == HB_LineBreak_LF) 1425569331642446be05292e3e1f8a51218827168cdclaireho cls = HB_LineBreak_BK; 1435569331642446be05292e3e1f8a51218827168cdclaireho 1445569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[0].whiteSpace = (cls == HB_LineBreak_SP || cls == HB_LineBreak_BK); 1455569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[0].charStop = true; 1465569331642446be05292e3e1f8a51218827168cdclaireho 1475569331642446be05292e3e1f8a51218827168cdclaireho int lcls = cls; 1485569331642446be05292e3e1f8a51218827168cdclaireho for (hb_uint32 i = 1; i < len; ++i) { 1495569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i].whiteSpace = false; 1505569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i].charStop = true; 1515569331642446be05292e3e1f8a51218827168cdclaireho 1525569331642446be05292e3e1f8a51218827168cdclaireho HB_UChar32 code = uc[i]; 1535569331642446be05292e3e1f8a51218827168cdclaireho HB_GraphemeClass ngrapheme; 1545569331642446be05292e3e1f8a51218827168cdclaireho HB_LineBreakClass ncls; 1555569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGraphemeAndLineBreakClass(code, &ngrapheme, &ncls); 1565569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i].charStop = graphemeTable[ngrapheme][grapheme]; 1575569331642446be05292e3e1f8a51218827168cdclaireho // handle surrogates 1585569331642446be05292e3e1f8a51218827168cdclaireho if (ncls == HB_LineBreak_SG) { 1595569331642446be05292e3e1f8a51218827168cdclaireho if (HB_IsHighSurrogate(uc[i]) && i < len - 1 && HB_IsLowSurrogate(uc[i+1])) { 1605569331642446be05292e3e1f8a51218827168cdclaireho continue; 1615569331642446be05292e3e1f8a51218827168cdclaireho } else if (HB_IsLowSurrogate(uc[i]) && HB_IsHighSurrogate(uc[i-1])) { 1625569331642446be05292e3e1f8a51218827168cdclaireho code = HB_SurrogateToUcs4(uc[i-1], uc[i]); 1635569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGraphemeAndLineBreakClass(code, &ngrapheme, &ncls); 1645569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i].charStop = false; 1655569331642446be05292e3e1f8a51218827168cdclaireho } else { 1665569331642446be05292e3e1f8a51218827168cdclaireho ncls = HB_LineBreak_AL; 1675569331642446be05292e3e1f8a51218827168cdclaireho } 1685569331642446be05292e3e1f8a51218827168cdclaireho } 1695569331642446be05292e3e1f8a51218827168cdclaireho 1705569331642446be05292e3e1f8a51218827168cdclaireho // set white space and char stop flag 1715569331642446be05292e3e1f8a51218827168cdclaireho if (ncls >= HB_LineBreak_SP) 1725569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i].whiteSpace = true; 1735569331642446be05292e3e1f8a51218827168cdclaireho 1745569331642446be05292e3e1f8a51218827168cdclaireho HB_LineBreakType lineBreakType = HB_NoBreak; 1755569331642446be05292e3e1f8a51218827168cdclaireho if (cls >= HB_LineBreak_LF) { 1765569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_ForcedBreak; 1775569331642446be05292e3e1f8a51218827168cdclaireho } else if(cls == HB_LineBreak_CR) { 1785569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = (ncls == HB_LineBreak_LF) ? HB_NoBreak : HB_ForcedBreak; 1795569331642446be05292e3e1f8a51218827168cdclaireho } 1805569331642446be05292e3e1f8a51218827168cdclaireho 1815569331642446be05292e3e1f8a51218827168cdclaireho if (ncls == HB_LineBreak_SP) 1825569331642446be05292e3e1f8a51218827168cdclaireho goto next_no_cls_update; 1835569331642446be05292e3e1f8a51218827168cdclaireho if (ncls >= HB_LineBreak_CR) 1845569331642446be05292e3e1f8a51218827168cdclaireho goto next; 1855569331642446be05292e3e1f8a51218827168cdclaireho 1865569331642446be05292e3e1f8a51218827168cdclaireho // two complex chars (thai or lao), thai_attributes might override, but here we do a best guess 1875569331642446be05292e3e1f8a51218827168cdclaireho if (cls == HB_LineBreak_SA && ncls == HB_LineBreak_SA) { 1885569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_Break; 1895569331642446be05292e3e1f8a51218827168cdclaireho goto next; 1905569331642446be05292e3e1f8a51218827168cdclaireho } 1915569331642446be05292e3e1f8a51218827168cdclaireho 1925569331642446be05292e3e1f8a51218827168cdclaireho { 1935569331642446be05292e3e1f8a51218827168cdclaireho int tcls = ncls; 1945569331642446be05292e3e1f8a51218827168cdclaireho if (tcls >= HB_LineBreak_SA) 1955569331642446be05292e3e1f8a51218827168cdclaireho tcls = HB_LineBreak_ID; 1965569331642446be05292e3e1f8a51218827168cdclaireho if (cls >= HB_LineBreak_SA) 1975569331642446be05292e3e1f8a51218827168cdclaireho cls = HB_LineBreak_ID; 1985569331642446be05292e3e1f8a51218827168cdclaireho 1995569331642446be05292e3e1f8a51218827168cdclaireho int brk = breakTable[cls][tcls]; 2005569331642446be05292e3e1f8a51218827168cdclaireho switch (brk) { 2015569331642446be05292e3e1f8a51218827168cdclaireho case DirectBreak: 2025569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_Break; 2035569331642446be05292e3e1f8a51218827168cdclaireho if (uc[i-1] == 0xad) // soft hyphen 2045569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_SoftHyphen; 2055569331642446be05292e3e1f8a51218827168cdclaireho break; 2065569331642446be05292e3e1f8a51218827168cdclaireho case IndirectBreak: 2075569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = (lcls == HB_LineBreak_SP) ? HB_Break : HB_NoBreak; 2085569331642446be05292e3e1f8a51218827168cdclaireho break; 2095569331642446be05292e3e1f8a51218827168cdclaireho case CombiningIndirectBreak: 2105569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_NoBreak; 2115569331642446be05292e3e1f8a51218827168cdclaireho if (lcls == HB_LineBreak_SP){ 2125569331642446be05292e3e1f8a51218827168cdclaireho if (i > 1) 2135569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i-2].lineBreakType = HB_Break; 2145569331642446be05292e3e1f8a51218827168cdclaireho } else { 2155569331642446be05292e3e1f8a51218827168cdclaireho goto next_no_cls_update; 2165569331642446be05292e3e1f8a51218827168cdclaireho } 2175569331642446be05292e3e1f8a51218827168cdclaireho break; 2185569331642446be05292e3e1f8a51218827168cdclaireho case CombiningProhibitedBreak: 2195569331642446be05292e3e1f8a51218827168cdclaireho lineBreakType = HB_NoBreak; 2205569331642446be05292e3e1f8a51218827168cdclaireho if (lcls != HB_LineBreak_SP) 2215569331642446be05292e3e1f8a51218827168cdclaireho goto next_no_cls_update; 2225569331642446be05292e3e1f8a51218827168cdclaireho case ProhibitedBreak: 2235569331642446be05292e3e1f8a51218827168cdclaireho default: 2245569331642446be05292e3e1f8a51218827168cdclaireho break; 2255569331642446be05292e3e1f8a51218827168cdclaireho } 2265569331642446be05292e3e1f8a51218827168cdclaireho } 2275569331642446be05292e3e1f8a51218827168cdclaireho next: 2285569331642446be05292e3e1f8a51218827168cdclaireho cls = ncls; 2295569331642446be05292e3e1f8a51218827168cdclaireho next_no_cls_update: 2305569331642446be05292e3e1f8a51218827168cdclaireho lcls = ncls; 2315569331642446be05292e3e1f8a51218827168cdclaireho grapheme = ngrapheme; 2325569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[i-1].lineBreakType = lineBreakType; 2335569331642446be05292e3e1f8a51218827168cdclaireho } 2345569331642446be05292e3e1f8a51218827168cdclaireho charAttributes[len-1].lineBreakType = HB_ForcedBreak; 2355569331642446be05292e3e1f8a51218827168cdclaireho} 2365569331642446be05292e3e1f8a51218827168cdclaireho 2375569331642446be05292e3e1f8a51218827168cdclaireho// -------------------------------------------------------------------------------------------------------------------------------------------- 2385569331642446be05292e3e1f8a51218827168cdclaireho// 2395569331642446be05292e3e1f8a51218827168cdclaireho// Basic processing 2405569331642446be05292e3e1f8a51218827168cdclaireho// 2415569331642446be05292e3e1f8a51218827168cdclaireho// -------------------------------------------------------------------------------------------------------------------------------------------- 2425569331642446be05292e3e1f8a51218827168cdclaireho 2435569331642446be05292e3e1f8a51218827168cdclairehostatic inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast) 2445569331642446be05292e3e1f8a51218827168cdclaireho{ 2455569331642446be05292e3e1f8a51218827168cdclaireho int nmarks = glast - gfrom; 2465569331642446be05292e3e1f8a51218827168cdclaireho assert(nmarks > 0); 2475569331642446be05292e3e1f8a51218827168cdclaireho 2485569331642446be05292e3e1f8a51218827168cdclaireho HB_Glyph *glyphs = item->glyphs; 2495569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = item->attributes; 2505569331642446be05292e3e1f8a51218827168cdclaireho 2515569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphMetrics baseMetrics; 2525569331642446be05292e3e1f8a51218827168cdclaireho item->font->klass->getGlyphMetrics(item->font, glyphs[gfrom], &baseMetrics); 2535569331642446be05292e3e1f8a51218827168cdclaireho 2545569331642446be05292e3e1f8a51218827168cdclaireho if (item->item.script == HB_Script_Hebrew 2555569331642446be05292e3e1f8a51218827168cdclaireho && (-baseMetrics.y) > baseMetrics.height) 2565569331642446be05292e3e1f8a51218827168cdclaireho // we need to attach below the baseline, because of the hebrew iud. 2575569331642446be05292e3e1f8a51218827168cdclaireho baseMetrics.height = -baseMetrics.y; 2585569331642446be05292e3e1f8a51218827168cdclaireho 2595569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("---> positionCluster: cluster from %d to %d", gfrom, glast); 2605569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff); 2615569331642446be05292e3e1f8a51218827168cdclaireho 2625569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed size = item->font->klass->getFontMetric(item->font, HB_FontAscent) / 10; 2635569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed offsetBase = HB_FIXED_CONSTANT(1) + (size - HB_FIXED_CONSTANT(4)) / 4; 2645569331642446be05292e3e1f8a51218827168cdclaireho if (size > HB_FIXED_CONSTANT(4)) 2655569331642446be05292e3e1f8a51218827168cdclaireho offsetBase += HB_FIXED_CONSTANT(4); 2665569331642446be05292e3e1f8a51218827168cdclaireho else 2675569331642446be05292e3e1f8a51218827168cdclaireho offsetBase += size; 2685569331642446be05292e3e1f8a51218827168cdclaireho //qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1; 2695569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("offset = %f", offsetBase); 2705569331642446be05292e3e1f8a51218827168cdclaireho 2715569331642446be05292e3e1f8a51218827168cdclaireho bool rightToLeft = item->item.bidiLevel % 2; 2725569331642446be05292e3e1f8a51218827168cdclaireho 2735569331642446be05292e3e1f8a51218827168cdclaireho int i; 2745569331642446be05292e3e1f8a51218827168cdclaireho unsigned char lastCmb = 0; 2755569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphMetrics attachmentRect; 2765569331642446be05292e3e1f8a51218827168cdclaireho memset(&attachmentRect, 0, sizeof(attachmentRect)); 2775569331642446be05292e3e1f8a51218827168cdclaireho 2785569331642446be05292e3e1f8a51218827168cdclaireho for(i = 1; i <= nmarks; i++) { 2795569331642446be05292e3e1f8a51218827168cdclaireho HB_Glyph mark = glyphs[gfrom+i]; 2805569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphMetrics markMetrics; 2815569331642446be05292e3e1f8a51218827168cdclaireho item->font->klass->getGlyphMetrics(item->font, mark, &markMetrics); 2825569331642446be05292e3e1f8a51218827168cdclaireho HB_FixedPoint p; 2835569331642446be05292e3e1f8a51218827168cdclaireho p.x = p.y = 0; 2845569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff); 2855569331642446be05292e3e1f8a51218827168cdclaireho 2865569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed offset = offsetBase; 2875569331642446be05292e3e1f8a51218827168cdclaireho unsigned char cmb = attributes[gfrom+i].combiningClass; 2885569331642446be05292e3e1f8a51218827168cdclaireho 2895569331642446be05292e3e1f8a51218827168cdclaireho // ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some 2905569331642446be05292e3e1f8a51218827168cdclaireho // bits in the glyphAttributes structure. 2915569331642446be05292e3e1f8a51218827168cdclaireho if (cmb < 200) { 2925569331642446be05292e3e1f8a51218827168cdclaireho // fixed position classes. We approximate by mapping to one of the others. 2935569331642446be05292e3e1f8a51218827168cdclaireho // currently I added only the ones for arabic, hebrew, lao and thai. 2945569331642446be05292e3e1f8a51218827168cdclaireho 2955569331642446be05292e3e1f8a51218827168cdclaireho // for Lao and Thai marks with class 0, see below (heuristicSetGlyphAttributes) 2965569331642446be05292e3e1f8a51218827168cdclaireho 2975569331642446be05292e3e1f8a51218827168cdclaireho // add a bit more offset to arabic, a bit hacky 2985569331642446be05292e3e1f8a51218827168cdclaireho if (cmb >= 27 && cmb <= 36 && offset < 3) 2995569331642446be05292e3e1f8a51218827168cdclaireho offset +=1; 3005569331642446be05292e3e1f8a51218827168cdclaireho // below 3015569331642446be05292e3e1f8a51218827168cdclaireho if ((cmb >= 10 && cmb <= 18) || 3025569331642446be05292e3e1f8a51218827168cdclaireho cmb == 20 || cmb == 22 || 3035569331642446be05292e3e1f8a51218827168cdclaireho cmb == 29 || cmb == 32) 3045569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_Below; 3055569331642446be05292e3e1f8a51218827168cdclaireho // above 3065569331642446be05292e3e1f8a51218827168cdclaireho else if (cmb == 23 || cmb == 27 || cmb == 28 || 3075569331642446be05292e3e1f8a51218827168cdclaireho cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36)) 3085569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_Above; 3095569331642446be05292e3e1f8a51218827168cdclaireho //below-right 3105569331642446be05292e3e1f8a51218827168cdclaireho else if (cmb == 9 || cmb == 103 || cmb == 118) 3115569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_BelowRight; 3125569331642446be05292e3e1f8a51218827168cdclaireho // above-right 3135569331642446be05292e3e1f8a51218827168cdclaireho else if (cmb == 24 || cmb == 107 || cmb == 122) 3145569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_AboveRight; 3155569331642446be05292e3e1f8a51218827168cdclaireho else if (cmb == 25) 3165569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_AboveLeft; 3175569331642446be05292e3e1f8a51218827168cdclaireho // fixed: 3185569331642446be05292e3e1f8a51218827168cdclaireho // 19 21 3195569331642446be05292e3e1f8a51218827168cdclaireho 3205569331642446be05292e3e1f8a51218827168cdclaireho } 3215569331642446be05292e3e1f8a51218827168cdclaireho 3225569331642446be05292e3e1f8a51218827168cdclaireho // combining marks of different class don't interact. Reset the rectangle. 3235569331642446be05292e3e1f8a51218827168cdclaireho if (cmb != lastCmb) { 3245569331642446be05292e3e1f8a51218827168cdclaireho //qDebug("resetting rect"); 3255569331642446be05292e3e1f8a51218827168cdclaireho attachmentRect = baseMetrics; 3265569331642446be05292e3e1f8a51218827168cdclaireho } 3275569331642446be05292e3e1f8a51218827168cdclaireho 3285569331642446be05292e3e1f8a51218827168cdclaireho switch(cmb) { 3295569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_DoubleBelow: 3305569331642446be05292e3e1f8a51218827168cdclaireho // ### wrong in rtl context! 3315569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_BelowLeft: 3325569331642446be05292e3e1f8a51218827168cdclaireho p.y += offset; 3335569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_BelowLeftAttached: 3345569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x - markMetrics.x; 3355569331642446be05292e3e1f8a51218827168cdclaireho p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y; 3365569331642446be05292e3e1f8a51218827168cdclaireho break; 3375569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_Below: 3385569331642446be05292e3e1f8a51218827168cdclaireho p.y += offset; 3395569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_BelowAttached: 3405569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x - markMetrics.x; 3415569331642446be05292e3e1f8a51218827168cdclaireho p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y; 3425569331642446be05292e3e1f8a51218827168cdclaireho 3435569331642446be05292e3e1f8a51218827168cdclaireho p.x += (attachmentRect.width - markMetrics.width) / 2; 3445569331642446be05292e3e1f8a51218827168cdclaireho break; 3455569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_BelowRight: 3465569331642446be05292e3e1f8a51218827168cdclaireho p.y += offset; 3475569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_BelowRightAttached: 3485569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x + attachmentRect.width - markMetrics.width - markMetrics.x; 3495569331642446be05292e3e1f8a51218827168cdclaireho p.y += attachmentRect.y + attachmentRect.height - markMetrics.y; 3505569331642446be05292e3e1f8a51218827168cdclaireho break; 3515569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_Left: 3525569331642446be05292e3e1f8a51218827168cdclaireho p.x -= offset; 3535569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_LeftAttached: 3545569331642446be05292e3e1f8a51218827168cdclaireho break; 3555569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_Right: 3565569331642446be05292e3e1f8a51218827168cdclaireho p.x += offset; 3575569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_RightAttached: 3585569331642446be05292e3e1f8a51218827168cdclaireho break; 3595569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_DoubleAbove: 3605569331642446be05292e3e1f8a51218827168cdclaireho // ### wrong in RTL context! 3615569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_AboveLeft: 3625569331642446be05292e3e1f8a51218827168cdclaireho p.y -= offset; 3635569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_AboveLeftAttached: 3645569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x - markMetrics.x; 3655569331642446be05292e3e1f8a51218827168cdclaireho p.y += attachmentRect.y - markMetrics.y - markMetrics.height; 3665569331642446be05292e3e1f8a51218827168cdclaireho break; 3675569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_Above: 3685569331642446be05292e3e1f8a51218827168cdclaireho p.y -= offset; 3695569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_AboveAttached: 3705569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x - markMetrics.x; 3715569331642446be05292e3e1f8a51218827168cdclaireho p.y += attachmentRect.y - markMetrics.y - markMetrics.height; 3725569331642446be05292e3e1f8a51218827168cdclaireho 3735569331642446be05292e3e1f8a51218827168cdclaireho p.x += (attachmentRect.width - markMetrics.width) / 2; 3745569331642446be05292e3e1f8a51218827168cdclaireho break; 3755569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_AboveRight: 3765569331642446be05292e3e1f8a51218827168cdclaireho p.y -= offset; 3775569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_AboveRightAttached: 3785569331642446be05292e3e1f8a51218827168cdclaireho p.x += attachmentRect.x + attachmentRect.width - markMetrics.x - markMetrics.width; 3795569331642446be05292e3e1f8a51218827168cdclaireho p.y += attachmentRect.y - markMetrics.y - markMetrics.height; 3805569331642446be05292e3e1f8a51218827168cdclaireho break; 3815569331642446be05292e3e1f8a51218827168cdclaireho 3825569331642446be05292e3e1f8a51218827168cdclaireho case HB_Combining_IotaSubscript: 3835569331642446be05292e3e1f8a51218827168cdclaireho default: 3845569331642446be05292e3e1f8a51218827168cdclaireho break; 3855569331642446be05292e3e1f8a51218827168cdclaireho } 3865569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("char=%x combiningClass = %d offset=%f/%f", mark, cmb, p.x(), p.y()); 3875569331642446be05292e3e1f8a51218827168cdclaireho markMetrics.x += p.x; 3885569331642446be05292e3e1f8a51218827168cdclaireho markMetrics.y += p.y; 3895569331642446be05292e3e1f8a51218827168cdclaireho 3905569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphMetrics unitedAttachmentRect = attachmentRect; 3915569331642446be05292e3e1f8a51218827168cdclaireho unitedAttachmentRect.x = HB_MIN(attachmentRect.x, markMetrics.x); 3925569331642446be05292e3e1f8a51218827168cdclaireho unitedAttachmentRect.y = HB_MIN(attachmentRect.y, markMetrics.y); 3935569331642446be05292e3e1f8a51218827168cdclaireho unitedAttachmentRect.width = HB_MAX(attachmentRect.x + attachmentRect.width, markMetrics.x + markMetrics.width) - unitedAttachmentRect.x; 3945569331642446be05292e3e1f8a51218827168cdclaireho unitedAttachmentRect.height = HB_MAX(attachmentRect.y + attachmentRect.height, markMetrics.y + markMetrics.height) - unitedAttachmentRect.y; 3955569331642446be05292e3e1f8a51218827168cdclaireho attachmentRect = unitedAttachmentRect; 3965569331642446be05292e3e1f8a51218827168cdclaireho 3975569331642446be05292e3e1f8a51218827168cdclaireho lastCmb = cmb; 3985569331642446be05292e3e1f8a51218827168cdclaireho if (rightToLeft) { 3995569331642446be05292e3e1f8a51218827168cdclaireho item->offsets[gfrom+i].x = p.x; 4005569331642446be05292e3e1f8a51218827168cdclaireho item->offsets[gfrom+i].y = p.y; 4015569331642446be05292e3e1f8a51218827168cdclaireho } else { 4025569331642446be05292e3e1f8a51218827168cdclaireho item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset; 4035569331642446be05292e3e1f8a51218827168cdclaireho item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset; 4045569331642446be05292e3e1f8a51218827168cdclaireho } 4055569331642446be05292e3e1f8a51218827168cdclaireho item->advances[gfrom+i] = 0; 4065569331642446be05292e3e1f8a51218827168cdclaireho } 4075569331642446be05292e3e1f8a51218827168cdclaireho} 4085569331642446be05292e3e1f8a51218827168cdclaireho 4095569331642446be05292e3e1f8a51218827168cdclairehovoid HB_HeuristicPosition(HB_ShaperItem *item) 4105569331642446be05292e3e1f8a51218827168cdclaireho{ 4115569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGlyphAdvances(item); 4125569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = item->attributes; 4135569331642446be05292e3e1f8a51218827168cdclaireho 4145569331642446be05292e3e1f8a51218827168cdclaireho int cEnd = -1; 4155569331642446be05292e3e1f8a51218827168cdclaireho int i = item->num_glyphs; 4165569331642446be05292e3e1f8a51218827168cdclaireho while (i--) { 4175569331642446be05292e3e1f8a51218827168cdclaireho if (cEnd == -1 && attributes[i].mark) { 4185569331642446be05292e3e1f8a51218827168cdclaireho cEnd = i; 4195569331642446be05292e3e1f8a51218827168cdclaireho } else if (cEnd != -1 && !attributes[i].mark) { 4205569331642446be05292e3e1f8a51218827168cdclaireho positionCluster(item, i, cEnd); 4215569331642446be05292e3e1f8a51218827168cdclaireho cEnd = -1; 4225569331642446be05292e3e1f8a51218827168cdclaireho } 4235569331642446be05292e3e1f8a51218827168cdclaireho } 4245569331642446be05292e3e1f8a51218827168cdclaireho} 4255569331642446be05292e3e1f8a51218827168cdclaireho 4265569331642446be05292e3e1f8a51218827168cdclaireho// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs 4275569331642446be05292e3e1f8a51218827168cdclaireho// and no reordering. 4285569331642446be05292e3e1f8a51218827168cdclaireho// also computes logClusters heuristically 4295569331642446be05292e3e1f8a51218827168cdclairehovoid HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item) 4305569331642446be05292e3e1f8a51218827168cdclaireho{ 4315569331642446be05292e3e1f8a51218827168cdclaireho const HB_UChar16 *uc = item->string + item->item.pos; 4325569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 length = item->item.length; 4335569331642446be05292e3e1f8a51218827168cdclaireho 4345569331642446be05292e3e1f8a51218827168cdclaireho // ### zeroWidth and justification are missing here!!!!! 4355569331642446be05292e3e1f8a51218827168cdclaireho 4365569331642446be05292e3e1f8a51218827168cdclaireho // BEGIN android-changed 4375569331642446be05292e3e1f8a51218827168cdclaireho // We apply the same fix for Chrome to Android. 4385569331642446be05292e3e1f8a51218827168cdclaireho // Chrome team will talk with upsteam about it. 4395569331642446be05292e3e1f8a51218827168cdclaireho assert(length <= item->num_glyphs); 4405569331642446be05292e3e1f8a51218827168cdclaireho // END android-changed 4415569331642446be05292e3e1f8a51218827168cdclaireho 4425569331642446be05292e3e1f8a51218827168cdclaireho// qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs); 4435569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = item->attributes; 4445569331642446be05292e3e1f8a51218827168cdclaireho unsigned short *logClusters = item->log_clusters; 4455569331642446be05292e3e1f8a51218827168cdclaireho 4465569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 glyph_pos = 0; 4475569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 i; 4485569331642446be05292e3e1f8a51218827168cdclaireho for (i = 0; i < length; i++) { 4495569331642446be05292e3e1f8a51218827168cdclaireho if (HB_IsHighSurrogate(uc[i]) && i < length - 1 4505569331642446be05292e3e1f8a51218827168cdclaireho && HB_IsLowSurrogate(uc[i + 1])) { 4515569331642446be05292e3e1f8a51218827168cdclaireho logClusters[i] = glyph_pos; 4525569331642446be05292e3e1f8a51218827168cdclaireho logClusters[++i] = glyph_pos; 4535569331642446be05292e3e1f8a51218827168cdclaireho } else { 4545569331642446be05292e3e1f8a51218827168cdclaireho logClusters[i] = glyph_pos; 4555569331642446be05292e3e1f8a51218827168cdclaireho } 4565569331642446be05292e3e1f8a51218827168cdclaireho ++glyph_pos; 4575569331642446be05292e3e1f8a51218827168cdclaireho } 4585569331642446be05292e3e1f8a51218827168cdclaireho 4595569331642446be05292e3e1f8a51218827168cdclaireho // BEGIN android-removed 4605569331642446be05292e3e1f8a51218827168cdclaireho // We apply the same fix for Chrome to Android. 4615569331642446be05292e3e1f8a51218827168cdclaireho // Chrome team will talk with upsteam about it 4625569331642446be05292e3e1f8a51218827168cdclaireho // 4635569331642446be05292e3e1f8a51218827168cdclaireho // assert(glyph_pos == item->num_glyphs); 4645569331642446be05292e3e1f8a51218827168cdclaireho // 4655569331642446be05292e3e1f8a51218827168cdclaireho // END android-removed 4665569331642446be05292e3e1f8a51218827168cdclaireho 4675569331642446be05292e3e1f8a51218827168cdclaireho // first char in a run is never (treated as) a mark 4685569331642446be05292e3e1f8a51218827168cdclaireho int cStart = 0; 4695569331642446be05292e3e1f8a51218827168cdclaireho const bool symbolFont = item->face->isSymbolFont; 4705569331642446be05292e3e1f8a51218827168cdclaireho attributes[0].mark = false; 4715569331642446be05292e3e1f8a51218827168cdclaireho attributes[0].clusterStart = true; 4725569331642446be05292e3e1f8a51218827168cdclaireho attributes[0].dontPrint = (!symbolFont && uc[0] == 0x00ad) || HB_IsControlChar(uc[0]); 4735569331642446be05292e3e1f8a51218827168cdclaireho 4745569331642446be05292e3e1f8a51218827168cdclaireho int pos = 0; 4755569331642446be05292e3e1f8a51218827168cdclaireho HB_CharCategory lastCat; 4765569331642446be05292e3e1f8a51218827168cdclaireho int dummy; 4775569331642446be05292e3e1f8a51218827168cdclaireho HB_GetUnicodeCharProperties(uc[0], &lastCat, &dummy); 4785569331642446be05292e3e1f8a51218827168cdclaireho for (i = 1; i < length; ++i) { 4795569331642446be05292e3e1f8a51218827168cdclaireho if (logClusters[i] == pos) 4805569331642446be05292e3e1f8a51218827168cdclaireho // same glyph 4815569331642446be05292e3e1f8a51218827168cdclaireho continue; 4825569331642446be05292e3e1f8a51218827168cdclaireho ++pos; 4835569331642446be05292e3e1f8a51218827168cdclaireho while (pos < logClusters[i]) { 4845569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos] = attributes[pos-1]; 4855569331642446be05292e3e1f8a51218827168cdclaireho ++pos; 4865569331642446be05292e3e1f8a51218827168cdclaireho } 4875569331642446be05292e3e1f8a51218827168cdclaireho // hide soft-hyphens by default 4885569331642446be05292e3e1f8a51218827168cdclaireho if ((!symbolFont && uc[i] == 0x00ad) || HB_IsControlChar(uc[i])) 4895569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].dontPrint = true; 4905569331642446be05292e3e1f8a51218827168cdclaireho HB_CharCategory cat; 4915569331642446be05292e3e1f8a51218827168cdclaireho int cmb; 4925569331642446be05292e3e1f8a51218827168cdclaireho HB_GetUnicodeCharProperties(uc[i], &cat, &cmb); 4935569331642446be05292e3e1f8a51218827168cdclaireho if (cat != HB_Mark_NonSpacing) { 4945569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].mark = false; 4955569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].clusterStart = true; 4965569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].combiningClass = 0; 4975569331642446be05292e3e1f8a51218827168cdclaireho cStart = logClusters[i]; 4985569331642446be05292e3e1f8a51218827168cdclaireho } else { 4995569331642446be05292e3e1f8a51218827168cdclaireho if (cmb == 0) { 5005569331642446be05292e3e1f8a51218827168cdclaireho // Fix 0 combining classes 5015569331642446be05292e3e1f8a51218827168cdclaireho if ((uc[pos] & 0xff00) == 0x0e00) { 5025569331642446be05292e3e1f8a51218827168cdclaireho // thai or lao 5035569331642446be05292e3e1f8a51218827168cdclaireho if (uc[pos] == 0xe31 || 5045569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe34 || 5055569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe35 || 5065569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe36 || 5075569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe37 || 5085569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe47 || 5095569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe4c || 5105569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe4d || 5115569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xe4e) { 5125569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_AboveRight; 5135569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[pos] == 0xeb1 || 5145569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xeb4 || 5155569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xeb5 || 5165569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xeb6 || 5175569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xeb7 || 5185569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xebb || 5195569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xecc || 5205569331642446be05292e3e1f8a51218827168cdclaireho uc[pos] == 0xecd) { 5215569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_Above; 5225569331642446be05292e3e1f8a51218827168cdclaireho } else if (uc[pos] == 0xebc) { 5235569331642446be05292e3e1f8a51218827168cdclaireho cmb = HB_Combining_Below; 5245569331642446be05292e3e1f8a51218827168cdclaireho } 5255569331642446be05292e3e1f8a51218827168cdclaireho } 5265569331642446be05292e3e1f8a51218827168cdclaireho } 5275569331642446be05292e3e1f8a51218827168cdclaireho 5285569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].mark = true; 5295569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].clusterStart = false; 5305569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].combiningClass = cmb; 5315569331642446be05292e3e1f8a51218827168cdclaireho logClusters[i] = cStart; 5325569331642446be05292e3e1f8a51218827168cdclaireho } 5335569331642446be05292e3e1f8a51218827168cdclaireho // one gets an inter character justification point if the current char is not a non spacing mark. 5345569331642446be05292e3e1f8a51218827168cdclaireho // as then the current char belongs to the last one and one gets a space justification point 5355569331642446be05292e3e1f8a51218827168cdclaireho // after the space char. 5365569331642446be05292e3e1f8a51218827168cdclaireho if (lastCat == HB_Separator_Space) 5375569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos-1].justification = HB_Space; 5385569331642446be05292e3e1f8a51218827168cdclaireho else if (cat != HB_Mark_NonSpacing) 5395569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos-1].justification = HB_Character; 5405569331642446be05292e3e1f8a51218827168cdclaireho else 5415569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos-1].justification = HB_NoJustification; 5425569331642446be05292e3e1f8a51218827168cdclaireho 5435569331642446be05292e3e1f8a51218827168cdclaireho lastCat = cat; 5445569331642446be05292e3e1f8a51218827168cdclaireho } 5455569331642446be05292e3e1f8a51218827168cdclaireho pos = logClusters[length-1]; 5465569331642446be05292e3e1f8a51218827168cdclaireho if (lastCat == HB_Separator_Space) 5475569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].justification = HB_Space; 5485569331642446be05292e3e1f8a51218827168cdclaireho else 5495569331642446be05292e3e1f8a51218827168cdclaireho attributes[pos].justification = HB_Character; 5505569331642446be05292e3e1f8a51218827168cdclaireho} 5515569331642446be05292e3e1f8a51218827168cdclaireho 5525569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE 5535569331642446be05292e3e1f8a51218827168cdclairehostatic const HB_OpenTypeFeature basic_features[] = { 5545569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, 5555569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty }, 5565569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty }, 5575569331642446be05292e3e1f8a51218827168cdclaireho {0, 0} 5585569331642446be05292e3e1f8a51218827168cdclaireho}; 5595569331642446be05292e3e1f8a51218827168cdclaireho#endif 5605569331642446be05292e3e1f8a51218827168cdclaireho 5615569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item) 5625569331642446be05292e3e1f8a51218827168cdclaireho{ 5635569331642446be05292e3e1f8a51218827168cdclaireho if (shaper_item->glyphIndicesPresent) { 5645569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->num_glyphs = shaper_item->initialGlyphCount; 5655569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphIndicesPresent = false; 5665569331642446be05292e3e1f8a51218827168cdclaireho return true; 5675569331642446be05292e3e1f8a51218827168cdclaireho } 5685569331642446be05292e3e1f8a51218827168cdclaireho return shaper_item->font->klass 5695569331642446be05292e3e1f8a51218827168cdclaireho ->convertStringToGlyphIndices(shaper_item->font, 5705569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->string + shaper_item->item.pos, shaper_item->item.length, 5715569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphs, &shaper_item->num_glyphs, 5725569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->item.bidiLevel % 2); 5735569331642446be05292e3e1f8a51218827168cdclaireho} 5745569331642446be05292e3e1f8a51218827168cdclaireho 5755569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_BasicShape(HB_ShaperItem *shaper_item) 5765569331642446be05292e3e1f8a51218827168cdclaireho{ 5775569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE 5785569331642446be05292e3e1f8a51218827168cdclaireho const int availableGlyphs = shaper_item->num_glyphs; 5795569331642446be05292e3e1f8a51218827168cdclaireho#endif 5805569331642446be05292e3e1f8a51218827168cdclaireho 5815569331642446be05292e3e1f8a51218827168cdclaireho if (!HB_ConvertStringToGlyphIndices(shaper_item)) 5825569331642446be05292e3e1f8a51218827168cdclaireho return false; 5835569331642446be05292e3e1f8a51218827168cdclaireho 5845569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicSetGlyphAttributes(shaper_item); 5855569331642446be05292e3e1f8a51218827168cdclaireho 5865569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE 5875569331642446be05292e3e1f8a51218827168cdclaireho if (HB_SelectScript(shaper_item, basic_features)) { 5885569331642446be05292e3e1f8a51218827168cdclaireho HB_OpenTypeShape(shaper_item, /*properties*/0); 5895569331642446be05292e3e1f8a51218827168cdclaireho return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/true); 5905569331642446be05292e3e1f8a51218827168cdclaireho } 5915569331642446be05292e3e1f8a51218827168cdclaireho#endif 5925569331642446be05292e3e1f8a51218827168cdclaireho 5935569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicPosition(shaper_item); 5945569331642446be05292e3e1f8a51218827168cdclaireho return true; 5955569331642446be05292e3e1f8a51218827168cdclaireho} 5965569331642446be05292e3e1f8a51218827168cdclaireho 5975569331642446be05292e3e1f8a51218827168cdclairehoconst HB_ScriptEngine HB_ScriptEngines[] = { 5985569331642446be05292e3e1f8a51218827168cdclaireho // Common 5995569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0}, 6005569331642446be05292e3e1f8a51218827168cdclaireho // Greek 6015569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0}, 6025569331642446be05292e3e1f8a51218827168cdclaireho // Cyrillic 6035569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0}, 6045569331642446be05292e3e1f8a51218827168cdclaireho // Armenian 6055569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0}, 6065569331642446be05292e3e1f8a51218827168cdclaireho // Hebrew 6075569331642446be05292e3e1f8a51218827168cdclaireho { HB_HebrewShape, 0 }, 6085569331642446be05292e3e1f8a51218827168cdclaireho // Arabic 6095569331642446be05292e3e1f8a51218827168cdclaireho { HB_ArabicShape, 0}, 6105569331642446be05292e3e1f8a51218827168cdclaireho // Syriac 6115569331642446be05292e3e1f8a51218827168cdclaireho { HB_ArabicShape, 0}, 6125569331642446be05292e3e1f8a51218827168cdclaireho // Thaana 6135569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0 }, 6145569331642446be05292e3e1f8a51218827168cdclaireho // Devanagari 6155569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6165569331642446be05292e3e1f8a51218827168cdclaireho // Bengali 6175569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6185569331642446be05292e3e1f8a51218827168cdclaireho // Gurmukhi 6195569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6205569331642446be05292e3e1f8a51218827168cdclaireho // Gujarati 6215569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6225569331642446be05292e3e1f8a51218827168cdclaireho // Oriya 6235569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6245569331642446be05292e3e1f8a51218827168cdclaireho // Tamil 6255569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6265569331642446be05292e3e1f8a51218827168cdclaireho // Telugu 6275569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6285569331642446be05292e3e1f8a51218827168cdclaireho // Kannada 6295569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6305569331642446be05292e3e1f8a51218827168cdclaireho // Malayalam 6315569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6325569331642446be05292e3e1f8a51218827168cdclaireho // Sinhala 6335569331642446be05292e3e1f8a51218827168cdclaireho { HB_IndicShape, HB_IndicAttributes }, 6345569331642446be05292e3e1f8a51218827168cdclaireho // Thai 6355569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, HB_ThaiAttributes }, 6365569331642446be05292e3e1f8a51218827168cdclaireho // Lao 6375569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0 }, 6385569331642446be05292e3e1f8a51218827168cdclaireho // Tibetan 6395569331642446be05292e3e1f8a51218827168cdclaireho { HB_TibetanShape, HB_TibetanAttributes }, 6405569331642446be05292e3e1f8a51218827168cdclaireho // Myanmar 6415569331642446be05292e3e1f8a51218827168cdclaireho { HB_MyanmarShape, HB_MyanmarAttributes }, 6425569331642446be05292e3e1f8a51218827168cdclaireho // Georgian 6435569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0 }, 6445569331642446be05292e3e1f8a51218827168cdclaireho // Hangul 6455569331642446be05292e3e1f8a51218827168cdclaireho { HB_HangulShape, 0 }, 6465569331642446be05292e3e1f8a51218827168cdclaireho // Ogham 6475569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0 }, 6485569331642446be05292e3e1f8a51218827168cdclaireho // Runic 6495569331642446be05292e3e1f8a51218827168cdclaireho { HB_BasicShape, 0 }, 6505569331642446be05292e3e1f8a51218827168cdclaireho // Khmer 6515569331642446be05292e3e1f8a51218827168cdclaireho { HB_KhmerShape, HB_KhmerAttributes }, 6525569331642446be05292e3e1f8a51218827168cdclaireho // N'Ko 6535569331642446be05292e3e1f8a51218827168cdclaireho { HB_ArabicShape, 0} 6545569331642446be05292e3e1f8a51218827168cdclaireho}; 6555569331642446be05292e3e1f8a51218827168cdclaireho 6565569331642446be05292e3e1f8a51218827168cdclairehovoid HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength, 6575569331642446be05292e3e1f8a51218827168cdclaireho const HB_ScriptItem *items, hb_uint32 numItems, 6585569331642446be05292e3e1f8a51218827168cdclaireho HB_CharAttributes *attributes) 6595569331642446be05292e3e1f8a51218827168cdclaireho{ 6605569331642446be05292e3e1f8a51218827168cdclaireho calcLineBreaks(string, stringLength, attributes); 6615569331642446be05292e3e1f8a51218827168cdclaireho 6625569331642446be05292e3e1f8a51218827168cdclaireho for (hb_uint32 i = 0; i < numItems; ++i) { 6635569331642446be05292e3e1f8a51218827168cdclaireho HB_Script script = items[i].script; 6645569331642446be05292e3e1f8a51218827168cdclaireho if (script == HB_Script_Inherited) 6655569331642446be05292e3e1f8a51218827168cdclaireho script = HB_Script_Common; 6665569331642446be05292e3e1f8a51218827168cdclaireho HB_AttributeFunction attributeFunction = HB_ScriptEngines[script].charAttributes; 6675569331642446be05292e3e1f8a51218827168cdclaireho if (!attributeFunction) 6685569331642446be05292e3e1f8a51218827168cdclaireho continue; 6695569331642446be05292e3e1f8a51218827168cdclaireho attributeFunction(script, string, items[i].pos, items[i].length, attributes); 6705569331642446be05292e3e1f8a51218827168cdclaireho } 6715569331642446be05292e3e1f8a51218827168cdclaireho} 6725569331642446be05292e3e1f8a51218827168cdclaireho 6735569331642446be05292e3e1f8a51218827168cdclaireho 6745569331642446be05292e3e1f8a51218827168cdclairehoenum BreakRule { NoBreak = 0, Break = 1, Middle = 2 }; 6755569331642446be05292e3e1f8a51218827168cdclaireho 6765569331642446be05292e3e1f8a51218827168cdclairehostatic const hb_uint8 wordbreakTable[HB_Word_ExtendNumLet + 1][HB_Word_ExtendNumLet + 1] = { 6775569331642446be05292e3e1f8a51218827168cdclaireho// Other Format Katakana ALetter MidLetter MidNum Numeric ExtendNumLet 6785569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, Break, Break, Break, Break, Break }, // Other 6795569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, Break, Break, Break, Break, Break }, // Format 6805569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, NoBreak, Break, Break, Break, Break, NoBreak }, // Katakana 6815569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, NoBreak, Middle, Break, NoBreak, NoBreak }, // ALetter 6825569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, Break, Break, Break, Break, Break }, // MidLetter 6835569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, Break, Break, Break, Break, Break }, // MidNum 6845569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, Break, NoBreak, Break, Middle, NoBreak, NoBreak }, // Numeric 6855569331642446be05292e3e1f8a51218827168cdclaireho { Break, Break, NoBreak, NoBreak, Break, Break, NoBreak, NoBreak }, // ExtendNumLet 6865569331642446be05292e3e1f8a51218827168cdclaireho}; 6875569331642446be05292e3e1f8a51218827168cdclaireho 6885569331642446be05292e3e1f8a51218827168cdclairehovoid HB_GetWordBoundaries(const HB_UChar16 *string, hb_uint32 stringLength, 6895569331642446be05292e3e1f8a51218827168cdclaireho const HB_ScriptItem * /*items*/, hb_uint32 /*numItems*/, 6905569331642446be05292e3e1f8a51218827168cdclaireho HB_CharAttributes *attributes) 6915569331642446be05292e3e1f8a51218827168cdclaireho{ 6925569331642446be05292e3e1f8a51218827168cdclaireho if (stringLength == 0) 6935569331642446be05292e3e1f8a51218827168cdclaireho return; 6945569331642446be05292e3e1f8a51218827168cdclaireho unsigned int brk = HB_GetWordClass(string[0]); 6955569331642446be05292e3e1f8a51218827168cdclaireho attributes[0].wordBoundary = true; 6965569331642446be05292e3e1f8a51218827168cdclaireho for (hb_uint32 i = 1; i < stringLength; ++i) { 6975569331642446be05292e3e1f8a51218827168cdclaireho if (!attributes[i].charStop) { 6985569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].wordBoundary = false; 6995569331642446be05292e3e1f8a51218827168cdclaireho continue; 7005569331642446be05292e3e1f8a51218827168cdclaireho } 7015569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 nbrk = HB_GetWordClass(string[i]); 7025569331642446be05292e3e1f8a51218827168cdclaireho if (nbrk == HB_Word_Format) { 7035569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].wordBoundary = (HB_GetSentenceClass(string[i-1]) == HB_Sentence_Sep); 7045569331642446be05292e3e1f8a51218827168cdclaireho continue; 7055569331642446be05292e3e1f8a51218827168cdclaireho } 7065569331642446be05292e3e1f8a51218827168cdclaireho BreakRule rule = (BreakRule)wordbreakTable[brk][nbrk]; 7075569331642446be05292e3e1f8a51218827168cdclaireho if (rule == Middle) { 7085569331642446be05292e3e1f8a51218827168cdclaireho rule = Break; 7095569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 lookahead = i + 1; 7105569331642446be05292e3e1f8a51218827168cdclaireho while (lookahead < stringLength) { 7115569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 testbrk = HB_GetWordClass(string[lookahead]); 7125569331642446be05292e3e1f8a51218827168cdclaireho if (testbrk == HB_Word_Format && HB_GetSentenceClass(string[lookahead]) != HB_Sentence_Sep) { 7135569331642446be05292e3e1f8a51218827168cdclaireho ++lookahead; 7145569331642446be05292e3e1f8a51218827168cdclaireho continue; 7155569331642446be05292e3e1f8a51218827168cdclaireho } 7165569331642446be05292e3e1f8a51218827168cdclaireho if (testbrk == brk) { 7175569331642446be05292e3e1f8a51218827168cdclaireho rule = NoBreak; 7185569331642446be05292e3e1f8a51218827168cdclaireho while (i < lookahead) 7195569331642446be05292e3e1f8a51218827168cdclaireho attributes[i++].wordBoundary = false; 7205569331642446be05292e3e1f8a51218827168cdclaireho nbrk = testbrk; 7215569331642446be05292e3e1f8a51218827168cdclaireho } 7225569331642446be05292e3e1f8a51218827168cdclaireho break; 7235569331642446be05292e3e1f8a51218827168cdclaireho } 7245569331642446be05292e3e1f8a51218827168cdclaireho } 7255569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].wordBoundary = (rule == Break); 7265569331642446be05292e3e1f8a51218827168cdclaireho brk = nbrk; 7275569331642446be05292e3e1f8a51218827168cdclaireho } 7285569331642446be05292e3e1f8a51218827168cdclaireho} 7295569331642446be05292e3e1f8a51218827168cdclaireho 7305569331642446be05292e3e1f8a51218827168cdclaireho 7315569331642446be05292e3e1f8a51218827168cdclairehoenum SentenceBreakStates { 7325569331642446be05292e3e1f8a51218827168cdclaireho SB_Initial, 7335569331642446be05292e3e1f8a51218827168cdclaireho SB_Upper, 7345569331642446be05292e3e1f8a51218827168cdclaireho SB_UpATerm, 7355569331642446be05292e3e1f8a51218827168cdclaireho SB_ATerm, 7365569331642446be05292e3e1f8a51218827168cdclaireho SB_ATermC, 7375569331642446be05292e3e1f8a51218827168cdclaireho SB_ACS, 7385569331642446be05292e3e1f8a51218827168cdclaireho SB_STerm, 7395569331642446be05292e3e1f8a51218827168cdclaireho SB_STermC, 7405569331642446be05292e3e1f8a51218827168cdclaireho SB_SCS, 7415569331642446be05292e3e1f8a51218827168cdclaireho SB_BAfter, 7425569331642446be05292e3e1f8a51218827168cdclaireho SB_Break, 7435569331642446be05292e3e1f8a51218827168cdclaireho SB_Look 7445569331642446be05292e3e1f8a51218827168cdclaireho}; 7455569331642446be05292e3e1f8a51218827168cdclaireho 7465569331642446be05292e3e1f8a51218827168cdclairehostatic const hb_uint8 sentenceBreakTable[HB_Sentence_Close + 1][HB_Sentence_Close + 1] = { 7475569331642446be05292e3e1f8a51218827168cdclaireho// Other Sep Format Sp Lower Upper OLetter Numeric ATerm STerm Close 7485569331642446be05292e3e1f8a51218827168cdclaireho { SB_Initial, SB_BAfter , SB_Initial, SB_Initial, SB_Initial, SB_Upper , SB_Initial, SB_Initial, SB_ATerm , SB_STerm , SB_Initial }, // SB_Initial, 7495569331642446be05292e3e1f8a51218827168cdclaireho { SB_Initial, SB_BAfter , SB_Upper , SB_Initial, SB_Initial, SB_Upper , SB_Initial, SB_Initial, SB_UpATerm, SB_STerm , SB_Initial }, // SB_Upper 7505569331642446be05292e3e1f8a51218827168cdclaireho 7515569331642446be05292e3e1f8a51218827168cdclaireho { SB_Look , SB_BAfter , SB_UpATerm, SB_ACS , SB_Initial, SB_Upper , SB_Break , SB_Initial, SB_ATerm , SB_STerm , SB_ATermC }, // SB_UpATerm 7525569331642446be05292e3e1f8a51218827168cdclaireho { SB_Look , SB_BAfter , SB_ATerm , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Initial, SB_ATerm , SB_STerm , SB_ATermC }, // SB_ATerm 7535569331642446be05292e3e1f8a51218827168cdclaireho { SB_Look , SB_BAfter , SB_ATermC , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Look , SB_ATerm , SB_STerm , SB_ATermC }, // SB_ATermC, 7545569331642446be05292e3e1f8a51218827168cdclaireho { SB_Look , SB_BAfter , SB_ACS , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Look , SB_ATerm , SB_STerm , SB_Look }, // SB_ACS, 7555569331642446be05292e3e1f8a51218827168cdclaireho 7565569331642446be05292e3e1f8a51218827168cdclaireho { SB_Break , SB_BAfter , SB_STerm , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_STermC }, // SB_STerm, 7575569331642446be05292e3e1f8a51218827168cdclaireho { SB_Break , SB_BAfter , SB_STermC , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_STermC }, // SB_STermC, 7585569331642446be05292e3e1f8a51218827168cdclaireho { SB_Break , SB_BAfter , SB_SCS , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_Break }, // SB_SCS, 7595569331642446be05292e3e1f8a51218827168cdclaireho { SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break }, // SB_BAfter, 7605569331642446be05292e3e1f8a51218827168cdclaireho}; 7615569331642446be05292e3e1f8a51218827168cdclaireho 7625569331642446be05292e3e1f8a51218827168cdclairehovoid HB_GetSentenceBoundaries(const HB_UChar16 *string, hb_uint32 stringLength, 7635569331642446be05292e3e1f8a51218827168cdclaireho const HB_ScriptItem * /*items*/, hb_uint32 /*numItems*/, 7645569331642446be05292e3e1f8a51218827168cdclaireho HB_CharAttributes *attributes) 7655569331642446be05292e3e1f8a51218827168cdclaireho{ 7665569331642446be05292e3e1f8a51218827168cdclaireho if (stringLength == 0) 7675569331642446be05292e3e1f8a51218827168cdclaireho return; 7685569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 brk = sentenceBreakTable[SB_Initial][HB_GetSentenceClass(string[0])]; 7695569331642446be05292e3e1f8a51218827168cdclaireho attributes[0].sentenceBoundary = true; 7705569331642446be05292e3e1f8a51218827168cdclaireho for (hb_uint32 i = 1; i < stringLength; ++i) { 7715569331642446be05292e3e1f8a51218827168cdclaireho if (!attributes[i].charStop) { 7725569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].sentenceBoundary = false; 7735569331642446be05292e3e1f8a51218827168cdclaireho continue; 7745569331642446be05292e3e1f8a51218827168cdclaireho } 7755569331642446be05292e3e1f8a51218827168cdclaireho brk = sentenceBreakTable[brk][HB_GetSentenceClass(string[i])]; 7765569331642446be05292e3e1f8a51218827168cdclaireho if (brk == SB_Look) { 7775569331642446be05292e3e1f8a51218827168cdclaireho brk = SB_Break; 7785569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 lookahead = i + 1; 7795569331642446be05292e3e1f8a51218827168cdclaireho while (lookahead < stringLength) { 7805569331642446be05292e3e1f8a51218827168cdclaireho hb_uint32 sbrk = HB_GetSentenceClass(string[lookahead]); 7815569331642446be05292e3e1f8a51218827168cdclaireho if (sbrk != HB_Sentence_Other && sbrk != HB_Sentence_Numeric && sbrk != HB_Sentence_Close) { 7825569331642446be05292e3e1f8a51218827168cdclaireho break; 7835569331642446be05292e3e1f8a51218827168cdclaireho } else if (sbrk == HB_Sentence_Lower) { 7845569331642446be05292e3e1f8a51218827168cdclaireho brk = SB_Initial; 7855569331642446be05292e3e1f8a51218827168cdclaireho break; 7865569331642446be05292e3e1f8a51218827168cdclaireho } 7875569331642446be05292e3e1f8a51218827168cdclaireho ++lookahead; 7885569331642446be05292e3e1f8a51218827168cdclaireho } 7895569331642446be05292e3e1f8a51218827168cdclaireho if (brk == SB_Initial) { 7905569331642446be05292e3e1f8a51218827168cdclaireho while (i < lookahead) 7915569331642446be05292e3e1f8a51218827168cdclaireho attributes[i++].sentenceBoundary = false; 7925569331642446be05292e3e1f8a51218827168cdclaireho } 7935569331642446be05292e3e1f8a51218827168cdclaireho } 7945569331642446be05292e3e1f8a51218827168cdclaireho if (brk == SB_Break) { 7955569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].sentenceBoundary = true; 7965569331642446be05292e3e1f8a51218827168cdclaireho brk = sentenceBreakTable[SB_Initial][HB_GetSentenceClass(string[i])]; 7975569331642446be05292e3e1f8a51218827168cdclaireho } else { 7985569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].sentenceBoundary = false; 7995569331642446be05292e3e1f8a51218827168cdclaireho } 8005569331642446be05292e3e1f8a51218827168cdclaireho } 8015569331642446be05292e3e1f8a51218827168cdclaireho} 8025569331642446be05292e3e1f8a51218827168cdclaireho 8035569331642446be05292e3e1f8a51218827168cdclaireho 8045569331642446be05292e3e1f8a51218827168cdclairehostatic inline char *tag_to_string(HB_UInt tag) 8055569331642446be05292e3e1f8a51218827168cdclaireho{ 8065569331642446be05292e3e1f8a51218827168cdclaireho static char string[5]; 8075569331642446be05292e3e1f8a51218827168cdclaireho string[0] = (tag >> 24)&0xff; 8085569331642446be05292e3e1f8a51218827168cdclaireho string[1] = (tag >> 16)&0xff; 8095569331642446be05292e3e1f8a51218827168cdclaireho string[2] = (tag >> 8)&0xff; 8105569331642446be05292e3e1f8a51218827168cdclaireho string[3] = tag&0xff; 8115569331642446be05292e3e1f8a51218827168cdclaireho string[4] = 0; 8125569331642446be05292e3e1f8a51218827168cdclaireho return string; 8135569331642446be05292e3e1f8a51218827168cdclaireho} 8145569331642446be05292e3e1f8a51218827168cdclaireho 8155569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 8165569331642446be05292e3e1f8a51218827168cdclairehostatic void dump_string(HB_Buffer buffer) 8175569331642446be05292e3e1f8a51218827168cdclaireho{ 8185569331642446be05292e3e1f8a51218827168cdclaireho for (uint i = 0; i < buffer->in_length; ++i) { 8195569331642446be05292e3e1f8a51218827168cdclaireho qDebug(" %x: cluster=%d", buffer->in_string[i].gindex, buffer->in_string[i].cluster); 8205569331642446be05292e3e1f8a51218827168cdclaireho } 8215569331642446be05292e3e1f8a51218827168cdclaireho} 8225569331642446be05292e3e1f8a51218827168cdclaireho#define DEBUG printf 8235569331642446be05292e3e1f8a51218827168cdclaireho#else 8245569331642446be05292e3e1f8a51218827168cdclaireho#define DEBUG if (1) ; else printf 8255569331642446be05292e3e1f8a51218827168cdclaireho#endif 8265569331642446be05292e3e1f8a51218827168cdclaireho 8275569331642446be05292e3e1f8a51218827168cdclaireho#define DefaultLangSys 0xffff 8285569331642446be05292e3e1f8a51218827168cdclaireho#define DefaultScript HB_MAKE_TAG('D', 'F', 'L', 'T') 8295569331642446be05292e3e1f8a51218827168cdclaireho 8305569331642446be05292e3e1f8a51218827168cdclairehoenum { 8315569331642446be05292e3e1f8a51218827168cdclaireho RequiresGsub = 1, 8325569331642446be05292e3e1f8a51218827168cdclaireho RequiresGpos = 2 8335569331642446be05292e3e1f8a51218827168cdclaireho}; 8345569331642446be05292e3e1f8a51218827168cdclaireho 8355569331642446be05292e3e1f8a51218827168cdclairehostruct OTScripts { 8365569331642446be05292e3e1f8a51218827168cdclaireho unsigned int tag; 8375569331642446be05292e3e1f8a51218827168cdclaireho int flags; 8385569331642446be05292e3e1f8a51218827168cdclaireho}; 8395569331642446be05292e3e1f8a51218827168cdclairehostatic const OTScripts ot_scripts [] = { 8405569331642446be05292e3e1f8a51218827168cdclaireho // Common 8415569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('l', 'a', 't', 'n'), 0 }, 8425569331642446be05292e3e1f8a51218827168cdclaireho // Greek 8435569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('g', 'r', 'e', 'k'), 0 }, 8445569331642446be05292e3e1f8a51218827168cdclaireho // Cyrillic 8455569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('c', 'y', 'r', 'l'), 0 }, 8465569331642446be05292e3e1f8a51218827168cdclaireho // Armenian 8475569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('a', 'r', 'm', 'n'), 0 }, 8485569331642446be05292e3e1f8a51218827168cdclaireho // Hebrew 8495569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('h', 'e', 'b', 'r'), 1 }, 8505569331642446be05292e3e1f8a51218827168cdclaireho // Arabic 8515569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('a', 'r', 'a', 'b'), 1 }, 8525569331642446be05292e3e1f8a51218827168cdclaireho // Syriac 8535569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('s', 'y', 'r', 'c'), 1 }, 8545569331642446be05292e3e1f8a51218827168cdclaireho // Thaana 8555569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('t', 'h', 'a', 'a'), 1 }, 8565569331642446be05292e3e1f8a51218827168cdclaireho // Devanagari 8575569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('d', 'e', 'v', 'a'), 1 }, 8585569331642446be05292e3e1f8a51218827168cdclaireho // Bengali 8595569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('b', 'e', 'n', 'g'), 1 }, 8605569331642446be05292e3e1f8a51218827168cdclaireho // Gurmukhi 8615569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('g', 'u', 'r', 'u'), 1 }, 8625569331642446be05292e3e1f8a51218827168cdclaireho // Gujarati 8635569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('g', 'u', 'j', 'r'), 1 }, 8645569331642446be05292e3e1f8a51218827168cdclaireho // Oriya 8655569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('o', 'r', 'y', 'a'), 1 }, 8665569331642446be05292e3e1f8a51218827168cdclaireho // Tamil 8675569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('t', 'a', 'm', 'l'), 1 }, 8685569331642446be05292e3e1f8a51218827168cdclaireho // Telugu 8695569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('t', 'e', 'l', 'u'), 1 }, 8705569331642446be05292e3e1f8a51218827168cdclaireho // Kannada 8715569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('k', 'n', 'd', 'a'), 1 }, 8725569331642446be05292e3e1f8a51218827168cdclaireho // Malayalam 8735569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('m', 'l', 'y', 'm'), 1 }, 8745569331642446be05292e3e1f8a51218827168cdclaireho // Sinhala 8755569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('s', 'i', 'n', 'h'), 1 }, 8765569331642446be05292e3e1f8a51218827168cdclaireho // Thai 8775569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('t', 'h', 'a', 'i'), 1 }, 8785569331642446be05292e3e1f8a51218827168cdclaireho // Lao 8795569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('l', 'a', 'o', ' '), 1 }, 8805569331642446be05292e3e1f8a51218827168cdclaireho // Tibetan 8815569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('t', 'i', 'b', 't'), 1 }, 8825569331642446be05292e3e1f8a51218827168cdclaireho // Myanmar 8835569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('m', 'y', 'm', 'r'), 1 }, 8845569331642446be05292e3e1f8a51218827168cdclaireho // Georgian 8855569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('g', 'e', 'o', 'r'), 0 }, 8865569331642446be05292e3e1f8a51218827168cdclaireho // Hangul 8875569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('h', 'a', 'n', 'g'), 1 }, 8885569331642446be05292e3e1f8a51218827168cdclaireho // Ogham 8895569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('o', 'g', 'a', 'm'), 0 }, 8905569331642446be05292e3e1f8a51218827168cdclaireho // Runic 8915569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('r', 'u', 'n', 'r'), 0 }, 8925569331642446be05292e3e1f8a51218827168cdclaireho // Khmer 8935569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('k', 'h', 'm', 'r'), 1 }, 8945569331642446be05292e3e1f8a51218827168cdclaireho // N'Ko 8955569331642446be05292e3e1f8a51218827168cdclaireho { HB_MAKE_TAG('n', 'k', 'o', ' '), 1 } 8965569331642446be05292e3e1f8a51218827168cdclaireho}; 8975569331642446be05292e3e1f8a51218827168cdclairehoenum { NumOTScripts = sizeof(ot_scripts)/sizeof(OTScripts) }; 8985569331642446be05292e3e1f8a51218827168cdclaireho 8995569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Bool checkScript(HB_Face face, int script) 9005569331642446be05292e3e1f8a51218827168cdclaireho{ 9015569331642446be05292e3e1f8a51218827168cdclaireho assert(script < HB_ScriptCount); 9025569331642446be05292e3e1f8a51218827168cdclaireho 9035569331642446be05292e3e1f8a51218827168cdclaireho if (!face->gsub && !face->gpos) 9045569331642446be05292e3e1f8a51218827168cdclaireho return false; 9055569331642446be05292e3e1f8a51218827168cdclaireho 9065569331642446be05292e3e1f8a51218827168cdclaireho unsigned int tag = ot_scripts[script].tag; 9075569331642446be05292e3e1f8a51218827168cdclaireho int requirements = ot_scripts[script].flags; 9085569331642446be05292e3e1f8a51218827168cdclaireho 9095569331642446be05292e3e1f8a51218827168cdclaireho if (requirements & RequiresGsub) { 9105569331642446be05292e3e1f8a51218827168cdclaireho if (!face->gsub) 9115569331642446be05292e3e1f8a51218827168cdclaireho return false; 9125569331642446be05292e3e1f8a51218827168cdclaireho 9135569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort script_index; 9145569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index); 9155569331642446be05292e3e1f8a51218827168cdclaireho if (error) { 9165569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("could not select script %d in GSub table: %d", (int)script, error); 9175569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GSUB_Select_Script(face->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index); 9185569331642446be05292e3e1f8a51218827168cdclaireho if (error) 9195569331642446be05292e3e1f8a51218827168cdclaireho return false; 9205569331642446be05292e3e1f8a51218827168cdclaireho } 9215569331642446be05292e3e1f8a51218827168cdclaireho } 9225569331642446be05292e3e1f8a51218827168cdclaireho 9235569331642446be05292e3e1f8a51218827168cdclaireho if (requirements & RequiresGpos) { 9245569331642446be05292e3e1f8a51218827168cdclaireho if (!face->gpos) 9255569331642446be05292e3e1f8a51218827168cdclaireho return false; 9265569331642446be05292e3e1f8a51218827168cdclaireho 9275569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort script_index; 9285569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error = HB_GPOS_Select_Script(face->gpos, script, &script_index); 9295569331642446be05292e3e1f8a51218827168cdclaireho if (error) { 9305569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("could not select script in gpos table: %d", error); 9315569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GPOS_Select_Script(face->gpos, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index); 9325569331642446be05292e3e1f8a51218827168cdclaireho if (error) 9335569331642446be05292e3e1f8a51218827168cdclaireho return false; 9345569331642446be05292e3e1f8a51218827168cdclaireho } 9355569331642446be05292e3e1f8a51218827168cdclaireho 9365569331642446be05292e3e1f8a51218827168cdclaireho } 9375569331642446be05292e3e1f8a51218827168cdclaireho return true; 9385569331642446be05292e3e1f8a51218827168cdclaireho} 9395569331642446be05292e3e1f8a51218827168cdclaireho 9405569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Tag tag) 9415569331642446be05292e3e1f8a51218827168cdclaireho{ 9425569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error; 9435569331642446be05292e3e1f8a51218827168cdclaireho HB_UInt length = 0; 9445569331642446be05292e3e1f8a51218827168cdclaireho HB_Stream stream = 0; 9455569331642446be05292e3e1f8a51218827168cdclaireho 9465569331642446be05292e3e1f8a51218827168cdclaireho if (!font) 9475569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9485569331642446be05292e3e1f8a51218827168cdclaireho 9495569331642446be05292e3e1f8a51218827168cdclaireho error = tableFunc(font, tag, 0, &length); 9505569331642446be05292e3e1f8a51218827168cdclaireho if (error) 9515569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9525569331642446be05292e3e1f8a51218827168cdclaireho stream = (HB_Stream)malloc(sizeof(HB_StreamRec)); 9535569331642446be05292e3e1f8a51218827168cdclaireho if (!stream) 9545569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9555569331642446be05292e3e1f8a51218827168cdclaireho stream->base = (HB_Byte*)malloc(length); 9565569331642446be05292e3e1f8a51218827168cdclaireho if (!stream->base) { 9575569331642446be05292e3e1f8a51218827168cdclaireho free(stream); 9585569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9595569331642446be05292e3e1f8a51218827168cdclaireho } 9605569331642446be05292e3e1f8a51218827168cdclaireho error = tableFunc(font, tag, stream->base, &length); 9615569331642446be05292e3e1f8a51218827168cdclaireho if (error) { 9625569331642446be05292e3e1f8a51218827168cdclaireho _hb_close_stream(stream); 9635569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9645569331642446be05292e3e1f8a51218827168cdclaireho } 9655569331642446be05292e3e1f8a51218827168cdclaireho stream->size = length; 9665569331642446be05292e3e1f8a51218827168cdclaireho stream->pos = 0; 9675569331642446be05292e3e1f8a51218827168cdclaireho stream->cursor = NULL; 9685569331642446be05292e3e1f8a51218827168cdclaireho return stream; 9695569331642446be05292e3e1f8a51218827168cdclaireho} 9705569331642446be05292e3e1f8a51218827168cdclaireho 9715569331642446be05292e3e1f8a51218827168cdclairehoHB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) 9725569331642446be05292e3e1f8a51218827168cdclaireho{ 9735569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec)); 9745569331642446be05292e3e1f8a51218827168cdclaireho if (!face) 9755569331642446be05292e3e1f8a51218827168cdclaireho return 0; 9765569331642446be05292e3e1f8a51218827168cdclaireho 9775569331642446be05292e3e1f8a51218827168cdclaireho face->isSymbolFont = false; 9785569331642446be05292e3e1f8a51218827168cdclaireho face->gdef = 0; 9795569331642446be05292e3e1f8a51218827168cdclaireho face->gpos = 0; 9805569331642446be05292e3e1f8a51218827168cdclaireho face->gsub = 0; 9815569331642446be05292e3e1f8a51218827168cdclaireho face->current_script = HB_ScriptCount; 9825569331642446be05292e3e1f8a51218827168cdclaireho face->current_flags = HB_ShaperFlag_Default; 9835569331642446be05292e3e1f8a51218827168cdclaireho face->has_opentype_kerning = false; 9845569331642446be05292e3e1f8a51218827168cdclaireho face->tmpAttributes = 0; 9855569331642446be05292e3e1f8a51218827168cdclaireho face->tmpLogClusters = 0; 9865569331642446be05292e3e1f8a51218827168cdclaireho face->glyphs_substituted = false; 9875569331642446be05292e3e1f8a51218827168cdclaireho face->buffer = 0; 9885569331642446be05292e3e1f8a51218827168cdclaireho 9895569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error; 9905569331642446be05292e3e1f8a51218827168cdclaireho HB_Stream stream; 9915569331642446be05292e3e1f8a51218827168cdclaireho HB_Stream gdefStream; 9925569331642446be05292e3e1f8a51218827168cdclaireho 9935569331642446be05292e3e1f8a51218827168cdclaireho gdefStream = getTableStream(font, tableFunc, TTAG_GDEF); 9945569331642446be05292e3e1f8a51218827168cdclaireho if (!gdefStream || (error = HB_Load_GDEF_Table(gdefStream, &face->gdef))) { 9955569331642446be05292e3e1f8a51218827168cdclaireho //DEBUG("error loading gdef table: %d", error); 9965569331642446be05292e3e1f8a51218827168cdclaireho face->gdef = 0; 9975569331642446be05292e3e1f8a51218827168cdclaireho } 9985569331642446be05292e3e1f8a51218827168cdclaireho 9995569331642446be05292e3e1f8a51218827168cdclaireho //DEBUG() << "trying to load gsub table"; 10005569331642446be05292e3e1f8a51218827168cdclaireho stream = getTableStream(font, tableFunc, TTAG_GSUB); 10015569331642446be05292e3e1f8a51218827168cdclaireho if (!stream || (error = HB_Load_GSUB_Table(stream, &face->gsub, face->gdef, gdefStream))) { 10025569331642446be05292e3e1f8a51218827168cdclaireho face->gsub = 0; 10035569331642446be05292e3e1f8a51218827168cdclaireho if (error != HB_Err_Not_Covered) { 10045569331642446be05292e3e1f8a51218827168cdclaireho //DEBUG("error loading gsub table: %d", error); 10055569331642446be05292e3e1f8a51218827168cdclaireho } else { 10065569331642446be05292e3e1f8a51218827168cdclaireho //DEBUG("face doesn't have a gsub table"); 10075569331642446be05292e3e1f8a51218827168cdclaireho } 10085569331642446be05292e3e1f8a51218827168cdclaireho } 10095569331642446be05292e3e1f8a51218827168cdclaireho _hb_close_stream(stream); 10105569331642446be05292e3e1f8a51218827168cdclaireho 10115569331642446be05292e3e1f8a51218827168cdclaireho stream = getTableStream(font, tableFunc, TTAG_GPOS); 10125569331642446be05292e3e1f8a51218827168cdclaireho if (!stream || (error = HB_Load_GPOS_Table(stream, &face->gpos, face->gdef, gdefStream))) { 10135569331642446be05292e3e1f8a51218827168cdclaireho face->gpos = 0; 10145569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("error loading gpos table: %d", error); 10155569331642446be05292e3e1f8a51218827168cdclaireho } 10165569331642446be05292e3e1f8a51218827168cdclaireho _hb_close_stream(stream); 10175569331642446be05292e3e1f8a51218827168cdclaireho 10185569331642446be05292e3e1f8a51218827168cdclaireho _hb_close_stream(gdefStream); 10195569331642446be05292e3e1f8a51218827168cdclaireho 10205569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < HB_ScriptCount; ++i) 10215569331642446be05292e3e1f8a51218827168cdclaireho face->supported_scripts[i] = checkScript(face, i); 10225569331642446be05292e3e1f8a51218827168cdclaireho 10235569331642446be05292e3e1f8a51218827168cdclaireho if (hb_buffer_new(&face->buffer) != HB_Err_Ok) { 10245569331642446be05292e3e1f8a51218827168cdclaireho HB_FreeFace(face); 10255569331642446be05292e3e1f8a51218827168cdclaireho return 0; 10265569331642446be05292e3e1f8a51218827168cdclaireho } 10275569331642446be05292e3e1f8a51218827168cdclaireho 10285569331642446be05292e3e1f8a51218827168cdclaireho return face; 10295569331642446be05292e3e1f8a51218827168cdclaireho} 10305569331642446be05292e3e1f8a51218827168cdclaireho 10315569331642446be05292e3e1f8a51218827168cdclairehovoid HB_FreeFace(HB_Face face) 10325569331642446be05292e3e1f8a51218827168cdclaireho{ 10335569331642446be05292e3e1f8a51218827168cdclaireho if (!face) 10345569331642446be05292e3e1f8a51218827168cdclaireho return; 10355569331642446be05292e3e1f8a51218827168cdclaireho if (face->gpos) 10365569331642446be05292e3e1f8a51218827168cdclaireho HB_Done_GPOS_Table(face->gpos); 10375569331642446be05292e3e1f8a51218827168cdclaireho if (face->gsub) 10385569331642446be05292e3e1f8a51218827168cdclaireho HB_Done_GSUB_Table(face->gsub); 10395569331642446be05292e3e1f8a51218827168cdclaireho if (face->gdef) 10405569331642446be05292e3e1f8a51218827168cdclaireho HB_Done_GDEF_Table(face->gdef); 10415569331642446be05292e3e1f8a51218827168cdclaireho if (face->buffer) 10425569331642446be05292e3e1f8a51218827168cdclaireho hb_buffer_free(face->buffer); 10435569331642446be05292e3e1f8a51218827168cdclaireho if (face->tmpAttributes) 10445569331642446be05292e3e1f8a51218827168cdclaireho free(face->tmpAttributes); 10455569331642446be05292e3e1f8a51218827168cdclaireho if (face->tmpLogClusters) 10465569331642446be05292e3e1f8a51218827168cdclaireho free(face->tmpLogClusters); 10475569331642446be05292e3e1f8a51218827168cdclaireho free(face); 10485569331642446be05292e3e1f8a51218827168cdclaireho} 10495569331642446be05292e3e1f8a51218827168cdclaireho 10505569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *features) 10515569331642446be05292e3e1f8a51218827168cdclaireho{ 10525569331642446be05292e3e1f8a51218827168cdclaireho HB_Script script = shaper_item->item.script; 10535569331642446be05292e3e1f8a51218827168cdclaireho 10545569331642446be05292e3e1f8a51218827168cdclaireho if (!shaper_item->face->supported_scripts[script]) 10555569331642446be05292e3e1f8a51218827168cdclaireho return false; 10565569331642446be05292e3e1f8a51218827168cdclaireho 10575569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = shaper_item->face; 10585569331642446be05292e3e1f8a51218827168cdclaireho if (face->current_script == script && face->current_flags == shaper_item->shaperFlags) 10595569331642446be05292e3e1f8a51218827168cdclaireho return true; 10605569331642446be05292e3e1f8a51218827168cdclaireho 10615569331642446be05292e3e1f8a51218827168cdclaireho face->current_script = script; 10625569331642446be05292e3e1f8a51218827168cdclaireho face->current_flags = shaper_item->shaperFlags; 10635569331642446be05292e3e1f8a51218827168cdclaireho 10645569331642446be05292e3e1f8a51218827168cdclaireho assert(script < HB_ScriptCount); 10655569331642446be05292e3e1f8a51218827168cdclaireho // find script in our list of supported scripts. 10665569331642446be05292e3e1f8a51218827168cdclaireho unsigned int tag = ot_scripts[script].tag; 10675569331642446be05292e3e1f8a51218827168cdclaireho 10685569331642446be05292e3e1f8a51218827168cdclaireho if (face->gsub && features) { 10695569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 10705569331642446be05292e3e1f8a51218827168cdclaireho { 10715569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureList featurelist = face->gsub->FeatureList; 10725569331642446be05292e3e1f8a51218827168cdclaireho int numfeatures = featurelist.FeatureCount; 10735569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("gsub table has %d features", numfeatures); 10745569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < numfeatures; i++) { 10755569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureRecord *r = featurelist.FeatureRecord + i; 10765569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" feature '%s'", tag_to_string(r->FeatureTag)); 10775569331642446be05292e3e1f8a51218827168cdclaireho } 10785569331642446be05292e3e1f8a51218827168cdclaireho } 10795569331642446be05292e3e1f8a51218827168cdclaireho#endif 10805569331642446be05292e3e1f8a51218827168cdclaireho HB_GSUB_Clear_Features(face->gsub); 10815569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort script_index; 10825569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index); 10835569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 10845569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("script %s has script index %d", tag_to_string(script), script_index); 10855569331642446be05292e3e1f8a51218827168cdclaireho while (features->tag) { 10865569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 10875569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GSUB_Select_Feature(face->gsub, features->tag, script_index, 0xffff, &feature_index); 10885569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 10895569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" adding feature %s", tag_to_string(features->tag)); 10905569331642446be05292e3e1f8a51218827168cdclaireho HB_GSUB_Add_Feature(face->gsub, feature_index, features->property); 10915569331642446be05292e3e1f8a51218827168cdclaireho } 10925569331642446be05292e3e1f8a51218827168cdclaireho ++features; 10935569331642446be05292e3e1f8a51218827168cdclaireho } 10945569331642446be05292e3e1f8a51218827168cdclaireho } 10955569331642446be05292e3e1f8a51218827168cdclaireho } 10965569331642446be05292e3e1f8a51218827168cdclaireho 10975569331642446be05292e3e1f8a51218827168cdclaireho // reset 10985569331642446be05292e3e1f8a51218827168cdclaireho face->has_opentype_kerning = false; 10995569331642446be05292e3e1f8a51218827168cdclaireho 11005569331642446be05292e3e1f8a51218827168cdclaireho if (face->gpos) { 11015569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Clear_Features(face->gpos); 11025569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort script_index; 11035569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error = HB_GPOS_Select_Script(face->gpos, tag, &script_index); 11045569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 11055569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11065569331642446be05292e3e1f8a51218827168cdclaireho { 11075569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureList featurelist = face->gpos->FeatureList; 11085569331642446be05292e3e1f8a51218827168cdclaireho int numfeatures = featurelist.FeatureCount; 11095569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("gpos table has %d features", numfeatures); 11105569331642446be05292e3e1f8a51218827168cdclaireho for(int i = 0; i < numfeatures; i++) { 11115569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureRecord *r = featurelist.FeatureRecord + i; 11125569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 11135569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Select_Feature(face->gpos, r->FeatureTag, script_index, 0xffff, &feature_index); 11145569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" feature '%s'", tag_to_string(r->FeatureTag)); 11155569331642446be05292e3e1f8a51218827168cdclaireho } 11165569331642446be05292e3e1f8a51218827168cdclaireho } 11175569331642446be05292e3e1f8a51218827168cdclaireho#endif 11185569331642446be05292e3e1f8a51218827168cdclaireho HB_UInt *feature_tag_list_buffer; 11195569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GPOS_Query_Features(face->gpos, script_index, 0xffff, &feature_tag_list_buffer); 11205569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 11215569331642446be05292e3e1f8a51218827168cdclaireho HB_UInt *feature_tag_list = feature_tag_list_buffer; 11225569331642446be05292e3e1f8a51218827168cdclaireho while (*feature_tag_list) { 11235569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 11245569331642446be05292e3e1f8a51218827168cdclaireho if (*feature_tag_list == HB_MAKE_TAG('k', 'e', 'r', 'n')) { 11255569331642446be05292e3e1f8a51218827168cdclaireho if (face->current_flags & HB_ShaperFlag_NoKerning) { 11265569331642446be05292e3e1f8a51218827168cdclaireho ++feature_tag_list; 11275569331642446be05292e3e1f8a51218827168cdclaireho continue; 11285569331642446be05292e3e1f8a51218827168cdclaireho } 11295569331642446be05292e3e1f8a51218827168cdclaireho face->has_opentype_kerning = true; 11305569331642446be05292e3e1f8a51218827168cdclaireho } 11315569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GPOS_Select_Feature(face->gpos, *feature_tag_list, script_index, 0xffff, &feature_index); 11325569331642446be05292e3e1f8a51218827168cdclaireho if (!error) 11335569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Add_Feature(face->gpos, feature_index, PositioningProperties); 11345569331642446be05292e3e1f8a51218827168cdclaireho ++feature_tag_list; 11355569331642446be05292e3e1f8a51218827168cdclaireho } 11365569331642446be05292e3e1f8a51218827168cdclaireho FREE(feature_tag_list_buffer); 11375569331642446be05292e3e1f8a51218827168cdclaireho } 11385569331642446be05292e3e1f8a51218827168cdclaireho } 11395569331642446be05292e3e1f8a51218827168cdclaireho } 11405569331642446be05292e3e1f8a51218827168cdclaireho 11415569331642446be05292e3e1f8a51218827168cdclaireho return true; 11425569331642446be05292e3e1f8a51218827168cdclaireho} 11435569331642446be05292e3e1f8a51218827168cdclaireho 11445569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties) 11455569331642446be05292e3e1f8a51218827168cdclaireho{ 11465569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *tmpAttributes; 11475569331642446be05292e3e1f8a51218827168cdclaireho unsigned int *tmpLogClusters; 11485569331642446be05292e3e1f8a51218827168cdclaireho 11495569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = item->face; 11505569331642446be05292e3e1f8a51218827168cdclaireho 11515569331642446be05292e3e1f8a51218827168cdclaireho face->length = item->num_glyphs; 11525569331642446be05292e3e1f8a51218827168cdclaireho 11535569331642446be05292e3e1f8a51218827168cdclaireho hb_buffer_clear(face->buffer); 11545569331642446be05292e3e1f8a51218827168cdclaireho 11555569331642446be05292e3e1f8a51218827168cdclaireho tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes)); 11565569331642446be05292e3e1f8a51218827168cdclaireho if (!tmpAttributes) 11575569331642446be05292e3e1f8a51218827168cdclaireho return false; 11585569331642446be05292e3e1f8a51218827168cdclaireho face->tmpAttributes = tmpAttributes; 11595569331642446be05292e3e1f8a51218827168cdclaireho 11605569331642446be05292e3e1f8a51218827168cdclaireho tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int)); 11615569331642446be05292e3e1f8a51218827168cdclaireho if (!tmpLogClusters) 11625569331642446be05292e3e1f8a51218827168cdclaireho return false; 11635569331642446be05292e3e1f8a51218827168cdclaireho face->tmpLogClusters = tmpLogClusters; 11645569331642446be05292e3e1f8a51218827168cdclaireho 11655569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < face->length; ++i) { 11665569331642446be05292e3e1f8a51218827168cdclaireho hb_buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i); 11675569331642446be05292e3e1f8a51218827168cdclaireho face->tmpAttributes[i] = item->attributes[i]; 11685569331642446be05292e3e1f8a51218827168cdclaireho face->tmpLogClusters[i] = item->log_clusters[i]; 11695569331642446be05292e3e1f8a51218827168cdclaireho } 11705569331642446be05292e3e1f8a51218827168cdclaireho 11715569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11725569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 11735569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("log clusters before shaping:"); 11745569331642446be05292e3e1f8a51218827168cdclaireho// for (int j = 0; j < length; j++) 11755569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 11765569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("original glyphs: %p", item->glyphs); 11775569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < length; ++i) 11785569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex); 11795569331642446be05292e3e1f8a51218827168cdclaireho// dump_string(hb_buffer); 11805569331642446be05292e3e1f8a51218827168cdclaireho#endif 11815569331642446be05292e3e1f8a51218827168cdclaireho 11825569331642446be05292e3e1f8a51218827168cdclaireho face->glyphs_substituted = false; 11835569331642446be05292e3e1f8a51218827168cdclaireho if (face->gsub) { 11845569331642446be05292e3e1f8a51218827168cdclaireho unsigned int error = HB_GSUB_Apply_String(face->gsub, face->buffer); 11855569331642446be05292e3e1f8a51218827168cdclaireho if (error && error != HB_Err_Not_Covered) 11865569331642446be05292e3e1f8a51218827168cdclaireho return false; 11875569331642446be05292e3e1f8a51218827168cdclaireho face->glyphs_substituted = (error != HB_Err_Not_Covered); 11885569331642446be05292e3e1f8a51218827168cdclaireho } 11895569331642446be05292e3e1f8a51218827168cdclaireho 11905569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11915569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("log clusters before shaping:"); 11925569331642446be05292e3e1f8a51218827168cdclaireho// for (int j = 0; j < length; j++) 11935569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 11945569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("shaped glyphs:"); 11955569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < length; ++i) 11965569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex); 11975569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 11985569331642446be05292e3e1f8a51218827168cdclaireho// dump_string(hb_buffer); 11995569331642446be05292e3e1f8a51218827168cdclaireho#endif 12005569331642446be05292e3e1f8a51218827168cdclaireho 12015569331642446be05292e3e1f8a51218827168cdclaireho return true; 12025569331642446be05292e3e1f8a51218827168cdclaireho} 12035569331642446be05292e3e1f8a51218827168cdclaireho 12045569331642446be05292e3e1f8a51218827168cdclaireho/* See comments near the definition of HB_ShaperFlag_ForceMarksToZeroWidth for a description 12055569331642446be05292e3e1f8a51218827168cdclaireho of why this function exists. */ 12065569331642446be05292e3e1f8a51218827168cdclairehovoid HB_FixupZeroWidth(HB_ShaperItem *item) 12075569331642446be05292e3e1f8a51218827168cdclaireho{ 12085569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort property; 12095569331642446be05292e3e1f8a51218827168cdclaireho 12105569331642446be05292e3e1f8a51218827168cdclaireho if (!item->face->gdef) 12115569331642446be05292e3e1f8a51218827168cdclaireho return; 12125569331642446be05292e3e1f8a51218827168cdclaireho 12135569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < item->num_glyphs; ++i) { 12145569331642446be05292e3e1f8a51218827168cdclaireho /* If the glyph is a mark, force its advance to zero. */ 12155569331642446be05292e3e1f8a51218827168cdclaireho if (HB_GDEF_Get_Glyph_Property (item->face->gdef, item->glyphs[i], &property) == HB_Err_Ok && 12165569331642446be05292e3e1f8a51218827168cdclaireho property == HB_GDEF_MARK) { 12175569331642446be05292e3e1f8a51218827168cdclaireho item->advances[i] = 0; 12185569331642446be05292e3e1f8a51218827168cdclaireho } 12195569331642446be05292e3e1f8a51218827168cdclaireho } 12205569331642446be05292e3e1f8a51218827168cdclaireho} 12215569331642446be05292e3e1f8a51218827168cdclaireho 12225569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters) 12235569331642446be05292e3e1f8a51218827168cdclaireho{ 12245569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = item->face; 12255569331642446be05292e3e1f8a51218827168cdclaireho 12265569331642446be05292e3e1f8a51218827168cdclaireho bool glyphs_positioned = false; 12275569331642446be05292e3e1f8a51218827168cdclaireho if (face->gpos) { 12285569331642446be05292e3e1f8a51218827168cdclaireho if (face->buffer->positions) 12295569331642446be05292e3e1f8a51218827168cdclaireho memset(face->buffer->positions, 0, face->buffer->in_length*sizeof(HB_PositionRec)); 12305569331642446be05292e3e1f8a51218827168cdclaireho // #### check that passing "false,false" is correct 12315569331642446be05292e3e1f8a51218827168cdclaireho glyphs_positioned = HB_GPOS_Apply_String(item->font, face->gpos, face->current_flags, face->buffer, false, false) != HB_Err_Not_Covered; 12325569331642446be05292e3e1f8a51218827168cdclaireho } 12335569331642446be05292e3e1f8a51218827168cdclaireho 12345569331642446be05292e3e1f8a51218827168cdclaireho if (!face->glyphs_substituted && !glyphs_positioned) { 12355569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGlyphAdvances(item); 12365569331642446be05292e3e1f8a51218827168cdclaireho if (item->face->current_flags & HB_ShaperFlag_ForceMarksToZeroWidth) 12375569331642446be05292e3e1f8a51218827168cdclaireho HB_FixupZeroWidth(item); 12385569331642446be05292e3e1f8a51218827168cdclaireho return true; // nothing to do for us 12395569331642446be05292e3e1f8a51218827168cdclaireho } 12405569331642446be05292e3e1f8a51218827168cdclaireho 12415569331642446be05292e3e1f8a51218827168cdclaireho // make sure we have enough space to write everything back 12425569331642446be05292e3e1f8a51218827168cdclaireho if (availableGlyphs < (int)face->buffer->in_length) { 12435569331642446be05292e3e1f8a51218827168cdclaireho item->num_glyphs = face->buffer->in_length; 12445569331642446be05292e3e1f8a51218827168cdclaireho return false; 12455569331642446be05292e3e1f8a51218827168cdclaireho } 12465569331642446be05292e3e1f8a51218827168cdclaireho 12475569331642446be05292e3e1f8a51218827168cdclaireho HB_Glyph *glyphs = item->glyphs; 12485569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = item->attributes; 12495569331642446be05292e3e1f8a51218827168cdclaireho 12505569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; ++i) { 12515569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i] = face->buffer->in_string[i].gindex; 12525569331642446be05292e3e1f8a51218827168cdclaireho attributes[i] = face->tmpAttributes[face->buffer->in_string[i].cluster]; 12535569331642446be05292e3e1f8a51218827168cdclaireho if (i && face->buffer->in_string[i].cluster == face->buffer->in_string[i-1].cluster) 12545569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].clusterStart = false; 12555569331642446be05292e3e1f8a51218827168cdclaireho } 12565569331642446be05292e3e1f8a51218827168cdclaireho item->num_glyphs = face->buffer->in_length; 12575569331642446be05292e3e1f8a51218827168cdclaireho 12585569331642446be05292e3e1f8a51218827168cdclaireho if (doLogClusters && face->glyphs_substituted) { 12595569331642446be05292e3e1f8a51218827168cdclaireho // we can't do this for indic, as we pass the stuf in syllables and it's easier to do it in the shaper. 12605569331642446be05292e3e1f8a51218827168cdclaireho unsigned short *logClusters = item->log_clusters; 12615569331642446be05292e3e1f8a51218827168cdclaireho int clusterStart = 0; 12625569331642446be05292e3e1f8a51218827168cdclaireho int oldCi = 0; 12635569331642446be05292e3e1f8a51218827168cdclaireho // #### the reconstruction of the logclusters currently does not work if the original string 12645569331642446be05292e3e1f8a51218827168cdclaireho // contains surrogate pairs 12655569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; ++i) { 12665569331642446be05292e3e1f8a51218827168cdclaireho int ci = face->buffer->in_string[i].cluster; 12675569331642446be05292e3e1f8a51218827168cdclaireho // DEBUG(" ci[%d] = %d mark=%d, cmb=%d, cs=%d", 12685569331642446be05292e3e1f8a51218827168cdclaireho // i, ci, glyphAttributes[i].mark, glyphAttributes[i].combiningClass, glyphAttributes[i].clusterStart); 12695569331642446be05292e3e1f8a51218827168cdclaireho if (!attributes[i].mark && attributes[i].clusterStart && ci != oldCi) { 12705569331642446be05292e3e1f8a51218827168cdclaireho for (int j = oldCi; j < ci; j++) 12715569331642446be05292e3e1f8a51218827168cdclaireho logClusters[j] = clusterStart; 12725569331642446be05292e3e1f8a51218827168cdclaireho clusterStart = i; 12735569331642446be05292e3e1f8a51218827168cdclaireho oldCi = ci; 12745569331642446be05292e3e1f8a51218827168cdclaireho } 12755569331642446be05292e3e1f8a51218827168cdclaireho } 12765569331642446be05292e3e1f8a51218827168cdclaireho for (int j = oldCi; j < face->length; j++) 12775569331642446be05292e3e1f8a51218827168cdclaireho logClusters[j] = clusterStart; 12785569331642446be05292e3e1f8a51218827168cdclaireho } 12795569331642446be05292e3e1f8a51218827168cdclaireho 12805569331642446be05292e3e1f8a51218827168cdclaireho // calulate the advances for the shaped glyphs 12815569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("unpositioned: "); 12825569331642446be05292e3e1f8a51218827168cdclaireho 12835569331642446be05292e3e1f8a51218827168cdclaireho // positioning code: 12845569331642446be05292e3e1f8a51218827168cdclaireho if (glyphs_positioned) { 12855569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGlyphAdvances(item); 12865569331642446be05292e3e1f8a51218827168cdclaireho HB_Position positions = face->buffer->positions; 12875569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed *advances = item->advances; 12885569331642446be05292e3e1f8a51218827168cdclaireho 12895569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("positioned glyphs:"); 12905569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; i++) { 12915569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" %d:\t orig advance: (%d/%d)\tadv=(%d/%d)\tpos=(%d/%d)\tback=%d\tnew_advance=%d", i, 12925569331642446be05292e3e1f8a51218827168cdclaireho// glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(), 12935569331642446be05292e3e1f8a51218827168cdclaireho// (int)(positions[i].x_advance >> 6), (int)(positions[i].y_advance >> 6), 12945569331642446be05292e3e1f8a51218827168cdclaireho// (int)(positions[i].x_pos >> 6), (int)(positions[i].y_pos >> 6), 12955569331642446be05292e3e1f8a51218827168cdclaireho// positions[i].back, positions[i].new_advance); 12965569331642446be05292e3e1f8a51218827168cdclaireho 12975569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed adjustment = (item->item.bidiLevel % 2) ? -positions[i].x_advance : positions[i].x_advance; 12985569331642446be05292e3e1f8a51218827168cdclaireho 12995569331642446be05292e3e1f8a51218827168cdclaireho if (!(face->current_flags & HB_ShaperFlag_UseDesignMetrics)) 13005569331642446be05292e3e1f8a51218827168cdclaireho adjustment = HB_FIXED_ROUND(adjustment); 13015569331642446be05292e3e1f8a51218827168cdclaireho 13025569331642446be05292e3e1f8a51218827168cdclaireho if (positions[i].new_advance) { 13035569331642446be05292e3e1f8a51218827168cdclaireho advances[i] = adjustment; 13045569331642446be05292e3e1f8a51218827168cdclaireho } else { 13055569331642446be05292e3e1f8a51218827168cdclaireho advances[i] += adjustment; 13065569331642446be05292e3e1f8a51218827168cdclaireho } 13075569331642446be05292e3e1f8a51218827168cdclaireho 13085569331642446be05292e3e1f8a51218827168cdclaireho int back = 0; 13095569331642446be05292e3e1f8a51218827168cdclaireho HB_FixedPoint *offsets = item->offsets; 13105569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x = positions[i].x_pos; 13115569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y = positions[i].y_pos; 13125569331642446be05292e3e1f8a51218827168cdclaireho while (positions[i - back].back) { 13135569331642446be05292e3e1f8a51218827168cdclaireho back += positions[i - back].back; 13145569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x += positions[i - back].x_pos; 13155569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y += positions[i - back].y_pos; 13165569331642446be05292e3e1f8a51218827168cdclaireho } 13175569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y = -offsets[i].y; 13185569331642446be05292e3e1f8a51218827168cdclaireho 13195569331642446be05292e3e1f8a51218827168cdclaireho if (item->item.bidiLevel % 2) { 13205569331642446be05292e3e1f8a51218827168cdclaireho // ### may need to go back multiple glyphs like in ltr 13215569331642446be05292e3e1f8a51218827168cdclaireho back = positions[i].back; 13225569331642446be05292e3e1f8a51218827168cdclaireho while (back--) 13235569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x -= advances[i-back]; 13245569331642446be05292e3e1f8a51218827168cdclaireho } else { 13255569331642446be05292e3e1f8a51218827168cdclaireho back = 0; 13265569331642446be05292e3e1f8a51218827168cdclaireho while (positions[i - back].back) { 13275569331642446be05292e3e1f8a51218827168cdclaireho back += positions[i - back].back; 13285569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x -= advances[i-back]; 13295569331642446be05292e3e1f8a51218827168cdclaireho } 13305569331642446be05292e3e1f8a51218827168cdclaireho } 13315569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" ->\tadv=%d\tpos=(%d/%d)", 13325569331642446be05292e3e1f8a51218827168cdclaireho// glyphs[i].advance.x.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); 13335569331642446be05292e3e1f8a51218827168cdclaireho } 13345569331642446be05292e3e1f8a51218827168cdclaireho item->kerning_applied = face->has_opentype_kerning; 13355569331642446be05292e3e1f8a51218827168cdclaireho } else { 13365569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicPosition(item); 13375569331642446be05292e3e1f8a51218827168cdclaireho } 13385569331642446be05292e3e1f8a51218827168cdclaireho 13395569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 13405569331642446be05292e3e1f8a51218827168cdclaireho if (doLogClusters) { 13415569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("log clusters after shaping:"); 13425569331642446be05292e3e1f8a51218827168cdclaireho for (int j = 0; j < length; j++) 13435569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 13445569331642446be05292e3e1f8a51218827168cdclaireho } 13455569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("final glyphs:"); 13465569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < (int)hb_buffer->in_length; ++i) 13475569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x char_index=%d mark: %d cmp: %d, clusterStart: %d advance=%d/%d offset=%d/%d", 13485569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].glyph, hb_buffer->in_string[i].cluster, glyphs[i].attributes.mark, 13495569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].attributes.combiningClass, glyphs[i].attributes.clusterStart, 13505569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(), 13515569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); 13525569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 13535569331642446be05292e3e1f8a51218827168cdclaireho#endif 13545569331642446be05292e3e1f8a51218827168cdclaireho return true; 13555569331642446be05292e3e1f8a51218827168cdclaireho} 13565569331642446be05292e3e1f8a51218827168cdclaireho 13575569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_ShapeItem(HB_ShaperItem *shaper_item) 13585569331642446be05292e3e1f8a51218827168cdclaireho{ 13595569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool result = false; 13605569331642446be05292e3e1f8a51218827168cdclaireho if (shaper_item->num_glyphs < shaper_item->item.length) { 13615569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->num_glyphs = shaper_item->item.length; 13625569331642446be05292e3e1f8a51218827168cdclaireho return false; 13635569331642446be05292e3e1f8a51218827168cdclaireho } 13645569331642446be05292e3e1f8a51218827168cdclaireho assert(shaper_item->item.script < HB_ScriptCount); 13655569331642446be05292e3e1f8a51218827168cdclaireho result = HB_ScriptEngines[shaper_item->item.script].shape(shaper_item); 13665569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphIndicesPresent = false; 13675569331642446be05292e3e1f8a51218827168cdclaireho return result; 13685569331642446be05292e3e1f8a51218827168cdclaireho} 13695569331642446be05292e3e1f8a51218827168cdclaireho 1370