Commit 9409ba5b authored by rjw's avatar rjw

WebCore:

        Fixed 3133261.  This fix really has two parts.  This first part
        fixes the stupid stack allocated buffer that caused the crash.
        The second part makes any RenderText with a large string perform
        much faster.  The page mentioned in the bug used to load and draw
        in about 15 minutes.  Now it loads in about 10 seconds and draws in about
        2 seconds.  The performance optimization caches a widths array
        for the string in the RenderText, and only updates that array if
        the font or text for the RenderText change.

        Reviewed by john.

        * khtml/rendering/render_text.cpp:
        (RenderText::RenderText):
        (RenderText::setStyle):
        (RenderText::~RenderText):
        (RenderText::computeWidths):
        (RenderText::widthFromBuffer):
        (RenderText::trimmedMinMaxWidth):
        (RenderText::calcMinMaxWidth):
        (RenderText::setText):
        (RenderText::width):
        * khtml/rendering/render_text.h:

WebKit:
        Fixed 3133261.  This fix really has two parts.  This first part
        is here in WebTextRenderer.  The second part adds some width
        caching to RenderText.  I was using a stack allocated array,
        this would blow out the stack for large strings.

        Reviewed by john.

        * WebCoreSupport.subproj/WebTextRenderer.m:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@3152 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2bacd046
2002-12-20 Richard Williamson <rjw@apple.com>
Fixed 3133261. This fix really has two parts. This first part
fixes the stupid stack allocated buffer that caused the crash.
The second part makes any RenderText with a large string perform
much faster. The page mentioned in the bug used to load and draw
in about 15 minutes. Now it loads in about 10 seconds and draws in about
2 seconds. The performance optimization caches a widths array
for the string in the RenderText, and only updates that array if
the font or text for the RenderText change.
Reviewed by john.
* khtml/rendering/render_text.cpp:
(RenderText::RenderText):
(RenderText::setStyle):
(RenderText::~RenderText):
(RenderText::computeWidths):
(RenderText::widthFromBuffer):
(RenderText::trimmedMinMaxWidth):
(RenderText::calcMinMaxWidth):
(RenderText::setText):
(RenderText::width):
* khtml/rendering/render_text.h:
2002-12-20 Trey Matteson <trey@apple.com>
We now build with symbols the B&I. Deployment builds are without symbols,
......
2002-12-20 Richard Williamson <rjw@apple.com>
Fixed 3133261. This fix really has two parts. This first part
fixes the stupid stack allocated buffer that caused the crash.
The second part makes any RenderText with a large string perform
much faster. The page mentioned in the bug used to load and draw
in about 15 minutes. Now it loads in about 10 seconds and draws in about
2 seconds. The performance optimization caches a widths array
for the string in the RenderText, and only updates that array if
the font or text for the RenderText change.
Reviewed by john.
* khtml/rendering/render_text.cpp:
(RenderText::RenderText):
(RenderText::setStyle):
(RenderText::~RenderText):
(RenderText::computeWidths):
(RenderText::widthFromBuffer):
(RenderText::trimmedMinMaxWidth):
(RenderText::calcMinMaxWidth):
(RenderText::setText):
(RenderText::width):
* khtml/rendering/render_text.h:
2002-12-20 Trey Matteson <trey@apple.com>
We now build with symbols the B&I. Deployment builds are without symbols,
......
......@@ -326,6 +326,9 @@ RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
m_minWidth = -1;
m_maxWidth = -1;
#if APPLE_CHANGES
m_widths = 0;
#endif
str = _str;
if(str) str->ref();
KHTMLAssert(!str || !str->l || str->s);
......@@ -351,12 +354,21 @@ void RenderText::setStyle(RenderStyle *_style)
if (changedText && element() && element()->string())
setText(element()->string(), changedText);
#if APPLE_CHANGES
// set also call computeWidths(), so no need to recache if that has already been done.
else
computeWidths();
#endif
}
}
RenderText::~RenderText()
{
if(str) str->deref();
#if APPLE_CHANGES
if (m_widths)
free (m_widths);
#endif
}
void RenderText::detach(RenderArena* renderArena)
......@@ -760,6 +772,50 @@ void RenderText::paint(QPainter *p, int x, int y, int w, int h,
paintObject(p, x, y, w, h, tx, ty, paintPhase);
}
#ifdef APPLE_CHANGES
// We cache the widths array for the characters in the string only
// if the string is very large. This is a short term performance
// optimization. It has the downside of increasing the size
// of each render text by float * str->l. The performance
// gained is huge though, so this is justifiable. The long term
// fix is to rework the word break/line break/bidi mechanisms
// to reduce the measurement performed, and to correctly account
// for unicode break points and surrogate pairs.
#define MIN_STRING_LENGTH_FOR_WIDTH_CACHE 1024
void RenderText::computeWidths()
{
const Font *f = htmlFont( false );
if (f){
if (m_widths){
free (m_widths);
m_widths = 0;
}
if (str->l > MIN_STRING_LENGTH_FOR_WIDTH_CACHE){
m_widths = (float *)malloc(str->l * sizeof(float));
f->floatCharacterWidths( str->s, str->l, 0, str->l, 0, m_widths);
}
}
}
inline int RenderText::widthFromBuffer(const Font *f, int start, int len) const
{
float width = 0;
int i;
if (m_widths == 0)
return f->width(str->s, str->l, start, len);
for (i = start; i < start+len; i++){
width += m_widths[i];
}
return (int)width;
}
#endif
void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
short& endMinW, bool& endWS,
bool& hasBreakableChar, bool& hasBreak,
......@@ -781,7 +837,6 @@ void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
endMinW = m_endMinWidth;
hasBreakableChar = m_hasBreakableChar;
hasBreak = m_hasBreak;
if (len == 0)
return;
......@@ -799,35 +854,9 @@ void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
minW = maxW;
else if (minW > maxW)
minW = maxW;
// Compute our max widths by scanning the string for newlines.
if (hasBreak) {
const Font *f = htmlFont( false );
bool firstLine = true;
beginMaxW = endMaxW = maxW;
for(int i = 0; i < len; i++)
{
int linelen = 0;
while( i+linelen < len && str->s[i+linelen] != '\n')
linelen++;
if (linelen)
{
endMaxW = f->width(str->s, str->l, i, linelen);
if (firstLine) {
firstLine = false;
beginMaxW = endMaxW;
}
i += linelen;
if (i == len-1)
endMaxW = 0;
}
else if (firstLine) {
beginMaxW = 0;
firstLine = false;
}
}
}
beginMaxW = m_beginMaxWidth;
endMaxW = m_endMaxWidth;
}
void RenderText::calcMinMaxWidth()
......@@ -836,7 +865,7 @@ void RenderText::calcMinMaxWidth()
// ### calc Min and Max width...
m_minWidth = m_beginMinWidth = m_endMinWidth = 0;
m_maxWidth = 0;
m_maxWidth = m_beginMaxWidth = m_endMaxWidth = 0;
if (isBR())
return;
......@@ -889,7 +918,11 @@ void RenderText::calcMinMaxWidth()
if (wordlen)
{
#if !APPLE_CHANGES
int w = f->width(str->s, str->l, i, wordlen);
#else
int w = widthFromBuffer(f, i, wordlen);
#endif
currMinWidth += w;
currMaxWidth += w;
if (firstWord) {
......@@ -930,6 +963,39 @@ void RenderText::calcMinMaxWidth()
if (style()->whiteSpace() == NOWRAP)
m_minWidth = m_maxWidth;
// Compute our max widths by scanning the string for newlines.
m_beginMaxWidth = m_endMaxWidth = m_maxWidth;
if (m_hasBreak) {
const Font *f = htmlFont( false );
bool firstLine = true;
for(int i = 0; i < len; i++)
{
int linelen = 0;
while( i+linelen < len && str->s[i+linelen] != '\n')
linelen++;
if (linelen)
{
#if !APPLE_CHANGES
m_endMaxWidth = f->width(str->s, str->l, i, linelen);
#else
m_endMaxWidth = widthFromBuffer(f, i, linelen);
#endif
if (firstLine) {
firstLine = false;
m_beginMaxWidth = m_endMaxWidth;
}
i += linelen;
if (i == len-1)
m_endMaxWidth = 0;
}
else if (firstLine) {
m_beginMaxWidth = 0;
firstLine = false;
}
}
}
setMinMaxKnown();
//kdDebug( 6040 ) << "Text::calcMinMaxWidth(): min = " << m_minWidth << " max = " << m_maxWidth << endl;
}
......@@ -991,6 +1057,9 @@ void RenderText::setText(DOMStringImpl *text, bool force)
str->ref();
}
#if APPLE_CHANGES
computeWidths();
#endif
// ### what should happen if we change the text of a
// RenderBR object ?
KHTMLAssert(!isBR() || (str->l == 1 && (*str->s) == '\n'));
......@@ -1082,6 +1151,10 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *
int w;
if ( f == &style()->htmlFont() && from == 0 && len == str->l )
w = m_maxWidth;
#if APPLE_CHANGES
else if (f == &style()->htmlFont())
w = widthFromBuffer (f, from, len);
#endif
else
w = f->width(str->s, str->l, from, len );
......
......@@ -217,6 +217,8 @@ public:
#if APPLE_CHANGES
TextSlave * findTextSlave( int offset, int &pos );
TextSlaveArray textSlaves() { return m_lines; }
int widthFromBuffer(const Font *, int start, int len) const;
void computeWidths();
#endif
protected:
......@@ -236,6 +238,8 @@ protected: // members
short m_maxWidth;
short m_beginMinWidth;
short m_endMinWidth;
short m_beginMaxWidth;
short m_endMaxWidth;
SelectionState m_selectionState : 3 ;
bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
......@@ -244,6 +248,9 @@ protected: // members
bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
// 19 bits left
#if APPLE_CHANGES
float *m_widths;
#endif
};
......
2002-12-20 Richard Williamson <rjw@apple.com>
Fixed 3133261. This fix really has two parts. This first part
is here in WebTextRenderer. The second part adds some width
caching to RenderText. I was using a stack allocated array,
this would blow out the stack for large strings.
Reviewed by john.
* WebCoreSupport.subproj/WebTextRenderer.m:
2002-12-20 Trey Matteson <trey@apple.com>
We now build with symbols the B&I. Deployment builds are without symbols,
......
......@@ -889,7 +889,8 @@ - (float)_floatWidthForCharacters:(const UniChar *)characters stringLength:(unsi
#define SHAPE_STRINGS
#ifdef SHAPE_STRINGS
UniChar munged[stringLength];
UniChar *munged = 0;
UniChar _localMunged[LOCAL_BUFFER_SIZE];
{
UniChar *shaped;
int lengthOut;
......@@ -898,6 +899,10 @@ - (float)_floatWidthForCharacters:(const UniChar *)characters stringLength:(unsi
len,
0, &lengthOut);
if (shaped){
if (stringLength < LOCAL_BUFFER_SIZE)
munged = &_localMunged[0];
else
munged = (UniChar *)malloc(stringLength * sizeof(UniChar));
//printf ("%d input, %d output\n", len, lengthOut);
//for (i = 0; i < (int)len; i++){
// printf ("0x%04x shaped to 0x%04x\n", characters[i], shaped[i]);
......@@ -1126,6 +1131,11 @@ - (float)_floatWidthForCharacters:(const UniChar *)characters stringLength:(unsi
if (_numGlyphs)
*_numGlyphs = numGlyphs;
#ifdef SHAPE_STRINGS
if (munged != &_localMunged[0])
free (munged);
#endif
return totalWidth;
}
......
Markdown is supported
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