[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
rjw
rjw at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 05:57:52 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 4fb7fb69f79bd471a3a66748708f6ead830380ba
Author: rjw <rjw at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Mar 18 23:26:30 2002 +0000
Added comments about new layout scheme. Cleaned up code.
Improved core measurement routine.
Turned off logging by default.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@777 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2002-12-03 b/WebCore/ChangeLog-2002-12-03
index 8d37337..9f59876 100644
--- a/WebCore/ChangeLog-2002-12-03
+++ b/WebCore/ChangeLog-2002-12-03
@@ -1,3 +1,11 @@
+2002-03-18 Richard Williamson <rjw at apple.com>
+
+ Added comments about new layout scheme. Cleaned up code.
+ Improved core measurement routine.
+
+ * src/kwq/KWQFontMetrics.mm: (QFontMetrics::boundingRect):
+ * src/kwq/kwqdebug.h:
+
2002-03-18 Darin Adler <darin at apple.com>
* src/kwq/KWQString.mm: (QString::latin1): Handle null case properly.
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index 8d37337..9f59876 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,11 @@
+2002-03-18 Richard Williamson <rjw at apple.com>
+
+ Added comments about new layout scheme. Cleaned up code.
+ Improved core measurement routine.
+
+ * src/kwq/KWQFontMetrics.mm: (QFontMetrics::boundingRect):
+ * src/kwq/kwqdebug.h:
+
2002-03-18 Darin Adler <darin at apple.com>
* src/kwq/KWQString.mm: (QString::latin1): Handle null case properly.
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 8d37337..9f59876 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,11 @@
+2002-03-18 Richard Williamson <rjw at apple.com>
+
+ Added comments about new layout scheme. Cleaned up code.
+ Improved core measurement routine.
+
+ * src/kwq/KWQFontMetrics.mm: (QFontMetrics::boundingRect):
+ * src/kwq/kwqdebug.h:
+
2002-03-18 Darin Adler <darin at apple.com>
* src/kwq/KWQString.mm: (QString::latin1): Handle null case properly.
diff --git a/WebCore/kwq/KWQFontMetrics.mm b/WebCore/kwq/KWQFontMetrics.mm
index eafa2da..18b848c 100644
--- a/WebCore/kwq/KWQFontMetrics.mm
+++ b/WebCore/kwq/KWQFontMetrics.mm
@@ -415,12 +415,12 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
- if ((errCode = ATSUCreateStyle(&_asciiStyle)) != noErr)
+ if ((errCode = ATSUCreateStyle(&_latinStyle)) != noErr)
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to alloc ATSUStyle %d", self, errCode];
- __IFFillStyleWithAttributes(_asciiStyle, aFont);
+ __IFFillStyleWithAttributes(_latinStyle, aFont);
- if ((errCode = ATSUGetStyleGroup(_asciiStyle, &_asciiStyleGroup)) != noErr) {
+ if ((errCode = ATSUGetStyleGroup(_latinStyle, &_latinStyleGroup)) != noErr) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
#endif
@@ -452,6 +452,7 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
int i, errorResult;
size_t numGlyphsInFont = CGFontGetNumberOfGlyphs([font _backingCGSFont]);
short unsigned int sequentialGlyphs[GLYPH_CACHE_MAX];
+ ATSLayoutRecord *glyphRecords;
if (numGlyphsInFont > GLYPH_CACHE_MAX)
widthCacheSize = GLYPH_CACHE_MAX;
@@ -461,23 +462,39 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
for (i = 0; i < widthCacheSize; i++)
sequentialGlyphs[i] = i;
- fprintf (stdout, "number of glyphs in font %s %f = %ld\n", [[font displayName] cString], [font pointSize], CGFontGetNumberOfGlyphs([font _backingCGSFont]));
widthCache = (float *)calloc (1, widthCacheSize * sizeof(float));
errorResult = CGFontGetGlyphScaledAdvances ([font _backingCGSFont], &sequentialGlyphs[0], widthCacheSize, widthCache, [font pointSize]);
if (errorResult == 0)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: unable to cache glyph advances - for %@ %f", self, [font displayName], [font pointSize]];
- unsigned int asciiCount = LAST_ASCII_CHAR - FIRST_ASCII_CHAR + 1;
- short unsigned int asciiBuffer[LAST_ASCII_CHAR+1];
- for (i = FIRST_ASCII_CHAR; i <= LAST_ASCII_CHAR; i++){
- asciiBuffer[i] = i;
+ unsigned int latinCount = LAST_CACHE_CHAR - FIRST_CACHE_CHAR + 1;
+ short unsigned int latinBuffer[LAST_CACHE_CHAR+1];
+
+ for (i = FIRST_CACHE_CHAR; i <= LAST_CACHE_CHAR; i++){
+ latinBuffer[i] = i;
}
- __IFInitATSGlyphVector(&_asciiCacheGlyphVector, asciiCount);
- (void)ATSUConvertCharToGlyphs(_asciiStyleGroup, &asciiBuffer[FIRST_ASCII_CHAR], 0, asciiCount, 0, (ATSGlyphVector *)&_asciiCacheGlyphVector);
- if (_asciiCacheGlyphVector.numGlyphs != asciiCount)
+ __IFInitATSGlyphVector(&_latinCacheGlyphVector, latinCount);
+ (void)ATSUConvertCharToGlyphs(_latinStyleGroup, &latinBuffer[FIRST_CACHE_CHAR], 0, latinCount, 0, (ATSGlyphVector *)&_latinCacheGlyphVector);
+ if (_latinCacheGlyphVector.numGlyphs != latinCount)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: ascii and glyphID count not equal - for %@ %f", self, [font displayName], [font pointSize]];
+
+ int numGlyphs = _latinCacheGlyphVector.numGlyphs;
+ characterToGlyph = (ATSGlyphRef *)calloc (1, _latinCacheGlyphVector.numGlyphs * sizeof(ATSGlyphRef));
+ glyphRecords = _latinCacheGlyphVector.firstRecord;
+ for (i = 0; i < numGlyphs; i++){
+ characterToGlyph[i] = glyphRecords[i].glyphID;
+ }
+ __IFResetATSGlyphVector(&_latinCacheGlyphVector);
+
+#define DEBUG_CACHE_SIZE
+#ifdef DEBUG_CACHE_SIZE
+ static int totalCacheSize = 0;
+
+ totalCacheSize += widthCacheSize * sizeof(float) + numGlyphs * sizeof(ATSGlyphRef) + sizeof(KWQLayoutInfo);
+ KWQDEBUGLEVEL7 (KWQ_LOG_MEMUSAGE, "Cache initialized for font %s %f (%ld font glyphs), memory usage in bytes: widths = %ld, latin1 ext. character-to-glyph = %ld, total this cache = %ld, total all caches %d\n", [[font displayName] cString], [font pointSize], numGlyphsInFont, widthCacheSize * sizeof(float), numGlyphs * sizeof(ATSGlyphRef), widthCacheSize * sizeof(float) + numGlyphs * sizeof(ATSGlyphRef) + sizeof(KWQLayoutInfo), totalCacheSize);
+#endif
}
#endif
@@ -486,129 +503,149 @@ static NSRect _rectForString (KWQLayoutInfo *self, const UniChar *internalBuffer
{
CGContextRef cgContext;
int totalWidth = 0;
- unsigned int i, numGlyphs, index;
+ unsigned int i, index;
int glyphID;
ATSLayoutRecord *glyphRecords, *glyphRecordsPtr;
NSFont *font = [self font];
+
+ ATSGlyphRef localCharacterToGlyph[LOCAL_GLYPH_BUFFER_SIZE];
+ ATSGlyphRef *usedCharacterToGlyph, *allocateCharacterToGlyph;
+
BOOL needGlyphAdvanceLookup = NO;
BOOL needCharToGlyphLookup = NO;
+ // Best case, and common case for latin1, performance will require two iterations over
+ // the internalBuffer.
+ // Pass 1 (on characters):
+ // Determine if we can use character-to-glyph map by comparing characters to cache
+ // range.
+ // Pass 2 (on characters):
+ // Sum the widths using the character-to-glyph map and width cache.
+
+ // FIXME: For non-latin1 character sets we don't optimize.
+ // Worst case performance we must lookup the character-to-glyph map and lookup the glyph
+ // widths.
+
if ([font glyphPacking] != NSNativeShortGlyphPacking &&
[font glyphPacking] != NSTwoByteGlyphPacking)
[NSException raise:NSInternalInconsistencyException format:@"%@: Don't know how to pack glyphs for font %@ %f", self, [font displayName], [font pointSize]];
-
- cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-
+
if (self->widthCache == 0)
[self _initializeCaches];
// Check if we can use the cached character-to-glyph map. We only use the character-to-glyph map
- // if all the characters in the string fall in the safe ASCII range.
+ // if ALL the characters in the string fall in the safe cache range. This must be done
+ // to ensure that we don't match composable characters incorrectly. This check could
+ // be smarter. Also the character-to-glyph could be extended to support other ranges
+ // of unicode. For now, we only optimize for latin1.
for (i = 0; i < stringLength; i++){
- if (internalBuffer[i] < FIRST_ASCII_CHAR || internalBuffer[i] > LAST_ASCII_CHAR){
+ if (internalBuffer[i] < FIRST_CACHE_CHAR || internalBuffer[i] > LAST_CACHE_CHAR){
//fprintf (stdout, "char to glyph cache miss because of character 0x%04x\n", internalBuffer[i]);
needCharToGlyphLookup = YES;
break;
}
}
- // If we can't use the cached map, the calculate a map for this string.
+ // If we can't use the cached map, the calculate a map for this string. Expensive.
if (needCharToGlyphLookup){
+ unsigned int numGlyphs;
+
__IFInitATSGlyphVector(&self->_glyphVector, stringLength);
(void)ATSUConvertCharToGlyphs(self->_styleGroup, internalBuffer, 0, stringLength, 0, (ATSGlyphVector *)&self->_glyphVector);
glyphRecords = self->_glyphVector.firstRecord;
numGlyphs = self->_glyphVector.numGlyphs;
- }
- else {
- glyphRecords = self->_asciiCacheGlyphVector.firstRecord;
- numGlyphs = stringLength;
- }
-
- // Now we have the glyphs, determine if we can use the cached glyph measurements.
- for (i = 0; i < numGlyphs; i++){
- if (needCharToGlyphLookup)
- index = i;
- else
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- glyphID = glyphRecords[index].glyphID;
- if (glyphID > self->widthCacheSize){
- needGlyphAdvanceLookup = YES;
- break;
- }
- }
- // If we can't use the cached glyph measurement ask CG for the measurements.
- if (needGlyphAdvanceLookup){
- char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
- char *usedGlyphBuf, *glyphBufPtr, *allocatedGlyphBuf = 0;
-
- fprintf (stdout, "glyph measurement cache miss\n");
-
- // Now construct the glyph buffer.
- if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
- usedGlyphBuf = glyphBufPtr = allocatedGlyphBuf = (char *)malloc (numGlyphs * 2);
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
+ usedCharacterToGlyph = allocateCharacterToGlyph = (ATSGlyphRef *)calloc (1, numGlyphs * sizeof(ATSGlyphRef));
else
- usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
-
- if (needCharToGlyphLookup){
- int glyphID;
+ usedCharacterToGlyph = &localCharacterToGlyph[0];
+
+ for (i = 0; i < numGlyphs; i++)
+ usedCharacterToGlyph[i] = glyphRecords[i].glyphID;
- glyphRecordsPtr = glyphRecords;
- for (i = 0; i < numGlyphs; i++){
- glyphID = glyphRecordsPtr->glyphID;
- *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
- *glyphBufPtr++ = (char)(glyphID & 0x00FF);
- glyphRecordsPtr++;
- }
- }
- else {
- int glyphID;
+ __IFResetATSGlyphVector(&self->_glyphVector);
- for (i = 0; i < numGlyphs; i++){
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- glyphID = glyphRecords[index].glyphID;
- *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
- *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ // Now we have the glyphs, determine if we can use the cached glyph measurements.
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphRecords[i].glyphID;
+ if (glyphID >= self->widthCacheSize){
+ needGlyphAdvanceLookup = YES;
+ break;
}
}
-
- float localAdvanceBuf[LOCAL_GLYPH_BUFFER_SIZE];
- float *usedAdvanceBuf, *allocatedAdvanceBuf = 0;
- if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
- usedAdvanceBuf = allocatedAdvanceBuf = (float *)malloc (numGlyphs * sizeof(float));
- else
- usedAdvanceBuf = &localAdvanceBuf[0];
+ // If we can't use the cached glyph measurement ask CG for the measurements. Expensive.
+ if (needGlyphAdvanceLookup){
+ char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
+ char *usedGlyphBuf, *glyphBufPtr, *allocatedGlyphBuf = 0;
- if (numGlyphs < LOCAL_GLYPH_BUFFER_SIZE){
+ fprintf (stdout, "glyph measurement cache miss\n");
+
+ // Now construct the glyph buffer.
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
+ usedGlyphBuf = glyphBufPtr = allocatedGlyphBuf = (char *)malloc (numGlyphs * 2);
+ else
+ usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
+
+ if (needCharToGlyphLookup){
+ int glyphID;
+
+ glyphRecordsPtr = glyphRecords;
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphRecordsPtr->glyphID;
+ *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
+ *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ glyphRecordsPtr++;
+ }
+ }
+ else {
+ int glyphID;
+
+ for (i = 0; i < numGlyphs; i++){
+ index = internalBuffer[i]-FIRST_CACHE_CHAR;
+ glyphID = glyphRecords[index].glyphID;
+ *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
+ *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ }
+ }
+
+ float localAdvanceBuf[LOCAL_GLYPH_BUFFER_SIZE];
+ float *usedAdvanceBuf, *allocatedAdvanceBuf = 0;
+
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
+ usedAdvanceBuf = allocatedAdvanceBuf = (float *)malloc (numGlyphs * sizeof(float));
+ else
+ usedAdvanceBuf = &localAdvanceBuf[0];
+
+ cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGFontGetGlyphScaledAdvances ([font _backingCGSFont], (const short unsigned int *)usedGlyphBuf, numGlyphs, usedAdvanceBuf, [font pointSize]);
for (i = 0; i < numGlyphs; i++){
//totalWidth += ScaleEmToUnits (advance[i], info->unitsPerEm);
totalWidth += ROUND_TO_INT(usedAdvanceBuf[i]);
}
- }
+
+ if (allocatedAdvanceBuf)
+ free (allocatedAdvanceBuf);
- if (allocatedAdvanceBuf)
- free (allocatedAdvanceBuf);
-
- if (allocatedGlyphBuf)
- free (allocatedGlyphBuf);
- }
- else {
+ if (allocatedGlyphBuf)
+ free (allocatedGlyphBuf);
+ }
+ }
+ else
+ usedCharacterToGlyph = self->characterToGlyph;
+
+ if (!needGlyphAdvanceLookup){
float *widthCache = self->widthCache;
- for (i = 0; i < numGlyphs; i++){
+ for (i = 0; i < stringLength; i++){
if (needCharToGlyphLookup)
index = i;
else
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- totalWidth += ROUND_TO_INT(widthCache[glyphRecords[index].glyphID]);
+ index = internalBuffer[i]-FIRST_CACHE_CHAR;
+ totalWidth += ROUND_TO_INT(widthCache[usedCharacterToGlyph[index]]);
}
}
- if (needCharToGlyphLookup)
- __IFResetATSGlyphVector(&self->_glyphVector);
-
return NSMakeRect (0,0,(float)totalWidth, (float)self->lineHeight);
}
#endif
diff --git a/WebCore/kwq/KWQMetrics.h b/WebCore/kwq/KWQMetrics.h
index b7246e0..088a079 100644
--- a/WebCore/kwq/KWQMetrics.h
+++ b/WebCore/kwq/KWQMetrics.h
@@ -35,8 +35,15 @@
#define LOCAL_GLYPH_BUFFER_SIZE 1024
#define GLYPH_CACHE_MAX 1024
-#define FIRST_ASCII_CHAR ((int)' ')
-#define LAST_ASCII_CHAR ((int)'}')
+// These definitions are used to bound the character-to-glyph mapping cache. The
+// range is limited to LATIN1. Also a check must be made to determine that a
+// character range does not include a composable charcter.
+
+// The first displayable character in latin1. (SPACE)
+#define FIRST_CACHE_CHAR (0x20)
+
+// The last character in latin1 extended A. (LATIN SMALL LETTER LONG S)
+#define LAST_CACHE_CHAR (0x17F)
#define Boolean MacBoolean
#define Fixed MacFixed
@@ -74,11 +81,12 @@ CG_EXTERN size_t CGFontGetNumberOfGlyphs(CGFontRef font);
ATSStyleGroupPtr _styleGroup;
ATSUStyle _style;
ATSGlyphVector _glyphVector;
- ATSStyleGroupPtr _asciiStyleGroup;
- ATSUStyle _asciiStyle;
- ATSGlyphVector _asciiCacheGlyphVector;
+ ATSStyleGroupPtr _latinStyleGroup;
+ ATSUStyle _latinStyle;
+ ATSGlyphVector _latinCacheGlyphVector;
int widthCacheSize;
float *widthCache;
+ ATSGlyphRef *characterToGlyph;
#endif
}
diff --git a/WebCore/kwq/kwqdebug.h b/WebCore/kwq/kwqdebug.h
index 39b6b73..59bf968 100644
--- a/WebCore/kwq/kwqdebug.h
+++ b/WebCore/kwq/kwqdebug.h
@@ -50,6 +50,7 @@ long _GetMillisecondsSinceEpoch();
#define KWQ_LOG_ERROR 0x00000010
#define KWQ_LOG_TIMING 0x00000020
#define KWQ_LOG_LOADING 0x00000040
+#define KWQ_LOG_MEMUSAGE 0x00000080
#define KWQ_LOG_NONE 0
@@ -111,6 +112,10 @@ void KWQLogAtLevel(unsigned int level, NSString *format, ...);
KWQDebugAtLevel (level,"[%s:%d %s] ", __FILE__, __LINE__, __FUNCTION__);\
KWQDebugAtLevel (level,format,arg1,arg2,arg3,arg4,arg5,arg6);
+#define KWQDEBUGLEVEL7(level,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
+ KWQDebugAtLevel (level,"[%s:%d %s] ", __FILE__, __LINE__, __FUNCTION__);\
+ KWQDebugAtLevel (level,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+
#define DEBUG_OBJECT(object) [[object description] cString]
/*-----------------------------------------------------------------------------
diff --git a/WebCore/kwq/kwqdebug.mm b/WebCore/kwq/kwqdebug.mm
index 70691c2..fbd7d04 100644
--- a/WebCore/kwq/kwqdebug.mm
+++ b/WebCore/kwq/kwqdebug.mm
@@ -25,7 +25,7 @@
#include <kwqdebug.h>
-unsigned int KWQ_LOG_LEVEL = KWQ_LOG_ALL;
+unsigned int KWQ_LOG_LEVEL = 0;
void KWQSetLogLevel(int mask) {
KWQ_LOG_LEVEL = mask;
diff --git a/WebCore/src/kwq/KWQFontMetrics.mm b/WebCore/src/kwq/KWQFontMetrics.mm
index eafa2da..18b848c 100644
--- a/WebCore/src/kwq/KWQFontMetrics.mm
+++ b/WebCore/src/kwq/KWQFontMetrics.mm
@@ -415,12 +415,12 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
- if ((errCode = ATSUCreateStyle(&_asciiStyle)) != noErr)
+ if ((errCode = ATSUCreateStyle(&_latinStyle)) != noErr)
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to alloc ATSUStyle %d", self, errCode];
- __IFFillStyleWithAttributes(_asciiStyle, aFont);
+ __IFFillStyleWithAttributes(_latinStyle, aFont);
- if ((errCode = ATSUGetStyleGroup(_asciiStyle, &_asciiStyleGroup)) != noErr) {
+ if ((errCode = ATSUGetStyleGroup(_latinStyle, &_latinStyleGroup)) != noErr) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
#endif
@@ -452,6 +452,7 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
int i, errorResult;
size_t numGlyphsInFont = CGFontGetNumberOfGlyphs([font _backingCGSFont]);
short unsigned int sequentialGlyphs[GLYPH_CACHE_MAX];
+ ATSLayoutRecord *glyphRecords;
if (numGlyphsInFont > GLYPH_CACHE_MAX)
widthCacheSize = GLYPH_CACHE_MAX;
@@ -461,23 +462,39 @@ static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
for (i = 0; i < widthCacheSize; i++)
sequentialGlyphs[i] = i;
- fprintf (stdout, "number of glyphs in font %s %f = %ld\n", [[font displayName] cString], [font pointSize], CGFontGetNumberOfGlyphs([font _backingCGSFont]));
widthCache = (float *)calloc (1, widthCacheSize * sizeof(float));
errorResult = CGFontGetGlyphScaledAdvances ([font _backingCGSFont], &sequentialGlyphs[0], widthCacheSize, widthCache, [font pointSize]);
if (errorResult == 0)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: unable to cache glyph advances - for %@ %f", self, [font displayName], [font pointSize]];
- unsigned int asciiCount = LAST_ASCII_CHAR - FIRST_ASCII_CHAR + 1;
- short unsigned int asciiBuffer[LAST_ASCII_CHAR+1];
- for (i = FIRST_ASCII_CHAR; i <= LAST_ASCII_CHAR; i++){
- asciiBuffer[i] = i;
+ unsigned int latinCount = LAST_CACHE_CHAR - FIRST_CACHE_CHAR + 1;
+ short unsigned int latinBuffer[LAST_CACHE_CHAR+1];
+
+ for (i = FIRST_CACHE_CHAR; i <= LAST_CACHE_CHAR; i++){
+ latinBuffer[i] = i;
}
- __IFInitATSGlyphVector(&_asciiCacheGlyphVector, asciiCount);
- (void)ATSUConvertCharToGlyphs(_asciiStyleGroup, &asciiBuffer[FIRST_ASCII_CHAR], 0, asciiCount, 0, (ATSGlyphVector *)&_asciiCacheGlyphVector);
- if (_asciiCacheGlyphVector.numGlyphs != asciiCount)
+ __IFInitATSGlyphVector(&_latinCacheGlyphVector, latinCount);
+ (void)ATSUConvertCharToGlyphs(_latinStyleGroup, &latinBuffer[FIRST_CACHE_CHAR], 0, latinCount, 0, (ATSGlyphVector *)&_latinCacheGlyphVector);
+ if (_latinCacheGlyphVector.numGlyphs != latinCount)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: ascii and glyphID count not equal - for %@ %f", self, [font displayName], [font pointSize]];
+
+ int numGlyphs = _latinCacheGlyphVector.numGlyphs;
+ characterToGlyph = (ATSGlyphRef *)calloc (1, _latinCacheGlyphVector.numGlyphs * sizeof(ATSGlyphRef));
+ glyphRecords = _latinCacheGlyphVector.firstRecord;
+ for (i = 0; i < numGlyphs; i++){
+ characterToGlyph[i] = glyphRecords[i].glyphID;
+ }
+ __IFResetATSGlyphVector(&_latinCacheGlyphVector);
+
+#define DEBUG_CACHE_SIZE
+#ifdef DEBUG_CACHE_SIZE
+ static int totalCacheSize = 0;
+
+ totalCacheSize += widthCacheSize * sizeof(float) + numGlyphs * sizeof(ATSGlyphRef) + sizeof(KWQLayoutInfo);
+ KWQDEBUGLEVEL7 (KWQ_LOG_MEMUSAGE, "Cache initialized for font %s %f (%ld font glyphs), memory usage in bytes: widths = %ld, latin1 ext. character-to-glyph = %ld, total this cache = %ld, total all caches %d\n", [[font displayName] cString], [font pointSize], numGlyphsInFont, widthCacheSize * sizeof(float), numGlyphs * sizeof(ATSGlyphRef), widthCacheSize * sizeof(float) + numGlyphs * sizeof(ATSGlyphRef) + sizeof(KWQLayoutInfo), totalCacheSize);
+#endif
}
#endif
@@ -486,129 +503,149 @@ static NSRect _rectForString (KWQLayoutInfo *self, const UniChar *internalBuffer
{
CGContextRef cgContext;
int totalWidth = 0;
- unsigned int i, numGlyphs, index;
+ unsigned int i, index;
int glyphID;
ATSLayoutRecord *glyphRecords, *glyphRecordsPtr;
NSFont *font = [self font];
+
+ ATSGlyphRef localCharacterToGlyph[LOCAL_GLYPH_BUFFER_SIZE];
+ ATSGlyphRef *usedCharacterToGlyph, *allocateCharacterToGlyph;
+
BOOL needGlyphAdvanceLookup = NO;
BOOL needCharToGlyphLookup = NO;
+ // Best case, and common case for latin1, performance will require two iterations over
+ // the internalBuffer.
+ // Pass 1 (on characters):
+ // Determine if we can use character-to-glyph map by comparing characters to cache
+ // range.
+ // Pass 2 (on characters):
+ // Sum the widths using the character-to-glyph map and width cache.
+
+ // FIXME: For non-latin1 character sets we don't optimize.
+ // Worst case performance we must lookup the character-to-glyph map and lookup the glyph
+ // widths.
+
if ([font glyphPacking] != NSNativeShortGlyphPacking &&
[font glyphPacking] != NSTwoByteGlyphPacking)
[NSException raise:NSInternalInconsistencyException format:@"%@: Don't know how to pack glyphs for font %@ %f", self, [font displayName], [font pointSize]];
-
- cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-
+
if (self->widthCache == 0)
[self _initializeCaches];
// Check if we can use the cached character-to-glyph map. We only use the character-to-glyph map
- // if all the characters in the string fall in the safe ASCII range.
+ // if ALL the characters in the string fall in the safe cache range. This must be done
+ // to ensure that we don't match composable characters incorrectly. This check could
+ // be smarter. Also the character-to-glyph could be extended to support other ranges
+ // of unicode. For now, we only optimize for latin1.
for (i = 0; i < stringLength; i++){
- if (internalBuffer[i] < FIRST_ASCII_CHAR || internalBuffer[i] > LAST_ASCII_CHAR){
+ if (internalBuffer[i] < FIRST_CACHE_CHAR || internalBuffer[i] > LAST_CACHE_CHAR){
//fprintf (stdout, "char to glyph cache miss because of character 0x%04x\n", internalBuffer[i]);
needCharToGlyphLookup = YES;
break;
}
}
- // If we can't use the cached map, the calculate a map for this string.
+ // If we can't use the cached map, the calculate a map for this string. Expensive.
if (needCharToGlyphLookup){
+ unsigned int numGlyphs;
+
__IFInitATSGlyphVector(&self->_glyphVector, stringLength);
(void)ATSUConvertCharToGlyphs(self->_styleGroup, internalBuffer, 0, stringLength, 0, (ATSGlyphVector *)&self->_glyphVector);
glyphRecords = self->_glyphVector.firstRecord;
numGlyphs = self->_glyphVector.numGlyphs;
- }
- else {
- glyphRecords = self->_asciiCacheGlyphVector.firstRecord;
- numGlyphs = stringLength;
- }
-
- // Now we have the glyphs, determine if we can use the cached glyph measurements.
- for (i = 0; i < numGlyphs; i++){
- if (needCharToGlyphLookup)
- index = i;
- else
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- glyphID = glyphRecords[index].glyphID;
- if (glyphID > self->widthCacheSize){
- needGlyphAdvanceLookup = YES;
- break;
- }
- }
- // If we can't use the cached glyph measurement ask CG for the measurements.
- if (needGlyphAdvanceLookup){
- char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
- char *usedGlyphBuf, *glyphBufPtr, *allocatedGlyphBuf = 0;
-
- fprintf (stdout, "glyph measurement cache miss\n");
-
- // Now construct the glyph buffer.
- if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
- usedGlyphBuf = glyphBufPtr = allocatedGlyphBuf = (char *)malloc (numGlyphs * 2);
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
+ usedCharacterToGlyph = allocateCharacterToGlyph = (ATSGlyphRef *)calloc (1, numGlyphs * sizeof(ATSGlyphRef));
else
- usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
-
- if (needCharToGlyphLookup){
- int glyphID;
+ usedCharacterToGlyph = &localCharacterToGlyph[0];
+
+ for (i = 0; i < numGlyphs; i++)
+ usedCharacterToGlyph[i] = glyphRecords[i].glyphID;
- glyphRecordsPtr = glyphRecords;
- for (i = 0; i < numGlyphs; i++){
- glyphID = glyphRecordsPtr->glyphID;
- *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
- *glyphBufPtr++ = (char)(glyphID & 0x00FF);
- glyphRecordsPtr++;
- }
- }
- else {
- int glyphID;
+ __IFResetATSGlyphVector(&self->_glyphVector);
- for (i = 0; i < numGlyphs; i++){
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- glyphID = glyphRecords[index].glyphID;
- *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
- *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ // Now we have the glyphs, determine if we can use the cached glyph measurements.
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphRecords[i].glyphID;
+ if (glyphID >= self->widthCacheSize){
+ needGlyphAdvanceLookup = YES;
+ break;
}
}
-
- float localAdvanceBuf[LOCAL_GLYPH_BUFFER_SIZE];
- float *usedAdvanceBuf, *allocatedAdvanceBuf = 0;
- if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
- usedAdvanceBuf = allocatedAdvanceBuf = (float *)malloc (numGlyphs * sizeof(float));
- else
- usedAdvanceBuf = &localAdvanceBuf[0];
+ // If we can't use the cached glyph measurement ask CG for the measurements. Expensive.
+ if (needGlyphAdvanceLookup){
+ char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
+ char *usedGlyphBuf, *glyphBufPtr, *allocatedGlyphBuf = 0;
- if (numGlyphs < LOCAL_GLYPH_BUFFER_SIZE){
+ fprintf (stdout, "glyph measurement cache miss\n");
+
+ // Now construct the glyph buffer.
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
+ usedGlyphBuf = glyphBufPtr = allocatedGlyphBuf = (char *)malloc (numGlyphs * 2);
+ else
+ usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
+
+ if (needCharToGlyphLookup){
+ int glyphID;
+
+ glyphRecordsPtr = glyphRecords;
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphRecordsPtr->glyphID;
+ *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
+ *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ glyphRecordsPtr++;
+ }
+ }
+ else {
+ int glyphID;
+
+ for (i = 0; i < numGlyphs; i++){
+ index = internalBuffer[i]-FIRST_CACHE_CHAR;
+ glyphID = glyphRecords[index].glyphID;
+ *glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
+ *glyphBufPtr++ = (char)(glyphID & 0x00FF);
+ }
+ }
+
+ float localAdvanceBuf[LOCAL_GLYPH_BUFFER_SIZE];
+ float *usedAdvanceBuf, *allocatedAdvanceBuf = 0;
+
+ if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
+ usedAdvanceBuf = allocatedAdvanceBuf = (float *)malloc (numGlyphs * sizeof(float));
+ else
+ usedAdvanceBuf = &localAdvanceBuf[0];
+
+ cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGFontGetGlyphScaledAdvances ([font _backingCGSFont], (const short unsigned int *)usedGlyphBuf, numGlyphs, usedAdvanceBuf, [font pointSize]);
for (i = 0; i < numGlyphs; i++){
//totalWidth += ScaleEmToUnits (advance[i], info->unitsPerEm);
totalWidth += ROUND_TO_INT(usedAdvanceBuf[i]);
}
- }
+
+ if (allocatedAdvanceBuf)
+ free (allocatedAdvanceBuf);
- if (allocatedAdvanceBuf)
- free (allocatedAdvanceBuf);
-
- if (allocatedGlyphBuf)
- free (allocatedGlyphBuf);
- }
- else {
+ if (allocatedGlyphBuf)
+ free (allocatedGlyphBuf);
+ }
+ }
+ else
+ usedCharacterToGlyph = self->characterToGlyph;
+
+ if (!needGlyphAdvanceLookup){
float *widthCache = self->widthCache;
- for (i = 0; i < numGlyphs; i++){
+ for (i = 0; i < stringLength; i++){
if (needCharToGlyphLookup)
index = i;
else
- index = internalBuffer[i]-FIRST_ASCII_CHAR;
- totalWidth += ROUND_TO_INT(widthCache[glyphRecords[index].glyphID]);
+ index = internalBuffer[i]-FIRST_CACHE_CHAR;
+ totalWidth += ROUND_TO_INT(widthCache[usedCharacterToGlyph[index]]);
}
}
- if (needCharToGlyphLookup)
- __IFResetATSGlyphVector(&self->_glyphVector);
-
return NSMakeRect (0,0,(float)totalWidth, (float)self->lineHeight);
}
#endif
diff --git a/WebCore/src/kwq/KWQMetrics.h b/WebCore/src/kwq/KWQMetrics.h
index b7246e0..088a079 100644
--- a/WebCore/src/kwq/KWQMetrics.h
+++ b/WebCore/src/kwq/KWQMetrics.h
@@ -35,8 +35,15 @@
#define LOCAL_GLYPH_BUFFER_SIZE 1024
#define GLYPH_CACHE_MAX 1024
-#define FIRST_ASCII_CHAR ((int)' ')
-#define LAST_ASCII_CHAR ((int)'}')
+// These definitions are used to bound the character-to-glyph mapping cache. The
+// range is limited to LATIN1. Also a check must be made to determine that a
+// character range does not include a composable charcter.
+
+// The first displayable character in latin1. (SPACE)
+#define FIRST_CACHE_CHAR (0x20)
+
+// The last character in latin1 extended A. (LATIN SMALL LETTER LONG S)
+#define LAST_CACHE_CHAR (0x17F)
#define Boolean MacBoolean
#define Fixed MacFixed
@@ -74,11 +81,12 @@ CG_EXTERN size_t CGFontGetNumberOfGlyphs(CGFontRef font);
ATSStyleGroupPtr _styleGroup;
ATSUStyle _style;
ATSGlyphVector _glyphVector;
- ATSStyleGroupPtr _asciiStyleGroup;
- ATSUStyle _asciiStyle;
- ATSGlyphVector _asciiCacheGlyphVector;
+ ATSStyleGroupPtr _latinStyleGroup;
+ ATSUStyle _latinStyle;
+ ATSGlyphVector _latinCacheGlyphVector;
int widthCacheSize;
float *widthCache;
+ ATSGlyphRef *characterToGlyph;
#endif
}
diff --git a/WebCore/src/kwq/kwqdebug.h b/WebCore/src/kwq/kwqdebug.h
index 39b6b73..59bf968 100644
--- a/WebCore/src/kwq/kwqdebug.h
+++ b/WebCore/src/kwq/kwqdebug.h
@@ -50,6 +50,7 @@ long _GetMillisecondsSinceEpoch();
#define KWQ_LOG_ERROR 0x00000010
#define KWQ_LOG_TIMING 0x00000020
#define KWQ_LOG_LOADING 0x00000040
+#define KWQ_LOG_MEMUSAGE 0x00000080
#define KWQ_LOG_NONE 0
@@ -111,6 +112,10 @@ void KWQLogAtLevel(unsigned int level, NSString *format, ...);
KWQDebugAtLevel (level,"[%s:%d %s] ", __FILE__, __LINE__, __FUNCTION__);\
KWQDebugAtLevel (level,format,arg1,arg2,arg3,arg4,arg5,arg6);
+#define KWQDEBUGLEVEL7(level,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
+ KWQDebugAtLevel (level,"[%s:%d %s] ", __FILE__, __LINE__, __FUNCTION__);\
+ KWQDebugAtLevel (level,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+
#define DEBUG_OBJECT(object) [[object description] cString]
/*-----------------------------------------------------------------------------
diff --git a/WebCore/src/kwq/kwqdebug.mm b/WebCore/src/kwq/kwqdebug.mm
index 70691c2..fbd7d04 100644
--- a/WebCore/src/kwq/kwqdebug.mm
+++ b/WebCore/src/kwq/kwqdebug.mm
@@ -25,7 +25,7 @@
#include <kwqdebug.h>
-unsigned int KWQ_LOG_LEVEL = KWQ_LOG_ALL;
+unsigned int KWQ_LOG_LEVEL = 0;
void KWQSetLogLevel(int mask) {
KWQ_LOG_LEVEL = mask;
diff --git a/WebKit/Misc.subproj/WebKitDebug.m b/WebKit/Misc.subproj/WebKitDebug.m
index 8697238..6f16b27 100644
--- a/WebKit/Misc.subproj/WebKitDebug.m
+++ b/WebKit/Misc.subproj/WebKitDebug.m
@@ -4,7 +4,7 @@
#import "WebKitDebug.h"
-unsigned int WEBKIT_LOG_LEVEL = WEBKIT_LOG_ALL;
+unsigned int WEBKIT_LOG_LEVEL = 0;
void WebKitSetLogLevel(int mask) {
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list