Commit b026936c authored by rjw's avatar rjw

WebCore:

        Fixed 3138743, 3138678, and 3138854.  Removed the RenderText
        widths cache, replaced it with a much simply monospace character
        cache.  Should be much faster for covered cases too!  Also fixed
        buffer overrun problem causing the crash in 3138854.

        Reviewed by darin.

        * khtml/rendering/font.cpp:
        (Font::isFixedPitch):
        * khtml/rendering/font.h:
        * khtml/rendering/render_text.cpp:
        (TextSlave::checkSelectionPoint):
        (RenderText::RenderText):
        (RenderText::setStyle):
        (RenderText::~RenderText):
        (RenderText::shouldUseMonospaceCache):
        (RenderText::cacheWidths):
        (RenderText::widthFromCache):
        (RenderText::trimmedMinMaxWidth):
        (RenderText::calcMinMaxWidth):
        (RenderText::setText):
        (RenderText::width):
        * khtml/rendering/render_text.h:
        * kwq/KWQFont.h:
        * kwq/KWQFont.mm:
        (QFont::isFixedPitch):
        * kwq/WebCoreTextRendererFactory.h:
        * kwq/WebCoreTextRendererFactory.m:
        (-[WebCoreTextRendererFactory isFontFixedPitch:]):

WebKit:
        Support for fixes to 3138743, 3138678.  Added
        isFontFixedPitch used to determine if font is fixed
        pitch.  Makes use of appkit private _isFakeFixedPitch
        (detects courier and monoca).  Updated our fakey test
        to use the appkit's version.

        Reviewed by darin.

        * WebCoreSupport.subproj/WebTextRenderer.m:
        * WebCoreSupport.subproj/WebTextRendererFactory.m:
        (-[WebTextRendererFactory isFontFixedPitch:]):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@3250 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4d497e95
