📄 render_text.cpp
字号:
curr->setExtracted(false); last = curr; } m_lastTextBox = last;}void RenderText::removeTextBox(InlineTextBox* box){ if (box == m_firstTextBox) m_firstTextBox = box->nextTextBox(); if (box == m_lastTextBox) m_lastTextBox = box->prevTextBox(); if (box->nextTextBox()) box->nextTextBox()->setPreviousLineBox(box->prevTextBox()); if (box->prevTextBox()) box->prevTextBox()->setNextLineBox(box->nextTextBox());}void RenderText::deleteTextBoxes(){ if (firstTextBox()) { RenderArena* arena = renderArena(); InlineTextBox *curr = firstTextBox(), *next = 0; while (curr) { next = curr->nextTextBox(); curr->detach(arena); curr = next; } m_firstTextBox = m_lastTextBox = 0; }}bool RenderText::isTextFragment() const{ return false;}DOM::DOMStringImpl* RenderText::originalString() const{ return element() ? element()->string() : 0;}void RenderText::absoluteRects(QValueList<QRect>& rects, int _tx, int _ty){ for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) rects.append(QRect(_tx + box->xPos(), _ty + box->yPos(), box->width(), box->height()));}InlineTextBox* RenderText::findNextInlineTextBox(int offset, int &pos){ // The text runs point to parts of the rendertext's str string // (they don't include '\n') // Find the text run that includes the character at @p offset // and return pos, which is the position of the char in the run. if (!m_firstTextBox) return 0; InlineTextBox* s = m_firstTextBox; int off = s->m_len; while (offset > off && s->nextTextBox()) { s = s->nextTextBox(); off = s->m_start + s->m_len; } // we are now in the correct text run pos = (offset > off ? s->m_len : s->m_len - (off - offset) ); return s;}bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside){ assert(parent()); for (InlineTextBox *s = m_firstTextBox; s; s = s->nextTextBox()) { if((_y >=_ty + s->m_y) && (_y < _ty + s->m_y + s->height()) && (_x >= _tx + s->m_x) && (_x <_tx + s->m_x + s->m_width) ) { inside = true; break; } } if (inside && element()) { if (info.innerNode() && info.innerNode()->renderer() && !info.innerNode()->renderer()->isInline()) { // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node. info.setInnerNode(element()); // Clear everything else. info.setInnerNonSharedNode(0); info.setURLElement(0); } if (!info.innerNode()) info.setInnerNode(element()); if (!info.innerNonSharedNode()) info.setInnerNonSharedNode(element()); } return inside;}Position RenderText::positionForCoordinates(int _x, int _y){ if (!firstTextBox() || stringLength() == 0) return Position(element(), 0); int absx, absy; containingBlock()->absolutePosition(absx, absy); if (firstTextBox() && _y < absy + firstTextBox()->root()->bottomOverflow() && _x < absx + firstTextBox()->m_x) { // at the y coordinate of the first line or above // and the x coordinate is to the left than the first text box left edge return Position(element(), firstTextBox()->m_start); } if (lastTextBox() && _y >= absy + lastTextBox()->root()->topOverflow() && _x >= absx + lastTextBox()->m_x + lastTextBox()->m_width) { // at the y coordinate of the last line or below // and the x coordinate is to the right than the last text box right edge return Position(element(), lastTextBox()->m_start + lastTextBox()->m_len); } for (InlineTextBox *box = firstTextBox(); box; box = box->nextTextBox()) { if (_y >= absy + box->root()->topOverflow() && _y < absy + box->root()->bottomOverflow()) { if (_x < absx + box->m_x + box->m_width) { // and the x coordinate is to the left of the right edge of this box // check to see if position goes in this box int offset = box->offsetForPosition(_x - absx); if (offset != -1) { return Position(element(), offset + box->m_start); } } else if (!box->prevOnLine() && _x < absx + box->m_x) // box is first on line // and the x coordinate is to the left than the first text box left edge return Position(element(), box->m_start); else if (!box->nextOnLine() && _x >= absx + box->m_x + box->m_width) // box is last on line // and the x coordinate is to the right than the last text box right edge return Position(element(), box->m_start + box->m_len); } } return Position(element(), 0);}void RenderText::caretPos(int offset, bool override, int &_x, int &_y, int &width, int &height){ if (!firstTextBox() || stringLength() == 0) { _x = _y = height = -1; return; } // Find the text box for the given offset InlineTextBox *box = 0; for (box = firstTextBox(); box; box = box->nextTextBox()) { if (offset <= box->m_start + box->m_len) break; } if (!box) { _x = _y = height = -1; return; } height = box->root()->bottomOverflow() - box->root()->topOverflow(); _y = box->root()->topOverflow(); const QFontMetrics &fm = metrics(box->isFirstLineStyle()); QString string(str->s + box->m_start, box->m_len); long pos = offset - box->m_start; // the number of characters we are into the string _x = box->m_x + (fm.boundingRect(string, pos)).right();#if 0 // EDIT FIXME if (pos) _x += fm.rightBearing(*(str->s + box->m_start + offset));#endif int absx, absy; absolutePosition(absx,absy); _x += absx; _y += absy;}void RenderText::posOfChar(int chr, int &x, int &y){ absolutePosition( x, y, false ); //if( chr > (int) str->l ) //chr = str->l; int pos; InlineTextBox * s = findNextInlineTextBox( chr, pos ); if ( s ) { // s is the line containing the character x += s->m_x; // this is the x of the beginning of the line, but it's good enough for now y += s->m_y; }}static intsimpleDifferenceBetweenColors(QColor c1, QColor c2){ // a distance could be computed by squaring the differences between components, but // this is faster and so far seems good enough for our purposes. return abs(c1.red() - c2.red()) + abs(c1.green() - c2.green()) + abs(c1.blue() - c2.blue());}static QColor correctedTextColor(QColor textColor, QColor backgroundColor) { // Adjust the text color if it is too close to the background color, // by darkening or lightening it to move it further away. int d = simpleDifferenceBetweenColors(textColor, backgroundColor); // semi-arbitrarily chose 255 value here after a few tests; if (d > 255) { return textColor; } int distanceFromWhite = simpleDifferenceBetweenColors(textColor, Qt::white); int distanceFromBlack = simpleDifferenceBetweenColors(textColor, Qt::black); if (distanceFromWhite < distanceFromBlack) { return textColor.dark(); } return textColor.light();}void RenderText::paint(PaintInfo& i, int tx, int ty){ if (i.phase != PaintActionForeground && i.phase != PaintActionSelection) return; if (!shouldPaintWithinRoot(i)) return; if (style()->visibility() != VISIBLE || !firstTextBox()) return; if (ty + firstTextBox()->yPos() > i.r.y() + i.r.height()) return; if (ty + lastTextBox()->yPos() + lastTextBox()->height() < i.r.y()) return; QPainter* p = i.p; RenderStyle* pseudoStyle = style(true); if (pseudoStyle == style()) pseudoStyle = 0; int d = style()->textDecorationsInEffect(); bool isPrinting = (p->device()->devType() == QInternal::Printer); // Walk forward until we hit the first line that needs to be painted. InlineTextBox* s = firstTextBox(); for (; s && !s->checkVerticalPoint(i.r.y(), ty, i.r.height()); s = s->nextTextBox()); if (!s) return; // Now calculate startPos and endPos, for painting selection. // We paint selection while endPos > 0 int endPos = 0, startPos = 0; if (!isPrinting && (selectionState() != SelectionNone)) { if (selectionState() == SelectionInside) { //kdDebug(6040) << this << " SelectionInside -> 0 to end" << endl; startPos = 0; endPos = str->l; } else { selectionStartEnd(startPos, endPos); if(selectionState() == SelectionStart) endPos = str->l; else if(selectionState() == SelectionEnd) startPos = 0; } //kdDebug(6040) << this << " Selection from " << startPos << " to " << endPos << endl; } const Font *font = &style()->htmlFont();#if APPLE_CHANGES // Do one pass for the selection, then another for the rest. bool haveSelection = startPos != endPos && !isPrinting && selectionState() != SelectionNone; if (!haveSelection && i.phase == PaintActionSelection) { // When only painting the selection, don't bother to paint if there is none. return; } InlineTextBox* startBox = s; for (int pass = 0; pass < (haveSelection ? 2 : 1); pass++) { s = startBox; bool drawSelectionBackground = haveSelection && pass == 0 && i.phase != PaintActionSelection; bool drawText = !haveSelection || pass == 1;#endif // run until we find one that is outside the range, then we // know we can stop do { if (isPrinting) { if (ty+s->m_y+s->height() > i.r.y() + i.r.height()) { RenderCanvas* canvasObj = canvas(); if (ty+s->m_y < canvasObj->truncatedAt())#if APPLE_CHANGES && !KWIQ canvasObj->setBestTruncatedAt(ty+s->m_y, this);#else canvasObj->setTruncatedAt(ty+s->m_y);#endif // Let's stop here. break; } } if (s->m_truncation == cFullTruncation) continue; RenderStyle* _style = pseudoStyle && s->m_firstLine ? pseudoStyle : style(); if (_style->font() != p->font()) p->setFont(_style->font()); font = &_style->htmlFont(); // Always update, since smallCaps is not stored in the QFont.#if APPLE_CHANGES if (drawText) {#endif QColor textColor = _style->color(); if (_style->shouldCorrectTextColor()) { textColor = correctedTextColor(textColor, _style->backgroundColor()); } if(textColor != p->pen().color()) p->setPen(textColor);#if APPLE_CHANGES // Set a text shadow if we have one. // FIXME: Support multiple shadow effects. Need more from the CG API before // we can do this. bool setShadow = false; if (_style->textShadow()) { p->setShadow(_style->textShadow()->x, _style->textShadow()->y, _style->textShadow()->blur, _style->textShadow()->color); setShadow = true; }#endif if (s->m_len > 0) { bool paintSelectedTextOnly = (i.phase == PaintActionSelection); bool paintSelectedTextSeparately = false; // Whether or not we have to do multiple paints. Only // necessary when a custom ::selection foreground color is applied. QColor selectionColor = p->pen().color(); ShadowData* selectionTextShadow = 0; if (haveSelection) { RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION); if (pseudoStyle) { if (pseudoStyle->color() != selectionColor || pseudoStyle->textShadow()) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; if (pseudoStyle->color() != selectionColor) selectionColor = pseudoStyle->color(); if (pseudoStyle->textShadow()) selectionTextShadow = pseudoStyle->textShadow(); } } } if (!paintSelectedTextOnly && !paintSelectedTextSeparately) { // FIXME: Handle RTL direction, handle reversed strings. For now truncation can only be turned on // for non-reversed LTR strings. int endPoint = s->m_len; if (s->m_truncation != cNoTruncation) endPoint = s->m_truncation - s->m_start; font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, endPoint, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered()); } else { int offset = s->m_start;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -