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); 10855569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 10865569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("script %s has script index %d", tag_to_string(script), script_index); 10875569331642446be05292e3e1f8a51218827168cdclaireho while (features->tag) { 10885569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 10895569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GSUB_Select_Feature(face->gsub, features->tag, script_index, 0xffff, &feature_index); 10905569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 10915569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" adding feature %s", tag_to_string(features->tag)); 10925569331642446be05292e3e1f8a51218827168cdclaireho HB_GSUB_Add_Feature(face->gsub, feature_index, features->property); 10935569331642446be05292e3e1f8a51218827168cdclaireho } 10945569331642446be05292e3e1f8a51218827168cdclaireho ++features; 10955569331642446be05292e3e1f8a51218827168cdclaireho } 10965569331642446be05292e3e1f8a51218827168cdclaireho } 10975569331642446be05292e3e1f8a51218827168cdclaireho } 10985569331642446be05292e3e1f8a51218827168cdclaireho 10995569331642446be05292e3e1f8a51218827168cdclaireho // reset 11005569331642446be05292e3e1f8a51218827168cdclaireho face->has_opentype_kerning = false; 11015569331642446be05292e3e1f8a51218827168cdclaireho 11025569331642446be05292e3e1f8a51218827168cdclaireho if (face->gpos) { 11035569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Clear_Features(face->gpos); 11045569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort script_index; 11055569331642446be05292e3e1f8a51218827168cdclaireho HB_Error error = HB_GPOS_Select_Script(face->gpos, tag, &script_index); 11065569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 11075569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11085569331642446be05292e3e1f8a51218827168cdclaireho { 11095569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureList featurelist = face->gpos->FeatureList; 11105569331642446be05292e3e1f8a51218827168cdclaireho int numfeatures = featurelist.FeatureCount; 11115569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("gpos table has %d features", numfeatures); 11125569331642446be05292e3e1f8a51218827168cdclaireho for(int i = 0; i < numfeatures; i++) { 11135569331642446be05292e3e1f8a51218827168cdclaireho HB_FeatureRecord *r = featurelist.FeatureRecord + i; 11145569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 11155569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Select_Feature(face->gpos, r->FeatureTag, script_index, 0xffff, &feature_index); 11165569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" feature '%s'", tag_to_string(r->FeatureTag)); 11175569331642446be05292e3e1f8a51218827168cdclaireho } 11185569331642446be05292e3e1f8a51218827168cdclaireho } 11195569331642446be05292e3e1f8a51218827168cdclaireho#endif 11205569331642446be05292e3e1f8a51218827168cdclaireho HB_UInt *feature_tag_list_buffer; 11215569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GPOS_Query_Features(face->gpos, script_index, 0xffff, &feature_tag_list_buffer); 11225569331642446be05292e3e1f8a51218827168cdclaireho if (!error) { 11235569331642446be05292e3e1f8a51218827168cdclaireho HB_UInt *feature_tag_list = feature_tag_list_buffer; 11245569331642446be05292e3e1f8a51218827168cdclaireho while (*feature_tag_list) { 11255569331642446be05292e3e1f8a51218827168cdclaireho HB_UShort feature_index; 11265569331642446be05292e3e1f8a51218827168cdclaireho if (*feature_tag_list == HB_MAKE_TAG('k', 'e', 'r', 'n')) { 11275569331642446be05292e3e1f8a51218827168cdclaireho if (face->current_flags & HB_ShaperFlag_NoKerning) { 11285569331642446be05292e3e1f8a51218827168cdclaireho ++feature_tag_list; 11295569331642446be05292e3e1f8a51218827168cdclaireho continue; 11305569331642446be05292e3e1f8a51218827168cdclaireho } 11315569331642446be05292e3e1f8a51218827168cdclaireho face->has_opentype_kerning = true; 11325569331642446be05292e3e1f8a51218827168cdclaireho } 11335569331642446be05292e3e1f8a51218827168cdclaireho error = HB_GPOS_Select_Feature(face->gpos, *feature_tag_list, script_index, 0xffff, &feature_index); 11345569331642446be05292e3e1f8a51218827168cdclaireho if (!error) 11355569331642446be05292e3e1f8a51218827168cdclaireho HB_GPOS_Add_Feature(face->gpos, feature_index, PositioningProperties); 11365569331642446be05292e3e1f8a51218827168cdclaireho ++feature_tag_list; 11375569331642446be05292e3e1f8a51218827168cdclaireho } 11385569331642446be05292e3e1f8a51218827168cdclaireho FREE(feature_tag_list_buffer); 11395569331642446be05292e3e1f8a51218827168cdclaireho } 11405569331642446be05292e3e1f8a51218827168cdclaireho } 11415569331642446be05292e3e1f8a51218827168cdclaireho } 11425569331642446be05292e3e1f8a51218827168cdclaireho 11435569331642446be05292e3e1f8a51218827168cdclaireho return true; 11445569331642446be05292e3e1f8a51218827168cdclaireho} 11455569331642446be05292e3e1f8a51218827168cdclaireho 11465569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties) 11475569331642446be05292e3e1f8a51218827168cdclaireho{ 11485569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *tmpAttributes; 11495569331642446be05292e3e1f8a51218827168cdclaireho unsigned int *tmpLogClusters; 11505569331642446be05292e3e1f8a51218827168cdclaireho 11515569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = item->face; 11525569331642446be05292e3e1f8a51218827168cdclaireho 11535569331642446be05292e3e1f8a51218827168cdclaireho face->length = item->num_glyphs; 11545569331642446be05292e3e1f8a51218827168cdclaireho 11555569331642446be05292e3e1f8a51218827168cdclaireho hb_buffer_clear(face->buffer); 11565569331642446be05292e3e1f8a51218827168cdclaireho 11575569331642446be05292e3e1f8a51218827168cdclaireho tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes)); 11585569331642446be05292e3e1f8a51218827168cdclaireho if (!tmpAttributes) 11595569331642446be05292e3e1f8a51218827168cdclaireho return false; 11605569331642446be05292e3e1f8a51218827168cdclaireho face->tmpAttributes = tmpAttributes; 11615569331642446be05292e3e1f8a51218827168cdclaireho 11625569331642446be05292e3e1f8a51218827168cdclaireho tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int)); 11635569331642446be05292e3e1f8a51218827168cdclaireho if (!tmpLogClusters) 11645569331642446be05292e3e1f8a51218827168cdclaireho return false; 11655569331642446be05292e3e1f8a51218827168cdclaireho face->tmpLogClusters = tmpLogClusters; 11665569331642446be05292e3e1f8a51218827168cdclaireho 11675569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < face->length; ++i) { 11685569331642446be05292e3e1f8a51218827168cdclaireho hb_buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i); 11695569331642446be05292e3e1f8a51218827168cdclaireho face->tmpAttributes[i] = item->attributes[i]; 11705569331642446be05292e3e1f8a51218827168cdclaireho face->tmpLogClusters[i] = item->log_clusters[i]; 11715569331642446be05292e3e1f8a51218827168cdclaireho } 11725569331642446be05292e3e1f8a51218827168cdclaireho 11735569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11745569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 11755569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("log clusters before shaping:"); 11765569331642446be05292e3e1f8a51218827168cdclaireho// for (int j = 0; j < length; j++) 11775569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 11785569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("original glyphs: %p", item->glyphs); 11795569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < length; ++i) 11805569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex); 11815569331642446be05292e3e1f8a51218827168cdclaireho// dump_string(hb_buffer); 11825569331642446be05292e3e1f8a51218827168cdclaireho#endif 11835569331642446be05292e3e1f8a51218827168cdclaireho 11845569331642446be05292e3e1f8a51218827168cdclaireho face->glyphs_substituted = false; 11855569331642446be05292e3e1f8a51218827168cdclaireho if (face->gsub) { 11865569331642446be05292e3e1f8a51218827168cdclaireho unsigned int error = HB_GSUB_Apply_String(face->gsub, face->buffer); 11875569331642446be05292e3e1f8a51218827168cdclaireho if (error && error != HB_Err_Not_Covered) 11885569331642446be05292e3e1f8a51218827168cdclaireho return false; 11895569331642446be05292e3e1f8a51218827168cdclaireho face->glyphs_substituted = (error != HB_Err_Not_Covered); 11905569331642446be05292e3e1f8a51218827168cdclaireho } 11915569331642446be05292e3e1f8a51218827168cdclaireho 11925569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 11935569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("log clusters before shaping:"); 11945569331642446be05292e3e1f8a51218827168cdclaireho// for (int j = 0; j < length; j++) 11955569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 11965569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("shaped glyphs:"); 11975569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < length; ++i) 11985569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex); 11995569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 12005569331642446be05292e3e1f8a51218827168cdclaireho// dump_string(hb_buffer); 12015569331642446be05292e3e1f8a51218827168cdclaireho#endif 12025569331642446be05292e3e1f8a51218827168cdclaireho 12035569331642446be05292e3e1f8a51218827168cdclaireho return true; 12045569331642446be05292e3e1f8a51218827168cdclaireho} 12055569331642446be05292e3e1f8a51218827168cdclaireho 12065569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters) 12075569331642446be05292e3e1f8a51218827168cdclaireho{ 12085569331642446be05292e3e1f8a51218827168cdclaireho HB_Face face = item->face; 12095569331642446be05292e3e1f8a51218827168cdclaireho 12105569331642446be05292e3e1f8a51218827168cdclaireho bool glyphs_positioned = false; 12115569331642446be05292e3e1f8a51218827168cdclaireho if (face->gpos) { 12125569331642446be05292e3e1f8a51218827168cdclaireho if (face->buffer->positions) 12135569331642446be05292e3e1f8a51218827168cdclaireho memset(face->buffer->positions, 0, face->buffer->in_length*sizeof(HB_PositionRec)); 12145569331642446be05292e3e1f8a51218827168cdclaireho // #### check that passing "false,false" is correct 12155569331642446be05292e3e1f8a51218827168cdclaireho glyphs_positioned = HB_GPOS_Apply_String(item->font, face->gpos, face->current_flags, face->buffer, false, false) != HB_Err_Not_Covered; 12165569331642446be05292e3e1f8a51218827168cdclaireho } 12175569331642446be05292e3e1f8a51218827168cdclaireho 12185569331642446be05292e3e1f8a51218827168cdclaireho if (!face->glyphs_substituted && !glyphs_positioned) { 12195569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGlyphAdvances(item); 12205569331642446be05292e3e1f8a51218827168cdclaireho return true; // nothing to do for us 12215569331642446be05292e3e1f8a51218827168cdclaireho } 12225569331642446be05292e3e1f8a51218827168cdclaireho 12235569331642446be05292e3e1f8a51218827168cdclaireho // make sure we have enough space to write everything back 12245569331642446be05292e3e1f8a51218827168cdclaireho if (availableGlyphs < (int)face->buffer->in_length) { 12255569331642446be05292e3e1f8a51218827168cdclaireho item->num_glyphs = face->buffer->in_length; 12265569331642446be05292e3e1f8a51218827168cdclaireho return false; 12275569331642446be05292e3e1f8a51218827168cdclaireho } 12285569331642446be05292e3e1f8a51218827168cdclaireho 12295569331642446be05292e3e1f8a51218827168cdclaireho HB_Glyph *glyphs = item->glyphs; 12305569331642446be05292e3e1f8a51218827168cdclaireho HB_GlyphAttributes *attributes = item->attributes; 12315569331642446be05292e3e1f8a51218827168cdclaireho 12325569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; ++i) { 12335569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i] = face->buffer->in_string[i].gindex; 12345569331642446be05292e3e1f8a51218827168cdclaireho attributes[i] = face->tmpAttributes[face->buffer->in_string[i].cluster]; 12355569331642446be05292e3e1f8a51218827168cdclaireho if (i && face->buffer->in_string[i].cluster == face->buffer->in_string[i-1].cluster) 12365569331642446be05292e3e1f8a51218827168cdclaireho attributes[i].clusterStart = false; 12375569331642446be05292e3e1f8a51218827168cdclaireho } 12385569331642446be05292e3e1f8a51218827168cdclaireho item->num_glyphs = face->buffer->in_length; 12395569331642446be05292e3e1f8a51218827168cdclaireho 12405569331642446be05292e3e1f8a51218827168cdclaireho if (doLogClusters && face->glyphs_substituted) { 12415569331642446be05292e3e1f8a51218827168cdclaireho // we can't do this for indic, as we pass the stuf in syllables and it's easier to do it in the shaper. 12425569331642446be05292e3e1f8a51218827168cdclaireho unsigned short *logClusters = item->log_clusters; 12435569331642446be05292e3e1f8a51218827168cdclaireho int clusterStart = 0; 12445569331642446be05292e3e1f8a51218827168cdclaireho int oldCi = 0; 12455569331642446be05292e3e1f8a51218827168cdclaireho // #### the reconstruction of the logclusters currently does not work if the original string 12465569331642446be05292e3e1f8a51218827168cdclaireho // contains surrogate pairs 12475569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; ++i) { 12485569331642446be05292e3e1f8a51218827168cdclaireho int ci = face->buffer->in_string[i].cluster; 12495569331642446be05292e3e1f8a51218827168cdclaireho // DEBUG(" ci[%d] = %d mark=%d, cmb=%d, cs=%d", 12505569331642446be05292e3e1f8a51218827168cdclaireho // i, ci, glyphAttributes[i].mark, glyphAttributes[i].combiningClass, glyphAttributes[i].clusterStart); 12515569331642446be05292e3e1f8a51218827168cdclaireho if (!attributes[i].mark && attributes[i].clusterStart && ci != oldCi) { 12525569331642446be05292e3e1f8a51218827168cdclaireho for (int j = oldCi; j < ci; j++) 12535569331642446be05292e3e1f8a51218827168cdclaireho logClusters[j] = clusterStart; 12545569331642446be05292e3e1f8a51218827168cdclaireho clusterStart = i; 12555569331642446be05292e3e1f8a51218827168cdclaireho oldCi = ci; 12565569331642446be05292e3e1f8a51218827168cdclaireho } 12575569331642446be05292e3e1f8a51218827168cdclaireho } 12585569331642446be05292e3e1f8a51218827168cdclaireho for (int j = oldCi; j < face->length; j++) 12595569331642446be05292e3e1f8a51218827168cdclaireho logClusters[j] = clusterStart; 12605569331642446be05292e3e1f8a51218827168cdclaireho } 12615569331642446be05292e3e1f8a51218827168cdclaireho 12625569331642446be05292e3e1f8a51218827168cdclaireho // calulate the advances for the shaped glyphs 12635569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("unpositioned: "); 12645569331642446be05292e3e1f8a51218827168cdclaireho 12655569331642446be05292e3e1f8a51218827168cdclaireho // positioning code: 12665569331642446be05292e3e1f8a51218827168cdclaireho if (glyphs_positioned) { 12675569331642446be05292e3e1f8a51218827168cdclaireho HB_GetGlyphAdvances(item); 12685569331642446be05292e3e1f8a51218827168cdclaireho HB_Position positions = face->buffer->positions; 12695569331642446be05292e3e1f8a51218827168cdclaireho HB_Fixed *advances = item->advances; 12705569331642446be05292e3e1f8a51218827168cdclaireho 12715569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG("positioned glyphs:"); 12725569331642446be05292e3e1f8a51218827168cdclaireho for (unsigned int i = 0; i < face->buffer->in_length; i++) { 12735569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" %d:\t orig advance: (%d/%d)\tadv=(%d/%d)\tpos=(%d/%d)\tback=%d\tnew_advance=%d", i, 12745569331642446be05292e3e1f8a51218827168cdclaireho// glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(), 12755569331642446be05292e3e1f8a51218827168cdclaireho// (int)(positions[i].x_advance >> 6), (int)(positions[i].y_advance >> 6), 12765569331642446be05292e3e1f8a51218827168cdclaireho// (int)(positions[i].x_pos >> 6), (int)(positions[i].y_pos >> 6), 12775569331642446be05292e3e1f8a51218827168cdclaireho// positions[i].back, positions[i].new_advance); 12785569331642446be05292e3e1f8a51218827168cdclaireho 1279e8c9796279273597ceacba17d7bf5bcdbcecaee1Fabrice Di Meglio HB_Fixed adjustment = positions[i].x_advance; 12805569331642446be05292e3e1f8a51218827168cdclaireho 12815569331642446be05292e3e1f8a51218827168cdclaireho if (!(face->current_flags & HB_ShaperFlag_UseDesignMetrics)) 12825569331642446be05292e3e1f8a51218827168cdclaireho adjustment = HB_FIXED_ROUND(adjustment); 12835569331642446be05292e3e1f8a51218827168cdclaireho 12845569331642446be05292e3e1f8a51218827168cdclaireho if (positions[i].new_advance) { 12855569331642446be05292e3e1f8a51218827168cdclaireho advances[i] = adjustment; 12865569331642446be05292e3e1f8a51218827168cdclaireho } else { 12875569331642446be05292e3e1f8a51218827168cdclaireho advances[i] += adjustment; 12885569331642446be05292e3e1f8a51218827168cdclaireho } 12895569331642446be05292e3e1f8a51218827168cdclaireho 12905569331642446be05292e3e1f8a51218827168cdclaireho int back = 0; 12915569331642446be05292e3e1f8a51218827168cdclaireho HB_FixedPoint *offsets = item->offsets; 12925569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x = positions[i].x_pos; 12935569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y = positions[i].y_pos; 12945569331642446be05292e3e1f8a51218827168cdclaireho while (positions[i - back].back) { 12955569331642446be05292e3e1f8a51218827168cdclaireho back += positions[i - back].back; 12965569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x += positions[i - back].x_pos; 12975569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y += positions[i - back].y_pos; 12985569331642446be05292e3e1f8a51218827168cdclaireho } 12995569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].y = -offsets[i].y; 13005569331642446be05292e3e1f8a51218827168cdclaireho 13015569331642446be05292e3e1f8a51218827168cdclaireho if (item->item.bidiLevel % 2) { 13025569331642446be05292e3e1f8a51218827168cdclaireho // ### may need to go back multiple glyphs like in ltr 13035569331642446be05292e3e1f8a51218827168cdclaireho back = positions[i].back; 13045569331642446be05292e3e1f8a51218827168cdclaireho while (back--) 13055569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x -= advances[i-back]; 13065569331642446be05292e3e1f8a51218827168cdclaireho } else { 13075569331642446be05292e3e1f8a51218827168cdclaireho back = 0; 13085569331642446be05292e3e1f8a51218827168cdclaireho while (positions[i - back].back) { 13095569331642446be05292e3e1f8a51218827168cdclaireho back += positions[i - back].back; 13105569331642446be05292e3e1f8a51218827168cdclaireho offsets[i].x -= advances[i-back]; 13115569331642446be05292e3e1f8a51218827168cdclaireho } 13125569331642446be05292e3e1f8a51218827168cdclaireho } 13135569331642446be05292e3e1f8a51218827168cdclaireho// DEBUG(" ->\tadv=%d\tpos=(%d/%d)", 13145569331642446be05292e3e1f8a51218827168cdclaireho// glyphs[i].advance.x.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); 1315d3671e03f6c96f8498ddccd3b175005537302bb5Fabrice Di Meglio DEBUG("Glyph offset[%d] x:%d, y: %d)", i, offsets[i].x, offsets[i].y); 13165569331642446be05292e3e1f8a51218827168cdclaireho } 13175569331642446be05292e3e1f8a51218827168cdclaireho item->kerning_applied = face->has_opentype_kerning; 13185569331642446be05292e3e1f8a51218827168cdclaireho } else { 13195569331642446be05292e3e1f8a51218827168cdclaireho HB_HeuristicPosition(item); 13205569331642446be05292e3e1f8a51218827168cdclaireho } 13215569331642446be05292e3e1f8a51218827168cdclaireho 13225569331642446be05292e3e1f8a51218827168cdclaireho#ifdef OT_DEBUG 13235569331642446be05292e3e1f8a51218827168cdclaireho if (doLogClusters) { 13245569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("log clusters after shaping:"); 13255569331642446be05292e3e1f8a51218827168cdclaireho for (int j = 0; j < length; j++) 13265569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" log[%d] = %d", j, item->log_clusters[j]); 13275569331642446be05292e3e1f8a51218827168cdclaireho } 13285569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("final glyphs:"); 13295569331642446be05292e3e1f8a51218827168cdclaireho for (int i = 0; i < (int)hb_buffer->in_length; ++i) 13305569331642446be05292e3e1f8a51218827168cdclaireho DEBUG(" glyph=%4x char_index=%d mark: %d cmp: %d, clusterStart: %d advance=%d/%d offset=%d/%d", 13315569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].glyph, hb_buffer->in_string[i].cluster, glyphs[i].attributes.mark, 13325569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].attributes.combiningClass, glyphs[i].attributes.clusterStart, 13335569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(), 13345569331642446be05292e3e1f8a51218827168cdclaireho glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); 13355569331642446be05292e3e1f8a51218827168cdclaireho DEBUG("-----------------------------------------"); 13365569331642446be05292e3e1f8a51218827168cdclaireho#endif 13375569331642446be05292e3e1f8a51218827168cdclaireho return true; 13385569331642446be05292e3e1f8a51218827168cdclaireho} 13395569331642446be05292e3e1f8a51218827168cdclaireho 13405569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_ShapeItem(HB_ShaperItem *shaper_item) 13415569331642446be05292e3e1f8a51218827168cdclaireho{ 13425569331642446be05292e3e1f8a51218827168cdclaireho HB_Bool result = false; 13435569331642446be05292e3e1f8a51218827168cdclaireho if (shaper_item->num_glyphs < shaper_item->item.length) { 13445569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->num_glyphs = shaper_item->item.length; 13455569331642446be05292e3e1f8a51218827168cdclaireho return false; 13465569331642446be05292e3e1f8a51218827168cdclaireho } 13475569331642446be05292e3e1f8a51218827168cdclaireho assert(shaper_item->item.script < HB_ScriptCount); 13485569331642446be05292e3e1f8a51218827168cdclaireho result = HB_ScriptEngines[shaper_item->item.script].shape(shaper_item); 13495569331642446be05292e3e1f8a51218827168cdclaireho shaper_item->glyphIndicesPresent = false; 13505569331642446be05292e3e1f8a51218827168cdclaireho return result; 13515569331642446be05292e3e1f8a51218827168cdclaireho} 13525569331642446be05292e3e1f8a51218827168cdclaireho 1353