2003-01-03 Richard Williamson <rjw@apple.com>
Fixed 3138743, 3138678, and 3138854. Removed the RenderText
widths cache, replaced it with a much simply monospace character
cache. Should be much faster for covered cases too! Also fixed
buffer overrun problem causing the crash in 3138854.
Reviewed by darin.
* khtml/rendering/font.cpp:
(Font::isFixedPitch):
* khtml/rendering/font.h:
* khtml/rendering/render_text.cpp:
(TextSlave::checkSelectionPoint):
(RenderText::RenderText):
(RenderText::setStyle):
(RenderText::~RenderText):
(RenderText::shouldUseMonospaceCache):
(RenderText::cacheWidths):
(RenderText::widthFromCache):
(RenderText::trimmedMinMaxWidth):
(RenderText::calcMinMaxWidth):
(RenderText::setText):
(RenderText::width):
* khtml/rendering/render_text.h:
* kwq/KWQFont.h:
* kwq/KWQFont.mm:
(QFont::isFixedPitch):
* kwq/WebCoreTextRendererFactory.h:
* kwq/WebCoreTextRendererFactory.m:
(-[WebCoreTextRendererFactory isFontFixedPitch:]):
2003-01-03 John Sullivan <sullivan@apple.com>
- fixed 3138673 -- reproducible crash in JavaScript
......
2003-01-03 Richard Williamson <rjw@apple.com>
Fixed 3138743, 3138678, and 3138854. Removed the RenderText
widths cache, replaced it with a much simply monospace character
cache. Should be much faster for covered cases too! Also fixed
buffer overrun problem causing the crash in 3138854.
Reviewed by darin.
* khtml/rendering/font.cpp:
(Font::isFixedPitch):
* khtml/rendering/font.h:
* khtml/rendering/render_text.cpp:
(TextSlave::checkSelectionPoint):
(RenderText::RenderText):
(RenderText::setStyle):
(RenderText::~RenderText):
(RenderText::shouldUseMonospaceCache):
(RenderText::cacheWidths):
(RenderText::widthFromCache):
(RenderText::trimmedMinMaxWidth):
(RenderText::calcMinMaxWidth):
(RenderText::setText):
(RenderText::width):
* khtml/rendering/render_text.h:
* kwq/KWQFont.h:
* kwq/KWQFont.mm:
(QFont::isFixedPitch):
* kwq/WebCoreTextRendererFactory.h:
* kwq/WebCoreTextRendererFactory.m:
(-[WebCoreTextRendererFactory isFontFixedPitch:]):
2003-01-03 John Sullivan <sullivan@apple.com>
- fixed 3138673 -- reproducible crash in JavaScript
......
......@@ -248,3 +248,11 @@ void Font::update( QPaintDeviceMetrics* devMetrics ) const
fontDef.hasNbsp = fm.inFont( 0xa0 );
#endif
}
#ifdef APPLE_CHANGES
bool Font::isFixedPitch() const
{
return f.isFixedPitch();
}
#endif
......@@ -102,6 +102,7 @@ public:
QPainter::TextDirection d) const;
float floatWidth( QChar *str, int slen, int pos, int len ) const;
void floatCharacterWidths( QChar *str, int slen, int pos, int len, int toAdd, float *buffer) const;
bool isFixedPitch() const;
#endif
int width( QChar *str, int slen, int pos, int len ) const;
int width( QChar *str, int slen, int pos ) const;
......
......@@ -175,6 +175,8 @@ void TextSlave::paintBoxDecorations(QPainter *pt, RenderStyle* style, RenderText
p->paintBorder(pt, _tx, _ty, width, height, style, begin, end);
}
#define LOCAL_WIDTH_BUF_SIZE 1024
FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int _ty, const Font *f, RenderText *text, int & offset, short lineHeight)
{
// kdDebug(6040) << "TextSlave::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y
......@@ -203,15 +205,27 @@ FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int
#if APPLE_CHANGES
// Floating point version needed for best results with Mac OS X text.
float delta = _x - (_tx + m_x);
float widths[text->str->l];
// Do width calculations for whole run once.
f->floatCharacterWidths( text->str->s, text->str->l, m_start, m_len, m_toAdd, &widths[0]);
float _widths[LOCAL_WIDTH_BUF_SIZE];
float *widths = 0;
float monospaceWidth = 0;
if (text->shouldUseMonospaceCache(f)){
monospaceWidth = text->widthFromCache (f, m_start, 1);
}
else {
if (text->str->l > LOCAL_WIDTH_BUF_SIZE)
widths = (float *)malloc(text->str->l * sizeof(float));
else
widths = &_widths[0];
// Do width calculations for whole run once.
f->floatCharacterWidths( text->str->s, text->str->l, m_start, m_len, m_toAdd, &widths[0]);
}
int pos = 0;
if ( m_reversed ) {
delta -= m_width;
while(pos < m_len) {
float w = widths[pos+m_start];
float w = (monospaceWidth != 0 ? monospaceWidth : widths[pos+m_start]);
float w2 = w/2;
w -= w2;
delta += w2;
......@@ -222,7 +236,7 @@ FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int
}
} else {
while(pos < m_len) {
float w = widths[pos+m_start];
float w = (monospaceWidth != 0 ? monospaceWidth : widths[pos+m_start]);
float w2 = w/2;
w -= w2;
delta -= w2;
......@@ -232,6 +246,9 @@ FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int
delta -= w;
}
}
if (widths != _widths)
free (widths);
#else
int delta = _x - (_tx + m_x);
//kdDebug(6040) << "TextSlave::checkSelectionPoint delta=" << delta << endl;
......@@ -326,9 +343,11 @@ RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
m_minWidth = -1;
m_maxWidth = -1;
#if APPLE_CHANGES
m_widths = 0;
#ifdef APPLE_CHANGES
m_monospaceCharacterWidth = 0;
#endif
str = _str;
if(str) str->ref();
KHTMLAssert(!str || !str->l || str->s);
......@@ -355,9 +374,9 @@ 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.
// set also call cacheWidths(), so no need to recache if that has already been done.
else
computeWidths();
cacheWidths();
#endif
}
}
......@@ -365,10 +384,6 @@ void RenderText::setStyle(RenderStyle *_style)
RenderText::~RenderText()
{
if(str) str->deref();
#if APPLE_CHANGES
if (m_widths)
free (m_widths);
#endif
}
void RenderText::detach(RenderArena* renderArena)
......@@ -774,48 +789,36 @@ void RenderText::paint(QPainter *p, int x, int y, int w, int h,
#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()
bool RenderText::shouldUseMonospaceCache(const Font *f) const
{
return (f && f->isFixedPitch());
}
// We cache the width of the ' ' character for <pre> text. We could go futher
// and cache a widths array for all styles, at the expense of increasing the size of the
// RenderText.
void RenderText::cacheWidths()
{
const Font *f = htmlFont( false );
if (f){
if (m_widths){
free (m_widths);
m_widths = 0;
}
// Only cache widths array if style()->whiteSpace() == PRE. This prevents
// inappropriate mismeasurement of extra whitespace embedded in the string.
if (str->l >= MIN_STRING_LENGTH_FOR_WIDTH_CACHE && style()->whiteSpace() == PRE){
m_widths = (float *)malloc(str->l * sizeof(float));
f->floatCharacterWidths( str->s, str->l, 0, str->l, 0, m_widths);
}
if (shouldUseMonospaceCache(f)){
float fw;
QChar c(' ');
f->floatCharacterWidths( &c, 1, 0, 1, 0, &fw);
m_monospaceCharacterWidth = (int)fw;
}
else
m_monospaceCharacterWidth = 0;
}
inline int RenderText::widthFromBuffer(const Font *f, int start, int len) const
inline int RenderText::widthFromCache(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];
if (m_monospaceCharacterWidth != 0){
return len * m_monospaceCharacterWidth;
}
return (int)width;
return f->width(str->s, str->l, start, len);
}
#endif
......@@ -875,7 +878,7 @@ void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
#if !APPLE_CHANGES
endMaxW = f->width(str->s, str->l, i, linelen);
#else
endMaxW = widthFromBuffer(f, i, linelen);
endMaxW = widthFromCache(f, i, linelen);
#endif
if (firstLine) {
firstLine = false;
......@@ -955,7 +958,7 @@ void RenderText::calcMinMaxWidth()
#if !APPLE_CHANGES
int w = f->width(str->s, str->l, i, wordlen);
#else
int w = widthFromBuffer(f, i, wordlen);
int w = widthFromCache(f, i, wordlen);
#endif
currMinWidth += w;
currMaxWidth += w;
......@@ -1059,7 +1062,7 @@ void RenderText::setText(DOMStringImpl *text, bool force)
}
#if APPLE_CHANGES
computeWidths();
cacheWidths();
#endif
// ### what should happen if we change the text of a
// RenderBR object ?
......@@ -1154,7 +1157,7 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *
w = m_maxWidth;
#if APPLE_CHANGES
else if (f == &style()->htmlFont())
w = widthFromBuffer (f, from, len);
w = widthFromCache (f, from, len);
#endif
else
w = f->width(str->s, str->l, from, len );
......
......@@ -217,8 +217,9 @@ 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();
int widthFromCache(const Font *, int start, int len) const;
bool shouldUseMonospaceCache(const Font *) const;
void cacheWidths();
#endif
protected:
......@@ -247,7 +248,7 @@ protected: // members
// 19 bits left
#if APPLE_CHANGES
float *m_widths;
int m_monospaceCharacterWidth;
#endif
};
......
......@@ -61,6 +61,8 @@ public:
void setPixelSize(float s);
int pixelSize() const { return (int)_size; }
bool isFixedPitch() const;
bool operator==(const QFont &x) const;
bool operator!=(const QFont &x) const { return !(*this == x); }
......
......@@ -136,6 +136,12 @@ bool QFont::bold() const
return _trait & NSBoldFontMask;
}
bool QFont::isFixedPitch() const
{
return [[WebCoreTextRendererFactory sharedFactory] isFontFixedPitch: getNSFont()];
}
bool QFont::operator==(const QFont &compareFont) const
{
return _family == compareFont._family
......
......@@ -32,6 +32,7 @@
}
+ (WebCoreTextRendererFactory *)sharedFactory;
- (BOOL)isFontFixedPitch: (NSFont *)font;
- (id <WebCoreTextRenderer>)rendererWithFont: (NSFont *)font;
- (NSFont *)fontWithFamilies:(NSString **)families traits:(NSFontTraitMask)traits size:(float)size;
......
......@@ -35,6 +35,10 @@ + (WebCoreTextRendererFactory *)sharedFactory
return sharedFactory;
}
- (BOOL)isFontFixedPitch: (NSFont *)font
{
return NO;
}
- init
{
......
......@@ -35,6 +35,10 @@ static WebCoreTextRendererFactory *sharedFactory;
return sharedFactory;
}
- (BOOL)isFontFixedPitch: (NSFont *)font
{
return NO;
}
- init
{
......
2003-01-03 Richard Williamson <rjw@apple.com>
Support for fixes to 3138743, 3138678. Added
isFontFixedPitch used to determine if font is fixed
pitch. Makes use of appkit private _isFakeFixedPitch
(detects courier and monoca). Updated our fakey test
to use the appkit's version.
Reviewed by darin.
* WebCoreSupport.subproj/WebTextRenderer.m:
* WebCoreSupport.subproj/WebTextRendererFactory.m:
(-[WebTextRendererFactory isFontFixedPitch:]):
2003-01-03 Darin Adler <darin@apple.com>
Reviewed by Chris.
......
......@@ -102,6 +102,7 @@ - (NSGlyph)_defaultGlyphForChar:(unichar)uu;
- (BOOL)_forceAscenderDelta;
- (BOOL)_canDrawOutsideLineHeight;
- (BOOL)_isSystemFont;
- (BOOL)_isFakeFixedPitch;
@end
@class NSCGSFont;
......@@ -436,36 +437,22 @@ - (void)convertUnicodeCharacters: (const UnicodeChar *)characters length: (unsig
}
// Nasty hack to determine if we should round or ceil space widths.
// If the font is monospace, or all the ascii characters have the same
// width as the space character we ceil to ensure that every character
// and the space are the same width. Otherwise we round.
// If the font is monospace, or fake monospace we ceil to ensure that
// every character and the space are the same width. Otherwise we round.
- (void)_computeWidthForSpace
{
float aWidth;
UniChar i;
UniChar c = ' ';
float _spaceWidth;
NSFont *substituteFont;
spaceGlyph = [self extendCharacterToGlyphMapToInclude: c];
_spaceWidth = widthForGlyph(self, glyphToWidthMap, spaceGlyph, 0);
ceiledSpaceWidth = (float)CEIL_TO_INT(_spaceWidth);
roundedSpaceWidth = (float)ROUND_TO_INT(_spaceWidth);
if ([font isFixedPitch]){
if ([font isFixedPitch] || [font _isFakeFixedPitch]){
adjustedSpaceWidth = ceiledSpaceWidth;
}
else {
for (i = 0x21; i < 0x7f; i++){
aWidth = widthForCharacter(self, i, &substituteFont);
if (aWidth != 0 && aWidth != _spaceWidth)
break;
}
if (i == 0x7f){
adjustedSpaceWidth = ceiledSpaceWidth;
}
else {
adjustedSpaceWidth = roundedSpaceWidth;
}
adjustedSpaceWidth = roundedSpaceWidth;
}
spaceWidth = _spaceWidth;
}
......
......@@ -15,6 +15,10 @@
#import <mach-o/dyld.h>
@interface NSFont (WebAppKitSecretAPI)
- (BOOL)_isFakeFixedPitch;
@end
@interface WebFontCacheKey : NSObject
{
NSString *family;
......@@ -250,6 +254,11 @@ + (WebTextRendererFactory *)sharedFactory;
return (WebTextRendererFactory *)[super sharedFactory];
}
- (BOOL)isFontFixedPitch: (NSFont *)font
{
return [font isFixedPitch] || [font _isFakeFixedPitch];
}
- init
{
[super init];
......
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