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

📄 qtextdocumentlayout.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    painter->restore();}static QFixed flowPosition(const QTextFrame::iterator it){    if (it.atEnd())        return 0;    if (it.currentFrame()) {        return data(it.currentFrame())->position.y;    } else {        QTextBlock block = it.currentBlock();        QTextLayout *layout = block.layout();        if (layout->lineCount() == 0)            return QFixed::fromReal(layout->position().y());        else            return QFixed::fromReal(layout->position().y() + layout->lineAt(0).y());    }}static QFixed firstChildPos(const QTextFrame *f){    return flowPosition(f->begin());}QLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width,                                                    int layoutFrom, int layoutTo, QTextTableData *td,                                                    QFixed absoluteTableY, bool withPageBreaks){    Q_Q(QTextDocumentLayout);    LDEBUG << "layoutCell";    QLayoutStruct layoutStruct;    layoutStruct.frame = t;    layoutStruct.minimumWidth = 0;    layoutStruct.maximumWidth = QFIXED_MAX;    layoutStruct.y = 0;    if (withPageBreaks) {        layoutStruct.frameY = absoluteTableY + td->rowPositions.at(cell.row()) + td->cellPadding;    }    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 re-laid out, even if layoutFrom/layoutTo is not in their range. Hence    // this line:    layoutStruct.pageHeight = QFixed::fromReal(q->document()->pageSize().height());    if (layoutStruct.pageHeight < 0 || !withPageBreaks)        layoutStruct.pageHeight = QFIXED_MAX;    const int currentPage = layoutStruct.currentPage();    layoutStruct.pageTopMargin = td->effectiveTopMargin + td->cellSpacing + td->border + td->cellPadding;    layoutStruct.pageBottomMargin = td->effectiveBottomMargin + td->cellSpacing + td->border + td->cellPadding;    layoutStruct.pageBottom = (currentPage + 1) * layoutStruct.pageHeight - layoutStruct.pageBottomMargin;    layoutStruct.fullLayout = true;    QFixed pageTop = currentPage * layoutStruct.pageHeight + layoutStruct.pageTopMargin - layoutStruct.frameY;    layoutStruct.y = qMax(layoutStruct.y, pageTop);    const QList<QTextFrame *> childFrames = td->childFrameMap.values(cell.row() + cell.column() * t->rows());    for (int i = 0; i < childFrames.size(); ++i) {        QTextFrame *frame = childFrames.at(i);        QTextFrameData *cd = data(frame);        cd->sizeDirty = true;    }    layoutFlow(cell.begin(), &layoutStruct, layoutFrom, layoutTo, width);    QFixed floatMinWidth;    // 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 < childFrames.size(); ++i) {        QTextFrame *frame = childFrames.at(i);        QTextFrameData *cd = data(frame);        if (frame->frameFormat().position() != QTextFrameFormat::InFlow)            layoutStruct.y = qMax(layoutStruct.y, cd->position.y + cd->size.height);        floatMinWidth = qMax(floatMinWidth, cd->minimumWidth);    }    // 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, QFixed parentY){    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();    td->childFrameMap.clear();    {        const QList<QTextFrame *> children = table->childFrames();        for (int i = 0; i < children.count(); ++i) {            QTextFrame *frame = children.at(i);            QTextTableCell cell = table->cellAt(frame->firstPosition());            td->childFrameMap.insertMulti(cell.row() + cell.column() * rows, frame);        }    }    QVector<QTextLength> columnWidthConstraints = fmt.columnWidthConstraints();    if (columnWidthConstraints.size() != columns)        columnWidthConstraints.resize(columns);    Q_ASSERT(columnWidthConstraints.count() == columns);    const QFixed cellSpacing = td->cellSpacing = QFixed::fromReal(scaleToDevice(fmt.cellSpacing()));    td->cellPadding = QFixed::fromReal(scaleToDevice(fmt.cellPadding()));    const QFixed leftMargin = td->leftMargin + td->border + td->padding;    const QFixed rightMargin = td->rightMargin + td->border + td->padding;    const QFixed topMargin = td->topMargin + td->border + td->padding;    const QFixed absoluteTableY = parentY + td->position.y;    QFixed totalWidth = 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    QFixed 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(QFIXED_MAX);    // 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, QFIXED_MAX, layoutFrom,                                                    layoutTo, td, absoluteTableY,                                                    /*withPageBreaks =*/false);            // distribute the minimum width over all columns the cell spans            QFixed widthToDistribute = layoutStruct.minimumWidth + 2 * td->cellPadding;            for (int n = 0; n < cspan; ++n) {                const int col = i + n;                QFixed w = widthToDistribute / (cspan - n);                td->minWidths[col] = qMax(td->minWidths.at(col), w);                widthToDistribute -= td->minWidths.at(col);                if (widthToDistribute <= 0)                    break;            }            QFixed maxW = td->maxWidths.at(i);            if (layoutStruct.maximumWidth != QFIXED_MAX) {                if (maxW == QFIXED_MAX)                    maxW = layoutStruct.maximumWidth + 2 * td->cellPadding;                else                    maxW = qMax(maxW, layoutStruct.maximumWidth + 2 * td->cellPadding);            }            if (maxW == QFIXED_MAX)                continue;            widthToDistribute = maxW;            for (int n = 0; n < cspan; ++n) {                const int col = i + n;                QFixed w = widthToDistribute / (cspan - n);                td->maxWidths[col] = qMax(td->minWidths.at(col), w);                widthToDistribute -= td->maxWidths.at(col);                if (widthToDistribute <= 0)                    break;            }        }    }    // set fixed values, figure out total percentages used and number of    // variable length cells. Also assign the minimum width for variable columns.    QFixed totalPercentage;    int variableCols = 0;    for (int i = 0; i < columns; ++i) {        const QTextLength &length = columnWidthConstraints.at(i);        if (length.type() == QTextLength::FixedLength) {            td->minWidths[i] = td->widths[i] = qMax(QFixed::fromReal(length.rawValue()), td->minWidths.at(i));            totalWidth -= td->widths.at(i);        } else if (length.type() == QTextLength::PercentageLength) {            totalPercentage += QFixed::fromReal(length.rawValue());        } else if (length.type() == QTextLength::VariableLength) {            variableCols++;            td->widths[i] = td->minWidths.at(i);            totalWidth -= td->minWidths.at(i);        }    }    // set percentage values    {        QFixed minimumSlack = QFIXED_MAX;        int colsWithSlack = 0;        QFixed overhangingPercent;        const QFixed totalPercentagedWidth = initialTotalWidth * totalPercentage / 100;        for (int i = 0; i < columns; ++i)            if (columnWidthConstraints.at(i).type() == QTextLength::PercentageLength) {                const QFixed allottedPercentage = QFixed::fromReal(columnWidthConstraints.at(i).rawValue());                const QFixed percentWidth = totalPercentagedWidth * allottedPercentage / totalPercentage;                if (percentWidth >= td->minWidths.at(i)) {                    td->widths[i] = percentWidth;                    if (td->widths.at(i) > td->minWidths.at(i)) {                        ++colsWithSlack;                        minimumSlack = qMin(minimumSlack, td->widths.at(i) - td->minWidths.at(i));                    }                } else {                    td->widths[i] = td->minWidths.at(i);                    QFixed effectivePercentage = td->widths.at(i) * 100 / totalPercentagedWidth;                    overhangingPercent += effectivePercentage - allottedPercentage;                }                totalWidth -= td->widths.at(i);            }        // subtract the overhanging percent from columns with slack        while (colsWithSlack > 0 && overhangingPercent > 0) {            const QFixed slackToSubtract = qMin(minimumSlack, totalPercentagedWidth * overhangingPercent / (colsWithSlack * totalPercentage));            overhangingPercent -= (slackToSubtract * colsWithSlack * 100) / totalPercentagedWidth;            minimumSlack = QFIXED_MAX;            colsWithSlack = 0;            for (int i = 0; i < columns; ++i)                if (columnWidthConstraints.at(i).type() == QTextLength::PercentageLength) {                    if (td->widths.at(i) > td->minWidths.at(i)) {                        td->widths[i] -= slackToSubtract;                        if (td->widths.at(i) > td->minWidths.at(i)) {                            ++colsWithSlack;                            minimumSlack = qMin(minimumSlack, td->widths.at(i) - td->minWidths.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) != QFIXED_MAX)                columnsWithProperMaxSize.append(i);        QFixed 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 QFixed 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 QFixed 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] = leftMargin /*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) + 2 * td->border + cellSpacing;    td->heights.resize(rows);    td->heights.fill(0);    td->rowPositions.resize(rows);    td->rowPositions[0] = topMargin /*includes table border*/ + cellSpacing + td->border;    bool haveRowSpannedCells = false;    // need to keep track of cell heights for vertical alignment    QVector<QFixed> cellHeights;    cellHeights.reserve(rows * columns);    Q_Q(QTextDocumentLayout);    QFixed pageHeight = QFixed::fromReal(q->document()->pageSize().height());    if (pageHeight <= 0)        pageHeight = QFIXED_MAX;    QVector<QFixed> heightToDistribute;    heightToDistribute.resize(columns);    td->headerHeight = 0;    const int headerRowCount = qMin(table->format().headerRowCount(), rows - 1);    const QFixed originalTopMargin = td->effectiveTopMargin;    bool hasDroppedTable = false;    // now that we have the column w

⌨️ 快捷键说明

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