Commit abdc5919 authored by antti's avatar antti
Browse files

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:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@20610 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 57cac343
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.
......@@ -178,9 +178,10 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
// 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.
......@@ -508,6 +509,11 @@ float Font::xHeight() const
return primaryFont()->xHeight();
}
int Font::spaceWidth() const
{
return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
}
bool Font::isFixedPitch() const
{
ASSERT(m_fontList);
......
......@@ -147,6 +147,8 @@ public:
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;
......
......@@ -25,9 +25,9 @@ namespace WebCore {
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)
......@@ -38,7 +38,7 @@ public:
{
}
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; }
......@@ -52,7 +52,7 @@ public:
void setRTL(bool b) { m_rtl = b; }
private:
int m_tabWidth;
bool m_allowTabs;
int m_xpos;
int m_padding;
bool m_rtl;
......
......@@ -126,7 +126,7 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
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);
......@@ -410,7 +410,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
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
......@@ -533,7 +533,7 @@ void InlineTextBox::paintSelection(GraphicsContext* p, int tx, int ty, RenderSty
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();
}
......@@ -556,7 +556,7 @@ void InlineTextBox::paintMarkedTextBackground(GraphicsContext* p, int tx, int ty
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();
}
......@@ -639,7 +639,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
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);
......@@ -676,7 +676,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do
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
......@@ -827,7 +827,7 @@ int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
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);
}
......@@ -842,7 +842,7 @@ int InlineTextBox::positionForOffset(int offset) const
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();
}
......
......@@ -100,7 +100,6 @@ RenderBlock::RenderBlock(Node* node)
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;
......@@ -135,7 +134,6 @@ void RenderBlock::setStyle(RenderStyle* _style)
}
m_lineHeight = -1;
m_tabWidth = -1;
// Update pseudos for :before and :after now.
updatePseudoChild(RenderStyle::BEFORE);
......
......@@ -137,7 +137,6 @@ public:
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();
......@@ -459,9 +458,7 @@ protected:
int m_overflowTop;
private:
// full width of a tab character
int m_tabWidth;
// Column information.
int m_desiredColumnWidth;
unsigned m_desiredColumnCount;
......
......@@ -2392,14 +2392,6 @@ int RenderObject::paddingRight() const
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());
......
......@@ -420,8 +420,6 @@ public:
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).
......
......@@ -64,7 +64,6 @@ RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
, m_linesDirty(false)
, m_containsReversedText(false)
, m_isAllASCII(m_text ? charactersAreAllASCII(m_text.get()) : true)
, m_monospaceCharacterWidth(0)
{
setRenderText();
if (m_text)
......@@ -78,8 +77,6 @@ void RenderText::setStyle(RenderStyle* newStyle)
if (oldStyle == newStyle)
return;
bool fontChanged = !oldStyle || oldStyle->font() != newStyle->font();
ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
......@@ -93,9 +90,6 @@ void RenderText::setStyle(RenderStyle* newStyle)
if (RefPtr<StringImpl> textToTransform = originalText())
setText(textToTransform.release(), true);
}
if (fontChanged)
updateMonospaceCharacterWidth();
}
void RenderText::destroy()
......@@ -394,22 +388,13 @@ IntRect RenderText::caretRect(int offset, EAffinity affinity, int* extraWidthToE
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++) {
......@@ -419,7 +404,7 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len,
if (c == '\t' && tabWidth)
w += tabWidth - ((xPos + w) % tabWidth);
else
w += m_monospaceCharacterWidth;
w += monospaceCharacterWidth;
if (isspace(c) && !isspace(previousChar))
w += f.wordSpacing();
}
......@@ -428,7 +413,7 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len,
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,
......@@ -487,7 +472,7 @@ 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;
......@@ -601,7 +586,7 @@ void RenderText::calcMinMaxWidthInternal(int leadWidth)
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;
......@@ -652,7 +637,7 @@ void RenderText::calcMinMaxWidthInternal(int leadWidth)
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;
}
}
......@@ -823,7 +808,6 @@ static inline bool isInlineFlowOrEmptyText(RenderObject* o)
void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
{
bool wasAllASCII = m_isAllASCII;
bool isAllASCII = true;
m_text = text;
......@@ -909,9 +893,6 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
ASSERT(!isBR() || (textLength() == 1 && (*m_text)[0] == '\n'));
ASSERT(!textLength() || characters());
if (wasAllASCII != isAllASCII)
updateMonospaceCharacterWidth();
}
void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
......@@ -1009,9 +990,9 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, const Font&
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;
}
......
......@@ -125,6 +125,8 @@ public:
InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
int allowTabs() const { return !style()->collapseWhiteSpace(); }
protected:
void setTextInternal(PassRefPtr<StringImpl>);
......@@ -138,8 +140,7 @@ private:
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;
......@@ -164,8 +165,6 @@ private:
// or removed).
bool m_containsReversedText : 1;
bool m_isAllASCII : 1;
int m_monospaceCharacterWidth;
};
} // namespace WebCore
......
......@@ -929,22 +929,6 @@ RootInlineBox* RenderBlock::constructLine(const BidiIterator& start, const BidiI
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.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment