Render tree memory savings, part 1
- Eliminate caching of monospace char width from RenderText. This optimization is not needed
anymore since Font already caches space width (RenderText -4 bytes)
- Eliminate caching of tab width from RenderBlock. Similary this optimization has become
obsolete (RenderBlock -4 bytes)
* platform/Font.cpp:
(WebCore::WidthIterator::advance):
(WebCore::Font::spaceWidth):
* platform/Font.h:
(WebCore::Font::tabWidth):
* platform/TextStyle.h:
(WebCore::TextStyle::TextStyle):
(WebCore::TextStyle::allowTabs):
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::selectionRect):
(WebCore::InlineTextBox::paint):
(WebCore::InlineTextBox::paintSelection):
(WebCore::InlineTextBox::paintMarkedTextBackground):
(WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
(WebCore::InlineTextBox::paintTextMatchMarker):
(WebCore::InlineTextBox::offsetForPosition):
(WebCore::InlineTextBox::positionForOffset):
* rendering/RenderBlock.cpp:
(WebCore:::RenderFlow):
(WebCore::RenderBlock::setStyle):
* rendering/RenderBlock.h:
* rendering/RenderObject.cpp:
* rendering/RenderObject.h:
* rendering/RenderText.cpp:
(WebCore::RenderText::RenderText):
(WebCore::RenderText::setStyle):
(WebCore::RenderText::widthFromCache):
(WebCore::RenderText::trimmedMinMaxWidth):
(WebCore::RenderText::calcMinMaxWidthInternal):
(WebCore::RenderText::setTextInternal):
(WebCore::RenderText::width):
* rendering/RenderText.h:
(WebCore::RenderText::allowTabs):
* rendering/bidi.cpp:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@20610
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-03-30 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Hyatt.
+
+ Render tree memory savings, part 1
+
+ - Eliminate caching of monospace char width from RenderText. This optimization is not needed
+ anymore since Font already caches space width (RenderText -4 bytes)
+ - Eliminate caching of tab width from RenderBlock. Similary this optimization has become
+ obsolete (RenderBlock -4 bytes)
+
+ * platform/Font.cpp:
+ (WebCore::WidthIterator::advance):
+ (WebCore::Font::spaceWidth):
+ * platform/Font.h:
+ (WebCore::Font::tabWidth):
+ * platform/TextStyle.h:
+ (WebCore::TextStyle::TextStyle):
+ (WebCore::TextStyle::allowTabs):
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::selectionRect):
+ (WebCore::InlineTextBox::paint):
+ (WebCore::InlineTextBox::paintSelection):
+ (WebCore::InlineTextBox::paintMarkedTextBackground):
+ (WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
+ (WebCore::InlineTextBox::paintTextMatchMarker):
+ (WebCore::InlineTextBox::offsetForPosition):
+ (WebCore::InlineTextBox::positionForOffset):
+ * rendering/RenderBlock.cpp:
+ (WebCore:::RenderFlow):
+ (WebCore::RenderBlock::setStyle):
+ * rendering/RenderBlock.h:
+ * rendering/RenderObject.cpp:
+ * rendering/RenderObject.h:
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::RenderText):
+ (WebCore::RenderText::setStyle):
+ (WebCore::RenderText::widthFromCache):
+ (WebCore::RenderText::trimmedMinMaxWidth):
+ (WebCore::RenderText::calcMinMaxWidthInternal):
+ (WebCore::RenderText::setTextInternal):
+ (WebCore::RenderText::width):
+ * rendering/RenderText.h:
+ (WebCore::RenderText::allowTabs):
+ * rendering/bidi.cpp:
+
2007-03-30 David Hyatt <hyatt@apple.com>
Fix (take 2) for bug 4334, flickering when floating elements gain/lose transparency.
// Now that we have a glyph and font data, get its width.
float width;
- if (c == '\t' && m_style.tabWidth())
- width = m_style.tabWidth() - fmodf(m_style.xPos() + runWidthSoFar, m_style.tabWidth());
- else {
+ if (c == '\t' && m_style.allowTabs()) {
+ int tabWidth = m_font->tabWidth();
+ width = tabWidth - fmodf(m_style.xPos() + runWidthSoFar, tabWidth);
+ } else {
width = fontData->widthForGlyph(glyph);
// We special case spaces in two ways when applying word rounding.
// First, we round spaces to an adjusted width in all fonts.
return primaryFont()->xHeight();
}
+int Font::spaceWidth() const
+{
+ return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
+}
+
bool Font::isFixedPitch() const
{
ASSERT(m_fontList);
int height() const { return ascent() + descent(); }
int lineSpacing() const;
float xHeight() const;
+ int spaceWidth() const;
+ int tabWidth() const { return 8 * spaceWidth(); }
const FontData* primaryFont() const;
const FontData* fontDataAt(unsigned) const;
class TextStyle {
public:
- TextStyle(int tabWidth = 0, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+ TextStyle(bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
bool applyRunRounding = true, bool applyWordRounding = true, bool attemptFontSubstitution = true)
- : m_tabWidth(tabWidth)
+ : m_allowTabs(allowTabs)
, m_xpos(xpos)
, m_padding(padding)
, m_rtl(rtl)
{
}
- int tabWidth() const { return m_tabWidth; }
+ bool allowTabs() const { return m_allowTabs; }
int xPos() const { return m_xpos; }
int padding() const { return m_padding; }
bool rtl() const { return m_rtl; }
void setRTL(bool b) { m_rtl = b; }
private:
- int m_tabWidth;
+ bool m_allowTabs;
int m_xpos;
int m_padding;
bool m_rtl;
const Font& f = textObj->style(m_firstLine)->font();
IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text(), m_start, m_len, sPos, ePos),
- TextStyle(textObj->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride),
+ TextStyle(textObj->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride),
IntPoint(tx + m_x, ty + selTop), selHeight));
if (r.x() > tx + m_x + m_width)
r.setWidth(0);
StringImpl* textStr = textObject()->text();
- TextStyle textStyle(textObject()->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered());
+ TextStyle textStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered());
if (!paintSelectedTextOnly && !paintSelectedTextSeparately) {
// paint all the text
int h = selectionHeight();
p->clip(IntRect(m_x + tx, y + ty, m_width, h));
p->drawHighlightForText(TextRun(textObject()->text(), m_start, m_len, sPos, ePos), IntPoint(m_x + tx, y + ty), h,
- TextStyle(textObject()->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()), c);
+ TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()), c);
p->restore();
}
int h = selectionHeight();
p->drawHighlightForText(TextRun(textObject()->text(), m_start, m_len, sPos, ePos),
IntPoint(m_x + tx, y + ty), h,
- TextStyle(textObject()->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()), c);
+ TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()), c);
p->restore();
}
if (grammar) {
int y = selectionTop();
IntPoint startPoint = IntPoint(m_x + tx, y + ty);
- TextStyle textStyle = TextStyle(textObject()->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
+ TextStyle textStyle = TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
int startPosition = max(marker.startOffset - m_start, (unsigned)0);
int endPosition = min(marker.endOffset - m_start, (unsigned)m_len);
TextRun run = TextRun(textObject()->text(), m_start, m_len, startPosition, endPosition);
int sPos = max(marker.startOffset - m_start, (unsigned)0);
int ePos = min(marker.endOffset - m_start, (unsigned)m_len);
TextRun run = TextRun(textObject()->text(), m_start, m_len, sPos, ePos);
- TextStyle renderStyle = TextStyle(textObject()->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
+ TextStyle renderStyle = TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
IntPoint startPoint = IntPoint(m_x + tx, y + ty);
// Always compute and store the rect associated with this marker
RenderStyle *style = text->style(m_firstLine);
const Font* f = &style->font();
return f->offsetForPosition(TextRun(textObject()->text(), m_start, m_len),
- TextStyle(text->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()),
+ TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()),
_x - m_x, includePartialGlyphs);
}
int to = m_reversed ? m_len : offset - m_start;
// FIXME: Do we need to add rightBearing here?
return enclosingIntRect(f.selectionRectForText(TextRun(text->text(), m_start, m_len, from, to),
- TextStyle(text->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride),
+ TextStyle(textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride),
IntPoint(m_x, 0), 0)).right();
}
m_topMarginQuirk = m_bottomMarginQuirk = false;
m_overflowHeight = m_overflowWidth = 0;
m_overflowLeft = m_overflowTop = 0;
- m_tabWidth = -1;
m_desiredColumnCount = 1;
m_desiredColumnWidth = 0;
m_columnRects = 0;
}
m_lineHeight = -1;
- m_tabWidth = -1;
// Update pseudos for :before and :after now.
updatePseudoChild(RenderStyle::BEFORE);
BidiIterator findNextLineBreak(BidiIterator& start, BidiState& info);
RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end);
InlineFlowBox* createLineBoxes(RenderObject*);
- int tabWidth(bool isWhitespacePre);
void computeHorizontalPositionsForLine(RootInlineBox*, BidiState&);
void computeVerticalPositionsForLine(RootInlineBox*);
void checkLinesForOverflow();
int m_overflowTop;
private:
- // full width of a tab character
- int m_tabWidth;
-
+
// Column information.
int m_desiredColumnWidth;
unsigned m_desiredColumnCount;
return w;
}
-int RenderObject::tabWidth() const
-{
- if (style()->collapseWhiteSpace())
- return 0;
-
- return containingBlock()->tabWidth(true);
-}
-
RenderView* RenderObject::view() const
{
return static_cast<RenderView*>(document()->renderer());
virtual short verticalPositionHint(bool firstLine) const;
// the offset of baseline from the top of the object.
virtual short baselinePosition(bool firstLine, bool isRootLineBox = false) const;
- // width of tab character
- int tabWidth() const;
/*
* Paint the object and its children, clipped by (x|y|w|h).
, m_linesDirty(false)
, m_containsReversedText(false)
, m_isAllASCII(m_text ? charactersAreAllASCII(m_text.get()) : true)
- , m_monospaceCharacterWidth(0)
{
setRenderText();
if (m_text)
if (oldStyle == newStyle)
return;
- bool fontChanged = !oldStyle || oldStyle->font() != newStyle->font();
-
ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
if (RefPtr<StringImpl> textToTransform = originalText())
setText(textToTransform.release(), true);
}
-
- if (fontChanged)
- updateMonospaceCharacterWidth();
}
void RenderText::destroy()
return IntRect(left, top, 1, height);
}
-void RenderText::updateMonospaceCharacterWidth()
+ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos) const
{
- const Font& f = style()->font();
if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) {
- const UChar c = ' ';
- m_monospaceCharacterWidth = f.width(TextRun(&c, 1));
- return;
- }
- m_monospaceCharacterWidth = 0;
-}
-
-ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int tabWidth, int xPos) const
-{
- if (m_monospaceCharacterWidth) {
// FIXME: This code should be simplfied; it's only run when m_text is known to be all 0000-007F,
// but is uses the general purpose Unicode direction function.
+ int monospaceCharacterWidth = f.spaceWidth();
+ int tabWidth = allowTabs() ? monospaceCharacterWidth * 8 : 0;
int w = 0;
char previousChar = ' '; // FIXME: Preserves historical behavior, but seems wrong for start > 0.
for (int i = start; i < start + len; i++) {
if (c == '\t' && tabWidth)
w += tabWidth - ((xPos + w) % tabWidth);
else
- w += m_monospaceCharacterWidth;
+ w += monospaceCharacterWidth;
if (isspace(c) && !isspace(previousChar))
w += f.wordSpacing();
}
return w;
}
- return f.width(TextRun(text(), start, len, 0), TextStyle(tabWidth, xPos));
+ return f.width(TextRun(text(), start, len, 0), TextStyle(allowTabs(), xPos));
}
void RenderText::trimmedMinMaxWidth(int leadWidth,
linelen++;
if (linelen) {
- endMaxW = widthFromCache(f, i, linelen, tabWidth(), leadWidth + endMaxW);
+ endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW);
if (firstLine) {
firstLine = false;
leadWidth = 0;
int wordLen = j - i;
if (wordLen) {
- int w = widthFromCache(f, i, wordLen, tabWidth(), leadWidth + currMaxWidth);
+ int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth);
currMinWidth += w;
currMaxWidth += w;
m_maxWidth = currMaxWidth;
currMaxWidth = 0;
} else {
- currMaxWidth += f.width(TextRun(txt + i, 1), TextStyle(tabWidth(), leadWidth + currMaxWidth));
+ currMaxWidth += f.width(TextRun(txt + i, 1), TextStyle(allowTabs(), leadWidth + currMaxWidth));
needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
}
}
void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
{
- bool wasAllASCII = m_isAllASCII;
bool isAllASCII = true;
m_text = text;
ASSERT(!isBR() || (textLength() == 1 && (*m_text)[0] == '\n'));
ASSERT(!textLength() || characters());
-
- if (wasAllASCII != isAllASCII)
- updateMonospaceCharacterWidth();
}
void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
if (!style()->preserveNewline() && !from && len == textLength())
w = m_maxWidth;
else
- w = widthFromCache(f, from, len, tabWidth(), xPos);
+ w = widthFromCache(f, from, len, xPos);
} else
- w = f.width(TextRun(text(), from, len, 0), TextStyle(tabWidth(), xPos));
+ w = f.width(TextRun(text(), from, len, 0), TextStyle(allowTabs(), xPos));
return w;
}
InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
+ int allowTabs() const { return !style()->collapseWhiteSpace(); }
+
protected:
void setTextInternal(PassRefPtr<StringImpl>);
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
void calcMinMaxWidthInternal(int leadWidth);
- void updateMonospaceCharacterWidth();
- int widthFromCache(const Font&, int start, int len, int tabWidth, int xPos) const;
+ int widthFromCache(const Font&, int start, int len, int xPos) const;
bool isAllASCII() const { return m_isAllASCII; }
RefPtr<StringImpl> m_text;
// or removed).
bool m_containsReversedText : 1;
bool m_isAllASCII : 1;
-
- int m_monospaceCharacterWidth;
};
} // namespace WebCore
return lastRootBox();
}
-// usage: tw - (xpos % tw);
-int RenderBlock::tabWidth(bool isWhitespacePre)
-{
- if (!isWhitespacePre)
- return 0;
-
- if (m_tabWidth == -1) {
- const UChar spaceChar = ' ';
- const Font& font = style()->font();
- int spaceWidth = font.width(TextRun(&spaceChar, 1));
- m_tabWidth = spaceWidth * 8;
- }
-
- return m_tabWidth;
-}
-
void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState& bidi)
{
// First determine our total width.