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
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * How to deal with composite fonts:
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Don't store the client's FontRuns; we'll need to compute sub-font FontRuns using Doug's
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * LEFontInstance method. Do that by intersecting the client's FontRuns with fScriptRuns. Use
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * that to compute fFontRuns, and then intersect fFontRuns, fScriptRuns and fLevelRuns. Doing
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * it in this order means we do a two-way intersection and a three-way intersection.
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * An optimization would be to only do this if there's at least one composite font...
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Other notes:
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Return the sub-fonts as the run fonts... could keep the mapping back to the client's FontRuns
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   but that probably makes it more complicated of everyone...
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Take the LineInfo and LineRun types from Paragraph and use them here, incorporate them into the API.
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * * Might want to change the name of the StyleRun type, and make a new one that holds fonts, scripts and levels?
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const FontRuns   *fontRuns,
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const ValueRuns  *levelRuns,
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const ValueRuns  *scriptRuns,
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const LocaleRuns *localeRuns,
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 UBiDiLevel paragraphLevel, le_bool vertical,
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 LEErrorCode &status)
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 : fChars(chars), fCharCount(count),
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fFontRuns(NULL), fLevelRuns(levelRuns), fScriptRuns(scriptRuns), fLocaleRuns(localeRuns),
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fVertical(vertical), fClientLevels(TRUE), fClientScripts(TRUE), fClientLocales(TRUE), fEmbeddingLevels(NULL),
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fAscent(0), fDescent(0), fLeading(0),
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fGlyphToCharMap(NULL), fCharToMinGlyphMap(NULL), fCharToMaxGlyphMap(NULL), fGlyphWidths(NULL), fGlyphCount(0),
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fParaBidi(NULL), fLineBidi(NULL),
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fStyleRunLimits(NULL), fStyleIndices(NULL), fStyleRunCount(0),
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fBreakIterator(NULL), fLineStart(-1), fLineEnd(0),
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 /*fVisualRuns(NULL), fStyleRunInfo(NULL), fVisualRunCount(-1),
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fFirstVisualRun(-1), fLastVisualRun(-1),*/ fVisualRunLastX(0), fVisualRunLastY(0)
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharCount = -1;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // FIXME: should check the limit arrays for consistency...
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    computeLevels(paragraphLevel);
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (scriptRuns == NULL) {
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        computeScripts();
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (localeRuns == NULL) {
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        computeLocales();
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    computeSubFonts(fontRuns, status);
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //other stuff?
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharCount = -1;
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // now intersect the font, direction and script runs...
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const RunArray *styleRunArrays[] = {fFontRuns, fLevelRuns, fScriptRuns, fLocaleRuns};
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  styleCount = sizeof styleRunArrays / sizeof styleRunArrays[0];
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StyleRuns styleRuns(styleRunArrays, styleCount);
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEErrorCode layoutStatus = LE_NO_ERROR;
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunCount = styleRuns.getRuns(NULL, NULL);
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunLimits = LE_NEW_ARRAY(le_int32, fStyleRunCount);
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleIndices   = LE_NEW_ARRAY(le_int32, fStyleRunCount * styleCount);
352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ((fStyleRunLimits == NULL) || (fStyleIndices == NULL)) {
353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    styleRuns.getRuns(fStyleRunLimits, fStyleIndices);
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // now build a LayoutEngine for each style run...
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleIndices = fStyleIndices;
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 run, runStart;
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fStyleRunInfo = LE_NEW_ARRAY(StyleRunInfo, fStyleRunCount);
364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (fStyleRunInfo == NULL) {
365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    else {
369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // initialize
370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].font = NULL;
372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].runBase = 0;
373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].runLimit = 0;
374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].script = (UScriptCode)0;
375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].locale = NULL;
376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].level = 0;
377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphBase = 0;
378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].engine = NULL;
379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphCount = 0;
380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].glyphs = NULL;
381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fStyleRunInfo[run].positions = NULL;
382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphCount = 0;
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].font      = fFontRuns->getFont(styleIndices[0]);
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].runBase   = runStart;
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].runLimit  = fStyleRunLimits[run];
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].script    = (UScriptCode) fScriptRuns->getValue(styleIndices[2]);
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].locale    = fLocaleRuns->getLocale(styleIndices[3]);
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].level     = (UBiDiLevel) fLevelRuns->getValue(styleIndices[1]);
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphBase = fGlyphCount;
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].engine = LayoutEngine::layoutEngineFactory(fStyleRunInfo[run].font,
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].script, getLanguageCode(fStyleRunInfo[run].locale), layoutStatus);
397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphCount = fStyleRunInfo[run].engine->layoutChars(fChars, runStart, fStyleRunLimits[run] - runStart, fCharCount,
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].level & 1, 0, 0, layoutStatus);
404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runStart = fStyleRunLimits[run];
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        styleIndices += styleCount;
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphCount += fStyleRunInfo[run].glyphCount;
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make big arrays for the glyph widths, glyph-to-char and char-to-glyph maps,
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // in logical order. (Both maps need an extra entry for the end of the text.)
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // For each layout get the positions and convert them into glyph widths, in
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // logical order. Get the glyph-to-char mapping, offset by starting index in the
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // character array. Swap the glyph width and glyph-to-char arrays into logical order.
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Finally, fill in the char-to-glyph mappings.
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphWidths       = LE_NEW_ARRAY(float, fGlyphCount);
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphToCharMap    = LE_NEW_ARRAY(le_int32, fGlyphCount + 1);
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMinGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMaxGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ((fGlyphWidths == NULL) || (fGlyphToCharMap == NULL) ||
426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (fCharToMinGlyphMap == NULL) || (fCharToMaxGlyphMap == NULL)) {
427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        status = LE_MEMORY_ALLOCATION_ERROR;
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyph;
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LayoutEngine *engine = fStyleRunInfo[run].engine;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyphCount  = fStyleRunInfo[run].glyphCount;
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyphBase   = fStyleRunInfo[run].glyphBase;
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].glyphs = LE_NEW_ARRAY(LEGlyphID, glyphCount);
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].positions = LE_NEW_ARRAY(float, glyphCount * 2 + 2);
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ((fStyleRunInfo[run].glyphs == NULL) ||
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (fStyleRunInfo[run].positions == NULL)) {
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = LE_MEMORY_ALLOCATION_ERROR;
443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getGlyphs(fStyleRunInfo[run].glyphs, layoutStatus);
447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getGlyphPositions(fStyleRunInfo[run].positions, layoutStatus);
453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        engine->getCharIndices(&fGlyphToCharMap[glyphBase], runStart, layoutStatus);
459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (LE_FAILURE(layoutStatus)) {
460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = layoutStatus;
461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (glyph = 0; glyph < glyphCount; glyph += 1) {
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fGlyphWidths[glyphBase + glyph] = fStyleRunInfo[run].positions[glyph * 2 + 2] - fStyleRunInfo[run].positions[glyph * 2];
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((fStyleRunInfo[run].level & 1) != 0) {
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LXUtilities::reverse(&fGlyphWidths[glyphBase], glyphCount);
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LXUtilities::reverse(&fGlyphToCharMap[glyphBase], glyphCount);
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runStart = fStyleRunLimits[run];
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete engine;
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo[run].engine = NULL;
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGlyphToCharMap[fGlyphCount] = fCharCount;
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (glyph = fGlyphCount - 1; glyph >= 0; glyph -= 1) {
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch = fGlyphToCharMap[glyph];
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMinGlyphMap[ch] = glyph;
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMinGlyphMap[fCharCount] = fGlyphCount;
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (glyph = 0; glyph < fGlyphCount; glyph += 1) {
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch = fGlyphToCharMap[glyph];
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMaxGlyphMap[ch] = glyph;
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCharToMaxGlyphMap[fCharCount] = fGlyphCount;
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::~ParagraphLayout()
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete (FontRuns *) fFontRuns;
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientLevels) {
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (ValueRuns *) fLevelRuns;
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLevelRuns = NULL;
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLevels = TRUE;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientScripts) {
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (ValueRuns *) fScriptRuns;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fScriptRuns = NULL;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientScripts = TRUE;
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fClientLocales) {
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete (LocaleRuns *) fLocaleRuns;
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLocaleRuns = NULL;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLocales = TRUE;
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fEmbeddingLevels != NULL) {
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fEmbeddingLevels);
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fEmbeddingLevels = NULL;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGlyphToCharMap != NULL) {
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fGlyphToCharMap);
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphToCharMap = NULL;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fCharToMinGlyphMap != NULL) {
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fCharToMinGlyphMap);
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMinGlyphMap = NULL;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fCharToMaxGlyphMap != NULL) {
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fCharToMaxGlyphMap);
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCharToMaxGlyphMap = NULL;
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGlyphWidths != NULL) {
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fGlyphWidths);
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphWidths = NULL;
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fParaBidi != NULL) {
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ubidi_close(fParaBidi);
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fParaBidi = NULL;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLineBidi != NULL) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ubidi_close(fLineBidi);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineBidi = NULL;
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fStyleRunCount > 0) {
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleRunLimits);
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleIndices);
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = 0; run < fStyleRunCount; run += 1) {
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LE_DELETE_ARRAY(fStyleRunInfo[run].glyphs);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LE_DELETE_ARRAY(fStyleRunInfo[run].positions);
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].glyphs    = NULL;
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fStyleRunInfo[run].positions = NULL;
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(fStyleRunInfo);
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunLimits = NULL;
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleIndices   = NULL;
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunInfo        = NULL;
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fStyleRunCount  = 0;
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fBreakIterator != NULL) {
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fBreakIterator;
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator = NULL;
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool ParagraphLayout::isComplex(const LEUnicode chars[], le_int32 count)
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode scriptStatus = U_ZERO_ERROR;
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptCode scriptCode  = USCRIPT_INVALID_CODE;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptRun *sr = uscript_openRun(chars, count, &scriptStatus);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_bool result = FALSE;
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (uscript_nextRun(sr, NULL, NULL, &scriptCode)) {
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (isComplex(scriptCode)) {
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = TRUE;
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uscript_closeRun(sr);
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getAscent() const
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fAscent;
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getDescent() const
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fDescent;
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLeading() const
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0 && fCharCount > 0) {
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout *) this)->computeMetrics();
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fLeading;
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehole_bool ParagraphLayout::isDone() const
63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return fLineEnd >= fCharCount;
63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line *ParagraphLayout::nextLine(float width)
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (isDone()) {
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLineStart = fLineEnd;
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (width > 0) {
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 glyph    = fCharToMinGlyphMap[fLineStart];
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        float widthSoFar  = 0;
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (glyph < fGlyphCount && widthSoFar + fGlyphWidths[glyph] <= width) {
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            widthSoFar += fGlyphWidths[glyph++];
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If no glyphs fit on the line, force one to fit.
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // (There shouldn't be any zero width glyphs at the
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // start of a line unless the paragraph consists of
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // only zero width glyphs, because otherwise the zero
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // width glyphs will have been included on the end of
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the previous line...)
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (widthSoFar == 0 && glyph < fGlyphCount) {
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyph += 1;
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineEnd = previousBreak(fGlyphToCharMap[glyph]);
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If this break is at or before the last one,
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // find a glyph, starting at the one which didn't
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // fit, that produces a break after the last one.
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (fLineEnd <= fLineStart) {
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLineEnd = fGlyphToCharMap[glyph++];
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineEnd = fCharCount;
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return computeVisualRuns();
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeLevels(UBiDiLevel paragraphLevel)
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode bidiStatus = U_ZERO_ERROR;
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLevelRuns != NULL) {
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ch;
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fEmbeddingLevels = LE_NEW_ARRAY(UBiDiLevel, fCharCount);
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (ch = 0, run = 0; run < fLevelRuns->getCount(); run += 1) {
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBiDiLevel runLevel = (UBiDiLevel) fLevelRuns->getValue(run) | UBIDI_LEVEL_OVERRIDE;
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32   runLimit = fLevelRuns->getLimit(run);
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (ch < runLimit) {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fEmbeddingLevels[ch++] = runLevel;
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fParaBidi = ubidi_openSized(fCharCount, 0, &bidiStatus);
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_setPara(fParaBidi, fChars, fCharCount, paragraphLevel, fEmbeddingLevels, &bidiStatus);
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLevelRuns == NULL) {
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 levelRunCount = ubidi_countRuns(fParaBidi, &bidiStatus);
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ValueRuns *levelRuns = new ValueRuns(levelRunCount);
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 logicalStart = 0;
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 run;
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 limit;
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel level;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = 0; run < levelRunCount; run += 1) {
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ubidi_getLogicalRun(fParaBidi, logicalStart, &limit, &level);
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            levelRuns->add(level, limit);
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalStart = limit;
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLevelRuns    = levelRuns;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fClientLevels = FALSE;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeScripts()
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode scriptStatus = U_ZERO_ERROR;
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptRun *sr = uscript_openRun(fChars, fCharCount, &scriptStatus);
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ValueRuns  *scriptRuns = new ValueRuns(0);
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 limit;
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UScriptCode script;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (uscript_nextRun(sr, NULL, &limit, &script)) {
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        scriptRuns->add(script, limit);
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uscript_closeRun(sr);
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fScriptRuns    = scriptRuns;
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fClientScripts = FALSE;
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeLocales()
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LocaleRuns *localeRuns = new LocaleRuns(0);
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Locale *defaultLocale = &Locale::getDefault();
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    localeRuns->add(defaultLocale, fCharCount);
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLocaleRuns    = localeRuns;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fClientLocales = FALSE;
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeSubFonts(const FontRuns *fontRuns, LEErrorCode &status)
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(status)) {
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const RunArray *styleRunArrays[] = {fontRuns, fScriptRuns};
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 styleCount = sizeof styleRunArrays / sizeof styleRunArrays[0];
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StyleRuns styleRuns(styleRunArrays, styleCount);
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 styleRunCount = styleRuns.getRuns(NULL, NULL);
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleRunLimits = LE_NEW_ARRAY(le_int32, styleRunCount);
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 *styleIndices = LE_NEW_ARRAY(le_int32, styleRunCount * styleCount);
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FontRuns *subFontRuns  = new FontRuns(0);
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  run, offset, *si;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    styleRuns.getRuns(styleRunLimits, styleIndices);
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    si = styleIndices;
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = 0;
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (run = 0; run < styleRunCount; run += 1) {
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const LEFontInstance *runFont = fontRuns->getFont(si[0]);
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 script = fScriptRuns->getValue(si[1]);
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (offset < styleRunLimits[run]) {
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const LEFontInstance *subFont = runFont->getSubFont(fChars, &offset, styleRunLimits[run], script, status);
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (LE_FAILURE(status)) {
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete subFontRuns;
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanUp;
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            subFontRuns->add(subFont, offset);
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        si += styleCount;
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFontRuns = subFontRuns;
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucleanUp:
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(styleIndices);
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(styleRunLimits);
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::computeMetrics()
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 i, count = fFontRuns->getCount();
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 maxDL = 0;
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < count; i += 1) {
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const LEFontInstance *font = fFontRuns->getFont(i);
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ascent  = font->getAscent();
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 descent = font->getDescent();
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 leading = font->getLeading();
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dl      = descent + leading;
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ascent > fAscent) {
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fAscent = ascent;
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (descent > fDescent) {
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDescent = descent;
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (leading > fLeading) {
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLeading = leading;
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dl > maxDL) {
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxDL = dl;
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLeading = maxDL - fDescent;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 1
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct LanguageMap
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *localeCode;
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 languageCode;
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const LanguageMap languageMap[] =
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
837c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"afr", afkLanguageCode}, // Afrikaans
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ara", araLanguageCode}, // Arabic
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"asm", asmLanguageCode}, // Assamese
840c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bel", belLanguageCode}, // Belarussian
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ben", benLanguageCode}, // Bengali
842c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bod", tibLanguageCode}, // Tibetan
843c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"bul", bgrLanguageCode}, // Bulgarian
844c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cat", catLanguageCode}, // Catalan
845c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ces", csyLanguageCode}, // Czech
846c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"che", cheLanguageCode}, // Chechen
847c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cop", copLanguageCode}, // Coptic
848c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"cym", welLanguageCode}, // Welsh
849c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"dan", danLanguageCode}, // Danish
850c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"deu", deuLanguageCode}, // German
851c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"dzo", dznLanguageCode}, // Dzongkha
852c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ell", ellLanguageCode}, // Greek
853c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"eng", engLanguageCode}, // English
854c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"est", etiLanguageCode}, // Estonian
855c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"eus", euqLanguageCode}, // Basque
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"fas", farLanguageCode}, // Farsi
857c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"fin", finLanguageCode}, // Finnish
858c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"fra", fraLanguageCode}, // French
859c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"gle", gaeLanguageCode}, // Irish Gaelic
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"guj", gujLanguageCode}, // Gujarati
861c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hau", hauLanguageCode}, // Hausa
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"heb", iwrLanguageCode}, // Hebrew
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"hin", hinLanguageCode}, // Hindi
864c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hrv", hrvLanguageCode}, // Croatian
865c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hun", hunLanguageCode}, // Hungarian
866c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"hye", hyeLanguageCode}, // Armenian
867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ind", indLanguageCode}, // Indonesian
868c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ita", itaLanguageCode}, // Italian
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"jpn", janLanguageCode}, // Japanese
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kan", kanLanguageCode}, // Kannada
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kas", kshLanguageCode}, // Kashmiri
872c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"khm", khmLanguageCode}, // Khmer
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kok", kokLanguageCode}, // Konkani
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"kor", korLanguageCode}, // Korean
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  {"mal_XXX", malLanguageCode}, // Malayalam - Traditional
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mal", mlrLanguageCode}, // Malayalam - Reformed
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mar", marLanguageCode}, // Marathi
878c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"mlt", mtsLanguageCode}, // Maltese
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"mni", mniLanguageCode}, // Manipuri
880c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"mon", mngLanguageCode}, // Mongolian
881c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"nep", nepLanguageCode}, // Nepali
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ori", oriLanguageCode}, // Oriya
883c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"pol", plkLanguageCode}, // Polish
884c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"por", ptgLanguageCode}, // Portuguese
885c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"pus", pasLanguageCode}, // Pashto
886c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ron", romLanguageCode}, // Romanian
887c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"rus", rusLanguageCode}, // Russian
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"san", sanLanguageCode}, // Sanskrit
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"sin", snhLanguageCode}, // Sinhalese
890c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"slk", skyLanguageCode}, // Slovak
891c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"snd", sndLanguageCode}, // Sindhi
892c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"slv", slvLanguageCode}, // Slovenian
893c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"spa", espLanguageCode}, // Spanish
894c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"sqi", sqiLanguageCode}, // Albanian
895c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"srp", srbLanguageCode}, // Serbian
896c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"swe", sveLanguageCode}, // Swedish
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"syr", syrLanguageCode}, // Syriac
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tam", tamLanguageCode}, // Tamil
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tel", telLanguageCode}, // Telugu
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"tha", thaLanguageCode}, // Thai
901c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"tur", trkLanguageCode}, // Turkish
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"urd", urdLanguageCode}, // Urdu
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"yid", jiiLanguageCode}, // Yiddish
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  {"zhp", zhpLanguageCode}, // Chinese - Phonetic
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho", zhsLanguageCode}, // Chinese
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_CHN", zhsLanguageCode}, // Chinese - China
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_HKG", zhsLanguageCode}, // Chinese - Hong Kong
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_MAC", zhtLanguageCode}, // Chinese - Macao
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_SGP", zhsLanguageCode}, // Chinese - Singapore
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"zho_TWN", zhtLanguageCode}  // Chinese - Taiwan
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const le_int32 languageMapCount = ARRAY_SIZE(languageMap);
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLanguageCode(const Locale *locale)
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char code[8] = {0, 0, 0, 0, 0, 0, 0, 0};
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *language = locale->getISO3Language();
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *country  = locale->getISO3Country();
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(code, language);
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((uprv_strcmp(language, "zho") == 0) && country != NULL) {
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcat(code, "_");
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcat(code, country);
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (le_int32 i = 0; i < languageMapCount; i += 1) {
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(code, languageMap[i].localeCode) == 0) {
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return languageMap[i].languageCode;
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return nullLanguageCode;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#else
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TODO - dummy implementation for right now...
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getLanguageCode(const Locale *locale)
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return nullLanguageCode;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool ParagraphLayout::isComplex(UScriptCode script)
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (script < 0 || script >= (UScriptCode) scriptCodeCount) {
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return complexTable[script];
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::previousBreak(le_int32 charIndex)
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // skip over any whitespace or control characters,
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // because they can hang in the margin.
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (charIndex < fCharCount &&
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           (u_isWhitespace(fChars[charIndex]) ||
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_iscntrl(fChars[charIndex]))) {
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        charIndex += 1;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create the BreakIterator if we don't already have one
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fBreakIterator == NULL) {
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale thai("th");
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UCharCharacterIterator *iter = new UCharCharacterIterator(fChars, fCharCount);
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator = BreakIterator::createLineInstance(thai, status);
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fBreakIterator->adoptText(iter);
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // return the break location that's at or before
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the character we stopped on. Note: if we're
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on a break, the "+ 1" will cause preceding to
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // back up to it.
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fBreakIterator->preceding(charIndex + 1);
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line *ParagraphLayout::computeVisualRuns()
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode bidiStatus = U_ZERO_ERROR;
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 dirRunCount, visualRun;
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX = 0;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastY = 0;
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFirstVisualRun = getCharRun(fLineStart);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLastVisualRun  = getCharRun(fLineEnd - 1);
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fLineBidi == NULL) {
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fLineBidi = ubidi_openSized(fCharCount, 0, &bidiStatus);
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_setLine(fParaBidi, fLineStart, fLineEnd, fLineBidi, &bidiStatus);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dirRunCount = ubidi_countRuns(fLineBidi, &bidiStatus);
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Line *line = new Line();
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (visualRun = 0; visualRun < dirRunCount; visualRun += 1) {
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 relStart, run, runLength;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiDirection runDirection = ubidi_getVisualRun(fLineBidi, visualRun, &relStart, &runLength);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 runStart = fLineStart + relStart;
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 runEnd   = runStart + runLength - 1;
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 firstRun = getCharRun(runStart);
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 lastRun  = getCharRun(runEnd);
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 startRun = (runDirection == UBIDI_LTR)? firstRun : lastRun;
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 stopRun  = (runDirection == UBIDI_LTR)? lastRun + 1 : firstRun - 1;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dir      = (runDirection == UBIDI_LTR)?  1 : -1;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (run = startRun; run != stopRun; run += dir) {
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32 firstChar = (run == firstRun)? runStart : fStyleRunInfo[run].runBase;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            le_int32 lastChar  = (run == lastRun)?  runEnd   : fStyleRunInfo[run].runLimit - 1;
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            appendRun(line, run, firstChar, lastChar);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return line;
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::appendRun(ParagraphLayout::Line *line, le_int32 run, le_int32 firstChar, le_int32 lastChar)
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphBase = fStyleRunInfo[run].glyphBase;
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 inGlyph, outGlyph;
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Get the glyph indices for all the characters between firstChar and lastChar,
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // make the minimum one be leftGlyph and the maximum one be rightGlyph.
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (need to do this to handle local reorderings like Indic left matras)
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 leftGlyph  = fGlyphCount;
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 rightGlyph = -1;
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 ch;
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (ch = firstChar; ch <= lastChar; ch += 1) {
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 minGlyph = fCharToMinGlyphMap[ch];
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 maxGlyph = fCharToMaxGlyphMap[ch];
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (minGlyph < leftGlyph) {
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            leftGlyph = minGlyph;
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (maxGlyph > rightGlyph) {
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            rightGlyph = maxGlyph;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((fStyleRunInfo[run].level & 1) != 0) {
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 swap = rightGlyph;
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 last = glyphBase + fStyleRunInfo[run].glyphCount - 1;
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Here, we want to remove the glyphBase bias...
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rightGlyph = last - leftGlyph;
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        leftGlyph  = last - swap;
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rightGlyph -= glyphBase;
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        leftGlyph  -= glyphBase;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set the position bias for the glyphs. If we're at the start of
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // a line, we want the first glyph to be at x = 0, even if it comes
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // from the middle of a layout. If we've got a right-to-left run, we
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // want the left-most glyph to start at the final x position of the
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // previous run, even though this glyph may be in the middle of the
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // run.
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX -= fStyleRunInfo[run].positions[leftGlyph * 2];
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make rightGlyph be the glyph just to the right of
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the run's glyphs
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rightGlyph += 1;
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiDirection direction  = ((fStyleRunInfo[run].level & 1) == 0)? UBIDI_LTR : UBIDI_RTL;
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32   glyphCount     = rightGlyph - leftGlyph;
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEGlyphID *glyphs         = LE_NEW_ARRAY(LEGlyphID, glyphCount);
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    float     *positions      = LE_NEW_ARRAY(float, glyphCount * 2 + 2);
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32  *glyphToCharMap = LE_NEW_ARRAY(le_int32, glyphCount);
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_ARRAY_COPY(glyphs, &fStyleRunInfo[run].glyphs[leftGlyph], glyphCount);
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (outGlyph = 0, inGlyph = leftGlyph * 2; inGlyph <= rightGlyph * 2; inGlyph += 2, outGlyph += 2) {
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        positions[outGlyph]     = fStyleRunInfo[run].positions[inGlyph] + fVisualRunLastX;
108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        positions[outGlyph + 1] = fStyleRunInfo[run].positions[inGlyph + 1] + fVisualRunLastY;
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Save the ending position of this run
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to use for the start of the next run
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fVisualRunLastX = positions[outGlyph - 2];
108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    fVisualRunLastY = positions[outGlyph - 1];
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((fStyleRunInfo[run].level & 1) == 0) {
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (outGlyph = 0, inGlyph = leftGlyph; inGlyph < rightGlyph; inGlyph += 1, outGlyph += 1) {
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyphToCharMap[outGlyph] = fGlyphToCharMap[glyphBase + inGlyph];
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Because fGlyphToCharMap is stored in logical order to facilitate line breaking,
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // we need to map the physical glyph indices to logical indices while we copy the
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // character indices.
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 base = glyphBase + fStyleRunInfo[run].glyphCount - 1;
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (outGlyph = 0, inGlyph = leftGlyph; inGlyph < rightGlyph; inGlyph += 1, outGlyph += 1) {
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyphToCharMap[outGlyph] = fGlyphToCharMap[base - inGlyph];
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    line->append(fStyleRunInfo[run].font, direction, glyphCount, glyphs, positions, glyphToCharMap);
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::getCharRun(le_int32 charIndex)
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (charIndex < 0 || charIndex > fCharCount) {
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 run;
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NOTE: as long as fStyleRunLimits is well-formed
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the above range check guarantees that we'll never
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fall off the end of the array.
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    run = 0;
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (charIndex >= fStyleRunLimits[run]) {
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        run += 1;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return run;
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char ParagraphLayout::Line::fgClassID = 0;
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define INITIAL_RUN_CAPACITY 4
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RUN_CAPACITY_GROW_LIMIT 16
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::Line::~Line()
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 i;
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < fRunCount; i += 1) {
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fRuns[i];
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fRuns);
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getAscent() const
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fAscent;
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getDescent() const
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fDescent;
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getLeading() const
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAscent <= 0) {
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((ParagraphLayout::Line *)this)->computeMetrics();
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fLeading;
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ParagraphLayout::Line::getWidth() const
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const VisualRun *lastRun = getVisualRun(fRunCount - 1);
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (lastRun == NULL) {
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphCount = lastRun->getGlyphCount();
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const float *positions = lastRun->getPositions();
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (le_int32) positions[glyphCount * 2];
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst ParagraphLayout::VisualRun *ParagraphLayout::Line::getVisualRun(le_int32 runIndex) const
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (runIndex < 0 || runIndex >= fRunCount) {
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fRuns[runIndex];
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::Line::append(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[])
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fRunCount >= fRunCapacity) {
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fRunCapacity == 0) {
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRunCapacity = INITIAL_RUN_CAPACITY;
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRuns = LE_NEW_ARRAY(ParagraphLayout::VisualRun *, fRunCapacity);
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRunCapacity += (fRunCapacity < RUN_CAPACITY_GROW_LIMIT? fRunCapacity : RUN_CAPACITY_GROW_LIMIT);
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fRuns = (ParagraphLayout::VisualRun **) LE_GROW_ARRAY(fRuns, fRunCapacity);
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fRuns[fRunCount++] = new ParagraphLayout::VisualRun(font, direction, glyphCount, glyphs, positions, glyphToCharMap);
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ParagraphLayout::Line::computeMetrics()
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 maxDL = 0;
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (le_int32 i = 0; i < fRunCount; i += 1) {
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 ascent  = fRuns[i]->getAscent();
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 descent = fRuns[i]->getDescent();
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 leading = fRuns[i]->getLeading();
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        le_int32 dl      = descent + leading;
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ascent > fAscent) {
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fAscent = ascent;
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (descent > fDescent) {
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDescent = descent;
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (leading > fLeading) {
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fLeading = leading;
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dl > maxDL) {
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxDL = dl;
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fLeading = maxDL - fDescent;
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char ParagraphLayout::VisualRun::fgClassID = 0;
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruParagraphLayout::VisualRun::~VisualRun()
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fGlyphToCharMap);
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fPositions);
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(fGlyphs);
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1252