⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtextdocumentlayout.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qtextdocumentlayout_p.h"#include "qtextimagehandler_p.h"#include "qtexttable.h"#include "qtextlist.h"#include "qabstracttextdocumentlayout_p.h"#include <qpainter.h>#include <qrect.h>#include <qpalette.h>#include <qdebug.h>#include <qvarlengtharray.h>#include <limits.h>#include <qstyle.h>#include <qbasictimer.h>// #define LAYOUT_DEBUG#ifdef LAYOUT_DEBUG#define LDEBUG qDebug()#define INC_INDENT debug_indent += "  "#define DEC_INDENT debug_indent = debug_indent.left(debug_indent.length()-2)#else#define LDEBUG if(0) qDebug()#define INC_INDENT do {} while(0)#define DEC_INDENT do {} while(0)#endif// ################ should probably add frameFormatChange notification!struct QLayoutStruct;class QTextFrameData : public QTextFrameLayoutData{public:    QTextFrameData()        : minimumWidth(0), maximumWidth(INT_MAX), currentLayoutStruct(0),          sizeDirty(true), layoutDirty(true)        {}    // relative to parent frame    QPointF position;    QSizeF size;    // contents starts at (margin+border/margin+border)    qreal margin;    qreal border;    qreal padding;    // contents width includes padding (as we need to treat this on a per cell basis for tables)    qreal contentsWidth;    qreal contentsHeight;    qreal minimumWidth;    qreal maximumWidth;    QTextFrameFormat::Position flow_position;    QLayoutStruct *currentLayoutStruct;    bool sizeDirty;    bool layoutDirty;    QList<QPointer<QTextFrame> > floats;};struct QLayoutStruct {    QLayoutStruct() : contentsWidth(0), minimumWidth(0), maximumWidth(INT_MAX),                      fullLayout(false), pageHeight(0.0),                      pageBottom(0.0), pageMargin(0.0)    {}    QTextFrame *frame;    qreal x_left;    qreal x_right;    qreal y;    qreal contentsWidth;    qreal minimumWidth;    qreal maximumWidth;    bool fullLayout;    QList<QTextFrame *> pendingFloats;    qreal pageHeight;    qreal pageBottom;    qreal pageMargin;    QRectF updateRect;    inline void newPage()    { pageBottom += pageHeight; y = pageBottom - pageHeight + 2 * pageMargin; }};class QTextTableData : public QTextFrameData{public:    inline QTextTableData() : cellSpacing(0), cellPadding(0) {}    qreal cellSpacing, cellPadding;    QVector<qreal> minWidths;    QVector<qreal> maxWidths;    QVector<qreal> widths;    QVector<qreal> heights;    QVector<qreal> columnPositions;    QVector<qreal> rowPositions;    // rows that appear at the top of a page after a page break    QVector<int> rowPageBreaks;    QVector<qreal> rowPositionsBeforePageBreak;    inline qreal cellWidth(int column, int colspan) const    { return columnPositions.at(column + colspan - 1) + widths.at(column + colspan - 1)             - columnPositions.at(column) - 2 * cellPadding; }    inline void calcRowPosition(int row)    {        if (row > 0)            rowPositions[row] = rowPositions.at(row - 1) + heights.at(row - 1) + border + cellSpacing + border;    }    QRectF cellRect(const QTextTableCell &cell) const;    inline QPointF cellPosition(int row, int col) const    { return QPointF(columnPositions.at(col) + cellPadding, rowPositions.at(row) + cellPadding); }    inline QPointF cellPosition(const QTextTableCell &cell) const    { return cellPosition(cell.row(), cell.column()); }    void updateSize();};static QTextFrameData *createData(QTextFrame *f){    QTextFrameData *data;    if (qobject_cast<QTextTable *>(f))        data = new QTextTableData;    else        data = new QTextFrameData;    f->setLayoutData(data);    return data;}static inline QTextFrameData *data(QTextFrame *f){    QTextFrameData *data = static_cast<QTextFrameData *>(f->layoutData());    if (!data)        data = createData(f);    return data;}void QTextTableData::updateSize(){    const qreal effectiveMargin = this->margin + border + padding;    qreal height = contentsHeight == -1                   ? rowPositions.last() + heights.last() + padding + border + cellSpacing + effectiveMargin                   : contentsHeight + 2*effectiveMargin;    size = QSizeF(contentsWidth + 2*effectiveMargin, height);}QRectF QTextTableData::cellRect(const QTextTableCell &cell) const{    const int row = cell.row();    const int rowSpan = cell.rowSpan();    const int column = cell.column();    const int colSpan = cell.columnSpan();    return QRectF(columnPositions.at(column),                  rowPositions.at(row),                  columnPositions.at(column + colSpan - 1) + widths.at(column + colSpan - 1) - columnPositions.at(column),                  rowPositions.at(row + rowSpan - 1) + heights.at(row + rowSpan - 1) - rowPositions.at(row));}static inline bool isEmptyBlockBeforeTable(const QTextBlock &block, const QTextFrame::Iterator &nextIt){    return !nextIt.atEnd()           && qobject_cast<QTextTable *>(nextIt.currentFrame())           && block.isValid()           && block.length() == 1           && !block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)           && nextIt.currentFrame()->firstPosition() == block.position() + 1           ;}static inline bool isEmptyBlockBeforeTable(QTextFrame::Iterator it){    QTextFrame::Iterator next = it; ++next;    return it.currentFrame() == 0           && isEmptyBlockBeforeTable(it.currentBlock(), next);}static inline bool isEmptyBlockAfterTable(const QTextBlock &block, const QTextFrame *lastFrame){    return qobject_cast<const QTextTable *>(lastFrame)           && block.isValid()           && block.length() == 1           && lastFrame->lastPosition() == block.position() - 1           ;}/*Optimisation strategies:HTML layout:* Distinguish between normal and special flow. For normal flow the condition:  y1 > y2 holds for all blocks with b1.key() > b2.key().* Special flow is: floats, table cells* Normal flow within table cells. Tables (not cells) are part of the normal flow.* If blocks grows/shrinks in height and extends over whole page width at the end, move following blocks.* If height doesn't change, no need to do anythingTable cells:* If minWidth of cell changes, recalculate table width, relayout if needed.* What about maxWidth when doing auto layout?Floats:* need fixed or proportional width, otherwise don't float!* On width/height change relayout surrounding paragraphs.Document width change:* full relayout neededFloat handling:* Floats are specified by a special format object.* currently only floating images are implemented.*//*   On the table layouting:   +---[ table border ]-------------------------   |      [ cell spacing ]   |  +------[ cell border ]-----+  +--------   |  |                          |  |   |  |   |  |   |  |   |   rowPositions[i] and columnPositions[i] point at the cell content   position. So for example the left border is drawn at   x = columnPositions[i] - fd->border and similar for y.*/enum {    TextIndentValue = 40};struct QCheckPoint{    qreal y;    int positionInFrame;    qreal minimumWidth;    qreal maximumWidth;    qreal contentsWidth;};Q_DECLARE_TYPEINFO(QCheckPoint, Q_PRIMITIVE_TYPE);static bool operator<(const QCheckPoint &checkPoint, qreal y){    return checkPoint.y < y;}static bool operator<(const QCheckPoint &checkPoint, int pos){    return checkPoint.positionInFrame < pos;}class QTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate{    Q_DECLARE_PUBLIC(QTextDocumentLayout)public:#if 0    struct Page {        QTextBlock first;        QTextBlock last;    };    QList<Page> pages;#endif    QTextDocumentLayoutPrivate()        : blockTextFlags(0), wordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere),          fixedColumnWidth(-1),          tabStopWidth(80), // same default as in qtextengine.cpp          currentLazyLayoutPosition(-1),          lazyLayoutStepSize(1000),          showLayoutProgress(true)    { }    bool pagedLayout;    int blockTextFlags;    QTextOption::WrapMode wordWrapMode;#ifdef LAYOUT_DEBUG    mutable QString debug_indent;#endif    int fixedColumnWidth;    qreal tabStopWidth;    mutable int currentLazyLayoutPosition;    mutable int lazyLayoutStepSize;    QBasicTimer layoutTimer;    mutable QBasicTimer sizeChangedTimer;    bool showLayoutProgress;    qreal indent(QTextBlock bl) const;    void drawFrame(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,                   QTextFrame *f) const;    void drawFlow(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,                  QTextFrame::Iterator it, QTextBlock *cursorBlockNeedingRepaint) const;    void drawBlock(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,                   QTextBlock bl) const;    void drawListItem(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,                      QTextBlock bl, const QTextCharFormat *selectionFormat) const;    enum HitPoint {        PointBefore,        PointAfter,        PointInside,        PointExact    };    HitPoint hitTest(QTextFrame *frame, const QPointF &point, int *position, QTextLayout **l) const;    HitPoint hitTest(QTextFrame::Iterator it, HitPoint hit, const QPointF &p,                      int *position, QTextLayout **l) const;    HitPoint hitTest(QTextTable *table, const QPointF &point, int *position, QTextLayout **l) const;    HitPoint hitTest(QTextBlock bl, const QPointF &point, int *position, QTextLayout **l) const;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -