1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *   Copyright (C) 2016 and later: Unicode, Inc. and others.
564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *   License & terms of use: http://www.unicode.org/copyright.html#License
664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *
764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *******************************************************************************
864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *******************************************************************************
964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *
10c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert *   Copyright (C) 1999-2015, International Business Machines
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   Corporation and others.  All Rights Reserved.
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *******************************************************************************
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   file name:  Paragraph.cpp
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   created on: 09/06/2000
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   created by: Eric R. Mader
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ubidi.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/ParagraphLayout.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "RenderingSurface.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "paragraph.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "UnicodeReader.h"
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MARGIN 10
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LINE_GROW 32
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define PARA_GROW 8
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_LF 0x000A
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_CR 0x000D
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_LSEP 0x2028
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CH_PSEP 0x2029
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic LEUnicode *skipLineEnd(LEUnicode *ptr)
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ptr[0] == CH_CR && ptr[1] == CH_LF) {
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ptr += 1;
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ptr + 1;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic le_int32 findRun(const RunArray *runArray, le_int32 offset)
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 runCount = runArray->getCount();
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 run = 0; run < runCount; run += 1) {
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (runArray->getLimit(run) > offset) {
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return run;
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void subsetFontRuns(const FontRuns *fontRuns, le_int32 start, le_int32 limit, FontRuns *sub)
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 startRun = findRun(fontRuns, start);
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 endRun   = findRun(fontRuns, limit - 1);
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sub->reset();
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 run = startRun; run <= endRun; run += 1) {
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const LEFontInstance *runFont = fontRuns->getFont(run);
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_int32 runLimit = fontRuns->getLimit(run) - start;
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (run == endRun) {
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            runLimit = limit - start;
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sub->add(runFont, runLimit);
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruParagraph::Paragraph(const LEUnicode chars[], int32_t charCount, const FontRuns *fontRuns, LEErrorCode &status)
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : fParagraphLayout(NULL), fParagraphCount(0), fParagraphMax(PARA_GROW), fParagraphGrow(PARA_GROW),
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLineCount(0), fLinesMax(LINE_GROW), fLinesGrow(LINE_GROW), fLines(NULL), fChars(NULL),
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLineHeight(-1), fAscent(-1), fWidth(-1), fHeight(-1), fParagraphLevel(UBIDI_DEFAULT_LTR)
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const LEUnicode separators[] = {CH_LF, CH_CR, CH_LSEP, CH_PSEP, 0x0000};
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (LE_FAILURE(status)) {
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		return;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 ascent  = 0;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 descent = 0;
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 leading = 0;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	LocaleRuns *locales = NULL;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FontRuns fr(0);
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLines = LE_NEW_ARRAY(const ParagraphLayout::Line *, fLinesMax);
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fParagraphLayout = LE_NEW_ARRAY(ParagraphLayout *, fParagraphMax);
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fChars = LE_NEW_ARRAY(LEUnicode, charCount + 1);
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_ARRAY_COPY(fChars, chars, charCount);
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fChars[charCount] = 0;
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEUnicode *pStart = &fChars[0];
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (*pStart != 0) {
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        LEUnicode *pEnd = u_strpbrk(pStart, separators);
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_int32 pAscent, pDescent, pLeading;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ParagraphLayout *paragraphLayout = NULL;
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pEnd == NULL) {
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pEnd = &fChars[charCount];
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pEnd != pStart) {
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            subsetFontRuns(fontRuns, pStart - fChars, pEnd - fChars, &fr);
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            paragraphLayout = new ParagraphLayout(pStart, pEnd - pStart, &fr, NULL, NULL, locales, fParagraphLevel, FALSE, status);
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (LE_FAILURE(status)) {
124c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                delete paragraphLayout;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break; // return? something else?
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (fParagraphLevel == UBIDI_DEFAULT_LTR) {
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fParagraphLevel = paragraphLayout->getParagraphLevel();
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pAscent  = paragraphLayout->getAscent();
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pDescent = paragraphLayout->getDescent();
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pLeading = paragraphLayout->getLeading();
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pAscent > ascent) {
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ascent = pAscent;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pDescent > descent) {
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                descent = pDescent;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pLeading > leading) {
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                leading = pLeading;
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fParagraphCount >= fParagraphMax) {
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fParagraphLayout = (ParagraphLayout **) LE_GROW_ARRAY(fParagraphLayout, fParagraphMax + fParagraphGrow);
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fParagraphMax += fParagraphGrow;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fParagraphLayout[fParagraphCount++] = paragraphLayout;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*pEnd == 0) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pStart = skipLineEnd(pEnd);
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLineHeight = ascent + descent + leading;
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fAscent     = ascent;
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruParagraph::~Paragraph()
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 line = 0; line < fLineCount; line += 1) {
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete /*(LineInfo *)*/ fLines[line];
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
173c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    for (le_int32 paragraph = 0; paragraph < fParagraphCount; paragraph += 1) {
174c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete fParagraphLayout[paragraph];
175c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
176c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_DELETE_ARRAY(fLines);
178c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LE_DELETE_ARRAY(fParagraphLayout);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_DELETE_ARRAY(fChars);
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Paragraph::addLine(const ParagraphLayout::Line *line)
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fLineCount >= fLinesMax) {
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fLines = (const ParagraphLayout::Line **) LE_GROW_ARRAY(fLines, fLinesMax + fLinesGrow);
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fLinesMax += fLinesGrow;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLines[fLineCount++] = line;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Paragraph::breakLines(le_int32 width, le_int32 height)
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fHeight = height;
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // don't re-break if the width hasn't changed
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fWidth == width) {
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fWidth  = width;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    float lineWidth = (float) (width - 2 * MARGIN);
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const ParagraphLayout::Line *line;
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Free the old LineInfo's...
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 li = 0; li < fLineCount; li += 1) {
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete fLines[li];
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLineCount = 0;
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (le_int32 p = 0; p < fParagraphCount; p += 1) {
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ParagraphLayout *paragraphLayout = fParagraphLayout[p];
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (paragraphLayout != NULL) {
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            paragraphLayout->reflow();
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while ((line = paragraphLayout->nextLine(lineWidth)) != NULL) {
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                addLine(line);
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            addLine(NULL);
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Paragraph::draw(RenderingSurface *surface, le_int32 firstLine, le_int32 lastLine)
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 li, x, y;
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    x = MARGIN;
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    y = fAscent;
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (li = firstLine; li <= lastLine; li += 1) {
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const ParagraphLayout::Line *line = fLines[li];
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (line != NULL) {
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 runCount = line->countRuns();
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 run;
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		    if (fParagraphLevel == UBIDI_RTL) {
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			    le_int32 lastX = line->getWidth();
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru			    x = (fWidth - lastX - MARGIN);
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		    }
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (run = 0; run < runCount; run += 1) {
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const ParagraphLayout::VisualRun *visualRun = line->getVisualRun(run);
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                le_int32 glyphCount = visualRun->getGlyphCount();
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const LEFontInstance *font = visualRun->getFont();
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const LEGlyphID *glyphs = visualRun->getGlyphs();
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const float *positions = visualRun->getPositions();
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                surface->drawGlyphs(font, glyphs, glyphCount, positions, x, y, fWidth, fHeight);
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        y += fLineHeight;
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruParagraph *Paragraph::paragraphFactory(const char *fileName, const LEFontInstance *font, GUISupport *guiSupport)
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEErrorCode status  = LE_NO_ERROR;
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 charCount;
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *text = UnicodeReader::readFile(fileName, guiSupport, charCount);
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Paragraph *result = NULL;
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (text == NULL) {
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FontRuns  fontRuns(0);
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fontRuns.add(font, charCount);
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = new Paragraph(text, charCount, &fontRuns, status);
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (LE_FAILURE(status)) {
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		delete result;
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		result = NULL;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LE_DELETE_ARRAY(text);
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
290