1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru **********************************************************************
350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   Copyright (C) 2002-2010, International Business Machines
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   Corporation and others.  All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru **********************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * paragraphLayout doesn't make much sense without
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * BreakIterator...
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/LETypes.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/LEScripts.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/LELanguages.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/LayoutEngine.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/LEFontInstance.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ubidi.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchriter.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/brkiter.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if ! UCONFIG_NO_BREAK_ITERATION
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LXUtilities.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "usc_impl.h" /* this is currently private! */
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"  /* this too! */
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "layout/ParagraphLayout.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Leave this copyright notice here! It needs to go somewhere in this library. */
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char copyright[] = U_COPYRIGHT_STRING;
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass StyleRuns
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StyleRuns(const RunArray *styleRunArrays[], le_int32 styleCount);
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ~StyleRuns();
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 getRuns(le_int32 runLimits[], le_int32 styleIndices[]);
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 fStyleCount;
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 fRunCount;
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *fRunLimits;
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *fStyleIndices;
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStyleRuns::StyleRuns(const RunArray *styleRunArrays[], le_int32 styleCount)
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    : fStyleCount(styleCount), fRunCount(0), fRunLimits(NULL), fStyleIndices(NULL)
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 maxRunCount = 0;
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 style, run, runStyle;
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *currentRun = LE_NEW_ARRAY(le_int32, styleCount);
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int i = 0; i < styleCount; i += 1) {
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        maxRunCount += styleRunArrays[i]->getCount();
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    maxRunCount -= styleCount - 1;
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRunLimits    = LE_NEW_ARRAY(le_int32, maxRunCount);
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleIndices = LE_NEW_ARRAY(le_int32, maxRunCount * styleCount);
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (style = 0; style < styleCount; style += 1) {
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        currentRun[style] = 0;
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    run = 0;
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runStyle = 0;
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Since the last run limit for each style run must be
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * the same, all the styles will hit the last limit at
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * the same time, so we know when we're done when the first
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * style hits the last limit.
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (currentRun[0] < styleRunArrays[0]->getCount()) {
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fRunLimits[run] = 0x7FFFFFFF;
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // find the minimum run limit for all the styles
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (style = 0; style < styleCount; style += 1) {
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (styleRunArrays[style]->getLimit(currentRun[style]) < fRunLimits[run]) {
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fRunLimits[run] = styleRunArrays[style]->getLimit(currentRun[style]);
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // advance all styles whose current run is at this limit to the next run
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (style = 0; style < styleCount; style += 1) {
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleIndices[runStyle++] = currentRun[style];
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (styleRunArrays[style]->getLimit(currentRun[style]) == fRunLimits[run]) {
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                currentRun[style] += 1;
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        run += 1;
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRunCount = run;
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(currentRun);
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStyleRuns::~StyleRuns()
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRunCount = 0;
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fStyleIndices);
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleIndices = NULL;
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fRunLimits);
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRunLimits = NULL;
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 StyleRuns::getRuns(le_int32 runLimits[], le_int32 styleIndices[])
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (runLimits != NULL) {
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_ARRAY_COPY(runLimits, fRunLimits, fRunCount);
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (styleIndices != NULL) {
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_ARRAY_COPY(styleIndices, fStyleIndices, fRunCount * fStyleCount);
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fRunCount;
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: This table only has "TRUE" values for
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * those scripts which the LayoutEngine can currently
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * process, rather for all scripts which require
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * complex processing for correct rendering.
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const le_bool complexTable[scriptCodeCount] = {
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE , /* Zyyy */
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Qaai */
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Arab */
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Armn */
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Beng */
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Bopo */
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cher */
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Copt=Qaac */
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cyrl */
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Dsrt */
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Deva */
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Ethi */
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Geor */
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Goth */
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Grek */
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Gujr */
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Guru */
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hani */
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hang */
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Hebr */
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hira */
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Knda */
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Kana */
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Khmr */
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Laoo */
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Latn */
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Mlym */
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Mong */
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Mymr */
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Ogam */
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Ital */
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Orya */
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Runr */
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Sinh */
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Syrc */
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Taml */
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Telu */
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Thaa */
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TRUE,   /* Thai */
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Tibt */
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cans */
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Yiii */
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Tglg */
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hano */
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Buhd */
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Tagb */
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Brai */
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cprt */
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Limb */
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Linb */
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Osma */
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Shaw */
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Tale */
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Ugar */
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hrkt */
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Bugi */
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Glag */
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Khar */
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Sylo */
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Talu */
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Tfng */
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Xpeo */
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Bali */
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Batk */
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Blis */
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Brah */
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cham */
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cirt */
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cyrs */
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Egyd */
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Egyh */
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Egyp */
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Geok */
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hans */
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hant */
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hmng */
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Hung */
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Inds */
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Java */
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Kali */
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Latf */
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Latg */
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Lepc */
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Lina */
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Mand */
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Maya */
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Mero */
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Nkoo */
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Orkh */
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Perm */
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Phag */
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Phnx */
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Plrd */
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Roro */
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Sara */
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Syre */
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Syrj */
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Syrn */
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Teng */
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Taii */
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Visp */
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Xsux */
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Zxxx */
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Zzzz */
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Cari */
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Jpan */
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Lana */
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Lyci */
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Lydi */
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Olck */
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Rjng */
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Saur */
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Sgnw */
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Sund */
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FALSE,  /* Moon */
254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Mtei */
255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Armi */
256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Avst */
257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Cakm */
258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Kore */
259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Kthi */
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Mani */
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Phli */
262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Phlp */
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Phlv */
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Prti */
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Samr */
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Tavt */
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    FALSE,  /* Zmth */
26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    FALSE,  /* Zsym */
26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    FALSE,  /* Bamu */
27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    FALSE,  /* Lisu */
27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    FALSE,  /* Nkgb */
27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    FALSE   /* Sarb */
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char ParagraphLayout::fgClassID = 0;
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic void fillMissingCharToGlyphMapValues(le_int32 *charToGlyphMap,
27927f654740f2a26ad62a5c155af9199af9e69b889claireho                                            le_int32 charCount) {
28027f654740f2a26ad62a5c155af9199af9e69b889claireho    le_int32 lastValidGlyph = -1;
28127f654740f2a26ad62a5c155af9199af9e69b889claireho    le_int32 ch;
28227f654740f2a26ad62a5c155af9199af9e69b889claireho    for (ch = 0; ch <= charCount; ch += 1) {
28327f654740f2a26ad62a5c155af9199af9e69b889claireho        if (charToGlyphMap[ch] == -1) {
28427f654740f2a26ad62a5c155af9199af9e69b889claireho            charToGlyphMap[ch] = lastValidGlyph;
28527f654740f2a26ad62a5c155af9199af9e69b889claireho        } else {
28627f654740f2a26ad62a5c155af9199af9e69b889claireho            lastValidGlyph = charToGlyphMap[ch];
28727f654740f2a26ad62a5c155af9199af9e69b889claireho        }
28827f654740f2a26ad62a5c155af9199af9e69b889claireho    }
28927f654740f2a26ad62a5c155af9199af9e69b889claireho}
29027f654740f2a26ad62a5c155af9199af9e69b889claireho
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * How to deal with composite fonts:
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Don't store the client's FontRuns; we'll need to compute sub-font FontRuns using Doug's
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * LEFontInstance method. Do that by intersecting the client's FontRuns with fScriptRuns. Use
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * that to compute fFontRuns, and then intersect fFontRuns, fScriptRuns and fLevelRuns. Doing
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * it in this order means we do a two-way intersection and a three-way intersection.
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * An optimization would be to only do this if there's at least one composite font...
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Other notes:
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Return the sub-fonts as the run fonts... could keep the mapping back to the client's FontRuns
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   but that probably makes it more complicated of everyone...
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Take the LineInfo and LineRun types from Paragraph and use them here, incorporate them into the API.
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Might want to change the name of the StyleRun type, and make a new one that holds fonts, scripts and levels?
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const FontRuns   *fontRuns,
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const ValueRuns  *levelRuns,
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const ValueRuns  *scriptRuns,
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const LocaleRuns *localeRuns,
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 UBiDiLevel paragraphLevel, le_bool vertical,
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 LEErrorCode &status)
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 : fChars(chars), fCharCount(count),
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fFontRuns(NULL), fLevelRuns(levelRuns), fScriptRuns(scriptRuns), fLocaleRuns(localeRuns),
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fVertical(vertical), fClientLevels(TRUE), fClientScripts(TRUE), fClientLocales(TRUE), fEmbeddingLevels(NULL),
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fAscent(0), fDescent(0), fLeading(0),
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fGlyphToCharMap(NULL), fCharToMinGlyphMap(NULL), fCharToMaxGlyphMap(NULL), fGlyphWidths(NULL), fGlyphCount(0),
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fParaBidi(NULL), fLineBidi(NULL),
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fStyleRunLimits(NULL), fStyleIndices(NULL), fStyleRunCount(0),
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fBreakIterator(NULL), fLineStart(-1), fLineEnd(0),
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 /*fVisualRuns(NULL), fStyleRunInfo(NULL), fVisualRunCount(-1),
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fFirstVisualRun(-1), fLastVisualRun(-1),*/ fVisualRunLastX(0), fVisualRunLastY(0)
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharCount = -1;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // FIXME: should check the limit arrays for consistency...
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    computeLevels(paragraphLevel);
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (scriptRuns == NULL) {
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        computeScripts();
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeRuns == NULL) {
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        computeLocales();
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    computeSubFonts(fontRuns, status);
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //other stuff?
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharCount = -1;
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // now intersect the font, direction and script runs...
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const RunArray *styleRunArrays[] = {fFontRuns, fLevelRuns, fScriptRuns, fLocaleRuns};
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  styleCount = sizeof styleRunArrays / sizeof styleRunArrays[0];
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StyleRuns styleRuns(styleRunArrays, styleCount);
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEErrorCode layoutStatus = LE_NO_ERROR;
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunCount = styleRuns.getRuns(NULL, NULL);
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunLimits = LE_NEW_ARRAY(le_int32, fStyleRunCount);
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleIndices   = LE_NEW_ARRAY(le_int32, fStyleRunCount * styleCount);
365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ((fStyleRunLimits == NULL) || (fStyleIndices == NULL)) {
366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    styleRuns.getRuns(fStyleRunLimits, fStyleIndices);
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // now build a LayoutEngine for each style run...
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleIndices = fStyleIndices;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 run, runStart;
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunInfo = LE_NEW_ARRAY(StyleRunInfo, fStyleRunCount);
377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (fStyleRunInfo == NULL) {
378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    else {
382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // initialize
383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].font = NULL;
385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].runBase = 0;
386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].runLimit = 0;
387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].script = (UScriptCode)0;
388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].locale = NULL;
389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].level = 0;
390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphBase = 0;
391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].engine = NULL;
392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphCount = 0;
393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphs = NULL;
394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].positions = NULL;
395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphCount = 0;
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].font      = fFontRuns->getFont(styleIndices[0]);
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].runBase   = runStart;
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].runLimit  = fStyleRunLimits[run];
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].script    = (UScriptCode) fScriptRuns->getValue(styleIndices[2]);
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].locale    = fLocaleRuns->getLocale(styleIndices[3]);
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].level     = (UBiDiLevel) fLevelRuns->getValue(styleIndices[1]);
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphBase = fGlyphCount;
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].engine = LayoutEngine::layoutEngineFactory(fStyleRunInfo[run].font,
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].script, getLanguageCode(fStyleRunInfo[run].locale), layoutStatus);
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphCount = fStyleRunInfo[run].engine->layoutChars(fChars, runStart, fStyleRunLimits[run] - runStart, fCharCount,
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].level & 1, 0, 0, layoutStatus);
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runStart = fStyleRunLimits[run];
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        styleIndices += styleCount;
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphCount += fStyleRunInfo[run].glyphCount;
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make big arrays for the glyph widths, glyph-to-char and char-to-glyph maps,
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // in logical order. (Both maps need an extra entry for the end of the text.)
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // For each layout get the positions and convert them into glyph widths, in
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // logical order. Get the glyph-to-char mapping, offset by starting index in the
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // character array. Swap the glyph width and glyph-to-char arrays into logical order.
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Finally, fill in the char-to-glyph mappings.
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphWidths       = LE_NEW_ARRAY(float, fGlyphCount);
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphToCharMap    = LE_NEW_ARRAY(le_int32, fGlyphCount + 1);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMinGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMaxGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ((fGlyphWidths == NULL) || (fGlyphToCharMap == NULL) ||
439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (fCharToMinGlyphMap == NULL) || (fCharToMaxGlyphMap == NULL)) {
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyph;
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LayoutEngine *engine = fStyleRunInfo[run].engine;
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyphCount  = fStyleRunInfo[run].glyphCount;
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyphBase   = fStyleRunInfo[run].glyphBase;
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphs = LE_NEW_ARRAY(LEGlyphID, glyphCount);
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].positions = LE_NEW_ARRAY(float, glyphCount * 2 + 2);
453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ((fStyleRunInfo[run].glyphs == NULL) ||
454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (fStyleRunInfo[run].positions == NULL)) {
455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = LE_MEMORY_ALLOCATION_ERROR;
456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getGlyphs(fStyleRunInfo[run].glyphs, layoutStatus);
460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getGlyphPositions(fStyleRunInfo[run].positions, layoutStatus);
466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getCharIndices(&fGlyphToCharMap[glyphBase], runStart, layoutStatus);
472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (glyph = 0; glyph < glyphCount; glyph += 1) {
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fGlyphWidths[glyphBase + glyph] = fStyleRunInfo[run].positions[glyph * 2 + 2] - fStyleRunInfo[run].positions[glyph * 2];
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((fStyleRunInfo[run].level & 1) != 0) {
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LXUtilities::reverse(&fGlyphWidths[glyphBase], glyphCount);
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LXUtilities::reverse(&fGlyphToCharMap[glyphBase], glyphCount);
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runStart = fStyleRunLimits[run];
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete engine;
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].engine = NULL;
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphToCharMap[fGlyphCount] = fCharCount;
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49427f654740f2a26ad62a5c155af9199af9e69b889claireho    // Initialize the char-to-glyph maps to -1 so that we can later figure out
49527f654740f2a26ad62a5c155af9199af9e69b889claireho    // whether any of the entries in the map aren't filled in below.
49627f654740f2a26ad62a5c155af9199af9e69b889claireho    le_int32 chIndex;
49727f654740f2a26ad62a5c155af9199af9e69b889claireho    for (chIndex = 0; chIndex <= fCharCount; chIndex += 1) {
49827f654740f2a26ad62a5c155af9199af9e69b889claireho        fCharToMinGlyphMap[chIndex] = -1;
49927f654740f2a26ad62a5c155af9199af9e69b889claireho        fCharToMaxGlyphMap[chIndex] = -1;
50027f654740f2a26ad62a5c155af9199af9e69b889claireho    }
50127f654740f2a26ad62a5c155af9199af9e69b889claireho
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (glyph = fGlyphCount - 1; glyph >= 0; glyph -= 1) {
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch = fGlyphToCharMap[glyph];
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMinGlyphMap[ch] = glyph;
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMinGlyphMap[fCharCount] = fGlyphCount;
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (glyph = 0; glyph < fGlyphCount; glyph += 1) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch = fGlyphToCharMap[glyph];
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMaxGlyphMap[ch] = glyph;
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMaxGlyphMap[fCharCount] = fGlyphCount;
51727f654740f2a26ad62a5c155af9199af9e69b889claireho
51827f654740f2a26ad62a5c155af9199af9e69b889claireho    // Now fill in the missing values in the char-to-glyph maps.
51927f654740f2a26ad62a5c155af9199af9e69b889claireho    fillMissingCharToGlyphMapValues(fCharToMinGlyphMap, fCharCount);
52027f654740f2a26ad62a5c155af9199af9e69b889claireho    fillMissingCharToGlyphMapValues(fCharToMaxGlyphMap, fCharCount);
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::~ParagraphLayout()
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete (FontRuns *) fFontRuns;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientLevels) {
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (ValueRuns *) fLevelRuns;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLevelRuns = NULL;
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLevels = TRUE;
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientScripts) {
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (ValueRuns *) fScriptRuns;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fScriptRuns = NULL;
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientScripts = TRUE;
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientLocales) {
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (LocaleRuns *) fLocaleRuns;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLocaleRuns = NULL;
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLocales = TRUE;
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fEmbeddingLevels != NULL) {
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fEmbeddingLevels);
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fEmbeddingLevels = NULL;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGlyphToCharMap != NULL) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fGlyphToCharMap);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphToCharMap = NULL;
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fCharToMinGlyphMap != NULL) {
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fCharToMinGlyphMap);
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMinGlyphMap = NULL;
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fCharToMaxGlyphMap != NULL) {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fCharToMaxGlyphMap);
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMaxGlyphMap = NULL;
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGlyphWidths != NULL) {
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fGlyphWidths);
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphWidths = NULL;
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fParaBidi != NULL) {
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ubidi_close(fParaBidi);
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fParaBidi = NULL;
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLineBidi != NULL) {
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ubidi_close(fLineBidi);
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineBidi = NULL;
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fStyleRunCount > 0) {
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleRunLimits);
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleIndices);
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = 0; run < fStyleRunCount; run += 1) {
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LE_DELETE_ARRAY(fStyleRunInfo[run].glyphs);
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LE_DELETE_ARRAY(fStyleRunInfo[run].positions);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].glyphs    = NULL;
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].positions = NULL;
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleRunInfo);
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunLimits = NULL;
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleIndices   = NULL;
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo        = NULL;
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunCount  = 0;
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fBreakIterator != NULL) {
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fBreakIterator;
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator = NULL;
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool ParagraphLayout::isComplex(const LEUnicode chars[], le_int32 count)
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode scriptStatus = U_ZERO_ERROR;
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptCode scriptCode  = USCRIPT_INVALID_CODE;
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptRun *sr = uscript_openRun(chars, count, &scriptStatus);
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_bool result = FALSE;
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (uscript_nextRun(sr, NULL, NULL, &scriptCode)) {
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (isComplex(scriptCode)) {
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = TRUE;
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uscript_closeRun(sr);
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getAscent() const
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fAscent;
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getDescent() const
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fDescent;
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLeading() const
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fLeading;
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
65750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehole_bool ParagraphLayout::isDone() const
65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return fLineEnd >= fCharCount;
66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line *ParagraphLayout::nextLine(float width)
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (isDone()) {
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLineStart = fLineEnd;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (width > 0) {
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyph    = fCharToMinGlyphMap[fLineStart];
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        float widthSoFar  = 0;
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (glyph < fGlyphCount && widthSoFar + fGlyphWidths[glyph] <= width) {
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            widthSoFar += fGlyphWidths[glyph++];
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If no glyphs fit on the line, force one to fit.
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // (There shouldn't be any zero width glyphs at the
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // start of a line unless the paragraph consists of
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // only zero width glyphs, because otherwise the zero
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // width glyphs will have been included on the end of
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the previous line...)
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (widthSoFar == 0 && glyph < fGlyphCount) {
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyph += 1;
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineEnd = previousBreak(fGlyphToCharMap[glyph]);
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If this break is at or before the last one,
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // find a glyph, starting at the one which didn't
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // fit, that produces a break after the last one.
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (fLineEnd <= fLineStart) {
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLineEnd = fGlyphToCharMap[glyph++];
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineEnd = fCharCount;
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return computeVisualRuns();
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeLevels(UBiDiLevel paragraphLevel)
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode bidiStatus = U_ZERO_ERROR;
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLevelRuns != NULL) {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fEmbeddingLevels = LE_NEW_ARRAY(UBiDiLevel, fCharCount);
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (ch = 0, run = 0; run < fLevelRuns->getCount(); run += 1) {
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBiDiLevel runLevel = (UBiDiLevel) fLevelRuns->getValue(run) | UBIDI_LEVEL_OVERRIDE;
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32   runLimit = fLevelRuns->getLimit(run);
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (ch < runLimit) {
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fEmbeddingLevels[ch++] = runLevel;
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fParaBidi = ubidi_openSized(fCharCount, 0, &bidiStatus);
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_setPara(fParaBidi, fChars, fCharCount, paragraphLevel, fEmbeddingLevels, &bidiStatus);
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLevelRuns == NULL) {
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 levelRunCount = ubidi_countRuns(fParaBidi, &bidiStatus);
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ValueRuns *levelRuns = new ValueRuns(levelRunCount);
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 logicalStart = 0;
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 limit;
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel level;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = 0; run < levelRunCount; run += 1) {
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ubidi_getLogicalRun(fParaBidi, logicalStart, &limit, &level);
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            levelRuns->add(level, limit);
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalStart = limit;
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLevelRuns    = levelRuns;
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLevels = FALSE;
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeScripts()
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode scriptStatus = U_ZERO_ERROR;
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptRun *sr = uscript_openRun(fChars, fCharCount, &scriptStatus);
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ValueRuns  *scriptRuns = new ValueRuns(0);
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 limit;
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptCode script;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (uscript_nextRun(sr, NULL, &limit, &script)) {
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        scriptRuns->add(script, limit);
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uscript_closeRun(sr);
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fScriptRuns    = scriptRuns;
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fClientScripts = FALSE;
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeLocales()
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LocaleRuns *localeRuns = new LocaleRuns(0);
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Locale *defaultLocale = &Locale::getDefault();
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    localeRuns->add(defaultLocale, fCharCount);
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLocaleRuns    = localeRuns;
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fClientLocales = FALSE;
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeSubFonts(const FontRuns *fontRuns, LEErrorCode &status)
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const RunArray *styleRunArrays[] = {fontRuns, fScriptRuns};
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 styleCount = sizeof styleRunArrays / sizeof styleRunArrays[0];
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StyleRuns styleRuns(styleRunArrays, styleCount);
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 styleRunCount = styleRuns.getRuns(NULL, NULL);
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleRunLimits = LE_NEW_ARRAY(le_int32, styleRunCount);
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleIndices = LE_NEW_ARRAY(le_int32, styleRunCount * styleCount);
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FontRuns *subFontRuns  = new FontRuns(0);
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  run, offset, *si;
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    styleRuns.getRuns(styleRunLimits, styleIndices);
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    si = styleIndices;
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = 0;
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (run = 0; run < styleRunCount; run += 1) {
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const LEFontInstance *runFont = fontRuns->getFont(si[0]);
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 script = fScriptRuns->getValue(si[1]);
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (offset < styleRunLimits[run]) {
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const LEFontInstance *subFont = runFont->getSubFont(fChars, &offset, styleRunLimits[run], script, status);
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (LE_FAILURE(status)) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete subFontRuns;
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanUp;
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            subFontRuns->add(subFont, offset);
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        si += styleCount;
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFontRuns = subFontRuns;
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucleanUp:
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(styleIndices);
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(styleRunLimits);
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeMetrics()
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 i, count = fFontRuns->getCount();
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 maxDL = 0;
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < count; i += 1) {
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const LEFontInstance *font = fFontRuns->getFont(i);
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ascent  = font->getAscent();
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 descent = font->getDescent();
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 leading = font->getLeading();
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dl      = descent + leading;
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ascent > fAscent) {
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fAscent = ascent;
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (descent > fDescent) {
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDescent = descent;
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (leading > fLeading) {
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLeading = leading;
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dl > maxDL) {
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxDL = dl;
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLeading = maxDL - fDescent;
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 1
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct LanguageMap
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *localeCode;
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 languageCode;
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const LanguageMap languageMap[] =
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
862c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"afr", afkLanguageCode}, // Afrikaans
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ara", araLanguageCode}, // Arabic
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"asm", asmLanguageCode}, // Assamese
865c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bel", belLanguageCode}, // Belarussian
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ben", benLanguageCode}, // Bengali
867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bod", tibLanguageCode}, // Tibetan
868c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bul", bgrLanguageCode}, // Bulgarian
869c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cat", catLanguageCode}, // Catalan
870c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ces", csyLanguageCode}, // Czech
871c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"che", cheLanguageCode}, // Chechen
872c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cop", copLanguageCode}, // Coptic
873c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cym", welLanguageCode}, // Welsh
874c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"dan", danLanguageCode}, // Danish
875c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"deu", deuLanguageCode}, // German
876c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"dzo", dznLanguageCode}, // Dzongkha
877c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ell", ellLanguageCode}, // Greek
878c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"eng", engLanguageCode}, // English
879c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"est", etiLanguageCode}, // Estonian
880c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"eus", euqLanguageCode}, // Basque
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"fas", farLanguageCode}, // Farsi
882c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"fin", finLanguageCode}, // Finnish
883c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"fra", fraLanguageCode}, // French
884c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"gle", gaeLanguageCode}, // Irish Gaelic
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"guj", gujLanguageCode}, // Gujarati
886c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hau", hauLanguageCode}, // Hausa
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"heb", iwrLanguageCode}, // Hebrew
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"hin", hinLanguageCode}, // Hindi
889c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hrv", hrvLanguageCode}, // Croatian
890c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hun", hunLanguageCode}, // Hungarian
891c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hye", hyeLanguageCode}, // Armenian
892c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ind", indLanguageCode}, // Indonesian
893c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ita", itaLanguageCode}, // Italian
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"jpn", janLanguageCode}, // Japanese
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kan", kanLanguageCode}, // Kannada
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kas", kshLanguageCode}, // Kashmiri
897c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"khm", khmLanguageCode}, // Khmer
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kok", kokLanguageCode}, // Konkani
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kor", korLanguageCode}, // Korean
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  {"mal_XXX", malLanguageCode}, // Malayalam - Traditional
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mal", mlrLanguageCode}, // Malayalam - Reformed
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mar", marLanguageCode}, // Marathi
903c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"mlt", mtsLanguageCode}, // Maltese
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mni", mniLanguageCode}, // Manipuri
905c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"mon", mngLanguageCode}, // Mongolian
906c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"nep", nepLanguageCode}, // Nepali
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ori", oriLanguageCode}, // Oriya
908c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"pol", plkLanguageCode}, // Polish
909c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"por", ptgLanguageCode}, // Portuguese
910c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"pus", pasLanguageCode}, // Pashto
911c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ron", romLanguageCode}, // Romanian
912c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"rus", rusLanguageCode}, // Russian
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"san", sanLanguageCode}, // Sanskrit
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"sin", snhLanguageCode}, // Sinhalese
915c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"slk", skyLanguageCode}, // Slovak
916c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"snd", sndLanguageCode}, // Sindhi
917c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"slv", slvLanguageCode}, // Slovenian
918c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"spa", espLanguageCode}, // Spanish
919c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"sqi", sqiLanguageCode}, // Albanian
920c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"srp", srbLanguageCode}, // Serbian
921c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"swe", sveLanguageCode}, // Swedish
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"syr", syrLanguageCode}, // Syriac
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tam", tamLanguageCode}, // Tamil
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tel", telLanguageCode}, // Telugu
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tha", thaLanguageCode}, // Thai
926c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"tur", trkLanguageCode}, // Turkish
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"urd", urdLanguageCode}, // Urdu
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"yid", jiiLanguageCode}, // Yiddish
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  {"zhp", zhpLanguageCode}, // Chinese - Phonetic
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho", zhsLanguageCode}, // Chinese
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_CHN", zhsLanguageCode}, // Chinese - China
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_HKG", zhsLanguageCode}, // Chinese - Hong Kong
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_MAC", zhtLanguageCode}, // Chinese - Macao
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_SGP", zhsLanguageCode}, // Chinese - Singapore
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_TWN", zhtLanguageCode}  // Chinese - Taiwan
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const le_int32 languageMapCount = ARRAY_SIZE(languageMap);
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLanguageCode(const Locale *locale)
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char code[8] = {0, 0, 0, 0, 0, 0, 0, 0};
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *language = locale->getISO3Language();
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *country  = locale->getISO3Country();
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(code, language);
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((uprv_strcmp(language, "zho") == 0) && country != NULL) {
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcat(code, "_");
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcat(code, country);
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (le_int32 i = 0; i < languageMapCount; i += 1) {
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(code, languageMap[i].localeCode) == 0) {
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return languageMap[i].languageCode;
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return nullLanguageCode;
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#else
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TODO - dummy implementation for right now...
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLanguageCode(const Locale *locale)
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return nullLanguageCode;
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool ParagraphLayout::isComplex(UScriptCode script)
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (script < 0 || script >= (UScriptCode) scriptCodeCount) {
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return complexTable[script];
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::previousBreak(le_int32 charIndex)
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // skip over any whitespace or control characters,
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // because they can hang in the margin.
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (charIndex < fCharCount &&
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           (u_isWhitespace(fChars[charIndex]) ||
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_iscntrl(fChars[charIndex]))) {
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        charIndex += 1;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create the BreakIterator if we don't already have one
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fBreakIterator == NULL) {
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale thai("th");
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UCharCharacterIterator *iter = new UCharCharacterIterator(fChars, fCharCount);
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator = BreakIterator::createLineInstance(thai, status);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator->adoptText(iter);
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // return the break location that's at or before
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the character we stopped on. Note: if we're
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on a break, the "+ 1" will cause preceding to
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // back up to it.
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fBreakIterator->preceding(charIndex + 1);
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line *ParagraphLayout::computeVisualRuns()
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode bidiStatus = U_ZERO_ERROR;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 dirRunCount, visualRun;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX = 0;
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastY = 0;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFirstVisualRun = getCharRun(fLineStart);
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLastVisualRun  = getCharRun(fLineEnd - 1);
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLineBidi == NULL) {
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineBidi = ubidi_openSized(fCharCount, 0, &bidiStatus);
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_setLine(fParaBidi, fLineStart, fLineEnd, fLineBidi, &bidiStatus);
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dirRunCount = ubidi_countRuns(fLineBidi, &bidiStatus);
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Line *line = new Line();
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (visualRun = 0; visualRun < dirRunCount; visualRun += 1) {
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 relStart, run, runLength;
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiDirection runDirection = ubidi_getVisualRun(fLineBidi, visualRun, &relStart, &runLength);
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 runStart = fLineStart + relStart;
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 runEnd   = runStart + runLength - 1;
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 firstRun = getCharRun(runStart);
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 lastRun  = getCharRun(runEnd);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 startRun = (runDirection == UBIDI_LTR)? firstRun : lastRun;
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 stopRun  = (runDirection == UBIDI_LTR)? lastRun + 1 : firstRun - 1;
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dir      = (runDirection == UBIDI_LTR)?  1 : -1;
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = startRun; run != stopRun; run += dir) {
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32 firstChar = (run == firstRun)? runStart : fStyleRunInfo[run].runBase;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32 lastChar  = (run == lastRun)?  runEnd   : fStyleRunInfo[run].runLimit - 1;
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            appendRun(line, run, firstChar, lastChar);
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return line;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::appendRun(ParagraphLayout::Line *line, le_int32 run, le_int32 firstChar, le_int32 lastChar)
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphBase = fStyleRunInfo[run].glyphBase;
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 inGlyph, outGlyph;
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Get the glyph indices for all the characters between firstChar and lastChar,
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // make the minimum one be leftGlyph and the maximum one be rightGlyph.
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (need to do this to handle local reorderings like Indic left matras)
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 leftGlyph  = fGlyphCount;
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 rightGlyph = -1;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 ch;
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (ch = firstChar; ch <= lastChar; ch += 1) {
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 minGlyph = fCharToMinGlyphMap[ch];
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 maxGlyph = fCharToMaxGlyphMap[ch];
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (minGlyph < leftGlyph) {
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            leftGlyph = minGlyph;
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (maxGlyph > rightGlyph) {
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            rightGlyph = maxGlyph;
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((fStyleRunInfo[run].level & 1) != 0) {
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 swap = rightGlyph;
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 last = glyphBase + fStyleRunInfo[run].glyphCount - 1;
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Here, we want to remove the glyphBase bias...
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rightGlyph = last - leftGlyph;
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        leftGlyph  = last - swap;
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rightGlyph -= glyphBase;
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        leftGlyph  -= glyphBase;
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set the position bias for the glyphs. If we're at the start of
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // a line, we want the first glyph to be at x = 0, even if it comes
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // from the middle of a layout. If we've got a right-to-left run, we
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // want the left-most glyph to start at the final x position of the
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // previous run, even though this glyph may be in the middle of the
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // run.
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX -= fStyleRunInfo[run].positions[leftGlyph * 2];
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make rightGlyph be the glyph just to the right of
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the run's glyphs
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rightGlyph += 1;
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiDirection direction  = ((fStyleRunInfo[run].level & 1) == 0)? UBIDI_LTR : UBIDI_RTL;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32   glyphCount     = rightGlyph - leftGlyph;
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEGlyphID *glyphs         = LE_NEW_ARRAY(LEGlyphID, glyphCount);
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    float     *positions      = LE_NEW_ARRAY(float, glyphCount * 2 + 2);
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  *glyphToCharMap = LE_NEW_ARRAY(le_int32, glyphCount);
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_ARRAY_COPY(glyphs, &fStyleRunInfo[run].glyphs[leftGlyph], glyphCount);
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (outGlyph = 0, inGlyph = leftGlyph * 2; inGlyph <= rightGlyph * 2; inGlyph += 2, outGlyph += 2) {
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        positions[outGlyph]     = fStyleRunInfo[run].positions[inGlyph] + fVisualRunLastX;
110650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        positions[outGlyph + 1] = fStyleRunInfo[run].positions[inGlyph + 1] + fVisualRunLastY;
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save the ending position of this run
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to use for the start of the next run
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX = positions[outGlyph - 2];
111250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    fVisualRunLastY = positions[outGlyph - 1];
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((fStyleRunInfo[run].level & 1) == 0) {
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (outGlyph = 0, inGlyph = leftGlyph; inGlyph < rightGlyph; inGlyph += 1, outGlyph += 1) {
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyphToCharMap[outGlyph] = fGlyphToCharMap[glyphBase + inGlyph];
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Because fGlyphToCharMap is stored in logical order to facilitate line breaking,
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // we need to map the physical glyph indices to logical indices while we copy the
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // character indices.
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 base = glyphBase + fStyleRunInfo[run].glyphCount - 1;
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (outGlyph = 0, inGlyph = leftGlyph; inGlyph < rightGlyph; inGlyph += 1, outGlyph += 1) {
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyphToCharMap[outGlyph] = fGlyphToCharMap[base - inGlyph];
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    line->append(fStyleRunInfo[run].font, direction, glyphCount, glyphs, positions, glyphToCharMap);
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getCharRun(le_int32 charIndex)
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (charIndex < 0 || charIndex > fCharCount) {
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 run;
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NOTE: as long as fStyleRunLimits is well-formed
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the above range check guarantees that we'll never
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fall off the end of the array.
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    run = 0;
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (charIndex >= fStyleRunLimits[run]) {
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        run += 1;
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return run;
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char ParagraphLayout::Line::fgClassID = 0;
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define INITIAL_RUN_CAPACITY 4
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RUN_CAPACITY_GROW_LIMIT 16
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line::~Line()
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 i;
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < fRunCount; i += 1) {
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fRuns[i];
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fRuns);
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getAscent() const
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fAscent;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getDescent() const
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fDescent;
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getLeading() const
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fLeading;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getWidth() const
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const VisualRun *lastRun = getVisualRun(fRunCount - 1);
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (lastRun == NULL) {
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphCount = lastRun->getGlyphCount();
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const float *positions = lastRun->getPositions();
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (le_int32) positions[glyphCount * 2];
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst ParagraphLayout::VisualRun *ParagraphLayout::Line::getVisualRun(le_int32 runIndex) const
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (runIndex < 0 || runIndex >= fRunCount) {
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fRuns[runIndex];
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::Line::append(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[])
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fRunCount >= fRunCapacity) {
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fRunCapacity == 0) {
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRunCapacity = INITIAL_RUN_CAPACITY;
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRuns = LE_NEW_ARRAY(ParagraphLayout::VisualRun *, fRunCapacity);
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRunCapacity += (fRunCapacity < RUN_CAPACITY_GROW_LIMIT? fRunCapacity : RUN_CAPACITY_GROW_LIMIT);
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRuns = (ParagraphLayout::VisualRun **) LE_GROW_ARRAY(fRuns, fRunCapacity);
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRuns[fRunCount++] = new ParagraphLayout::VisualRun(font, direction, glyphCount, glyphs, positions, glyphToCharMap);
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::Line::computeMetrics()
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 maxDL = 0;
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (le_int32 i = 0; i < fRunCount; i += 1) {
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ascent  = fRuns[i]->getAscent();
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 descent = fRuns[i]->getDescent();
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 leading = fRuns[i]->getLeading();
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dl      = descent + leading;
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ascent > fAscent) {
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fAscent = ascent;
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (descent > fDescent) {
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDescent = descent;
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (leading > fLeading) {
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLeading = leading;
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dl > maxDL) {
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxDL = dl;
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLeading = maxDL - fDescent;
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char ParagraphLayout::VisualRun::fgClassID = 0;
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::VisualRun::~VisualRun()
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fGlyphToCharMap);
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fPositions);
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fGlyphs);
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1277