util/src/gui/text/qtextengine_p.h
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    77 QT_BEGIN_NAMESPACE
       
    78 
       
    79 class QFontPrivate;
       
    80 class QFontEngine;
       
    81 
       
    82 class QString;
       
    83 class QPainter;
       
    84 
       
    85 class 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
       
    93 struct 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     inline bool isValid() const {return x != 100000 && y != 100000;}
       
   114 };
       
   115 Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE);
       
   116 
       
   117 struct Q_AUTOTEST_EXPORT QScriptAnalysis
       
   118 {
       
   119     enum Flags {
       
   120         None = 0,
       
   121         Lowercase = 1,
       
   122         Uppercase = 2,
       
   123         SmallCaps = 3,
       
   124         LineOrParagraphSeparator = 4,
       
   125         Space = 5,
       
   126         SpaceTabOrObject = Space,
       
   127         Tab = 6,
       
   128         TabOrObject = Tab,
       
   129         Object = 7
       
   130     };
       
   131     unsigned short script    : 8;
       
   132     unsigned short bidiLevel : 6;  // Unicode Bidi algorithm embedding level (0-61)
       
   133     unsigned short flags     : 3;
       
   134     inline bool operator == (const QScriptAnalysis &other) const {
       
   135         return script == other.script && bidiLevel == other.bidiLevel && flags == other.flags;
       
   136     }
       
   137 };
       
   138 Q_DECLARE_TYPEINFO(QScriptAnalysis, Q_PRIMITIVE_TYPE);
       
   139 
       
   140 struct QGlyphJustification
       
   141 {
       
   142     inline QGlyphJustification()
       
   143         : type(0), nKashidas(0), space_18d6(0)
       
   144     {}
       
   145 
       
   146     enum JustificationType {
       
   147         JustifyNone,
       
   148         JustifySpace,
       
   149         JustifyKashida
       
   150     };
       
   151 
       
   152     uint type :2;
       
   153     uint nKashidas : 6; // more do not make sense...
       
   154     uint space_18d6 : 24;
       
   155 };
       
   156 Q_DECLARE_TYPEINFO(QGlyphJustification, Q_PRIMITIVE_TYPE);
       
   157 
       
   158 struct QGlyphLayoutInstance
       
   159 {
       
   160     QFixedPoint offset;
       
   161     QFixedPoint advance;
       
   162     HB_Glyph glyph;
       
   163     QGlyphJustification justification;
       
   164     HB_GlyphAttributes attributes;
       
   165 };
       
   166 
       
   167 struct QGlyphLayout
       
   168 {
       
   169     // init to 0 not needed, done when shaping
       
   170     QFixedPoint *offsets; // 8 bytes per element
       
   171     HB_Glyph *glyphs; // 4 bytes per element
       
   172     QFixed *advances_x; // 4 bytes per element
       
   173     QFixed *advances_y; // 4 bytes per element
       
   174     QGlyphJustification *justifications; // 4 bytes per element
       
   175     HB_GlyphAttributes *attributes; // 2 bytes per element
       
   176 
       
   177     int numGlyphs;
       
   178 
       
   179     inline QGlyphLayout() : numGlyphs(0) {}
       
   180 
       
   181     inline explicit QGlyphLayout(char *address, int totalGlyphs)
       
   182     {
       
   183         offsets = reinterpret_cast<QFixedPoint *>(address);
       
   184         int offset = totalGlyphs * sizeof(HB_FixedPoint);
       
   185         glyphs = reinterpret_cast<HB_Glyph *>(address + offset);
       
   186         offset += totalGlyphs * sizeof(HB_Glyph);
       
   187         advances_x = reinterpret_cast<QFixed *>(address + offset);
       
   188         offset += totalGlyphs * sizeof(QFixed);
       
   189         advances_y = reinterpret_cast<QFixed *>(address + offset);
       
   190         offset += totalGlyphs * sizeof(QFixed);
       
   191         justifications = reinterpret_cast<QGlyphJustification *>(address + offset);
       
   192         offset += totalGlyphs * sizeof(QGlyphJustification);
       
   193         attributes = reinterpret_cast<HB_GlyphAttributes *>(address + offset);
       
   194         numGlyphs = totalGlyphs;
       
   195     }
       
   196 
       
   197     inline QGlyphLayout mid(int position, int n = -1) const {
       
   198         QGlyphLayout copy = *this;
       
   199         copy.glyphs += position;
       
   200         copy.advances_x += position;
       
   201         copy.advances_y += position;
       
   202         copy.offsets += position;
       
   203         copy.justifications += position;
       
   204         copy.attributes += position;
       
   205         if (n == -1)
       
   206             copy.numGlyphs -= position;
       
   207         else
       
   208             copy.numGlyphs = n;
       
   209         return copy;
       
   210     }
       
   211 
       
   212     static inline int spaceNeededForGlyphLayout(int totalGlyphs) {
       
   213         return totalGlyphs * (sizeof(HB_Glyph) + sizeof(HB_GlyphAttributes)
       
   214                 + sizeof(QFixed) + sizeof(QFixed) + sizeof(QFixedPoint)
       
   215                 + sizeof(QGlyphJustification));
       
   216     }
       
   217 
       
   218     inline QFixed effectiveAdvance(int item) const
       
   219     { return (advances_x[item] + QFixed::fromFixed(justifications[item].space_18d6)) * !attributes[item].dontPrint; }
       
   220 
       
   221     inline QGlyphLayoutInstance instance(int position) const {
       
   222         QGlyphLayoutInstance g;
       
   223         g.offset.x = offsets[position].x;
       
   224         g.offset.y = offsets[position].y;
       
   225         g.glyph = glyphs[position];
       
   226         g.advance.x = advances_x[position];
       
   227         g.advance.y = advances_y[position];
       
   228         g.justification = justifications[position];
       
   229         g.attributes = attributes[position];
       
   230         return g;
       
   231     }
       
   232 
       
   233     inline void setInstance(int position, const QGlyphLayoutInstance &g) {
       
   234         offsets[position].x = g.offset.x;
       
   235         offsets[position].y = g.offset.y;
       
   236         glyphs[position] = g.glyph;
       
   237         advances_x[position] = g.advance.x;
       
   238         advances_y[position] = g.advance.y;
       
   239         justifications[position] = g.justification;
       
   240         attributes[position] = g.attributes;
       
   241     }
       
   242 
       
   243     inline void clear(int first = 0, int last = -1) {
       
   244         if (last == -1)
       
   245             last = numGlyphs;
       
   246         if (first == 0 && last == numGlyphs
       
   247             && reinterpret_cast<char *>(offsets + numGlyphs) == reinterpret_cast<char *>(glyphs)) {
       
   248             memset(offsets, 0, spaceNeededForGlyphLayout(numGlyphs));
       
   249         } else {
       
   250             const int num = last - first;
       
   251             memset(offsets + first, 0, num * sizeof(QFixedPoint));
       
   252             memset(glyphs + first, 0, num * sizeof(HB_Glyph));
       
   253             memset(advances_x + first, 0, num * sizeof(QFixed));
       
   254             memset(advances_y + first, 0, num * sizeof(QFixed));
       
   255             memset(justifications + first, 0, num * sizeof(QGlyphJustification));
       
   256             memset(attributes + first, 0, num * sizeof(HB_GlyphAttributes));
       
   257         }
       
   258     }
       
   259 
       
   260     inline char *data() {
       
   261         return reinterpret_cast<char *>(offsets);
       
   262     }
       
   263 
       
   264     void grow(char *address, int totalGlyphs);
       
   265 };
       
   266 
       
   267 class QVarLengthGlyphLayoutArray : private QVarLengthArray<void *>, public QGlyphLayout
       
   268 {
       
   269 private:
       
   270     typedef QVarLengthArray<void *> Array;
       
   271 public:
       
   272     QVarLengthGlyphLayoutArray(int totalGlyphs)
       
   273         : Array(spaceNeededForGlyphLayout(totalGlyphs) / sizeof(void *) + 1)
       
   274         , QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs)
       
   275     {
       
   276         memset(Array::data(), 0, Array::size() * sizeof(void *));
       
   277     }
       
   278 
       
   279     void resize(int totalGlyphs)
       
   280     {
       
   281         Array::resize(spaceNeededForGlyphLayout(totalGlyphs) / sizeof(void *) + 1);
       
   282 
       
   283         *((QGlyphLayout *)this) = QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs);
       
   284         memset(Array::data(), 0, Array::size() * sizeof(void *));
       
   285     }
       
   286 };
       
   287 
       
   288 template <int N> struct QGlyphLayoutArray : public QGlyphLayout
       
   289 {
       
   290 public:
       
   291     QGlyphLayoutArray()
       
   292         : QGlyphLayout(reinterpret_cast<char *>(buffer), N)
       
   293     {
       
   294         memset(buffer, 0, sizeof(buffer));
       
   295     }
       
   296 
       
   297 private:
       
   298     void *buffer[(N * (sizeof(HB_Glyph) + sizeof(HB_GlyphAttributes)
       
   299                 + sizeof(QFixed) + sizeof(QFixed) + sizeof(QFixedPoint)
       
   300                 + sizeof(QGlyphJustification)))
       
   301                     / sizeof(void *) + 1];
       
   302 };
       
   303 
       
   304 struct QScriptItem;
       
   305 /// Internal QTextItem
       
   306 class QTextItemInt : public QTextItem
       
   307 {
       
   308 public:
       
   309     inline QTextItemInt()
       
   310         : justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(0),
       
   311           logClusters(0), f(0), fontEngine(0)
       
   312     {}
       
   313     QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
       
   314 
       
   315     /// copy the structure items, adjusting the glyphs arrays to the right subarrays.
       
   316     /// the width of the returned QTextItemInt is not adjusted, for speed reasons
       
   317     QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const;
       
   318 
       
   319     QFixed descent;
       
   320     QFixed ascent;
       
   321     QFixed width;
       
   322 
       
   323     RenderFlags flags;
       
   324     bool justified;
       
   325     QTextCharFormat::UnderlineStyle underlineStyle;
       
   326     const QTextCharFormat charFormat;
       
   327     int num_chars;
       
   328     const QChar *chars;
       
   329     const unsigned short *logClusters;
       
   330     const QFont *f;
       
   331 
       
   332     QGlyphLayout glyphs;
       
   333     QFontEngine *fontEngine;
       
   334 };
       
   335 
       
   336 inline bool qIsControlChar(ushort uc)
       
   337 {
       
   338     return uc >= 0x200b && uc <= 0x206f
       
   339         && (uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */
       
   340             || (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */)
       
   341             || uc >= 0x206a /* ISS, ASS, IAFS, AFS, NADS, NODS */);
       
   342 }
       
   343 
       
   344 struct Q_AUTOTEST_EXPORT QScriptItem
       
   345 {
       
   346     inline QScriptItem()
       
   347         : position(0),
       
   348           num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
       
   349           glyph_data_offset(0) {}
       
   350     inline QScriptItem(int p, const QScriptAnalysis &a)
       
   351         : position(p), analysis(a),
       
   352           num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
       
   353           glyph_data_offset(0) {}
       
   354 
       
   355     int position;
       
   356     QScriptAnalysis analysis;
       
   357     unsigned short num_glyphs;
       
   358     QFixed descent;
       
   359     QFixed ascent;
       
   360     QFixed leading;
       
   361     QFixed width;
       
   362     int glyph_data_offset;
       
   363     QFixed height() const { return ascent + descent + 1; }
       
   364 };
       
   365 
       
   366 
       
   367 Q_DECLARE_TYPEINFO(QScriptItem, Q_MOVABLE_TYPE);
       
   368 
       
   369 typedef QVector<QScriptItem> QScriptItemArray;
       
   370 
       
   371 struct Q_AUTOTEST_EXPORT QScriptLine
       
   372 {
       
   373     // created and filled in QTextLine::layout_helper
       
   374     QScriptLine()
       
   375         : from(0), length(0),
       
   376         justified(0), gridfitted(0),
       
   377         hasTrailingSpaces(0), leadingIncluded(0) {}
       
   378     QFixed descent;
       
   379     QFixed ascent;
       
   380     QFixed leading;
       
   381     QFixed x;
       
   382     QFixed y;
       
   383     QFixed width;
       
   384     QFixed textWidth;
       
   385     int from;
       
   386     signed int length : 29;
       
   387     mutable uint justified : 1;
       
   388     mutable uint gridfitted : 1;
       
   389     uint hasTrailingSpaces : 1;
       
   390     uint leadingIncluded : 1;
       
   391     QFixed height() const { return ascent + descent + 1
       
   392                             + (leadingIncluded?  qMax(QFixed(),leading) : QFixed()); }
       
   393     QFixed base() const { return ascent
       
   394                           + (leadingIncluded ? qMax(QFixed(),leading) : QFixed()); }
       
   395     void setDefaultHeight(QTextEngine *eng);
       
   396     void operator+=(const QScriptLine &other);
       
   397 };
       
   398 Q_DECLARE_TYPEINFO(QScriptLine, Q_PRIMITIVE_TYPE);
       
   399 
       
   400 
       
   401 inline void QScriptLine::operator+=(const QScriptLine &other)
       
   402 {
       
   403     leading= qMax(leading + ascent, other.leading + other.ascent) - qMax(ascent, other.ascent);
       
   404     descent = qMax(descent, other.descent);
       
   405     ascent = qMax(ascent, other.ascent);
       
   406     textWidth += other.textWidth;
       
   407     length += other.length;
       
   408 }
       
   409 
       
   410 typedef QVector<QScriptLine> QScriptLineArray;
       
   411 
       
   412 class QFontPrivate;
       
   413 class QTextFormatCollection;
       
   414 
       
   415 class Q_GUI_EXPORT QTextEngine {
       
   416 public:
       
   417     struct LayoutData {
       
   418         LayoutData(const QString &str, void **stack_memory, int mem_size);
       
   419         LayoutData();
       
   420         ~LayoutData();
       
   421         mutable QScriptItemArray items;
       
   422         int allocated;
       
   423         int available_glyphs;
       
   424         void **memory;
       
   425         unsigned short *logClustersPtr;
       
   426         QGlyphLayout glyphLayout;
       
   427         mutable int used;
       
   428         uint hasBidi : 1;
       
   429         uint inLayout : 1;
       
   430         uint memory_on_stack : 1;
       
   431         bool haveCharAttributes;
       
   432         QString string;
       
   433         void reallocate(int totalGlyphs);
       
   434     };
       
   435 
       
   436     QTextEngine(LayoutData *data);
       
   437     QTextEngine();
       
   438     QTextEngine(const QString &str, const QFont &f);
       
   439     ~QTextEngine();
       
   440 
       
   441     enum Mode {
       
   442         WidthOnly = 0x07
       
   443     };
       
   444 
       
   445     // keep in sync with QAbstractFontEngine::TextShapingFlag!!
       
   446     enum ShaperFlag {
       
   447         RightToLeft = 0x0001,
       
   448         DesignMetrics = 0x0002,
       
   449         GlyphIndicesOnly = 0x0004
       
   450     };
       
   451     Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag)
       
   452 
       
   453     void invalidate();
       
   454     void clearLineData();
       
   455 
       
   456     void validate() const;
       
   457     void itemize() const;
       
   458 
       
   459     static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder);
       
   460 
       
   461     const HB_CharAttributes *attributes() const;
       
   462 
       
   463     void shape(int item) const;
       
   464 
       
   465     void justify(const QScriptLine &si);
       
   466 
       
   467     QFixed width(int charFrom, int numChars) const;
       
   468     glyph_metrics_t boundingBox(int from,  int len) const;
       
   469     glyph_metrics_t tightBoundingBox(int from,  int len) const;
       
   470 
       
   471     int length(int item) const {
       
   472         const QScriptItem &si = layoutData->items[item];
       
   473         int from = si.position;
       
   474         item++;
       
   475         return (item < layoutData->items.size() ? layoutData->items[item].position : layoutData->string.length()) - from;
       
   476     }
       
   477     int length(const QScriptItem *si) const {
       
   478         int end;
       
   479         if (si + 1 < layoutData->items.constData()+ layoutData->items.size())
       
   480             end = (si+1)->position;
       
   481         else
       
   482             end = layoutData->string.length();
       
   483         return end - si->position;
       
   484     }
       
   485 
       
   486     QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0, QFixed *leading = 0) const;
       
   487     QFont font(const QScriptItem &si) const;
       
   488     inline QFont font() const { return fnt; }
       
   489 
       
   490     /**
       
   491      * Returns a pointer to an array of log clusters, offset at the script item.
       
   492      * Each item in the array is a unsigned short.  For each character in the original string there is an entry in the table
       
   493      * so there is a one to one correlation in indexes between the original text and the index in the logcluster.
       
   494      * The value of each item is the position in the glyphs array. Multiple similar pointers in the logclusters array imply
       
   495      * that one glyph is used for more than one character.
       
   496      * \sa glyphs()
       
   497      */
       
   498     inline unsigned short *logClusters(const QScriptItem *si) const
       
   499         { return layoutData->logClustersPtr+si->position; }
       
   500     /**
       
   501      * Returns an array of QGlyphLayout items, offset at the script item.
       
   502      * Each item in the array matches one glyph in the text, storing the advance, position etc.
       
   503      * The returned item's length equals to the number of available glyphs. This may be more
       
   504      * than what was actually shaped.
       
   505      * \sa logClusters()
       
   506      */
       
   507     inline QGlyphLayout availableGlyphs(const QScriptItem *si) const {
       
   508         return layoutData->glyphLayout.mid(si->glyph_data_offset);
       
   509     }
       
   510     /**
       
   511      * Returns an array of QGlyphLayout items, offset at the script item.
       
   512      * Each item in the array matches one glyph in the text, storing the advance, position etc.
       
   513      * The returned item's length equals to the number of shaped glyphs.
       
   514      * \sa logClusters()
       
   515      */
       
   516     inline QGlyphLayout shapedGlyphs(const QScriptItem *si) const {
       
   517         return layoutData->glyphLayout.mid(si->glyph_data_offset, si->num_glyphs);
       
   518     }
       
   519 
       
   520     inline void ensureSpace(int nGlyphs) const {
       
   521         if (layoutData->glyphLayout.numGlyphs - layoutData->used < nGlyphs)
       
   522             layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4);
       
   523     }
       
   524 
       
   525     void freeMemory();
       
   526 
       
   527     int findItem(int strPos) const;
       
   528     inline QTextFormatCollection *formats() const {
       
   529 #ifdef QT_BUILD_COMPAT_LIB
       
   530         return 0; // Compat should never reference this symbol
       
   531 #else
       
   532         return block.docHandle()->formatCollection();
       
   533 #endif
       
   534     }
       
   535     QTextCharFormat format(const QScriptItem *si) const;
       
   536     inline QAbstractTextDocumentLayout *docLayout() const {
       
   537 #ifdef QT_BUILD_COMPAT_LIB
       
   538         return 0; // Compat should never reference this symbol
       
   539 #else
       
   540         return block.docHandle()->document()->documentLayout();
       
   541 #endif
       
   542     }
       
   543     int formatIndex(const QScriptItem *si) const;
       
   544 
       
   545     /// returns the width of tab at index (in the tabs array) with the tab-start at position x
       
   546     QFixed calculateTabWidth(int index, QFixed x) const;
       
   547 
       
   548     mutable QScriptLineArray lines;
       
   549 
       
   550     QString text;
       
   551     QFont fnt;
       
   552     QTextBlock block;
       
   553 
       
   554     QTextOption option;
       
   555 
       
   556     QFixed minWidth;
       
   557     QFixed maxWidth;
       
   558     QPointF position;
       
   559     uint ignoreBidi : 1;
       
   560     uint cacheGlyphs : 1;
       
   561     uint stackEngine : 1;
       
   562     uint forceJustification : 1;
       
   563 
       
   564     int *underlinePositions;
       
   565 
       
   566     mutable LayoutData *layoutData;
       
   567 
       
   568     inline bool hasFormats() const { return (block.docHandle() || specialData); }
       
   569 
       
   570     struct SpecialData {
       
   571         int preeditPosition;
       
   572         QString preeditText;
       
   573         QList<QTextLayout::FormatRange> addFormats;
       
   574         QVector<int> addFormatIndices;
       
   575         QVector<int> resolvedFormatIndices;
       
   576     };
       
   577     SpecialData *specialData;
       
   578 
       
   579     bool atWordSeparator(int position) const;
       
   580     bool atSpace(int position) const;
       
   581     void indexAdditionalFormats();
       
   582 
       
   583     QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0) const;
       
   584 
       
   585     void shapeLine(const QScriptLine &line);
       
   586 
       
   587 private:
       
   588     void setBoundary(int strPos) const;
       
   589     void addRequiredBoundaries() const;
       
   590     void shapeText(int item) const;
       
   591     void shapeTextWithHarfbuzz(int item) const;
       
   592 #if defined(Q_WS_WINCE)
       
   593     void shapeTextWithCE(int item) const;
       
   594 #endif
       
   595 #if defined(Q_WS_MAC)
       
   596     void shapeTextMac(int item) const;
       
   597 #endif
       
   598     void splitItem(int item, int pos) const;
       
   599 
       
   600     void resolveAdditionalFormats() const;
       
   601 };
       
   602 
       
   603 class QStackTextEngine : public QTextEngine {
       
   604 public:
       
   605     enum { MemSize = 256*40/sizeof(void *) };
       
   606     QStackTextEngine(const QString &string, const QFont &f);
       
   607     LayoutData _layoutData;
       
   608     void *_memory[MemSize];
       
   609 };
       
   610 
       
   611 
       
   612 Q_DECLARE_OPERATORS_FOR_FLAGS(QTextEngine::ShaperFlags)
       
   613 
       
   614 QT_END_NAMESPACE
       
   615 
       
   616 #endif // QTEXTENGINE_P_H