📄 render_text.cpp
字号:
// kdDebug(6040) << "offset="<<offset << " pos="<<pos << endl; const QFontMetrics &fm = t->metrics( s->m_firstLine ); height = fm.height(); // s->m_height; _x = s->m_x + s->widthFromStart(pos); _y = s->m_y + s->baseline() - fm.ascent(); width = 1; if (flags & CFOverride) { width = offset < maxOffset() ? fm.width(str->s[offset]) : 1; }/*end if*/#if 0 kdDebug(6040) << "_x="<<_x << " s->m_x="<<s->m_x << " s->m_start"<<s->m_start << " s->m_len" << s->m_len << " _y=" << _y << endl;#endif int absx, absy; if (absolutePosition(absx,absy)) { //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl; _x += absx; _y += absy; } else { // we don't know our absolute position, and there is no point returning // just a relative one _x = _y = -1; }}long RenderText::minOffset() const{ if (!m_lines.count()) return 0; // 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) // (LS) return m_lines[0]->m_start;}long RenderText::maxOffset() const{ int count = m_lines.count(); if (!count) return str->l; // 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) // (LS) return m_lines[count - 1]->m_start + m_lines[count - 1]->m_len;}bool RenderText::absolutePosition(int &xPos, int &yPos, bool){ return RenderObject::absolutePosition(xPos, yPos, false); if(parent() && parent()->absolutePosition(xPos, yPos, false)) { xPos -= paddingLeft() + borderLeft(); yPos -= borderTop() + paddingTop(); return true; } xPos = yPos = 0; return false;}bool RenderText::posOfChar(int chr, int &x, int &y){ if (!parent()) return false; parent()->absolutePosition( x, y, false ); int pos; InlineTextBox * s = findInlineTextBox( 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; return true; } return false;}void RenderText::paint( PaintInfo& pI, int tx, int ty){ if (pI.phase == PaintActionSelection && selectionState() == SelectionNone) // When only painting the selection, don't bother to paint if there is none. return; if (pI.phase != PaintActionForeground && pI.phase != PaintActionSelection || style()->visibility() != VISIBLE) return; int s = m_lines.count() - 1; if ( s < 0 ) return; if ( ty + m_lines[0]->m_y > pI.r.bottom() ) return; if ( ty + m_lines[s]->m_y + m_lines[s]->height() < pI.r.top() ) return; int ow = style()->outlineWidth(); RenderStyle* pseudoStyle = hasFirstLine() ? style()->getPseudoStyle(RenderStyle::FIRST_LINE) : 0; InlineTextBox f(0, pI.r.top()-ty); int si = m_lines.findFirstMatching(&f); // something matching found, find the first one to paint bool isStatic = canvas()->staticMode(); if (isStatic && pI.phase == PaintActionSelection) return; if(si >= 0) { // Move up until out of area to be painted while(si > 0 && m_lines[si-1]->checkVerticalPoint(pI.r.y(), ty, pI.r.height(), m_lineHeight)) si--; // Now calculate startPos and endPos, for painting selection. // We paint selection while endPos > 0 int endPos, startPos; if (!isStatic && (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; } InlineTextBox* s; const Font *font = &style()->htmlFont(); bool haveSelection = !isStatic && selectionState() != SelectionNone && startPos != endPos; if (!haveSelection && pI.phase == PaintActionSelection) // When only painting the selection, don't bother to paint if there return; // 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(); int d = _style->textDecorationsInEffect(); if(_style->font() != pI.p->font()) pI.p->setFont(_style->font()); //has to be outside the above if because of small caps. font = &_style->htmlFont(); if(_style->color() != pI.p->pen().color()) pI.p->setPen(_style->color());#ifdef APPLE_CHANGES // Set a text shadow if we have one. 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 && pI.phase != PaintActionSelection) { if (!haveSelection) { //kdDebug( 6040 ) << "RenderObject::paintObject(" << QConstString(str->s + s->m_start, s->m_len).string() << ") at(" << s->m_x+tx << "/" << s->m_y+ty << ")" << endl;#ifndef APPLE_CHANGES if (_style->textShadow()) s->paintShadow(pI.p, font, tx, ty, _style->textShadow());#endif// kdDebug(6040) << QConstString(str->s + s->m_start, s->m_len).string().left(40) << endl; font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR); } else { int offset = s->m_start; int sPos = kMax( startPos - offset, 0 ); int ePos = kMin( endPos - offset, int( s->m_len ) );// selected text is always separate in konqueror#ifdef APPLE_CHANGES if (paintSelectedTextSeparately) {#endif#ifndef APPLE_CHANGES if (_style->textShadow()) s->paintShadow(pI.p, font, tx, ty, _style->textShadow());#endif if (sPos >= ePos) font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR); else { if (sPos-1 >= 0) font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, 0, sPos); if (ePos < s->m_len) font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, ePos, s->m_len); }#ifdef APPLE_CHANGES } if ( sPos < ePos ) { if (selectionColor != p->pen().color()) p->setPen(selectionColor); font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len, s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, sPos, ePos); }#endif } } if (d != TDNONE && pI.phase == PaintActionForeground && style()->htmlHacks()) { pI.p->setPen(_style->color()); s->paintDecoration(pI.p, font, tx, ty, d); } if (haveSelection && pI.phase == PaintActionSelection) { int offset = s->m_start; int sPos = kMax( startPos - offset, 0 ); int ePos = kMin( endPos - offset, int( s->m_len ) ); //kdDebug(6040) << this << " paintSelection with startPos=" << sPos << " endPos=" << ePos << endl; if ( sPos < ePos ) s->paintSelection(font, this, pI.p, _style, tx, ty, sPos, ePos, d); }#ifdef BIDI_DEBUG { int h = lineHeight( false ) + paddingTop() + paddingBottom() + borderTop() + borderBottom(); QColor c2 = QColor("#0000ff"); drawBorder(pI.p, tx + s->m_x, ty + s->m_y, tx + s->m_x + 1, ty + s->m_y + h, RenderObject::BSLeft, c2, c2, SOLID, 1, 1); drawBorder(pI.p, tx + s->m_x + s->m_width, ty + s->m_y, tx + s->m_x + s->m_width + 1, ty + s->m_y + h, RenderObject::BSRight, c2, c2, SOLID, 1, 1); }#endif } while (++si < (int)m_lines.count() && m_lines[si]->checkVerticalPoint(pI.r.y()-ow, ty, pI.r.height(), m_lineHeight)); }}void RenderText::calcMinMaxWidth(){ KHTMLAssert( !minMaxKnown() ); // ### calc Min and Max width... m_minWidth = m_beginMinWidth = m_endMinWidth = 0; m_maxWidth = 0; if (isBR()) return; int currMinWidth = 0; int currMaxWidth = 0; m_hasBreakableChar = m_hasBreak = m_hasBeginWS = m_hasEndWS = false; // ### not 100% correct for first-line const Font *f = htmlFont( false ); int wordSpacing = style()->wordSpacing(); int len = str->l; bool isSpace = false; bool firstWord = true; bool firstLine = true; for(int i = 0; i < len; i++) { unsigned short c = str->s[i].unicode(); bool isNewline = false; // If line-breaks survive to here they are preserved if ( c == '\n' ) { m_hasBreak = true; isNewline = true; isSpace = false; } else isSpace = c == ' '; if ((isSpace || isNewline) && i == 0) m_hasBeginWS = true; if ((isSpace || isNewline) && i == len-1) m_hasEndWS = true; if (i && c == SOFT_HYPHEN) continue; int wordlen = 0; while( i+wordlen < len && (i+wordlen == 0 || str->s[i+wordlen].unicode() != SOFT_HYPHEN) && !(isBreakable( str->s, i+wordlen, str->l )) ) wordlen++; if (wordlen) {#ifndef APPLE_CHANGES int w = f->width(str->s, str->l, i, wordlen);#else int w = widthFromCache(f, i, wordlen);#endif currMinWidth += w; currMaxWidth += w; // Add in wordspacing to our maxwidth, but not if this is the last word. if (wordSpacing && !containsOnlyWhitespace(i+wordlen, len-(i+wordlen))) currMaxWidth += wordSpacing; if (firstWord) { firstWord = false; m_beginMinWidth = w; } m_endMinWidth = w; if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; currMinWidth = 0; i += wordlen-1; } else { // Nowrap can never be broken, so don't bother setting the // breakable character boolean. Pre can only be broken if we encounter a newline. if (style()->autoWrap() || isNewline) m_hasBreakableChar = true; if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; currMinWidth = 0; if (isNewline) // Only set if isPre was true and we saw a newline. { if ( firstLine ) { firstLine = false; m_beginMinWidth = currMaxWidth; } if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth; currMaxWidth = 0; } else { currMaxWidth += f->width( str->s, str->l, i + wordlen ); } } } if(currMinWidth > m_minWidth) m_minWidth = currMinWidth; if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth; if (!style()->autoWrap()) { m_minWidth = m_maxWidth; if (style()->preserveLF()) { if (firstLine) m_beginMinWidth = m_maxWidth; m_endMinWidth = currMaxWidth; } } setMinMaxKnown(); //kdDebug( 6040 ) << "Text::calcMinMaxWidth(): min = " << m_minWidth << " max = " << m_maxWidth << endl;}int RenderText::minXPos() const{ if (!m_lines.count()) return 0; int retval=6666666; for (unsigned i=0;i < m_lines.count(); i++) { retval = kMin ( retval, int( m_lines[i]->m_x )); } return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -