📄 render_text.cpp
字号:
if (style()->whiteSpace() != NORMAL) m_minWidth = m_maxWidth; if (isPre) { if (firstLine) m_beginMinWidth = m_maxWidth; m_endMinWidth = currMaxWidth; } setMinMaxKnown(); //kdDebug( 6040 ) << "Text::calcMinMaxWidth(): min = " << m_minWidth << " max = " << m_maxWidth << endl;}bool RenderText::containsOnlyWhitespace(unsigned int from, unsigned int len) const{ unsigned int currPos; for (currPos = from; currPos < from+len && (str->s[currPos] == '\n' || str->s[currPos].unicode() == ' '); currPos++); return currPos >= (from+len);}int RenderText::minXPos() const{ if (!m_firstTextBox) return 0; int retval=6666666; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) retval = kMin(retval, (int)box->m_x); return retval;}int RenderText::xPos() const{ return m_firstTextBox ? m_firstTextBox->m_x : 0;}int RenderText::yPos() const{ return m_firstTextBox ? m_firstTextBox->m_y : 0;}const QFont &RenderText::font(){ return style()->font();}void RenderText::setTextWithOffset(DOMStringImpl *text, uint offset, uint len, bool force){ uint oldLen = str ? str->l : 0; uint newLen = text ? text->l : 0; int delta = newLen - oldLen; uint end = len ? offset+len-1 : offset; RootInlineBox* firstRootBox = 0; RootInlineBox* lastRootBox = 0; bool dirtiedLines = false; // Dirty all text boxes that include characters in between offset and offset+len. for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) { // Text run is entirely before the affected range. if (curr->end() < offset) continue; // Text run is entirely after the affected range. if (curr->start() > end) { curr->offsetRun(delta); RootInlineBox* root = curr->root(); if (!firstRootBox) { firstRootBox = root; if (!dirtiedLines) { // The affected area was in between two runs. Go ahead and mark the root box of the run after the affected area as dirty. firstRootBox->markDirty(); dirtiedLines = true; } } lastRootBox = root; } else if (curr->end() >= offset && curr->end() <= end) { curr->dirtyLineBoxes(); // Text run overlaps with the left end of the affected range. dirtiedLines = true; } else if (curr->start() <= offset && curr->end() >= end) { curr->dirtyLineBoxes(); // Text run subsumes the affected range. dirtiedLines = true; } else if (curr->start() <= end && curr->end() >= end) { curr->dirtyLineBoxes(); // Text run overlaps with right end of the affected range. dirtiedLines = true; } } // Now we have to walk all of the clean lines and adjust their cached line break information // to reflect our updated offsets. if (lastRootBox) lastRootBox = lastRootBox->nextRootBox(); if (firstRootBox) { RootInlineBox* prev = firstRootBox->prevRootBox(); if (prev) firstRootBox = prev; } for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) { if (!curr->isDirty() && curr->lineBreakObj() == this && curr->lineBreakPos() > end) curr->setLineBreakPos(curr->lineBreakPos()+delta); } m_linesDirty = dirtiedLines; setText(text, force);}void RenderText::setText(DOMStringImpl *text, bool force){ if (!text) return; if (!force && str == text) return; if (str) str->deref(); str = text; if (str) { str = str->replace('\\', backslashAsCurrencySymbol()); if ( style() ) { switch(style()->textTransform()) { case CAPITALIZE: str = str->capitalize(); break; case UPPERCASE: str = str->upper(); break; case LOWERCASE: str = str->lower(); break; case NONE: default:; } } str->ref(); }#if APPLE_CHANGES cacheWidths();#endif // ### what should happen if we change the text of a // RenderBR object ? KHTMLAssert(!isBR() || (str->l == 1 && (*str->s) == '\n')); KHTMLAssert(!str->l || str->s); setNeedsLayoutAndMinMaxRecalc(); #ifdef BIDI_DEBUG QConstString cstr(str->s, str->l); kdDebug( 6040 ) << "RenderText::setText( " << cstr.string().length() << " ) '" << cstr.string() << "'" << endl;#endif}int RenderText::height() const{ // FIXME: Why use line-height? Shouldn't we be adding in the height of the last text box? -dwh int retval = 0; if (firstTextBox()) retval = lastTextBox()->m_y + lineHeight(false) - firstTextBox()->m_y; return retval;}short RenderText::lineHeight(bool firstLine, bool) const{ // Always use the interior line height of the parent (e.g., if our parent is an inline block). return parent()->lineHeight(firstLine, true);}short RenderText::baselinePosition( bool firstLine, bool ) const{ const QFontMetrics &fm = metrics( firstLine ); return fm.ascent() + ( lineHeight( firstLine ) - fm.height() ) / 2;}void RenderText::dirtyLineBoxes(bool fullLayout, bool){ if (fullLayout) deleteTextBoxes(); else if (!m_linesDirty) { for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) box->dirtyLineBoxes(); } m_linesDirty = false;}InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool){ KHTMLAssert(!isRootLineBox); InlineTextBox* textBox = new (renderArena()) InlineTextBox(this); if (!m_firstTextBox) m_firstTextBox = m_lastTextBox = textBox; else { m_lastTextBox->setNextLineBox(textBox); textBox->setPreviousLineBox(m_lastTextBox); m_lastTextBox = textBox; } return textBox;}void RenderText::position(InlineBox* box, int from, int len, bool reverse){ InlineTextBox *s = static_cast<InlineTextBox*>(box); // ### should not be needed!!! if (len == 0) { // We want the box to be destroyed. s->remove(); s->detach(renderArena()); m_firstTextBox = m_lastTextBox = 0; return; } reverse = reverse && !style()->visuallyOrdered();#ifdef DEBUG_LAYOUT QChar *ch = str->s+from; QConstString cstr(ch, len); qDebug("setting run text to *%s*, len=%d, w)=%d" , cstr.string().latin1(), len, width );//" << y << ")" << " height=" << lineHeight(false) << " fontHeight=" << metrics(false).height() << " ascent =" << metrics(false).ascent() << endl;#endif s->m_reversed = reverse; s->m_start = from; s->m_len = len;}unsigned int RenderText::width(unsigned int from, unsigned int len, bool firstLine) const{ if(!str->s || from > str->l ) return 0; if ( from + len > str->l ) len = str->l - from; const Font *f = htmlFont( firstLine ); return width( from, len, f );}unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *f) const{ if(!str->s || from > str->l ) return 0; if ( from + len > str->l ) len = str->l - from; int w; if ( f == &style()->htmlFont() && from == 0 && len == str->l ) w = m_maxWidth;#if APPLE_CHANGES else if (f == &style()->htmlFont()) w = widthFromCache (f, from, len);#endif else w = f->width(str->s, str->l, from, len ); //kdDebug( 6040 ) << "RenderText::width(" << from << ", " << len << ") = " << w << endl; return w;}int RenderText::width() const{ int w; int minx = 100000000; int maxx = 0; // slooow for (InlineTextBox* s = firstTextBox(); s; s = s->nextTextBox()) { if(s->m_x < minx) minx = s->m_x; if(s->m_x + s->m_width > maxx) maxx = s->m_x + s->m_width; } w = kMax(0, maxx-minx); return w;}QRect RenderText::getAbsoluteRepaintRect(){ RenderObject *cb = containingBlock(); return cb->getAbsoluteRepaintRect();}short RenderText::verticalPositionHint( bool firstLine ) const{ return parent()->verticalPositionHint( firstLine );}const QFontMetrics &RenderText::metrics(bool firstLine) const{ return style(firstLine)->fontMetrics();}const Font *RenderText::htmlFont(bool firstLine) const{ return &style(firstLine)->htmlFont();}long RenderText::caretMinOffset() const{ if (!firstTextBox()) return 0; // EDIT FIXME: it is *not* guaranteed that the first run contains the lowest offset // Either make this a linear search (slow), // or maintain an index (needs much mem), // or calculate and store it in bidi.cpp (needs calculation even if not needed) return firstTextBox()->m_start;}long RenderText::caretMaxOffset() const{ if (!firstTextBox()) return str->l; // EDIT FIXME: it is *not* guaranteed that the last run contains the highest offset // Either make this a linear search (slow), // or maintain an index (needs much mem), // or calculate and store it in bidi.cpp (needs calculation even if not needed) return lastTextBox()->m_start + lastTextBox()->m_len;}unsigned long RenderText::caretMaxRenderedOffset() const{ int l = 0; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) l += box->m_len; return l;}InlineBox *RenderText::inlineBox(long offset){ for (InlineTextBox *box = firstTextBox(); box; box = box->nextTextBox()) { if (offset >= box->m_start && offset <= box->m_start + box->m_len) { return box; } else if (offset < box->m_start) { // The offset we're looking for is before this node // this means the offset must be in content that is // not rendered. return box->prevTextBox() ? box->prevTextBox() : firstTextBox(); } } return 0;}RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str, int startOffset, int endOffset):RenderText(_node, _str->substring(startOffset, endOffset)), m_start(startOffset), m_end(endOffset), m_generatedContentStr(0){}RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str):RenderText(_node, _str), m_start(0){ m_generatedContentStr = _str; if (_str) { _str->ref(); m_end = _str->l; } else m_end = 0;} RenderTextFragment::~RenderTextFragment(){ if (m_generatedContentStr) m_generatedContentStr->deref();}bool RenderTextFragment::isTextFragment() const{ return true;}DOM::DOMStringImpl* RenderTextFragment::originalString() const{ DOM::DOMStringImpl* result = 0; if (element()) result = element()->string(); else result = contentString(); if (result && (start() > 0 || start() < result->l)) result = result->substring(start(), end()); return result;}#undef BIDI_DEBUG#undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -