1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ubidi.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LETypes.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/loengine.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/playout.h"
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/plruns.h"
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "pflow.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "arraymem.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucreader.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Move the line below out of this comment
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to add a locale run to the pl_paragraphs
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * that are created.
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TEST_LOCALE "zh_TW"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MARGIN 10
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LINE_GROW 32
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define PARA_GROW 8
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_LF 0x000A
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_CR 0x000D
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_LSEP 0x2028
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_PSEP 0x2029
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct pf_object
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_paragraph    **fParagraphLayout;
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fParagraphCount;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fParagraphMax;
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fParagraphGrow;
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fLineCount;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fLinesMax;
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fLinesGrow;
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_line         **fLines;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   LEUnicode         *fChars;
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fLineHeight;
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fAscent;
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fWidth;
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32          fHeight;
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBiDiLevel        fParagraphLevel;
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct pf_object pf_object;
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic LEUnicode *skipLineEnd(LEUnicode *ptr)
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ptr[0] == CH_CR && ptr[1] == CH_LF) {
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ptr += 1;
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ptr + 1;
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic le_int32 findFontRun(const pl_fontRuns *fontRuns, le_int32 offset)
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 runCount = pl_getFontRunCount(fontRuns);
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 run;
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (run = 0; run < runCount; run += 1) {
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pl_getFontRunLimit(fontRuns, run) > offset) {
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return run;
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void subsetFontRuns(const pl_fontRuns *fontRuns, le_int32 start, le_int32 limit, pl_fontRuns *sub)
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 startRun = findFontRun(fontRuns, start);
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 endRun   = findFontRun(fontRuns, limit - 1);
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 run;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_resetFontRuns(sub);
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (run = startRun; run <= endRun; run += 1) {
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const le_font *runFont = pl_getFontRunFont(fontRuns, run);
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_int32 runLimit = pl_getFontRunLimit(fontRuns, run) - start;
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (run == endRun) {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            runLimit = limit - start;
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pl_addFontRun(sub, runFont, runLimit);
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupf_flow *pf_create(const LEUnicode chars[], le_int32 charCount, const pl_fontRuns *fontRuns, LEErrorCode *status)
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *flow;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 ascent  = 0;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 descent = 0;
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 leading = 0;
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	pl_localeRuns *locales = NULL;
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_fontRuns *fr;
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEUnicode *pStart;
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const LEUnicode separators[] = {CH_LF, CH_CR, CH_LSEP, CH_PSEP, 0x0000};
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (LE_FAILURE(*status)) {
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		return NULL;
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow = NEW_ARRAY(pf_object, 1);
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphLayout = NULL;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphCount  = 0;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphMax    = PARA_GROW;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphGrow   = PARA_GROW;
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLineCount       = 0;
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLinesMax        = LINE_GROW;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLinesGrow       = LINE_GROW;
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLines           = NULL;
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fChars           = NULL;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLineHeight      = -1;
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fAscent          = -1;
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fWidth           = -1;
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fHeight          = -1;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphLevel  = UBIDI_DEFAULT_LTR;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fr = pl_openEmptyFontRuns(0);
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef TEST_LOCALE
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    locales = pl_openEmptyLocaleRuns(0);
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLines = NEW_ARRAY(pl_line *, flow->fLinesMax);
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fParagraphLayout = NEW_ARRAY(pl_paragraph *, flow->fParagraphMax);
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fChars = NEW_ARRAY(LEUnicode, charCount + 1);
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_ARRAY_COPY(flow->fChars, chars, charCount);
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fChars[charCount] = 0;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pStart = &flow->fChars[0];
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (*pStart != 0) {
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        LEUnicode *pEnd = u_strpbrk(pStart, separators);
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_int32 pAscent, pDescent, pLeading;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pl_paragraph *paragraphLayout = NULL;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pEnd == NULL) {
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pEnd = &flow->fChars[charCount];
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pEnd != pStart) {
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            subsetFontRuns(fontRuns, pStart - flow->fChars, pEnd - flow->fChars, fr);
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef TEST_LOCALE
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pl_resetLocaleRuns(locales);
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pl_addLocaleRun(locales, TEST_LOCALE, pEnd - pStart);
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            paragraphLayout = pl_create(pStart, pEnd - pStart, fr, NULL, NULL, locales, flow->fParagraphLevel, FALSE, status);
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (LE_FAILURE(*status)) {
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break; /* return? something else? */
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (flow->fParagraphLevel == UBIDI_DEFAULT_LTR) {
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                flow->fParagraphLevel = pl_getParagraphLevel(paragraphLayout);
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pAscent  = pl_getAscent(paragraphLayout);
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pDescent = pl_getDescent(paragraphLayout);
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pLeading = pl_getLeading(paragraphLayout);
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pAscent > ascent) {
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ascent = pAscent;
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pDescent > descent) {
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                descent = pDescent;
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pLeading > leading) {
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                leading = pLeading;
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (flow->fParagraphCount >= flow->fParagraphMax) {
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flow->fParagraphLayout = (pl_paragraph **) GROW_ARRAY(flow->fParagraphLayout, flow->fParagraphMax + flow->fParagraphGrow);
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flow->fParagraphMax += flow->fParagraphGrow;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        flow->fParagraphLayout[flow->fParagraphCount++] = paragraphLayout;
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*pEnd == 0) {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pStart = skipLineEnd(pEnd);
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fLineHeight = ascent + descent + leading;
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    flow->fAscent     = ascent;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_closeLocaleRuns(locales);
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_closeFontRuns(fr);
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (pf_flow *) flow;
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid pf_close(pf_flow *flow)
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 i;
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i = 0; i < obj->fLineCount; i += 1) {
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(obj->fLines[i]);
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELETE_ARRAY(obj->fLines);
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i = 0; i < obj->fParagraphCount; i += 1) {
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pl_close(obj->fParagraphLayout[i]);
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELETE_ARRAY(obj->fParagraphLayout);
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELETE_ARRAY(obj->fChars);
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELETE_ARRAY(obj);
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 pf_getAscent(pf_flow *flow)
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return obj->fAscent;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 pf_getLineHeight(pf_flow *flow)
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return obj->fLineHeight;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 pf_getLineCount(pf_flow *flow)
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return obj->fLineCount;
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void addLine(pf_object *obj, pl_line *line)
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (obj->fLineCount >= obj->fLinesMax) {
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        obj->fLines = (pl_line **) GROW_ARRAY(obj->fLines, obj->fLinesMax + obj->fLinesGrow);
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        obj->fLinesMax += obj->fLinesGrow;
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    obj->fLines[obj->fLineCount++] = line;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid pf_breakLines(pf_flow *flow, le_int32 width, le_int32 height)
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 li, p;
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    float lineWidth;
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_line *line;
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    obj->fHeight = height;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* don't re-break if the width hasn't changed */
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (obj->fWidth == width) {
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    obj->fWidth  = width;
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lineWidth = (float) (width - 2 * MARGIN);
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Free the old Lines... */
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (li = 0; li < obj->fLineCount; li += 1) {
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pl_closeLine(obj->fLines[li]);
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    obj->fLineCount = 0;
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (p = 0; p < obj->fParagraphCount; p += 1) {
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pl_paragraph *paragraphLayout = obj->fParagraphLayout[p];
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (paragraphLayout != NULL) {
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pl_reflow(paragraphLayout);
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while ((line = pl_nextLine(paragraphLayout, lineWidth)) != NULL) {
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                addLine(obj, line);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            addLine(obj, NULL);
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid pf_draw(pf_flow *flow, rs_surface *surface, le_int32 firstLine, le_int32 lastLine)
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_object *obj = (pf_object *) flow;
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 li, x, y;
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    x = MARGIN;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    y = obj->fAscent;
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (li = firstLine; li <= lastLine; li += 1) {
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const pl_line *line = obj->fLines[li];
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (line != NULL) {
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 runCount = pl_countLineRuns(line);
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 run;
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		    if (obj->fParagraphLevel == UBIDI_RTL) {
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			    le_int32 lastX = pl_getLineWidth(line);
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			    x = (obj->fWidth - lastX - MARGIN);
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		    }
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (run = 0; run < runCount; run += 1) {
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const pl_visualRun *visualRun = pl_getLineVisualRun(line, run);
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                le_int32 glyphCount = pl_getVisualRunGlyphCount(visualRun);
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const le_font *font = pl_getVisualRunFont(visualRun);
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const LEGlyphID *glyphs = pl_getVisualRunGlyphs(visualRun);
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const float *positions = pl_getVisualRunPositions(visualRun);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rs_drawGlyphs(surface, font, glyphs, glyphCount, positions, x, y, obj->fWidth, obj->fHeight);
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        y += obj->fLineHeight;
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupf_flow *pf_factory(const char *fileName, const le_font *font, gs_guiSupport *guiSupport)
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEErrorCode status  = LE_NO_ERROR;
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 charCount;
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *text = uc_readFile(fileName, guiSupport, &charCount);
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_fontRuns *fontRuns;
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pf_flow *result = NULL;
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (text == NULL) {
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fontRuns = pl_openEmptyFontRuns(0);
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_addFontRun(fontRuns, font, charCount);
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = pf_create(text, charCount, fontRuns, &status);
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (LE_FAILURE(status)) {
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		pf_close(result);
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		result = NULL;
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pl_closeFontRuns(fontRuns);
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DELETE_ARRAY(text);
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
382