📄 render_text.cpp
字号:
} xPos = yPos = 0; return false;}void RenderText::posOfChar(int chr, int &x, int &y){ if (!parent()) { x = -1; y = -1; return; } parent()->absolutePosition( x, y, false ); //if( chr > (int) str->l ) //chr = str->l; int pos; TextSlave * s = findTextSlave( 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; }}void RenderText::printObject( QPainter *p, int /*x*/, int y, int /*w*/, int h, int tx, int ty){ RenderStyle* pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE); int d = style()->textDecoration(); TextSlave f(0, y-ty); int si = m_lines.findFirstMatching(&f); // something matching found, find the first one to print if(si >= 0) { // Move up until out of area to be printed while(si > 0 && m_lines[si-1]->checkVerticalPoint(y, ty, h, m_lineHeight)) si--; //QConstString cstr(str->s, str->l); //kdDebug(6040) << this << " RenderText text '" << (const char *)cstr.string().utf8() << "'" << endl; //kdDebug(6040) << this << " RenderText::printObject y=" << y << " ty=" << ty << " h=" << h << " first line is " << si << endl; // Now calculate startPos and endPos, for printing selection. // We print selection while endPos > 0 int endPos, startPos; if (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; // Eat the lines we don't print (startPos and endPos are from line 0!) // Note that we do this even if si==0, because we may have \n as the first char, // and this takes care of it too (David) if ( m_lines[si]->m_reversed ) endPos = -1; // No selection if RTL (TODO) else { // ## Only valid for visuallyOrdered int len = m_lines[si]->m_text - str->s; //kdDebug(6040) << this << " RenderText::printObject adjustement si=" << si << " len=" << len << endl; startPos -= len; endPos -= len; } } TextSlave* s; int minx = 1000000; int maxx = -1000000; int outlinebox_y = m_lines[si]->m_y; RenderStyle* outlineStyle = 0; if (!outlineStyle && style()->outlineWidth()) outlineStyle = style(); // run until we find one that is outside the range, then we // know we can stop do { s = m_lines[si]; RenderStyle* _style = pseudoStyle && s->m_firstLine ? pseudoStyle : style(); if(_style->font() != p->font()) p->setFont(_style->font()); if((hasSpecialObjects() && (parent()->isInline() || pseudoStyle)) && (!pseudoStyle || s->m_firstLine)) s->printBoxDecorations(p, _style, this, tx, ty, si == 0, si == (int)m_lines.count()-1); if(_style->color() != p->pen().color()) p->setPen(_style->color()); s->print(p, tx, ty); if(d != TDNONE) { p->setPen(_style->textDecorationColor()); s->printDecoration(p, this, tx, ty, d, si == 0, si == ( int ) m_lines.count()-1); } if (selectionState() != SelectionNone && endPos > 0) { //kdDebug(6040) << this << " printSelection with startPos=" << startPos << " endPos=" << endPos << endl; s->printSelection(p, _style, tx, ty, startPos, endPos); int diff; if(si < (int)m_lines.count()-1) // ### only for visuallyOrdered ! (we disabled endPos for RTL, so we can't go here in RTL mode) diff = m_lines[si+1]->m_text - s->m_text; else diff = s->m_len; //kdDebug(6040) << this << " RenderText::printSelection eating the line si=" << si << " length=" << diff << endl; endPos -= diff; startPos -= diff; //kdDebug(6040) << this << " startPos now " << startPos << ", endPos now " << endPos << endl; } if(outlineStyle) { if(outlinebox_y == s->m_y) { if(minx > s->m_x) minx = s->m_x; if(maxx < s->m_x+s->m_width) maxx = s->m_x+s->m_width; } else { printOutline(p, tx+minx, ty+outlinebox_y, maxx-minx, m_lineHeight, outlineStyle); outlinebox_y = s->m_y; minx = s->m_x; maxx = s->m_x+s->m_width; } } } while (++si < (int)m_lines.count() && m_lines[si]->checkVerticalPoint(y, ty, h, m_lineHeight)); if(outlineStyle) printOutline(p, tx+minx, ty+outlinebox_y, maxx-minx, m_lineHeight, outlineStyle); }}void RenderText::print( QPainter *p, int x, int y, int w, int h, int tx, int ty){ if ( !isVisible() ) return; int s = m_lines.count() - 1; if ( s < 0 ) return; // ### incorporate padding/border here! if ( ty + m_lines[0]->m_y > y + h + 64 ) return; if ( ty + m_lines[s]->m_y + m_lines[s]->m_baseline + m_lineHeight + 64 < y ) return; printObject(p, x, y, w, h, tx, ty);}void RenderText::calcMinMaxWidth(){ //kdDebug( 6040 ) << "Text::calcMinMaxWidth(): known=" << minMaxKnown() << endl; if(minMaxKnown()) return; // ### calc Min and Max width... m_minWidth = 0; m_maxWidth = 0; int currMinWidth = 0; int currMaxWidth = 0; m_hasReturn = false; m_hasBreakableChar = false; // ### not 100% correct for first-line QFontMetrics _fm = khtml::printpainter ? metrics( false ) : *fm; int len = str->l; if ( len == 1 && str->s->latin1() == '\n' ) m_hasReturn = true; for(int i = 0; i < len; i++) { int wordlen = 0; do { wordlen++; } while( i+wordlen < len && !(isBreakable( str->s, i+wordlen, str->l )) ); if (wordlen) { int w = _fm.width(QConstString(str->s+i, wordlen).string()); currMinWidth += w; currMaxWidth += w; } if(i+wordlen < len) { m_hasBreakableChar = true; if ( (*(str->s+i+wordlen)).latin1() == '\n' ) { m_hasReturn = true; if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; currMinWidth = 0; if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth; currMaxWidth = 0; } else { if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; currMinWidth = 0; currMaxWidth += _fm.width( *(str->s+i+wordlen) ); } /* else if( c == '-') { currMinWidth += minus_width; if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; currMinWidth = 0; currMaxWidth += minus_width; }*/ } i += wordlen; } if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth; setMinMaxKnown();}int RenderText::minXPos() const{ if (!m_lines.count()) return 0; int retval=6666666; for (unsigned i=0;i < m_lines.count(); i++) { retval = QMIN ( retval, m_lines[i]->m_x); } return retval;}int RenderText::xPos() const{ if (m_lines.count()) return m_lines[0]->m_x; else return 0;}int RenderText::yPos() const{ if (m_lines.count()) return m_lines[0]->m_y; else return 0;}const QFont &RenderText::font(){ return parent()->style()->font();}void RenderText::setText(DOMStringImpl *text){ if( str == text ) return; if(str) str->deref(); str = text; if(str) str->ref(); // ### what should happen if we change the text of a // RenderBR object ? assert(!isBR() || (str->l == 1 && (*str->s) == '\n')); assert(!str->l || str->s); setLayouted(false); RenderObject* cb = containingBlock(); if ( cb != this ) { cb->setLayouted(false); cb->layout(); }#ifdef DEBUG_LAYOUT QConstString cstr(str->s, str->l); kdDebug( 6040 ) << "RenderText::setText '" << (const char *)cstr.string().utf8() << "'" << endl;#endif}int RenderText::height() const{ // ### does this make sense?? int retval = metrics( false ).height() + paddingTop() + paddingBottom() + borderTop() + borderBottom(); if (m_lines.count()) retval += m_lineHeight; return retval;}int RenderText::lineHeight( bool firstLine ) const{ if ( firstLine ) return RenderObject::lineHeight( firstLine ); return m_lineHeight;}short RenderText::baselinePosition( bool firstLine ) const{ return metrics( firstLine ).ascent() + ( lineHeight( firstLine ) - metrics( firstLine ).height() ) / 2;}void RenderText::position(int x, int y, int from, int len, int width, bool reverse, bool firstLine){ // ### should not be needed!!! if(len == 0 || (len == 1 && *(str->s+from) == '\n') ) return; QChar *ch; reverse = reverse && !style()->visuallyOrdered(); if ( reverse ) { // reverse String QString aStr = QConstString(str->s+from, len).string(); //kdDebug( 6040 ) << "reversing '" << (const char *)aStr.utf8() << "' len=" << aStr.length() << " oldlen=" << len << endl; len = aStr.length(); ch = QT_ALLOC_QCHAR_VEC(len); int half = len/2; const QChar *s = aStr.unicode(); for(int i = 0; i <= half; i++) { ch[len-1-i] = s[i]; ch[i] = s[len-1-i]; if(ch[i].mirrored() && !style()->visuallyOrdered()) ch[i] = ch[i].mirroredChar(); if(ch[len-1-i].mirrored() && !style()->visuallyOrdered() && i != len-1-i) ch[len-1-i] = ch[len-1-i].mirroredChar(); } } else ch = str->s+from; // ### margins and RTL if(from == 0 && parent()->isInline() && parent()->firstChild()==this) { x += paddingLeft() + borderLeft() + marginLeft(); width -= marginLeft(); } if(from + len == int(str->l) && parent()->isInline() && parent()->lastChild()==this) width -= marginRight();#ifdef DEBUG_LAYOUT QConstString cstr(ch, len); kdDebug( 6040 ) << "setting slave text to '" << (const char *)cstr.string().utf8() << "' len=" << len << " width=" << width << " at (" << x << "/" << y << ")" << " height=" << lineHeight() << " fontHeight=" << metrics().height() << " ascent =" << metrics().ascent() << endl;#endif TextSlave *s = new TextSlave(x, y, ch, len, baselinePosition( firstLine ), width, reverse, firstLine); if(m_lines.count() == m_lines.size()) m_lines.resize(m_lines.size()*2+1); m_lines.insert(m_lines.count(), s);}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; if ( khtml::printpainter || ( firstLine && hasFirstLine() ) ) { QFontMetrics _fm = metrics( firstLine ); return width( from, len, &_fm ); } return width( from, len, fm );}unsigned int RenderText::width(unsigned int from, unsigned int len, QFontMetrics *_fm) const{ if(!str->s || from > str->l ) return 0; if ( from + len > str->l ) len = str->l - from; int w; if ( _fm == fm && from == 0 && len == str->l ) w = m_maxWidth; if( len == 1) w = _fm->width( *(str->s+from) ); else w = _fm->width(QConstString(str->s+from, len).string()); // ### add margins and support for RTL if(parent()->isInline()) { if(from == 0 && parent()->firstChild() == static_cast<const RenderObject*>(this)) w += borderLeft() + paddingLeft() + marginLeft(); if(from + len == str->l && parent()->lastChild() == static_cast<const RenderObject*>(this)) w += borderRight() + paddingRight() +marginRight(); } //kdDebug( 6040 ) << "RenderText::width(" << from << ", " << len << ") = " << w << endl; return w;}short RenderText::width() const{ int w; int minx = 100000000; int maxx = 0; // slooow for(unsigned int si = 0; si < m_lines.count(); si++) { TextSlave* s = m_lines[si]; 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 = QMAX(0, maxx-minx); if(parent()->isInline()) { if(parent()->firstChild() == static_cast<const RenderObject*>(this)) w += borderLeft() + paddingLeft(); if(parent()->lastChild() == static_cast<const RenderObject*>(this)) w += borderRight() + paddingRight(); } return w;}void RenderText::repaint(){ RenderObject *cb = containingBlock(); if(cb != this) cb->repaint();}bool RenderText::isFixedWidthFont() const{ return QFontInfo(style()->font()).fixedPitch();}short RenderText::verticalPositionHint( bool firstLine ) const{ return parent()->verticalPositionHint( firstLine );}QFontMetrics RenderText::metrics(bool firstLine) const{ if( firstLine && hasFirstLine() ) { RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE); if ( pseudoStyle ) return fontMetrics( pseudoStyle->font() ); } if ( khtml::printpainter ) return fontMetrics(style()->font()); return *fm;}#undef BIDI_DEBUG#undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -