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