[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 06:21:05 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 5105ed5c65eadda9162188fe9896d15857c86bff
Author: rjw <rjw at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Tue Jun 25 01:59:10 2002 +0000
Changed our usage of +[NSFont findFontLike:forString:withRange:inLanguage:]
after talking with Aki. We were erroneously passing a complete
string rather than a character cluster. Fixed 2964793.
* WebCoreSupport.subproj/IFTextRenderer.m:
(findLengthOfCharacterCluster):
(-[IFTextRenderer slowPackGlyphsForCharacters:numCharacters:glyphBuffer:numGlyphs:]):
(-[IFTextRenderer drawGlyphs:numGlyphs:atPoint:withColor:]):
(-[IFTextRenderer slowDrawCharacters:length:atPoint:withColor:]):
(-[IFTextRenderer _drawCharacters:length:atPoint:withColor:]):
(-[IFTextRenderer drawCharacters:length:atPoint:withColor:]):
(-[IFTextRenderer floatWidthForCharacters:length:applyRounding:]):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@1424 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index a244a4a..d7813d4 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,18 @@
+2002-06-24 Richard Williamson <rjw at apple.com>
+
+ Changed our usage of +[NSFont findFontLike:forString:withRange:inLanguage:]
+ after talking with Aki. We were erroneously passing a complete
+ string rather than a character cluster. Fixed 2964793.
+
+ * WebCoreSupport.subproj/IFTextRenderer.m:
+ (findLengthOfCharacterCluster):
+ (-[IFTextRenderer slowPackGlyphsForCharacters:numCharacters:glyphBuffer:numGlyphs:]):
+ (-[IFTextRenderer drawGlyphs:numGlyphs:atPoint:withColor:]):
+ (-[IFTextRenderer slowDrawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer _drawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer drawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer floatWidthForCharacters:length:applyRounding:]):
+
2002-06-24 Darin Adler <darin at apple.com>
* WebView.subproj/IFWebFramePrivate.mm:
diff --git a/WebKit/ChangeLog-2002-12-03 b/WebKit/ChangeLog-2002-12-03
index a244a4a..d7813d4 100644
--- a/WebKit/ChangeLog-2002-12-03
+++ b/WebKit/ChangeLog-2002-12-03
@@ -1,3 +1,18 @@
+2002-06-24 Richard Williamson <rjw at apple.com>
+
+ Changed our usage of +[NSFont findFontLike:forString:withRange:inLanguage:]
+ after talking with Aki. We were erroneously passing a complete
+ string rather than a character cluster. Fixed 2964793.
+
+ * WebCoreSupport.subproj/IFTextRenderer.m:
+ (findLengthOfCharacterCluster):
+ (-[IFTextRenderer slowPackGlyphsForCharacters:numCharacters:glyphBuffer:numGlyphs:]):
+ (-[IFTextRenderer drawGlyphs:numGlyphs:atPoint:withColor:]):
+ (-[IFTextRenderer slowDrawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer _drawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer drawCharacters:length:atPoint:withColor:]):
+ (-[IFTextRenderer floatWidthForCharacters:length:applyRounding:]):
+
2002-06-24 Darin Adler <darin at apple.com>
* WebView.subproj/IFWebFramePrivate.mm:
diff --git a/WebKit/WebCoreSupport.subproj/IFTextRenderer.m b/WebKit/WebCoreSupport.subproj/IFTextRenderer.m
index 2d227ae..9f283d0 100644
--- a/WebKit/WebCoreSupport.subproj/IFTextRenderer.m
+++ b/WebKit/WebCoreSupport.subproj/IFTextRenderer.m
@@ -187,19 +187,33 @@ static void FillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
}
-static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
+static unsigned int findLengthOfCharacterCluster(const UniChar *characters, unsigned int length)
{
- unsigned int i, numGlyphs = glyphs->numGlyphs;
- ATSLayoutRecord *glyphRecord;
+ unsigned int clusterLength = 1, k;
+ UniChar nextC;
- glyphRecord = (ATSLayoutRecord *)glyphs->firstRecord;
- for (i = 0; i < numGlyphs; i++) {
- if (glyphRecord->glyphID == 0) {
- return YES;
+ if (length == 0)
+ return 0;
+
+ if (length == 1)
+ return 1;
+
+ if (IsNonBaseChar(characters[0]))
+ return 1;
+
+ nextC = characters[1];
+ if (IsNonBaseChar(nextC)){
+ // Find all the non base characters after the current character.
+ for (k = 2; k < length; k++){
+ if (!IsNonBaseChar(characters[k]))
+ break;
}
- glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + glyphs->recordSize);
+ clusterLength = k;
}
- return NO;
+ else
+ clusterLength = 1;
+
+ return clusterLength;
}
@@ -375,7 +389,7 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
-- (bool) slowPackGlyphsForCharacters:(const UniChar *)characters numCharacters: (unsigned int)numCharacters glyphBuffer:(CGGlyph **)glyphBuffer numGlyphs:(unsigned int *)numGlyphs
+- (void) slowPackGlyphsForCharacters:(const UniChar *)characters numCharacters: (unsigned int)numCharacters glyphBuffer:(CGGlyph **)glyphBuffer numGlyphs:(unsigned int *)numGlyphs
{
ATSGlyphVector glyphVector;
unsigned int j;
@@ -384,8 +398,6 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
ATSInitializeGlyphVector(numCharacters, 0, &glyphVector);
[self convertCharacters: characters length: numCharacters toGlyphs: &glyphVector];
- if (hasMissingGlyphs (&glyphVector))
- return NO;
*numGlyphs = glyphVector.numGlyphs;
*glyphBuffer = glyphBufPtr = (CGGlyph *)malloc (*numGlyphs * sizeof(CGGlyph));
@@ -396,8 +408,6 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
ATSClearGlyphVector(&glyphVector);
-
- return YES;
}
@@ -424,16 +434,108 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
-- (void)drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+- (NSPoint)drawGlyphs: (CGGlyph *)glyphs numGlyphs: (unsigned int)numGlyphs atPoint: (NSPoint)point withColor: (NSColor *)color
{
- uint i, numGlyphs;
- CGGlyph *glyphs, localGlyphBuffer[LOCAL_BUFFER_SIZE];
-#ifndef DRAW_WITHOUT_ADVANCES
+ unsigned int i;
CGSize *advances, localAdvanceBuffer[LOCAL_BUFFER_SIZE];
-#endif
- ATSGlyphRef glyphID;
CGContextRef cgContext;
+ NSPoint advancePoint = point;
+
+ if (numGlyphs == 0)
+ return point;
+
+ // Determine if we can use the local stack buffer, otherwise allocate.
+ if (numGlyphs > LOCAL_BUFFER_SIZE) {
+ advances = (CGSize *)malloc(numGlyphs * sizeof(CGSize));
+ } else {
+ advances = localAdvanceBuffer;
+ }
+
+ for (i = 0; i < numGlyphs; i++) {
+ advances[i].width = widthForGlyph(self, glyphToWidthMap, glyphs[i]);
+ if (glyphs[i] == spaceGlyph)
+ advances[i].width = ROUND_TO_INT(advances[i].width);
+ advances[i].height = 0;
+ advancePoint.x += advances[i].width;
+ }
+
+ // Setup the color and font.
+ [color set];
+ [font set];
+
+ // Finally, draw the glyphs.
+ cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+
+ CGContextSetTextPosition (cgContext, point.x, point.y);
+ CGContextShowGlyphsWithAdvances (cgContext, glyphs, advances, numGlyphs);
+ //CGContextShowGlyphsWithDeviceAdvances (cgContext, glyphs, advances, numGlyphs);
+
+ if (advances != localAdvanceBuffer) {
+ free(advances);
+ }
+ return advancePoint;
+}
+
+// Useful page for testing http://home.att.net/~jameskass
+
+- (NSPoint)slowDrawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ unsigned int charPos = 0, lastDrawnGlyph = 0;
+ unsigned int clusterLength, i, numGlyphs, fragmentLength;
NSFont *substituteFont;
+ CGGlyph *glyphs;
+ ATSGlyphRef glyphID;
+
+ [self slowPackGlyphsForCharacters: characters numCharacters: length glyphBuffer: &glyphs numGlyphs: &numGlyphs];
+
+ // FIXME: This assumes that we'll always get one glyph per character cluster.
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphs[i];
+
+ clusterLength = findLengthOfCharacterCluster (&characters[charPos], length - charPos);
+
+ if (glyphID == 0){
+ // Draw everthing up to this point.
+ fragmentLength = i - lastDrawnGlyph;
+ if (fragmentLength > 0)
+ point = [self drawGlyphs: &glyphs[lastDrawnGlyph] numGlyphs: fragmentLength atPoint: point withColor: color];
+
+ // Draw the character in the alternate font.
+ substituteFont = [self substituteFontForCharacters: &characters[charPos] length: clusterLength];
+ if (substituteFont)
+ point = [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] slowDrawCharacters: &characters[charPos] length: clusterLength atPoint: point withColor: color];
+ else
+ point = [self drawGlyphs: &glyphs[i] numGlyphs: 1 atPoint: point withColor: color];
+
+ lastDrawnGlyph = i+1;
+ }
+
+ charPos += clusterLength;
+ }
+
+ fragmentLength = numGlyphs - lastDrawnGlyph;
+ if (fragmentLength > 0)
+ point = [self drawGlyphs: &glyphs[lastDrawnGlyph] numGlyphs: fragmentLength atPoint: point withColor: color];
+
+ if (glyphs)
+ free(glyphs);
+
+ return point;
+}
+
+
+typedef enum {
+ _IFNonBaseCharacter,
+ _IFMissingGlyph,
+ _IFDrawSucceeded,
+} _IFFailedDrawReason;
+
+- (_IFFailedDrawReason)_drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ uint i;
+ CGGlyph *glyphs, localGlyphBuffer[LOCAL_BUFFER_SIZE];
+ ATSGlyphRef glyphID;
+ _IFFailedDrawReason result = _IFDrawSucceeded;
// FIXME: Deal with other styles of glyph packing.
if ([font glyphPacking] != NSNativeShortGlyphPacking &&
@@ -447,12 +549,9 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
glyphs = localGlyphBuffer;
}
- // Set the number of glyphs to the character length. This may change during the character
- // scan if we find any non base characters.
- numGlyphs = length;
-
// Pack the glyph buffer and ensure that we have glyphs for all the
- // characters. If we're missing a glyph look for an alternate font.
+ // characters. If we're missing a glyph or have a non-base character
+ // stop drawing and return a failure code.
for (i = 0; i < length; i++) {
UniChar c = characters[i];
@@ -460,87 +559,59 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
if (c == NON_BREAKING_SPACE)
c = SPACE;
- // Is the a combining character? If so we have to do expensive
- // glyph lookup.
+ // Is the a non-base character?
if (IsNonBaseChar(c)) {
- CGGlyph *slowGlyphBuffer;
- bool hasGlyphs = [self slowPackGlyphsForCharacters: characters numCharacters: length glyphBuffer: &slowGlyphBuffer numGlyphs: &numGlyphs];
- if (hasGlyphs) {
- if (glyphs != localGlyphBuffer) {
- free(glyphs);
- }
- glyphs = slowGlyphBuffer;
- } else {
- substituteFont = [self substituteFontForCharacters: characters length: length];
- if (substituteFont) {
- [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] drawCharacters: characters length: length atPoint: point withColor: color];
- goto cleanup;
- }
- }
- break;
+ result = _IFNonBaseCharacter;
+ goto cleanup;
}
-
- glyphID = glyphForCharacter (characterToGlyphMap, c);
- // glyphID == 0 means that the font doesn't contain a glyph for the character.
- if (glyphID == 0) {
- substituteFont = [self substituteFontForCharacters: characters length: length];
- if (substituteFont) {
- [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] drawCharacters: characters length: length atPoint: point withColor: color];
- goto cleanup;
- }
+ glyphID = glyphForCharacter (characterToGlyphMap, c);
+ if (glyphID == nonGlyphID) {
+ glyphID = [self extendCharacterToGlyphMapToInclude: c];
}
+ // Does this font not contain a glyph for the character?
+ if (glyphID == 0){
+ result = _IFMissingGlyph;
+ goto cleanup;
+ }
+
glyphs[i] = glyphID;
}
-#ifndef DRAW_WITHOUT_ADVANCES
- // Determine if we can use the local stack buffer, otherwise allocate.
- if (numGlyphs > LOCAL_BUFFER_SIZE) {
- advances = (CGSize *)malloc(numGlyphs * sizeof(CGSize));
- } else {
- advances = localAdvanceBuffer;
- }
+ [self drawGlyphs: glyphs numGlyphs: length atPoint: point withColor: color];
- for (i = 0; i < numGlyphs; i++) {
- advances[i].width = widthForGlyph(self, glyphToWidthMap, glyphs[i]);
- if (glyphs[i] == spaceGlyph)
- advances[i].width = ROUND_TO_INT(advances[i].width);
- advances[i].height = 0;
+cleanup:
+ if (glyphs != localGlyphBuffer) {
+ free(glyphs);
}
-#endif
-
- // This will draw the text from the top of the bounding box down.
- // Qt expects to draw from the baseline.
-#ifdef DRAW_WITHOUT_ADVANCES
- point.y -= [self lineSpacing] - [self descent];
-#else
- point.y += [self descent] - 1;
-#endif
-
- // Setup the color and font.
- [color set];
- [font set];
-
- // Finally, draw the characters.
- cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ return result;
+}
-#ifdef DRAW_WITHOUT_ADVANCES
- CGContextSetCharacterSpacing(cgContext, 0.0);
- CGContextShowGlyphsAtPoint (cgContext, point.x, point.y + [font defaultLineHeightForFont] - [self descent] + 1, glyphs, numGlyphs);
-#else
- CGContextSetTextPosition (cgContext, point.x, point.y - [self descent] + 1);
- CGContextShowGlyphsWithAdvances (cgContext, glyphs, advances, numGlyphs);
- //CGContextShowGlyphsWithDeviceAdvances (cgContext, glyphs, advances, numGlyphs);
- if (advances != localAdvanceBuffer) {
- free(advances);
+- (void)drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ NSFont *substituteFont;
+ _IFFailedDrawReason reason = [self _drawCharacters: characters length: length atPoint: point withColor: color];
+
+ // ASSUMPTION: We normally fail because we're trying to render characters
+ // that doesn't have glyphs in the specified fonts. Instead of immediately using the slow path
+ // we look for a font corresponding to the first character cluster in the string
+ // and try rendering the entire string with that font. If that fails we fall back
+ // to the safe slow drawing.
+ if (reason == _IFMissingGlyph) {
+ unsigned int clusterLength;
+
+ clusterLength = findLengthOfCharacterCluster(characters, length);
+ substituteFont = [self substituteFontForCharacters: characters length: clusterLength];
+ if (substituteFont)
+ reason = [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] _drawCharacters: characters length: length atPoint: point withColor: color];
+
+ if (!substituteFont || reason != _IFDrawSucceeded)
+ [self slowDrawCharacters: characters length: length atPoint: point withColor: color];
}
-#endif
-
-cleanup:
- if (glyphs != localGlyphBuffer) {
- free(glyphs);
+ else if (reason == _IFNonBaseCharacter) {
+ [self slowDrawCharacters: characters length: length atPoint: point withColor: color];
}
}
@@ -605,10 +676,11 @@ cleanup:
return totalWidth;
}
+
- (float)floatWidthForCharacters:(const UniChar *)characters length:(unsigned)length applyRounding: (BOOL)applyRounding
{
float totalWidth = 0;
- unsigned int i;
+ unsigned int i, clusterLength;
NSFont *substituteFont;
ATSGlyphRef glyphID;
@@ -631,17 +703,20 @@ cleanup:
// Try to find a substitute font if this font didn't have a glyph for a character in the
// string. If one isn't found we end up drawing and measuring a box.
if (glyphID == 0) {
- substituteFont = [self substituteFontForCharacters: characters length: length];
+ clusterLength = findLengthOfCharacterCluster (&characters[i], length - i);
+ substituteFont = [self substituteFontForCharacters: &characters[i] length: clusterLength];
if (substituteFont) {
- WEBKITDEBUGLEVEL (WEBKIT_LOG_FONTCACHE, "substituting %s for %s, missing 0x%04x\n", DEBUG_OBJECT(substituteFont), DEBUG_OBJECT([font displayName]), c);
- return [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] widthForCharacters: characters length: length];
+ //WEBKITDEBUGLEVEL (WEBKIT_LOG_FONTCACHE, "substituting %s for %s, missing 0x%04x\n", DEBUG_OBJECT(substituteFont), DEBUG_OBJECT([font displayName]), c);
+ totalWidth += [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] floatWidthForCharacters: &characters[i] length: clusterLength applyRounding: YES];
}
}
-
- if (glyphID == spaceGlyph && applyRounding)
- totalWidth += ROUND_TO_INT(widthForGlyph(self, glyphToWidthMap, glyphID));
- else
- totalWidth += widthForGlyph(self, glyphToWidthMap, glyphID);
+
+ if (glyphID > 0 || ((glyphID == 0) && substituteFont == nil)) {
+ if (glyphID == spaceGlyph && applyRounding)
+ totalWidth += ROUND_TO_INT(widthForGlyph(self, glyphToWidthMap, glyphID));
+ else
+ totalWidth += widthForGlyph(self, glyphToWidthMap, glyphID);
+ }
}
return totalWidth;
diff --git a/WebKit/WebCoreSupport.subproj/WebTextRenderer.m b/WebKit/WebCoreSupport.subproj/WebTextRenderer.m
index 2d227ae..9f283d0 100644
--- a/WebKit/WebCoreSupport.subproj/WebTextRenderer.m
+++ b/WebKit/WebCoreSupport.subproj/WebTextRenderer.m
@@ -187,19 +187,33 @@ static void FillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
}
-static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
+static unsigned int findLengthOfCharacterCluster(const UniChar *characters, unsigned int length)
{
- unsigned int i, numGlyphs = glyphs->numGlyphs;
- ATSLayoutRecord *glyphRecord;
+ unsigned int clusterLength = 1, k;
+ UniChar nextC;
- glyphRecord = (ATSLayoutRecord *)glyphs->firstRecord;
- for (i = 0; i < numGlyphs; i++) {
- if (glyphRecord->glyphID == 0) {
- return YES;
+ if (length == 0)
+ return 0;
+
+ if (length == 1)
+ return 1;
+
+ if (IsNonBaseChar(characters[0]))
+ return 1;
+
+ nextC = characters[1];
+ if (IsNonBaseChar(nextC)){
+ // Find all the non base characters after the current character.
+ for (k = 2; k < length; k++){
+ if (!IsNonBaseChar(characters[k]))
+ break;
}
- glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + glyphs->recordSize);
+ clusterLength = k;
}
- return NO;
+ else
+ clusterLength = 1;
+
+ return clusterLength;
}
@@ -375,7 +389,7 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
-- (bool) slowPackGlyphsForCharacters:(const UniChar *)characters numCharacters: (unsigned int)numCharacters glyphBuffer:(CGGlyph **)glyphBuffer numGlyphs:(unsigned int *)numGlyphs
+- (void) slowPackGlyphsForCharacters:(const UniChar *)characters numCharacters: (unsigned int)numCharacters glyphBuffer:(CGGlyph **)glyphBuffer numGlyphs:(unsigned int *)numGlyphs
{
ATSGlyphVector glyphVector;
unsigned int j;
@@ -384,8 +398,6 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
ATSInitializeGlyphVector(numCharacters, 0, &glyphVector);
[self convertCharacters: characters length: numCharacters toGlyphs: &glyphVector];
- if (hasMissingGlyphs (&glyphVector))
- return NO;
*numGlyphs = glyphVector.numGlyphs;
*glyphBuffer = glyphBufPtr = (CGGlyph *)malloc (*numGlyphs * sizeof(CGGlyph));
@@ -396,8 +408,6 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
ATSClearGlyphVector(&glyphVector);
-
- return YES;
}
@@ -424,16 +434,108 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
}
-- (void)drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+- (NSPoint)drawGlyphs: (CGGlyph *)glyphs numGlyphs: (unsigned int)numGlyphs atPoint: (NSPoint)point withColor: (NSColor *)color
{
- uint i, numGlyphs;
- CGGlyph *glyphs, localGlyphBuffer[LOCAL_BUFFER_SIZE];
-#ifndef DRAW_WITHOUT_ADVANCES
+ unsigned int i;
CGSize *advances, localAdvanceBuffer[LOCAL_BUFFER_SIZE];
-#endif
- ATSGlyphRef glyphID;
CGContextRef cgContext;
+ NSPoint advancePoint = point;
+
+ if (numGlyphs == 0)
+ return point;
+
+ // Determine if we can use the local stack buffer, otherwise allocate.
+ if (numGlyphs > LOCAL_BUFFER_SIZE) {
+ advances = (CGSize *)malloc(numGlyphs * sizeof(CGSize));
+ } else {
+ advances = localAdvanceBuffer;
+ }
+
+ for (i = 0; i < numGlyphs; i++) {
+ advances[i].width = widthForGlyph(self, glyphToWidthMap, glyphs[i]);
+ if (glyphs[i] == spaceGlyph)
+ advances[i].width = ROUND_TO_INT(advances[i].width);
+ advances[i].height = 0;
+ advancePoint.x += advances[i].width;
+ }
+
+ // Setup the color and font.
+ [color set];
+ [font set];
+
+ // Finally, draw the glyphs.
+ cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+
+ CGContextSetTextPosition (cgContext, point.x, point.y);
+ CGContextShowGlyphsWithAdvances (cgContext, glyphs, advances, numGlyphs);
+ //CGContextShowGlyphsWithDeviceAdvances (cgContext, glyphs, advances, numGlyphs);
+
+ if (advances != localAdvanceBuffer) {
+ free(advances);
+ }
+ return advancePoint;
+}
+
+// Useful page for testing http://home.att.net/~jameskass
+
+- (NSPoint)slowDrawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ unsigned int charPos = 0, lastDrawnGlyph = 0;
+ unsigned int clusterLength, i, numGlyphs, fragmentLength;
NSFont *substituteFont;
+ CGGlyph *glyphs;
+ ATSGlyphRef glyphID;
+
+ [self slowPackGlyphsForCharacters: characters numCharacters: length glyphBuffer: &glyphs numGlyphs: &numGlyphs];
+
+ // FIXME: This assumes that we'll always get one glyph per character cluster.
+ for (i = 0; i < numGlyphs; i++){
+ glyphID = glyphs[i];
+
+ clusterLength = findLengthOfCharacterCluster (&characters[charPos], length - charPos);
+
+ if (glyphID == 0){
+ // Draw everthing up to this point.
+ fragmentLength = i - lastDrawnGlyph;
+ if (fragmentLength > 0)
+ point = [self drawGlyphs: &glyphs[lastDrawnGlyph] numGlyphs: fragmentLength atPoint: point withColor: color];
+
+ // Draw the character in the alternate font.
+ substituteFont = [self substituteFontForCharacters: &characters[charPos] length: clusterLength];
+ if (substituteFont)
+ point = [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] slowDrawCharacters: &characters[charPos] length: clusterLength atPoint: point withColor: color];
+ else
+ point = [self drawGlyphs: &glyphs[i] numGlyphs: 1 atPoint: point withColor: color];
+
+ lastDrawnGlyph = i+1;
+ }
+
+ charPos += clusterLength;
+ }
+
+ fragmentLength = numGlyphs - lastDrawnGlyph;
+ if (fragmentLength > 0)
+ point = [self drawGlyphs: &glyphs[lastDrawnGlyph] numGlyphs: fragmentLength atPoint: point withColor: color];
+
+ if (glyphs)
+ free(glyphs);
+
+ return point;
+}
+
+
+typedef enum {
+ _IFNonBaseCharacter,
+ _IFMissingGlyph,
+ _IFDrawSucceeded,
+} _IFFailedDrawReason;
+
+- (_IFFailedDrawReason)_drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ uint i;
+ CGGlyph *glyphs, localGlyphBuffer[LOCAL_BUFFER_SIZE];
+ ATSGlyphRef glyphID;
+ _IFFailedDrawReason result = _IFDrawSucceeded;
// FIXME: Deal with other styles of glyph packing.
if ([font glyphPacking] != NSNativeShortGlyphPacking &&
@@ -447,12 +549,9 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
glyphs = localGlyphBuffer;
}
- // Set the number of glyphs to the character length. This may change during the character
- // scan if we find any non base characters.
- numGlyphs = length;
-
// Pack the glyph buffer and ensure that we have glyphs for all the
- // characters. If we're missing a glyph look for an alternate font.
+ // characters. If we're missing a glyph or have a non-base character
+ // stop drawing and return a failure code.
for (i = 0; i < length; i++) {
UniChar c = characters[i];
@@ -460,87 +559,59 @@ static bool hasMissingGlyphs(ATSGlyphVector *glyphs)
if (c == NON_BREAKING_SPACE)
c = SPACE;
- // Is the a combining character? If so we have to do expensive
- // glyph lookup.
+ // Is the a non-base character?
if (IsNonBaseChar(c)) {
- CGGlyph *slowGlyphBuffer;
- bool hasGlyphs = [self slowPackGlyphsForCharacters: characters numCharacters: length glyphBuffer: &slowGlyphBuffer numGlyphs: &numGlyphs];
- if (hasGlyphs) {
- if (glyphs != localGlyphBuffer) {
- free(glyphs);
- }
- glyphs = slowGlyphBuffer;
- } else {
- substituteFont = [self substituteFontForCharacters: characters length: length];
- if (substituteFont) {
- [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] drawCharacters: characters length: length atPoint: point withColor: color];
- goto cleanup;
- }
- }
- break;
+ result = _IFNonBaseCharacter;
+ goto cleanup;
}
-
- glyphID = glyphForCharacter (characterToGlyphMap, c);
- // glyphID == 0 means that the font doesn't contain a glyph for the character.
- if (glyphID == 0) {
- substituteFont = [self substituteFontForCharacters: characters length: length];
- if (substituteFont) {
- [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] drawCharacters: characters length: length atPoint: point withColor: color];
- goto cleanup;
- }
+ glyphID = glyphForCharacter (characterToGlyphMap, c);
+ if (glyphID == nonGlyphID) {
+ glyphID = [self extendCharacterToGlyphMapToInclude: c];
}
+ // Does this font not contain a glyph for the character?
+ if (glyphID == 0){
+ result = _IFMissingGlyph;
+ goto cleanup;
+ }
+
glyphs[i] = glyphID;
}
-#ifndef DRAW_WITHOUT_ADVANCES
- // Determine if we can use the local stack buffer, otherwise allocate.
- if (numGlyphs > LOCAL_BUFFER_SIZE) {
- advances = (CGSize *)malloc(numGlyphs * sizeof(CGSize));
- } else {
- advances = localAdvanceBuffer;
- }
+ [self drawGlyphs: glyphs numGlyphs: length atPoint: point withColor: color];
- for (i = 0; i < numGlyphs; i++) {
- advances[i].width = widthForGlyph(self, glyphToWidthMap, glyphs[i]);
- if (glyphs[i] == spaceGlyph)
- advances[i].width = ROUND_TO_INT(advances[i].width);
- advances[i].height = 0;
+cleanup:
+ if (glyphs != localGlyphBuffer) {
+ free(glyphs);
}
-#endif
-
- // This will draw the text from the top of the bounding box down.
- // Qt expects to draw from the baseline.
-#ifdef DRAW_WITHOUT_ADVANCES
- point.y -= [self lineSpacing] - [self descent];
-#else
- point.y += [self descent] - 1;
-#endif
-
- // Setup the color and font.
- [color set];
- [font set];
-
- // Finally, draw the characters.
- cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ return result;
+}
-#ifdef DRAW_WITHOUT_ADVANCES
- CGContextSetCharacterSpacing(cgContext, 0.0);
- CGContextShowGlyphsAtPoint (cgContext, point.x, point.y + [font defaultLineHeightForFont] - [self descent] + 1, glyphs, numGlyphs);
-#else
- CGContextSetTextPosition (cgContext, point.x, point.y - [self descent] + 1);
- CGContextShowGlyphsWithAdvances (cgContext, glyphs, advances, numGlyphs);
- //CGContextShowGlyphsWithDeviceAdvances (cgContext, glyphs, advances, numGlyphs);
- if (advances != localAdvanceBuffer) {
- free(advances);
+- (void)drawCharacters:(const UniChar *)characters length: (unsigned int)length atPoint:(NSPoint)point withColor:(NSColor *)color
+{
+ NSFont *substituteFont;
+ _IFFailedDrawReason reason = [self _drawCharacters: characters length: length atPoint: point withColor: color];
+
+ // ASSUMPTION: We normally fail because we're trying to render characters
+ // that doesn't have glyphs in the specified fonts. Instead of immediately using the slow path
+ // we look for a font corresponding to the first character cluster in the string
+ // and try rendering the entire string with that font. If that fails we fall back
+ // to the safe slow drawing.
+ if (reason == _IFMissingGlyph) {
+ unsigned int clusterLength;
+
+ clusterLength = findLengthOfCharacterCluster(characters, length);
+ substituteFont = [self substituteFontForCharacters: characters length: clusterLength];
+ if (substituteFont)
+ reason = [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] _drawCharacters: characters length: length atPoint: point withColor: color];
+
+ if (!substituteFont || reason != _IFDrawSucceeded)
+ [self slowDrawCharacters: characters length: length atPoint: point withColor: color];
}
-#endif
-
-cleanup:
- if (glyphs != localGlyphBuffer) {
- free(glyphs);
+ else if (reason == _IFNonBaseCharacter) {
+ [self slowDrawCharacters: characters length: length atPoint: point withColor: color];
}
}
@@ -605,10 +676,11 @@ cleanup:
return totalWidth;
}
+
- (float)floatWidthForCharacters:(const UniChar *)characters length:(unsigned)length applyRounding: (BOOL)applyRounding
{
float totalWidth = 0;
- unsigned int i;
+ unsigned int i, clusterLength;
NSFont *substituteFont;
ATSGlyphRef glyphID;
@@ -631,17 +703,20 @@ cleanup:
// Try to find a substitute font if this font didn't have a glyph for a character in the
// string. If one isn't found we end up drawing and measuring a box.
if (glyphID == 0) {
- substituteFont = [self substituteFontForCharacters: characters length: length];
+ clusterLength = findLengthOfCharacterCluster (&characters[i], length - i);
+ substituteFont = [self substituteFontForCharacters: &characters[i] length: clusterLength];
if (substituteFont) {
- WEBKITDEBUGLEVEL (WEBKIT_LOG_FONTCACHE, "substituting %s for %s, missing 0x%04x\n", DEBUG_OBJECT(substituteFont), DEBUG_OBJECT([font displayName]), c);
- return [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] widthForCharacters: characters length: length];
+ //WEBKITDEBUGLEVEL (WEBKIT_LOG_FONTCACHE, "substituting %s for %s, missing 0x%04x\n", DEBUG_OBJECT(substituteFont), DEBUG_OBJECT([font displayName]), c);
+ totalWidth += [[[IFTextRendererFactory sharedFactory] rendererWithFont: substituteFont] floatWidthForCharacters: &characters[i] length: clusterLength applyRounding: YES];
}
}
-
- if (glyphID == spaceGlyph && applyRounding)
- totalWidth += ROUND_TO_INT(widthForGlyph(self, glyphToWidthMap, glyphID));
- else
- totalWidth += widthForGlyph(self, glyphToWidthMap, glyphID);
+
+ if (glyphID > 0 || ((glyphID == 0) && substituteFont == nil)) {
+ if (glyphID == spaceGlyph && applyRounding)
+ totalWidth += ROUND_TO_INT(widthForGlyph(self, glyphToWidthMap, glyphID));
+ else
+ totalWidth += widthForGlyph(self, glyphToWidthMap, glyphID);
+ }
}
return totalWidth;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list