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

📄 render_text.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
    : RenderObject(node), m_linesDirty(false)
{
    // init RenderObject attributes
    setRenderText();   // our object inherits from RenderText

    m_minWidth = -1;
    m_maxWidth = -1;

#ifdef APPLE_CHANGES
    m_monospaceCharacterWidth = 0;
    m_allAsciiChecked = false;
    m_allAscii = false;
#endif

    str = _str;
    if (str) {
        str = str->replace('\\', backslashAsCurrencySymbol());
        str->ref();
    }
    KHTMLAssert(!str || !str->l || str->s);

    m_firstTextBox = m_lastTextBox = 0;

    m_selectionState = SelectionNone;

#ifdef DEBUG_LAYOUT
    QConstString cstr(str->s, str->l);
    kdDebug( 6040 ) << "RenderText ctr( "<< cstr.string().length() << " )  '" << cstr.string() << "'" << endl;
#endif
}

void RenderText::setStyle(RenderStyle *_style)
{
    if ( style() != _style ) {
        bool needToTransformText = (!style() && _style->textTransform() != TTNONE) ||
                                   (style() && style()->textTransform() != _style->textTransform());

        RenderObject::setStyle( _style );

        if (needToTransformText) {
            DOM::DOMStringImpl* textToTransform = originalString();
            if (textToTransform)
                setText(textToTransform, true);
        }
#if APPLE_CHANGES
        // setText also calls cacheWidths(), so there is no need to call it again in that case.
        else
            cacheWidths();
#endif
    }
}

RenderText::~RenderText()
{
    if(str) str->deref();
}

void RenderText::detach()
{
    if (!documentBeingDestroyed()) {
        if (firstTextBox()) {
            if (isBR()) {
                RootInlineBox* next = firstTextBox()->root()->nextRootBox();
                if (next)
                    next->markDirty();
            }
            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
                box->remove();
        }
        else if (parent())
            parent()->dirtyLinesFromChangedChild(this, false);
    }
    deleteTextBoxes();
    RenderObject::detach();
}

void RenderText::extractTextBox(InlineTextBox* box)
{
    m_lastTextBox = box->prevTextBox();
    if (box == m_firstTextBox)
        m_firstTextBox = 0;
    if (box->prevTextBox())
        box->prevTextBox()->setNextLineBox(0);
    box->setPreviousLineBox(0);
    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
        curr->setExtracted();
}

void RenderText::attachTextBox(InlineTextBox* box)
{
    if (m_lastTextBox) {
        m_lastTextBox->setNextLineBox(box);
        box->setPreviousLineBox(m_lastTextBox);
    }
    else
        m_firstTextBox = box;
    InlineTextBox* last = box;
    for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) {
        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) const
{
    // 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;
}

VisiblePosition RenderText::positionForCoordinates(int _x, int _y)
{
    if (!firstTextBox() || stringLength() == 0)
        return VisiblePosition(element(), 0, DOWNSTREAM);

    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 VisiblePosition(element(), firstTextBox()->m_start, DOWNSTREAM);
    }

    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 VisiblePosition(element(), lastTextBox()->m_start + lastTextBox()->m_len, DOWNSTREAM);
    }

    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) {
                    EAffinity affinity = offset >= box->m_len && !box->nextOnLine() ? UPSTREAM : DOWNSTREAM;
                    return VisiblePosition(element(), offset + box->m_start, affinity);
                }
            }
            else if (!box->prevOnLine() && _x < absx + box->m_x) {
                // box is first on line
                // and the x coordinate is to the left of the first text box left edge
                return VisiblePosition(element(), box->m_start, DOWNSTREAM);
            }
            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 of the last text box right edge
                return VisiblePosition(element(), box->m_start + box->m_len, UPSTREAM);
        }
    }
    
    return VisiblePosition(element(), 0, DOWNSTREAM);
}

static RenderObject *firstRendererOnNextLine(InlineBox *box)
{
    if (!box)
        return 0;

    RootInlineBox *root = box->root();
    if (!root)
        return 0;

    if (root->endsWithBreak())
        return 0;

    RootInlineBox *nextRoot = root->nextRootBox();
    if (!nextRoot)
        return 0;

    InlineBox *firstChild = nextRoot->firstChild();
    if (!firstChild)
        return 0;

    return firstChild->object();
}

