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

📄 qtextdocumentlayout.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    painter->setRenderHint(QPainter::Antialiasing);    if (selectionFormat) {        painter->setPen(QPen(selectionFormat->foreground(), 0));        painter->fillRect(r, selectionFormat->background());    } else {        QBrush fg = charFormat.foreground();        if (fg == Qt::NoBrush)            fg = context.palette.text();        painter->setPen(QPen(fg, 0));    }    QBrush brush = context.palette.brush(QPalette::Text);    switch (style) {    case QTextListFormat::ListDecimal:    case QTextListFormat::ListLowerAlpha:    case QTextListFormat::ListUpperAlpha: {        QTextLayout layout(itemText, font, q->paintDevice());        layout.setCacheEnabled(true);        QTextOption option(Qt::AlignLeft | Qt::AlignAbsolute);        option.setTextDirection(dir);        layout.setTextOption(option);        layout.beginLayout();        layout.createLine();        layout.endLayout();        layout.draw(painter, QPointF(r.left(), pos.y()));        break;    }    case QTextListFormat::ListSquare:        painter->fillRect(r, brush);        break;    case QTextListFormat::ListCircle:        painter->drawEllipse(r);        break;    case QTextListFormat::ListDisc:        painter->setBrush(brush);        painter->drawEllipse(r);        painter->setBrush(Qt::NoBrush);        break;    case QTextListFormat::ListStyleUndefined:        break;    default:        break;    }    painter->restore();}static bool isFrameInCell(const QTextTableCell &cell, QTextFrame *frame){    const int cellStart = cell.firstPosition();    const int cellEnd = cell.lastPosition();    const int frameStart = frame->firstPosition();    const int frameEnd = frame->lastPosition();    return cellStart <= frameStart && cellStart <= frameEnd           && cellEnd >= frameStart && cellEnd >= frameEnd;}QLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QTextTableCell &cell, qreal width,                                                    int layoutFrom, int layoutTo){    LDEBUG << "layoutCell";    QLayoutStruct layoutStruct;    layoutStruct.frame = t;    layoutStruct.minimumWidth = 0;    layoutStruct.maximumWidth = INT_MAX;    layoutStruct.y = 0;    layoutStruct.x_left = 0;    layoutStruct.x_right = width;    // we get called with different widths all the time (for example for figuring    // out the min/max widths), so we always have to do the full layout ;(    // also when for example in a table layoutFrom/layoutTo affect only one cell,    // making that one cell grow the available width of the other cells may change    // (shrink) and therefore when layoutCell gets called for them they have to    // be relayouted, even if layoutFrom/layoutTo is not in their range. Hence    // this line:    layoutStruct.fullLayout = true;    QList<QTextFrame *> floats;    // ### speed up    // layout out child frames in that cell first    for (int i = 0; i < t->childFrames().size(); ++i){        QTextFrame *frame = t->childFrames().at(i);        if (isFrameInCell(cell, frame)) {            QTextFrameData *cd = data(frame);            cd->sizeDirty = true;                layoutFrame(frame, frame->firstPosition(), frame->lastPosition(), width, -1);            layoutStruct.minimumWidth = qMax(layoutStruct.minimumWidth, cd->minimumWidth);            layoutStruct.maximumWidth = qMin(layoutStruct.maximumWidth, cd->maximumWidth);            if (cd->flow_position != QTextFrameFormat::InFlow)                floats.append(frame);        }    }    qreal floatMinWidth = layoutStruct.minimumWidth;    layoutFlow(cell.begin(), &layoutStruct, layoutFrom, layoutTo);    // floats that are located inside the text (like inline images) aren't taken into account by    // layoutFlow with regards to the cell height (layoutStruct->y), so for a safety measure we    // do that here. For example with <td><img align="right" src="..." />blah</td>    // when the image happens to be higher than the text    for (int i = 0; i < floats.size(); ++i)        layoutStruct.y = qMax(layoutStruct.y, data(floats.at(i))->size.height());    // constraint the maximumWidth by the minimum width of the fixed size floats, to    // keep them visible    layoutStruct.maximumWidth = qMax(layoutStruct.maximumWidth, floatMinWidth);    // as floats in cells get added to the table's float list but must not affect    // floats in other cells we must clear the list here.    data(t)->floats.clear();//    qDebug() << "layoutCell done";    return layoutStruct;}QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom, int layoutTo){    LDEBUG << "layoutTable";    QTextTableData *td = static_cast<QTextTableData *>(data(table));    Q_ASSERT(td->sizeDirty);    const int rows = table->rows();    const int columns = table->columns();    const QTextTableFormat fmt = table->format();    QVector<QTextLength> columnWidthConstraints = fmt.columnWidthConstraints();    if (columnWidthConstraints.size() != columns)        columnWidthConstraints.resize(columns);    Q_ASSERT(columnWidthConstraints.count() == columns);    const qreal cellSpacing = td->cellSpacing = fmt.cellSpacing();    td->cellPadding = fmt.cellPadding();    const qreal margin = td->margin + td->border + td->padding;    qreal totalWidth = fmt.width().value(td->contentsWidth);    // two (vertical) borders per cell per column    totalWidth -= columns * 2 * td->border;    // inter-cell spacing    totalWidth -= (columns - 1) * cellSpacing;    // cell spacing at the left and right hand side    totalWidth -= 2 * cellSpacing;    // remember the width used to distribute to percentaged columns    qreal initialTotalWidth = totalWidth;    td->widths.resize(columns);    td->widths.fill(0);    td->minWidths.resize(columns);    // start with a minimum width of 0. totally empty    // cells of default created tables are invisible otherwise    // and therefore hardly editable    td->minWidths.fill(1);    td->maxWidths.resize(columns);    td->maxWidths.fill(INT_MAX);    td->rowPageBreaks.clear();    // calculate minimum and maximum sizes of the columns    for (int i = 0; i < columns; ++i) {        for (int row = 0; row < rows; ++row) {            const QTextTableCell cell = table->cellAt(row, i);            const int cspan = cell.columnSpan();            if (cspan > 1 && i != cell.column())                continue;            // to figure out the min and the max width lay out the cell at            // maximum width. otherwise the maxwidth calculation sometimes            // returns wrong values            QLayoutStruct layoutStruct = layoutCell(table, cell, INT_MAX, layoutFrom, layoutTo);            // distribute the minimum width over all columns the cell spans            qreal widthToDistribute = layoutStruct.minimumWidth + 2 * td->cellPadding;            for (int n = 0; n < cspan; ++n) {                const int col = i + n;                qreal w = widthToDistribute / (cspan - n);                td->minWidths[col] = qMax(td->minWidths.at(col), w);                widthToDistribute -= td->minWidths.at(col);                if (widthToDistribute <= 0)                    break;            }            // ### colspans            qreal maxW = td->maxWidths.at(i);            if (layoutStruct.maximumWidth != INT_MAX) {                if (maxW == INT_MAX)                    maxW = layoutStruct.maximumWidth + 2 * td->cellPadding;                else                    maxW = qMax(maxW, layoutStruct.maximumWidth + 2 * td->cellPadding);            }            td->maxWidths[i] = qMax(td->minWidths.at(i), maxW);        }    }    // set fixed values, figure out total percentages used and number of    // variable length cells. Also assign the minimum width for variable columns.    qreal totalPercentage = 0;    int variableCols = 0;    for (int i = 0; i < columns; ++i) {        const QTextLength &length = columnWidthConstraints.at(i);        if (length.type() == QTextLength::FixedLength) {            td->widths[i] = qMax(length.rawValue(), td->minWidths.at(i));            totalWidth -= td->widths.at(i);        } else if (length.type() == QTextLength::PercentageLength) {            totalPercentage += length.rawValue();        } else if (length.type() == QTextLength::VariableLength) {            variableCols++;            td->widths[i] = td->minWidths.at(i);            totalWidth -= td->minWidths.at(i);        }    }    // set percentage values    {        const qreal totalPercentagedWidth = initialTotalWidth * totalPercentage / 100;        for (int i = 0; i < columns; ++i)            if (columnWidthConstraints.at(i).type() == QTextLength::PercentageLength) {                const qreal percentWidth = totalPercentagedWidth * columnWidthConstraints.at(i).rawValue() / totalPercentage;                td->widths[i] = qMax(percentWidth, td->minWidths.at(i));                totalWidth -= td->widths.at(i);            }    }    // for variable columns distribute the remaining space    if (variableCols > 0 && totalWidth > 0) {        QVarLengthArray<int> columnsWithProperMaxSize;        for (int i = 0; i < columns; ++i)            if (columnWidthConstraints.at(i).type() == QTextLength::VariableLength                && td->maxWidths.at(i) != INT_MAX)                columnsWithProperMaxSize.append(i);        qreal lastTotalWidth = totalWidth;        while (totalWidth > 0) {            for (int k = 0; k < columnsWithProperMaxSize.count(); ++k) {                const int col = columnsWithProperMaxSize[k];                const int colsLeft = columnsWithProperMaxSize.count() - k;                const qreal w = qMin(td->maxWidths.at(col) - td->widths.at(col), totalWidth / colsLeft);                td->widths[col] += w;                totalWidth -= w;            }            if (totalWidth == lastTotalWidth)                break;            lastTotalWidth = totalWidth;        }        if (totalWidth > 0            // don't unnecessarily grow variable length sized tables            && fmt.width().type() != QTextLength::VariableLength) {            const qreal widthPerAnySizedCol = totalWidth / variableCols;            for (int col = 0; col < columns; ++col) {                if (columnWidthConstraints.at(col).type() == QTextLength::VariableLength)                    td->widths[col] += widthPerAnySizedCol;            }        }    }    td->columnPositions.resize(columns);    td->columnPositions[0] = margin /*includes table border*/ + cellSpacing + td->border;    for (int i = 1; i < columns; ++i)        td->columnPositions[i] = td->columnPositions.at(i-1) + td->widths.at(i-1) + td->border + cellSpacing + td->border;    td->heights.resize(rows);    td->heights.fill(0);    td->rowPositions.resize(rows);    td->rowPositions[0] = margin /*includes table border*/ + cellSpacing + td->border;    bool haveRowSpannedCells = false;    // now that we have the column widths we can lay out all cells with the right    // width, to calculate the row heights. we have to use two passes though, cells    // which span more than one row have to be processed later to avoid them enlarging    // other calls too much    //    // ### this could be made faster by iterating over the cells array of QTextTable    for (int r = 0; r < rows; ++r) {        td->calcRowPosition(r);        for (int c = 0; c < columns; ++c) {            QTextTableCell cell = table->cellAt(r, c);            const int rspan = cell.rowSpan();            const int cspan = cell.columnSpan();            if (cspan > 1 && cell.column() != c)                continue;            if (rspan > 1) {                haveRowSpannedCells = true;                continue;            }            const qreal width = td->cellWidth(c, cspan);//            qDebug() << "layoutCell for cell at row" << r << "col" << c;            QLayoutStruct layoutStruct = layoutCell(table, cell, width, layoutFrom, layoutTo);            td->heights[r] = qMax(td->heights.at(r), layoutStruct.y + 2 * td->cellPadding);        }    }    if (haveRowSpannedCells) {        for (int r = 0; r < rows; ++r) {            td->calcRowPosition(r);            for (int c = 0; c < columns; ++c) {                QTextTableCell cell = table->cellAt(r, c);                const int rspan = cell.rowSpan();                const int cspan = cell.columnSpan();                if (cspan > 1 && cell.column() != c)                    continue;                if (rspan == 1)                    continue;                if (cell.row() != r)                    continue;                const qreal width = td->cellWidth(c, cspan);                QLayoutStruct layoutStruct = layoutCell(table, cell, width, layoutFrom, layoutTo);                // the last row gets all the remaining space                qreal heightToDistribute = layoutStruct.y + 2 * td->cellPadding;                for (int n = 0; n < rspan - 1; ++n) {                    const int row = r + n;                    heightToDistribute -= td->heights.at(row) + td->border + cellSpacing + td->border;                    if (heightToDistribute <= 0)                        break;                }                if (heightToDistribute > 0) {                    const int lastRow = r + rspan - 1;                    td->heights[lastRow] = qMax(td->heights.at(lastRow), heightToDistribute);                }            }        }    }    // - margin to compensate the + margin in columnPositions[0]//    td->contentsWidth = qMax(td->contentsWidth,//                             td->columnPositions.last() + td->widths.last() + td->padding + td->border + cellSpacing - margin);    td->contentsWidth = td->columnPositions.last() + td->widths.last() + td->padding + td->border + cellSpacing - margin;    td->minimumWidth = td->columnPositions.at(0);    for (int i = 0; i < columns; ++i) {

⌨️ 快捷键说明

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