source: trunk/src/gui/text/qtextengine_p.h@ 135

Last change on this file since 135 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 19.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QTEXTENGINE_P_H
43#define QTEXTENGINE_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists for the convenience
50// of other Qt classes. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include "QtCore/qglobal.h"
57#include "QtCore/qstring.h"
58#include "QtCore/qvarlengtharray.h"
59#include "QtCore/qnamespace.h"
60#include "QtGui/qtextlayout.h"
61#include "private/qtextformat_p.h"
62#include "private/qfont_p.h"
63#include "QtCore/qvector.h"
64#include "QtGui/qpaintengine.h"
65#include "QtGui/qtextobject.h"
66#include "QtGui/qtextoption.h"
67#include "QtCore/qset.h"
68#include "QtCore/qdebug.h"
69#ifndef QT_BUILD_COMPAT_LIB
70#include "private/qtextdocument_p.h"
71#endif
72#include "private/qharfbuzz_p.h"
73#include "private/qfixed_p.h"
74
75#include <stdlib.h>
76
77QT_BEGIN_NAMESPACE
78
79class QFontPrivate;
80class QFontEngine;
81
82class QString;
83class QPainter;
84
85class QAbstractTextDocumentLayout;
86
87
88// this uses the same coordinate system as Qt, but a different one to freetype.
89// * y is usually negative, and is equal to the ascent.
90// * negative yoff means the following stuff is drawn higher up.
91// the characters bounding rect is given by QRect(x,y,width,height), its advance by
92// xoo and yoff
93struct glyph_metrics_t
94{
95 inline glyph_metrics_t()
96 : x(100000), y(100000) {}
97 inline glyph_metrics_t(QFixed _x, QFixed _y, QFixed _width, QFixed _height, QFixed _xoff, QFixed _yoff)
98 : x(_x),
99 y(_y),
100 width(_width),
101 height(_height),
102 xoff(_xoff),
103 yoff(_yoff)
104 {}
105 QFixed x;
106 QFixed y;
107 QFixed width;
108 QFixed height;
109 QFixed xoff;
110 QFixed yoff;
111
112 glyph_metrics_t transformed(const QTransform &xform) const;
113};
114Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE);
115
116struct Q_AUTOTEST_EXPORT QScriptAnalysis
117{
118 enum Flags {
119 None = 0,
120 Lowercase = 1,
121 Uppercase = 2,
122 SmallCaps = 3,
123 LineOrParagraphSeparator = 4,
124 Space = 5,
125 SpaceTabOrObject = Space,
126 Tab = 6,
127 TabOrObject = Tab,
128 Object = 7
129 };
130 unsigned short script : 8;
131 unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
132 unsigned short flags : 3;
133 inline bool operator == (const QScriptAnalysis &other) const {
134 return script == other.script && bidiLevel == other.bidiLevel && flags == other.flags;
135 }
136};
137Q_DECLARE_TYPEINFO(QScriptAnalysis, Q_PRIMITIVE_TYPE);
138
139struct QGlyphJustification
140{
141 inline QGlyphJustification()
142 : type(0), nKashidas(0), space_18d6(0)
143 {}
144
145 enum JustificationType {
146 JustifyNone,
147 JustifySpace,
148 JustifyKashida
149 };
150
151 uint type :2;
152 uint nKashidas : 6; // more do not make sense...
153 uint space_18d6 : 24;
154};
155Q_DECLARE_TYPEINFO(QGlyphJustification, Q_PRIMITIVE_TYPE);
156
157struct QGlyphLayoutInstance
158{
159 QFixedPoint offset;
160 QFixedPoint advance;
161 HB_Glyph glyph;
162 QGlyphJustification justification;
163 HB_GlyphAttributes attributes;
164};
165
166struct QGlyphLayout
167{
168 // init to 0 not needed, done when shaping
169 QFixedPoint *offsets; // 8 bytes per element
170 HB_Glyph *glyphs; // 4 bytes per element
171 QFixed *advances_x; // 4 bytes per element
172 QFixed *advances_y; // 4 bytes per element
173 QGlyphJustification *justifications; // 4 bytes per element
174 HB_GlyphAttributes *attributes; // 2 bytes per element
175
176 int numGlyphs;
177
178 inline QGlyphLayout() : numGlyphs(0) {}
179
180 inline explicit QGlyphLayout(char *address, int totalGlyphs)
181 {
182 offsets = reinterpret_cast<QFixedPoint *>(address);
183 int offset = totalGlyphs * sizeof(HB_FixedPoint);
184 glyphs = reinterpret_cast<HB_Glyph *>(address + offset);
185 offset += totalGlyphs * sizeof(HB_Glyph);
186 advances_x = reinterpret_cast<QFixed *>(address + offset);
187 offset += totalGlyphs * sizeof(QFixed);
188 advances_y = reinterpret_cast<QFixed *>(address + offset);
189 offset += totalGlyphs * sizeof(QFixed);
190 justifications = reinterpret_cast<QGlyphJustification *>(address + offset);
191 offset += totalGlyphs * sizeof(QGlyphJustification);
192 attributes = reinterpret_cast<HB_GlyphAttributes *>(address + offset);
193 numGlyphs = totalGlyphs;
194 }
195
196 inline QGlyphLayout mid(int position, int n = -1) const {
197 QGlyphLayout copy = *this;
198 copy.glyphs += position;
199 copy.advances_x += position;
200 copy.advances_y += position;
201 copy.offsets += position;
202 copy.justifications += position;
203 copy.attributes += position;
204 if (n == -1)
205 copy.numGlyphs -= position;
206 else
207 copy.numGlyphs = n;
208 return copy;
209 }
210
211 static inline int spaceNeededForGlyphLayout(int totalGlyphs) {
212 return totalGlyphs * (sizeof(HB_Glyph) + sizeof(HB_GlyphAttributes)
213 + sizeof(QFixed) + sizeof(QFixed) + sizeof(QFixedPoint)
214 + sizeof(QGlyphJustification));
215 }
216
217 inline QFixed effectiveAdvance(int item) const
218 { return (advances_x[item] + QFixed::fromFixed(justifications[item].space_18d6)) * !attributes[item].dontPrint; }
219
220 inline QGlyphLayoutInstance instance(int position) const {
221 QGlyphLayoutInstance g;
222 g.offset.x = offsets[position].x;
223 g.offset.y = offsets[position].y;
224 g.glyph = glyphs[position];
225 g.advance.x = advances_x[position];
226 g.advance.y = advances_y[position];
227 g.justification = justifications[position];
228 g.attributes = attributes[position];
229 return g;
230 }
231
232 inline void setInstance(int position, const QGlyphLayoutInstance &g) {
233 offsets[position].x = g.offset.x;
234 offsets[position].y = g.offset.y;
235 glyphs[position] = g.glyph;
236 advances_x[position] = g.advance.x;
237 advances_y[position] = g.advance.y;
238 justifications[position] = g.justification;
239 attributes[position] = g.attributes;
240 }
241
242 inline void clear(int first = 0, int last = -1) {
243 if (last == -1)
244 last = numGlyphs;
245 if (first == 0 && last == numGlyphs
246 && reinterpret_cast<char *>(offsets + numGlyphs) == reinterpret_cast<char *>(glyphs)) {
247 memset(offsets, 0, spaceNeededForGlyphLayout(numGlyphs));
248 } else {
249 const int num = last - first;
250 memset(offsets + first, 0, num * sizeof(QFixedPoint));
251 memset(glyphs + first, 0, num * sizeof(HB_Glyph));
252 memset(advances_x + first, 0, num * sizeof(QFixed));
253 memset(advances_y + first, 0, num * sizeof(QFixed));
254 memset(justifications + first, 0, num * sizeof(QGlyphJustification));
255 memset(attributes + first, 0, num * sizeof(HB_GlyphAttributes));
256 }
257 }
258
259 inline char *data() {
260 return reinterpret_cast<char *>(offsets);
261 }
262
263 void grow(char *address, int totalGlyphs);
264};
265
266class QVarLengthGlyphLayoutArray : private QVarLengthArray<void *>, public QGlyphLayout
267{
268private:
269 typedef QVarLengthArray<void *> Array;
270public:
271 QVarLengthGlyphLayoutArray(int totalGlyphs)
272 : Array(spaceNeededForGlyphLayout(totalGlyphs) / sizeof(void *) + 1)
273 , QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs)
274 {
275 memset(Array::data(), 0, Array::size() * sizeof(void *));
276 }
277
278 void resize(int totalGlyphs)
279 {
280 Array::resize(spaceNeededForGlyphLayout(totalGlyphs) / sizeof(void *) + 1);
281
282 *((QGlyphLayout *)this) = QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs);
283 memset(Array::data(), 0, Array::size() * sizeof(void *));
284 }
285};
286
287template <int N> struct QGlyphLayoutArray : public QGlyphLayout
288{
289public:
290 QGlyphLayoutArray()
291 : QGlyphLayout(reinterpret_cast<char *>(buffer), N)
292 {
293 memset(buffer, 0, sizeof(buffer));
294 }
295
296private:
297 void *buffer[(N * (sizeof(HB_Glyph) + sizeof(HB_GlyphAttributes)
298 + sizeof(QFixed) + sizeof(QFixed) + sizeof(QFixedPoint)
299 + sizeof(QGlyphJustification)))
300 / sizeof(void *) + 1];
301};
302
303struct QScriptItem;
304/// Internal QTextItem
305class QTextItemInt : public QTextItem
306{
307public:
308 inline QTextItemInt()
309 : justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(0),
310 logClusters(0), f(0), fontEngine(0)
311 {}
312 QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
313
314 /// copy the structure items, adjusting the glyphs arrays to the right subarrays.
315 /// the width of the returned QTextItemInt is not adjusted, for speed reasons
316 QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const;
317
318 QFixed descent;
319 QFixed ascent;
320 QFixed width;
321
322 RenderFlags flags;
323 bool justified;
324 QTextCharFormat::UnderlineStyle underlineStyle;
325 const QTextCharFormat charFormat;
326 int num_chars;
327 const QChar *chars;
328 const unsigned short *logClusters;
329 const QFont *f;
330
331 QGlyphLayout glyphs;
332 QFontEngine *fontEngine;
333};
334
335inline bool qIsControlChar(ushort uc)
336{
337 return uc >= 0x200b && uc <= 0x206f
338 && (uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */
339 || (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */)
340 || uc >= 0x206a /* ISS, ASS, IAFS, AFS, NADS, NODS */);
341}
342
343struct Q_AUTOTEST_EXPORT QScriptItem
344{
345 inline QScriptItem()
346 : position(0),
347 num_glyphs(0), descent(-1), ascent(-1), width(-1),
348 glyph_data_offset(0) {}
349 inline QScriptItem(int p, const QScriptAnalysis &a)
350 : position(p), analysis(a),
351 num_glyphs(0), descent(-1), ascent(-1), width(-1),
352 glyph_data_offset(0) {}
353
354 int position;
355 QScriptAnalysis analysis;
356 unsigned short num_glyphs;
357 QFixed descent;
358 QFixed ascent;
359 QFixed width;
360 int glyph_data_offset;
361 QFixed height() const { return ascent + descent + 1; }
362};
363
364
365Q_DECLARE_TYPEINFO(QScriptItem, Q_MOVABLE_TYPE);
366
367typedef QVector<QScriptItem> QScriptItemArray;
368
369struct Q_AUTOTEST_EXPORT QScriptLine
370{
371 // created and filled in QTextLine::layout_helper
372 QScriptLine()
373 : from(0), length(0),
374 justified(0), gridfitted(0),
375 hasTrailingSpaces(0) {}
376 QFixed descent;
377 QFixed ascent;
378 QFixed x;
379 QFixed y;
380 QFixed width;
381 QFixed textWidth;
382 int from;
383 signed int length : 29;
384 mutable uint justified : 1;
385 mutable uint gridfitted : 1;
386 uint hasTrailingSpaces : 1;
387 QFixed height() const { return ascent + descent + 1; }
388 void setDefaultHeight(QTextEngine *eng);
389 void operator+=(const QScriptLine &other);
390};
391Q_DECLARE_TYPEINFO(QScriptLine, Q_PRIMITIVE_TYPE);
392