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

📄 qtextlayout.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// You create a text layout with a string of text. Once you laid// it out, it contains a number of QTextLines. from() returns the position// inside the text string where this line starts. If you e.g. has a// text of "This is a string", laid out into two lines (the second// starting at the word 'a'), layout.lineAt(0).from() == 0 and// layout.lineAt(1).from() == 8./*!    Returns the start of the line from the beginning of the string    passed to the QTextLayout.*/int QTextLine::textStart() const{    return eng->lines[i].from;}/*!    Returns the length of the text in the line.    \sa naturalTextWidth()*/int QTextLine::textLength() const{    return eng->lines[i].length;}static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, QTextItemInt &gf, QTextEngine *eng,                         int start, int glyph_start){    int ge = glyph_start + gf.num_glyphs;    int gs = glyph_start;    int end = start + gf.num_chars;    unsigned short *logClusters = eng->logClusters(&si);    QGlyphLayout *glyphs = eng->glyphs(&si);    QFixed orig_width = gf.width;    int *ul = eng->underlinePositions;    if (ul)        while (*ul != -1 && *ul < start)            ++ul;    bool rtl = si.analysis.bidiLevel % 2;    if (rtl)        x += si.width;    do {        int gtmp = ge;        int stmp = end;        if (ul && *ul != -1 && *ul < end) {            stmp = *ul;            gtmp = logClusters[*ul-si.position];        }        gf.num_glyphs = gtmp - gs;        gf.glyphs = glyphs + gs;        gf.num_chars = stmp - start;        gf.chars = eng->layoutData->string.unicode() + start;        QFixed w = 0;        while (gs < gtmp) {            w += (glyphs[gs].advance.x + QFixed::fromFixed(glyphs[gs].space_18d6)) * !glyphs[gs].attributes.dontPrint;            ++gs;        }        start = stmp;        gf.width = w;        if (rtl)            x -= w;        if (gf.num_chars)            p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf);        if (!rtl)            x += w;        if (ul && *ul != -1 && *ul < end) {            // draw underline            gtmp = (*ul == end-1) ? ge : logClusters[*ul+1-si.position];            ++stmp;            gf.num_glyphs = gtmp - gs;            gf.glyphs = glyphs + gs;            gf.num_chars = stmp - start;            gf.chars = eng->layoutData->string.unicode() + start;            gf.logClusters = logClusters + start - si.position;            w = 0;            while (gs < gtmp) {                w += (glyphs[gs].advance.x + QFixed::fromFixed(glyphs[gs].space_18d6)) * !glyphs[gs].attributes.dontPrint;                ++gs;            }            ++start;            gf.width = w;            gf.underlineStyle = QTextCharFormat::SingleUnderline;            if (rtl)                x -= w;            p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf);            if (!rtl)                x += w;            gf.underlineStyle = QTextCharFormat::NoUnderline;            ++gf.chars;            ++ul;        }    } while (gs < ge);    gf.width = orig_width;}static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r){    QBrush c = chf.foreground();    if (c.style() == Qt::NoBrush)        p->setPen(defaultPen);    QBrush bg = chf.background();    if (bg.style() != Qt::NoBrush)        p->fillRect(r, bg);    if (c.style() != Qt::NoBrush)        p->setPen(QPen(c, 0));}/*!    \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const    Draws a line on the given \a painter at the specified \a position.    The \a selection is reserved for internal use.*/void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const{    const QScriptLine &line = eng->lines[i];    if (!line.length) {        if (selection            && selection->start <= line.from            && selection->start + selection->length > line.from) {            p->save();            const qreal lineHeight = line.height().toReal();            QRectF r(pos.x() + line.x.toReal(), pos.y() + line.y.toReal(),                     lineHeight / 2, lineHeight);            setPenAndDrawBackground(p, QPen(), selection->format, r);            p->restore();        }        return;    }    QPen pen = p->pen();    QTextLineItemIterator iterator(eng, i, pos, selection);    const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent;    while (!iterator.atEnd()) {        QScriptItem &si = iterator.next();        if (si.isObject || si.isTab) {            if (eng->layoutData->string.at(si.position) == QChar::LineSeparator)                continue;            if (eng->hasFormats() &&                (!selection || (si.position < selection->start + selection->length                                && si.position + iterator.itemLength > selection->start))) {                p->save();                QTextCharFormat format = eng->format(&si);                if (selection)                    format.merge(selection->format);                setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - line.ascent).toReal(), iterator.itemWidth.toReal(), line.height().toReal()));                if (si.isObject && eng->block.docHandle()) {                    QFixed itemY = y - si.ascent;                    if (format.verticalAlignment() == QTextCharFormat::AlignTop) {                        itemY = y - line.ascent;                    }                    QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());                    eng->docLayout()->drawInlineObject(p, itemRect,                                                       QTextInlineObject(iterator.item, eng),                                                       si.position + eng->block.position(),                                                       format);                    if (selection) {                        QBrush bg = format.brushProperty(ObjectSelectionBrush);                        if (bg.style() != Qt::NoBrush) {                            QColor c = bg.color();                            c.setAlpha(128);                            p->fillRect(itemRect, c);                        }                    }                } else { // si.isTab                    QFont f = eng->font(si);                    QTextItemInt gf(si, &f, format);                    gf.num_glyphs = 0;                    gf.chars = 0;                    gf.num_chars = 0;                    gf.width = iterator.itemWidth;                    p->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf);                }                p->restore();            }            continue;        }        if (selection && iterator.isOutsideSelection())            continue;        unsigned short *logClusters = eng->logClusters(&si);        QGlyphLayout *glyphs = eng->glyphs(&si);        QFixed itemBaseLine = y;        QFont f = eng->font(si);        QTextCharFormat chf;        if (eng->hasFormats() || selection) {            chf = eng->format(&si);            if (selection)                chf.merge(selection->format);            setPenAndDrawBackground(p, pen, chf, QRectF(iterator.x.toReal(), (y - line.ascent).toReal(),                                                        iterator.itemWidth.toReal(), line.height().toReal()));            QTextCharFormat::VerticalAlignment valign = chf.verticalAlignment();            if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {                QFontEngine *fe = f.d->engineForScript(si.analysis.script);                QFixed height = fe->ascent() + fe->descent();                if (valign == QTextCharFormat::AlignSubScript)                    itemBaseLine += height / 6;                else if (valign == QTextCharFormat::AlignSuperScript)                    itemBaseLine -= height / 2;            }        }        QTextItemInt gf(si, &f, chf);        gf.num_glyphs = iterator.glyphsEnd - iterator.glyphsStart;        gf.glyphs = glyphs + iterator.glyphsStart;        gf.chars = eng->layoutData->string.unicode() + iterator.itemStart;        gf.logClusters = logClusters + iterator.itemStart - si.position;        gf.num_chars = iterator.itemEnd - iterator.itemStart;        gf.width = iterator.itemWidth;        gf.justified = line.justified;        Q_ASSERT(gf.fontEngine);        if (eng->underlinePositions) {            // can't have selections in this case            drawMenuText(p, iterator.x, itemBaseLine, si, gf, eng, iterator.itemStart, iterator.glyphsStart);        } else {            QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());            if (chf.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {                QPainterPath path;                path.setFillRule(Qt::WindingFill);                if (gf.num_glyphs)                    gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, gf.num_glyphs, &path, gf.flags);                if (gf.flags) {                    const QFontEngine *fe = gf.fontEngine;                    const qreal lw = fe->lineThickness().toReal();                    if (gf.flags & QTextItem::Underline) {                        qreal offs = fe->underlinePosition().toReal();                        path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);                    }                    if (gf.flags & QTextItem::Overline) {                        qreal offs = fe->ascent().toReal() + 1;                        path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);                    }                    if (gf.flags & QTextItem::StrikeOut) {                        qreal offs = fe->ascent().toReal() / 3;                        path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);                    }                }                p->save();                p->setRenderHint(QPainter::Antialiasing);                //Currently QPen with a Qt::NoPen style still returns a default                //QBrush which != Qt::NoBrush so we need this specialcase to reset it                if (p->pen().style() == Qt::NoPen)                    p->setBrush(Qt::NoBrush);                else                    p->setBrush(p->pen().brush());                p->setPen(chf.textOutline());                p->drawPath(path);                p->restore();            } else {                p->drawTextItem(pos, gf);            }        }    }    if (eng->hasFormats())        p->setPen(pen);}/*!  \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const  \overload*//*!  Converts the cursor position \a cursorPos to the corresponding x position  inside the line, taking account of the \a edge.  If \a cursorPos is not a valid cursor position, the nearest valid  cursor position will be used instead, and cpos will be modified to  point to this valid cursor position.  \sa xToCursor()*/qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const{    if (!eng->layoutData)        eng->itemize();    const QScriptLine &line = eng->lines[i];    QFixed x = line.x;    x += alignLine(eng, line);    if (!i && !eng->layoutData->items.size()) {        *cursorPos = 0;        return x.toReal();    }    int pos = *cursorPos;    int itm = eng->findItem(pos);    if (pos == line.from + (int)line.length) {        // end of line ensure we have the last item on the line        itm = eng->findItem(pos-1);    }    const QScriptItem *si = &eng->layoutData->items[itm];    if (!si->num_glyphs)        eng->shape(itm);    pos -= si->position;    QGlyphLayout *glyphs = eng->glyphs(si);    unsigned short *logClusters = eng->logClusters(si);    int l = eng->length(itm);    if (pos > l)        pos = l;    if (pos < 0)        pos = 0;    int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];    if (edge == Trailing) {        // trailing edge is leading edge of next cluster        while (glyph_pos < si->num_glyphs && !glyphs[glyph_pos].attributes.clusterStart)            glyph_pos++;    }    bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2;    int lineEnd = line.from + line.length;    // add the items left of the cursor    int firstItem = eng->findItem(line.from);    int lastItem = eng->findItem(lineEnd - 1);    int nItems = lastItem-firstItem+1;    QVarLengthArray<int> visualOrder(nItems);    QVarLengthArray<uchar> levels(nItems);    for (int i = 0; i < nItems; ++i)        levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;    QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());    for (int i = 0; i < nItems; ++i) {        int item = visualOrder[i]+firstItem;        if (item == itm)            break;        QScriptItem &si = eng->layoutData->items[item];        if (!si.num_glyphs)            eng->shape(item);        if (si.isTab) {            x = eng->nextTab(&si, x);            continue;        } else if (si.isObject) {            x += si.width;            continue;        }        int start = qMax(line.from, si.position);        int end = qMin(lineEnd, si.position + eng->length(item));        logClusters = eng->logClusters(&si);        int gs = logClusters[start-si.position];        int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1];        QGlyphLayout *glyphs = eng->glyphs(&si);        while (gs <= ge) {            x += (glyphs[gs].advance.x + QFixed::fromFixed(glyphs[gs].space_18d6)) * !glyphs[gs].attributes.dontPrint;            ++gs;        }    }    logClusters = eng->logClusters(si);    glyphs = eng->glyphs(si);    if (si->isTab) {        if(pos == l)            x = eng->nextTab(si, x);    } else if (si->isObject) {        if(pos == l)            x += si->width;    } else {        if (reverse) {            int end = qMin(lineEnd, si->position + l) - si->position;            int glyph_end = end == l ? si->num_glyphs : logClusters[end];            for (int i = glyph_end - 1; i >= glyph_pos; i--)                x += (glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6)) * !glyphs[i].attributes.dontPrint;        } else {            int start = qMax(line.from - si->position, 0);            int glyph_start = logClusters[start];            for (int i = glyph_start; i < glyph_pos; i++)                x += (glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6)) *!glyphs[i].attributes.dontPrint;        }    }    *cursorPos = pos + si->position;    return x.toReal();}/*!  \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const  Converts the x-coordinate \a x, to the nearest matching cursor  position, depending on the cursor position type, \a cpos.  \sa c

⌨️ 快捷键说明

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