]> git.saurik.com Git - apple/icu.git/blob - icuSources/samples/layout/paragraph.cpp
ICU-6.2.8.tar.gz
[apple/icu.git] / icuSources / samples / layout / paragraph.cpp
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1999-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 * file name: Paragraph.cpp
9 *
10 * created on: 09/06/2000
11 * created by: Eric R. Mader
12 */
13
14 #include "unicode/utypes.h"
15 #include "unicode/uchar.h"
16 #include "unicode/ubidi.h"
17
18 #include "layout/ParagraphLayout.h"
19
20 #include "RenderingSurface.h"
21 #include "ScriptCompositeFontInstance.h"
22
23 #include "paragraph.h"
24 #include "UnicodeReader.h"
25 #include "FontMap.h"
26
27 #define MARGIN 10
28 #define LINE_GROW 32
29
30 Paragraph::Paragraph(const LEUnicode chars[], int32_t charCount, const FontRuns *fontRuns, LEErrorCode &status)
31 : fParagraphLayout(NULL), fLineCount(0), fLinesMax(0), fLinesGrow(LINE_GROW), fLines(NULL), fChars(NULL),
32 fLineHeight(-1), fAscent(-1), fWidth(-1), fHeight(-1)
33 {
34 if (LE_FAILURE(status)) {
35 return;
36 }
37
38 LocaleRuns *locales = NULL;
39
40 fChars = LE_NEW_ARRAY(LEUnicode, charCount);
41 LE_ARRAY_COPY(fChars, chars, charCount);
42
43 fParagraphLayout = new ParagraphLayout(fChars, charCount, fontRuns, NULL, NULL, locales, UBIDI_DEFAULT_LTR, FALSE, status);
44
45 if (LE_FAILURE(status)) {
46 return;
47 }
48
49 le_int32 ascent = fParagraphLayout->getAscent();
50 le_int32 descent = fParagraphLayout->getDescent();
51 le_int32 leading = fParagraphLayout->getLeading();
52
53 fLineHeight = ascent + descent + leading;
54 fAscent = ascent;
55 }
56
57 Paragraph::~Paragraph()
58 {
59 for (le_int32 line = 0; line < fLineCount; line += 1) {
60 delete /*(LineInfo *)*/ fLines[line];
61 }
62
63 LE_DELETE_ARRAY(fLines);
64 delete fParagraphLayout;
65 LE_DELETE_ARRAY(fChars);
66 }
67
68 void Paragraph::breakLines(le_int32 width, le_int32 height)
69 {
70 fHeight = height;
71
72 // don't re-break if the width hasn't changed
73 if (fWidth == width) {
74 return;
75 }
76
77 fWidth = width;
78
79 float lineWidth = (float) (width - 2 * MARGIN);
80 const ParagraphLayout::Line *line;
81 le_int32 li;
82
83 // Free the old LineInfo's...
84 for (li = 0; li < fLineCount; li += 1) {
85 delete fLines[li];
86 }
87
88 li = 0;
89 fParagraphLayout->reflow();
90 while ((line = fParagraphLayout->nextLine(lineWidth)) != NULL) {
91 // grow the line array, if we need to.
92 if (li >= fLinesMax) {
93 fLines = (const ParagraphLayout::Line **) LE_GROW_ARRAY(fLines, fLinesMax + fLinesGrow);
94 fLinesMax += fLinesGrow;
95 }
96
97 fLines[li++] = line;
98 }
99
100 fLineCount = li;
101 }
102
103 void Paragraph::draw(RenderingSurface *surface, le_int32 firstLine, le_int32 lastLine)
104 {
105 le_int32 li, x, y;
106
107 x = MARGIN;
108 y = fAscent;
109
110 for (li = firstLine; li <= lastLine; li += 1) {
111 const ParagraphLayout::Line *line = fLines[li];
112 le_int32 runCount = line->countRuns();
113 le_int32 run;
114
115 if (fParagraphLayout->getParagraphLevel() == UBIDI_RTL) {
116 le_int32 lastX = line->getWidth();
117
118 x = (fWidth - lastX - MARGIN);
119 }
120
121
122 for (run = 0; run < runCount; run += 1) {
123 const ParagraphLayout::VisualRun *visualRun = line->getVisualRun(run);
124 le_int32 glyphCount = visualRun->getGlyphCount();
125 const LEFontInstance *font = visualRun->getFont();
126 const LEGlyphID *glyphs = visualRun->getGlyphs();
127 const float *positions = visualRun->getPositions();
128
129 surface->drawGlyphs(font, glyphs, glyphCount, positions, x, y, fWidth, fHeight);
130 }
131
132 y += fLineHeight;
133 }
134 }
135
136 Paragraph *Paragraph::paragraphFactory(const char *fileName, const LEFontInstance *font, GUISupport *guiSupport)
137 {
138 LEErrorCode status = LE_NO_ERROR;
139 le_int32 charCount;
140 const UChar *text = UnicodeReader::readFile(fileName, guiSupport, charCount);
141 Paragraph *result = NULL;
142
143 if (text == NULL) {
144 return NULL;
145 }
146
147 FontRuns fontRuns(0);
148
149 fontRuns.add(font, charCount);
150
151 result = new Paragraph(text, charCount, &fontRuns, status);
152
153 if (LE_FAILURE(status)) {
154 delete result;
155 result = NULL;
156 }
157
158 LE_DELETE_ARRAY(text);
159
160 return result;
161 }
162