static RenderObject *lastRendererOnPrevLine(InlineBox *box)
{
    if (!box)
        return 0;
    
    RootInlineBox *root = box->root();
    if (!root)
        return 0;
    
    if (root->endsWithBreak())
        return 0;
    
    RootInlineBox *prevRoot = root->prevRootBox();
    if (!prevRoot)
        return 0;
    
    InlineBox *lastChild = prevRoot->lastChild();
    if (!lastChild)
        return 0;
    
    return lastChild->object();
}

QRect RenderText::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
{
    if (!firstTextBox() || stringLength() == 0) {
        return QRect();
    }

    // Find the text box for the given offset
    InlineTextBox *box = 0;
    for (box = firstTextBox(); box; box = box->nextTextBox()) {
        if ((offset >= box->m_start) && (offset <= box->m_start + box->m_len)) {
            // Check if downstream affinity would make us move to the next line.
            InlineTextBox *nextBox = box->nextTextBox();
            if (offset == box->m_start + box->m_len && affinity == DOWNSTREAM  && nextBox &&  !box->nextOnLine()) {
                // We're at the end of a line broken on a word boundary and affinity is downstream.
                // Try to jump down to the next line.
                if (nextBox) {
                    // Use the next text box
                    box = nextBox;
                    offset = box->m_start;
                } else {
                    // Look on the next line
                    RenderObject *object = firstRendererOnNextLine(box);
                    if (object)
                        return object->caretRect(0, affinity);
                }
            } else {
      InlineTextBox *prevBox = box->prevTextBox();
      if (offset == box->m_start && affinity == UPSTREAM && prevBox && !box->prevOnLine()) {
          if (prevBox) {
          box = prevBox;
          offset = box->m_start + box->m_len;
          } else {
          RenderObject *object = lastRendererOnPrevLine(box);
          if (object)
              return object->caretRect(0, affinity);
          }
      }
      }
            break;
        }
    }
    
    if (!box) {
        return QRect();
    }

    int height = box->root()->bottomOverflow() - box->root()->topOverflow();
    int top = box->root()->topOverflow();

    const QFontMetrics &fm = metrics(box->isFirstLineStyle());
    int left;
    if (box->m_reversed) {
  long len = box->m_start+box->m_len-offset;
  QString string(str->s +offset,len);
  left = box->m_x + fm.boundingRect(string,len).right();
    } else {
  long len = offset - box->m_start; // the number of characters we are into the string
  QString string(str->s + box->m_start,len);
  left = box->m_x + fm.boundingRect(string,len).right();
    }

    // FIXME: should we use the width of the root inline box or the
    // width of the containing block for this?
    if (extraWidthToEndOfLine)
        *extraWidthToEndOfLine = (box->root()->width() + box->root()->xPos()) - (left + 1);

    int absx, absy;
    absolutePosition(absx,absy);
    left += absx;
    top += absy;

    // FIXME: Need the +1 to match caret position of other programs on Macintosh.
    // Would be better to somehow derive it once we understand exactly why it's needed.
    left += 1;

    RenderBlock *cb = containingBlock();
    int availableWidth = cb->lineWidth(top);
    if (style()->whiteSpace() == NORMAL)
        left = kMin(left, absx + box->m_x + availableWidth - 1);

    return QRect(left, top, 1, height);
}

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;
    }
}

#ifdef NOKIA_CHANGES
void RenderText::getRenderersInRect(QPtrList<BoxInfo>& boxInfoList,int deltaX,int deltaY,const QRect& rect)
{
	if(!firstTextBox()||!lastTextBox()) return;
	if (deltaY + firstTextBox()->yPos() > rect.y() + rect.height()) return;
	if (deltaY + lastTextBox()->yPos() + lastTextBox()->height() < rect.y()) return;

	BoxInfo* sel = new BoxInfo;
	sel->renderObject = this;
	sel->absoluteXPos = deltaX;
	sel->absoluteYPos = deltaY;
	sel->width = width();

⌨️ 快捷键说明

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