Title: [104683] trunk/Source/WebCore
Revision
104683
Author
[email protected]
Date
2012-01-11 01:16:16 -0800 (Wed, 11 Jan 2012)

Log Message

Large SVG text layout performance regression in r81168
https://bugs.webkit.org/show_bug.cgi?id=65711

Reviewed by Zoltan Herczeg.

Introduce SVGTextMetricsBuilder, which will be used to speed-up measuring of SVG text,
by using the simple code path, whenever possibly. It's not enabled yet, as it requires
a restructurization of SVGTextLayoutAttributesBuilder - its the first chunk of a set
of patches, that all together fix the performance regression and much more :-)

Doesn't affect any tests, SVGTextMetricsBuilder is not turned on yet.

* CMakeLists.txt: Add SVGTextMetricsBuilder.cpp/h to build.
* GNUmakefile.list.am: Ditto.
* Target.pri: Ditto.
* WebCore.gypi: Ditto.
* WebCore.vcproj/WebCore.vcproj: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* platform/graphics/Font.h:
(WebCore::Font::codePath): Make it public, to be usable from SVGTextMetricsBuilder.
* rendering/svg/RenderSVGAllInOne.cpp: Add SVGTextMetricsBuilder.cpp to build.
* rendering/svg/RenderSVGText.cpp:
* rendering/svg/RenderSVGText.h:
* rendering/svg/SVGTextLayoutAttributesBuilder.cpp:
(WebCore::SVGTextLayoutAttributesBuilder::propagateLayoutAttributes): SVGTextMetrics::emptyMetrics() is gone, adapt code.
* rendering/svg/SVGTextLayoutEngine.cpp:
(WebCore::SVGTextLayoutEngine::currentLogicalCharacterMetrics): Ditto.
(WebCore::SVGTextLayoutEngine::layoutTextOnLineOrPath): Ditto.
* rendering/svg/SVGTextMetrics.cpp:
(WebCore::SVGTextMetrics::SVGTextMetrics): Made public, now used in SVGTextLayoutEngine.
(WebCore::SVGTextMetrics::constructTextRun): Move to public static function, to be usable from SVGTextMetricsBuilder.
* rendering/svg/SVGTextMetrics.h:
(WebCore::SVGTextMetrics::isEmpty): Add new isEmpty method, which replaces the == empyMetrics().
(WebCore::SVGTextMetrics::setWidth): Remove friendship with SVGTextLayoutAttributesBuilder, and make it public, to avoid another friendship.
* rendering/svg/SVGTextMetricsBuilder.cpp: Added.
(WebCore::SVGTextMetricsBuilder::SVGTextMetricsBuilder):
(WebCore::SVGTextMetricsBuilder::advance):
(WebCore::SVGTextMetricsBuilder::advanceSimpleText): New variant using WidthIterator directly, this is finally possible as SVG Fonts have been integrated into the glyph pages concept a while ago.
(WebCore::SVGTextMetricsBuilder::advanceComplexText): Complex code path, accounting for sum of glyph widths != run width.
(WebCore::SVGTextMetricsBuilder::measureTextRenderer): Either measure the text renderer, or just figure out lastCharacter.
(WebCore::SVGTextMetricsBuilder::walkTreeUntilSpecificLeafIsReached): Walks SVG <text> tree, correctly computing "lastCharacter" until the leaf is reached.
(WebCore::SVGTextMetricsBuilder::measureAllCharactersOfRenderer): Use above method.
* rendering/svg/SVGTextMetricsBuilder.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (104682 => 104683)


--- trunk/Source/WebCore/CMakeLists.txt	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/CMakeLists.txt	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1681,6 +1681,7 @@
         rendering/svg/SVGTextLayoutEngineSpacing.cpp
         rendering/svg/SVGTextRunRenderingContext.cpp
         rendering/svg/SVGTextMetrics.cpp
+        rendering/svg/SVGTextMetricsBuilder.cpp
         rendering/svg/SVGTextQuery.cpp
         svg/ColorDistance.cpp
         svg/SVGAElement.cpp

Modified: trunk/Source/WebCore/ChangeLog (104682 => 104683)


--- trunk/Source/WebCore/ChangeLog	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/ChangeLog	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1,3 +1,49 @@
+2012-01-10  Nikolas Zimmermann  <[email protected]>
+
+        Large SVG text layout performance regression in r81168
+        https://bugs.webkit.org/show_bug.cgi?id=65711
+
+        Reviewed by Zoltan Herczeg.
+
+        Introduce SVGTextMetricsBuilder, which will be used to speed-up measuring of SVG text,
+        by using the simple code path, whenever possibly. It's not enabled yet, as it requires
+        a restructurization of SVGTextLayoutAttributesBuilder - its the first chunk of a set
+        of patches, that all together fix the performance regression and much more :-)
+
+        Doesn't affect any tests, SVGTextMetricsBuilder is not turned on yet.
+
+        * CMakeLists.txt: Add SVGTextMetricsBuilder.cpp/h to build.
+        * GNUmakefile.list.am: Ditto.
+        * Target.pri: Ditto.
+        * WebCore.gypi: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * platform/graphics/Font.h:
+        (WebCore::Font::codePath): Make it public, to be usable from SVGTextMetricsBuilder.
+        * rendering/svg/RenderSVGAllInOne.cpp: Add SVGTextMetricsBuilder.cpp to build.
+        * rendering/svg/RenderSVGText.cpp:
+        * rendering/svg/RenderSVGText.h:
+        * rendering/svg/SVGTextLayoutAttributesBuilder.cpp:
+        (WebCore::SVGTextLayoutAttributesBuilder::propagateLayoutAttributes): SVGTextMetrics::emptyMetrics() is gone, adapt code.
+        * rendering/svg/SVGTextLayoutEngine.cpp:
+        (WebCore::SVGTextLayoutEngine::currentLogicalCharacterMetrics): Ditto.
+        (WebCore::SVGTextLayoutEngine::layoutTextOnLineOrPath): Ditto.
+        * rendering/svg/SVGTextMetrics.cpp:
+        (WebCore::SVGTextMetrics::SVGTextMetrics): Made public, now used in SVGTextLayoutEngine.
+        (WebCore::SVGTextMetrics::constructTextRun): Move to public static function, to be usable from SVGTextMetricsBuilder.
+        * rendering/svg/SVGTextMetrics.h:
+        (WebCore::SVGTextMetrics::isEmpty): Add new isEmpty method, which replaces the == empyMetrics().
+        (WebCore::SVGTextMetrics::setWidth): Remove friendship with SVGTextLayoutAttributesBuilder, and make it public, to avoid another friendship.
+        * rendering/svg/SVGTextMetricsBuilder.cpp: Added.
+        (WebCore::SVGTextMetricsBuilder::SVGTextMetricsBuilder):
+        (WebCore::SVGTextMetricsBuilder::advance):
+        (WebCore::SVGTextMetricsBuilder::advanceSimpleText): New variant using WidthIterator directly, this is finally possible as SVG Fonts have been integrated into the glyph pages concept a while ago.
+        (WebCore::SVGTextMetricsBuilder::advanceComplexText): Complex code path, accounting for sum of glyph widths != run width.
+        (WebCore::SVGTextMetricsBuilder::measureTextRenderer): Either measure the text renderer, or just figure out lastCharacter.
+        (WebCore::SVGTextMetricsBuilder::walkTreeUntilSpecificLeafIsReached): Walks SVG <text> tree, correctly computing "lastCharacter" until the leaf is reached.
+        (WebCore::SVGTextMetricsBuilder::measureAllCharactersOfRenderer): Use above method.
+        * rendering/svg/SVGTextMetricsBuilder.h: Added.
+
 2012-01-11  Dan Bernstein  <[email protected]>
 
         <rdar://problem/10674686> Implement the font-kerning CSS property

Modified: trunk/Source/WebCore/GNUmakefile.list.am (104682 => 104683)


--- trunk/Source/WebCore/GNUmakefile.list.am	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2012-01-11 09:16:16 UTC (rev 104683)
@@ -3744,6 +3744,8 @@
 	Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.h \
 	Source/WebCore/rendering/svg/SVGTextMetrics.cpp \
 	Source/WebCore/rendering/svg/SVGTextMetrics.h \
+	Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp \
+	Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h \
 	Source/WebCore/rendering/svg/SVGTextQuery.cpp \
 	Source/WebCore/rendering/svg/SVGTextQuery.h \
 	Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp \

Modified: trunk/Source/WebCore/Target.pri (104682 => 104683)


--- trunk/Source/WebCore/Target.pri	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/Target.pri	2012-01-11 09:16:16 UTC (rev 104683)
@@ -2470,6 +2470,7 @@
     rendering/svg/SVGTextLayoutEngineBaseline.h \
     rendering/svg/SVGTextLayoutEngineSpacing.h \
     rendering/svg/SVGTextMetrics.h \
+    rendering/svg/SVGTextMetricsBuilder.h \
     rendering/svg/SVGTextQuery.h \
     rendering/svg/SVGTextRunRenderingContext.h \
     storage/AbstractDatabase.h \
@@ -3425,6 +3426,7 @@
               rendering/svg/SVGTextLayoutEngineBaseline.cpp \
               rendering/svg/SVGTextLayoutEngineSpacing.cpp \
               rendering/svg/SVGTextMetrics.cpp \
+              rendering/svg/SVGTextMetricsBuilder.cpp \
               rendering/svg/SVGTextQuery.cpp \
               rendering/svg/SVGTextRunRenderingContext.cpp \
               svg/SVGDocumentExtensions.cpp \

Modified: trunk/Source/WebCore/WebCore.gypi (104682 => 104683)


--- trunk/Source/WebCore/WebCore.gypi	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/WebCore.gypi	2012-01-11 09:16:16 UTC (rev 104683)
@@ -4911,6 +4911,8 @@
             'rendering/svg/SVGTextLayoutEngineSpacing.h',
             'rendering/svg/SVGTextMetrics.cpp',
             'rendering/svg/SVGTextMetrics.h',
+            'rendering/svg/SVGTextMetricsBuilder.cpp',
+            'rendering/svg/SVGTextMetricsBuilder.h',
             'rendering/svg/SVGTextQuery.cpp',
             'rendering/svg/SVGTextQuery.h',
             'rendering/svg/SVGTextRunRenderingContext.cpp',
@@ -6011,6 +6013,8 @@
             'rendering/svg/SVGTextLayoutEngineSpacing.h',
             'rendering/svg/SVGTextMetrics.cpp',
             'rendering/svg/SVGTextMetrics.h',
+            'rendering/svg/SVGTextMetricsBuilder.cpp',
+            'rendering/svg/SVGTextMetricsBuilder.h',
             'rendering/svg/SVGTextQuery.cpp',
             'rendering/svg/SVGTextQuery.h',
             'rendering/svg/SVGTextRunRenderingContext.cpp',

Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (104682 => 104683)


--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2012-01-11 09:16:16 UTC (rev 104683)
@@ -44887,6 +44887,62 @@
 					>
 				</File>
 				<File
+					RelativePath="..\rendering\svg\SVGTextMetricsBuilder.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug_Cairo_CFLite|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release_Cairo_CFLite|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug_All|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Production|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\rendering\svg\SVGTextMetricsBuilder.h"
+					>
+				</File>
+				<File
 					RelativePath="..\rendering\svg\SVGTextMetrics.cpp"
 					>
 					<FileConfiguration

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (104682 => 104683)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1762,6 +1762,7 @@
 		6ED878C5147493F4004C3597 /* RenderTableCaption.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED878C3147493F4004C3597 /* RenderTableCaption.h */; };
 		6EE8A77210F803F3005A4A24 /* JSWebGLContextAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */; };
 		6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */; };
+		7117445914BC34EC00EE5FC8 /* SVGTextMetricsBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7117445714BC34E200EE5FC8 /* SVGTextMetricsBuilder.h */; };
 		7134496D146941B300720312 /* SVGLengthContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7134496B146941B300720312 /* SVGLengthContext.cpp */; };
 		7134496E146941B300720312 /* SVGLengthContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 7134496C146941B300720312 /* SVGLengthContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		71537A01146BD9D7008BD615 /* SVGPathData.h in Headers */ = {isa = PBXBuildFile; fileRef = 715379FF146BD9D6008BD615 /* SVGPathData.h */; };
@@ -9062,6 +9063,8 @@
 		6ED878C3147493F4004C3597 /* RenderTableCaption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTableCaption.h; sourceTree = "<group>"; };
 		6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
 		6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
+		7117445614BC34E200EE5FC8 /* SVGTextMetricsBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGTextMetricsBuilder.cpp; sourceTree = "<group>"; };
+		7117445714BC34E200EE5FC8 /* SVGTextMetricsBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTextMetricsBuilder.h; sourceTree = "<group>"; };
 		7134496B146941B300720312 /* SVGLengthContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGLengthContext.cpp; sourceTree = "<group>"; };
 		7134496C146941B300720312 /* SVGLengthContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGLengthContext.h; sourceTree = "<group>"; };
 		715379FE146BD9D6008BD615 /* SVGPathData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPathData.cpp; sourceTree = "<group>"; };
@@ -14165,6 +14168,8 @@
 				080E49241255F3BD00EFCA27 /* SVGTextLayoutEngineSpacing.h */,
 				08F0BFC01255C53C00075185 /* SVGTextMetrics.cpp */,
 				08F0BFC11255C53C00075185 /* SVGTextMetrics.h */,
+				7117445614BC34E200EE5FC8 /* SVGTextMetricsBuilder.cpp */,
+				7117445714BC34E200EE5FC8 /* SVGTextMetricsBuilder.h */,
 				0854B0121255E4E600B9CDD0 /* SVGTextQuery.cpp */,
 				0854B0131255E4E600B9CDD0 /* SVGTextQuery.h */,
 				08D29440138669E40097C89B /* SVGTextRunRenderingContext.cpp */,
@@ -24913,6 +24918,7 @@
 				97D2AD0414B823A60093DF32 /* DOMWindowProperty.h in Headers */,
 				7AABA25A14BC613300AA9A11 /* DOMEditor.h in Headers */,
 				A8F457A114BC1A94000CEA59 /* DOMWindowSQLDatabase.h in Headers */,
+				7117445914BC34EC00EE5FC8 /* SVGTextMetricsBuilder.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/WebCore/platform/graphics/Font.h (104682 => 104683)


--- trunk/Source/WebCore/platform/graphics/Font.h	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/platform/graphics/Font.h	2012-01-11 09:16:16 UTC (rev 104683)
@@ -171,6 +171,7 @@
     static bool shouldUseSmoothing();
 
     enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
+    CodePath codePath(const TextRun&) const;
 
 private:
     enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
@@ -191,8 +192,6 @@
     static bool canReturnFallbackFontsForComplexText();
     static bool canExpandAroundIdeographsInComplexText();
 
-    CodePath codePath(const TextRun&) const;
-
     // Returns the initial in-stream advance.
     float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
     void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -77,4 +77,5 @@
 #include "SVGTextLayoutEngineSpacing.cpp"
 #include "SVGTextRunRenderingContext.cpp"
 #include "SVGTextMetrics.cpp"
+#include "SVGTextMetricsBuilder.cpp"
 #include "SVGTextQuery.cpp"

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -5,7 +5,7 @@
  * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
  * Copyright (C) 2008 Rob Buis <[email protected]>
  * Copyright (C) 2009 Dirk Schulze <[email protected]>
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -43,6 +43,7 @@
 #include "SVGRootInlineBox.h"
 #include "SVGTextElement.h"
 #include "SVGTextLayoutAttributesBuilder.h"
+#include "SVGTextRunRenderingContext.h"
 #include "SVGTransformList.h"
 #include "SVGURIReference.h"
 #include "SimpleFontData.h"

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGText.h (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/RenderSVGText.h	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGText.h	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2006 Apple Computer, Inc.
  * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -30,6 +30,7 @@
 
 namespace WebCore {
 
+class RenderSVGInlineText;
 class SVGTextElement;
 
 class RenderSVGText : public RenderSVGBlock {

Modified: trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -198,7 +198,7 @@
     
             unsigned valueListPosition = atCharacter;
             unsigned metricsLength = 1;
-            SVGTextMetrics lastMetrics = SVGTextMetrics::emptyMetrics();
+            SVGTextMetrics lastMetrics(SVGTextMetrics::SkippedSpaceMetrics);
 
             for (unsigned textPosition = 0; textPosition < textLength; textPosition += metricsLength) {
                 const UChar& currentCharacter = characters[textPosition];
@@ -236,7 +236,7 @@
 
                 if (!preserveWhiteSpace && characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter)) {
                     attributes.positioningLists().appendEmptyValues();
-                    attributes.textMetricsValues().append(SVGTextMetrics::emptyMetrics());
+                    attributes.textMetricsValues().append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
                     continue;
                 }
 

Modified: trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -359,8 +359,7 @@
 
 bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes& logicalAttributes, SVGTextMetrics& logicalMetrics)
 {
-    logicalMetrics = SVGTextMetrics::emptyMetrics();
-
+    logicalMetrics = SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics);
     Vector<SVGTextMetrics>& textMetricsValues = logicalAttributes.textMetricsValues();
     unsigned textMetricsSize = textMetricsValues.size();
     while (true) {
@@ -376,7 +375,7 @@
         ASSERT(textMetricsSize);
         ASSERT(m_logicalMetricsListOffset < textMetricsSize);
         logicalMetrics = textMetricsValues.at(m_logicalMetricsListOffset);
-        if (logicalMetrics == SVGTextMetrics::emptyMetrics() || (!logicalMetrics.width() && !logicalMetrics.height())) {
+        if (logicalMetrics.isEmpty() || (!logicalMetrics.width() && !logicalMetrics.height())) {
             advanceToNextLogicalCharacter(logicalMetrics);
             continue;
         }
@@ -464,11 +463,11 @@
     // Main layout algorithm.
     while (true) {
         // Find the start of the current text box in this list, respecting ligatures.
-        SVGTextMetrics visualMetrics = SVGTextMetrics::emptyMetrics();
+        SVGTextMetrics visualMetrics(SVGTextMetrics::SkippedSpaceMetrics);
         if (!currentVisualCharacterMetrics(textBox, text, visualMetrics))
             break;
 
-        if (visualMetrics == SVGTextMetrics::emptyMetrics()) {
+        if (visualMetrics.isEmpty()) {
             advanceToNextVisualCharacter(visualMetrics);
             continue;
         }
@@ -477,7 +476,7 @@
         if (!currentLogicalCharacterAttributes(logicalAttributes))
             break;
 
-        SVGTextMetrics logicalMetrics = SVGTextMetrics::emptyMetrics();
+        SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics);
         if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics))
             break;
 

Modified: trunk/Source/WebCore/rendering/svg/SVGTextMetrics.cpp (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextMetrics.cpp	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/SVGTextMetrics.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -24,6 +24,7 @@
 
 #include "RenderSVGInlineText.h"
 #include "SVGTextRunRenderingContext.h"
+#include "WidthIterator.h"
 
 namespace WebCore {
 
@@ -34,6 +35,13 @@
 {
 }
 
+SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
+    : m_width(0)
+    , m_height(0)
+    , m_length(1)
+{
+}
+
 SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run)
 {
     ASSERT(textRenderer);
@@ -55,23 +63,8 @@
     m_length = static_cast<unsigned>(length);
 }
 
-bool SVGTextMetrics::operator==(const SVGTextMetrics& other)
+TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, const UChar* characters, unsigned position, unsigned length)
 {
-    return m_width == other.m_width
-        && m_height == other.m_height
-        && m_length == other.m_length
-        && m_glyph == other.m_glyph;
-}
-
-SVGTextMetrics SVGTextMetrics::emptyMetrics()
-{
-    DEFINE_STATIC_LOCAL(SVGTextMetrics, s_emptyMetrics, ());
-    s_emptyMetrics.m_length = 1;
-    return s_emptyMetrics;
-}
-
-static TextRun constructTextRun(RenderSVGInlineText* text, const UChar* characters, unsigned position, unsigned length)
-{
     RenderStyle* style = text->style();
     ASSERT(style);
 
@@ -104,6 +97,25 @@
     return SVGTextMetrics(text, constructTextRun(text, text->characters(), position, length));
 }
 
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName)
+{
+    ASSERT(text);
+
+    bool needsContext = textRunNeedsRenderingContext(text->style()->font());
+    float scalingFactor = text->scalingFactor();
+    ASSERT(scalingFactor);
+
+    m_width = width / scalingFactor;
+    m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
+    if (needsContext) {
+        m_glyph.isValid = true;
+        m_glyph.unicodeString = String(text->characters() + position, length);
+        m_glyph.name = glyphName;
+    }
+
+    m_length = length;
 }
 
+}
+
 #endif // ENABLE(SVG)

Modified: trunk/Source/WebCore/rendering/svg/SVGTextMetrics.h (104682 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextMetrics.h	2012-01-11 09:16:11 UTC (rev 104682)
+++ trunk/Source/WebCore/rendering/svg/SVGTextMetrics.h	2012-01-11 09:16:16 UTC (rev 104683)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -21,21 +21,34 @@
 #define SVGTextMetrics_h
 
 #if ENABLE(SVG)
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
 class RenderSVGInlineText;
+class SVGTextLayoutAttributes;
 class TextRun;
 
 class SVGTextMetrics {
 public:
-    static SVGTextMetrics emptyMetrics();
+    enum MetricsType {
+        SkippedSpaceMetrics
+    };
+
+    SVGTextMetrics();
+    SVGTextMetrics(MetricsType);
+    SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName);
+
     static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length);
+    static TextRun constructTextRun(RenderSVGInlineText*, const UChar* characters, unsigned position, unsigned length);
 
-    bool operator==(const SVGTextMetrics&);
+    bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; }
 
     float width() const { return m_width; }
+    void setWidth(float width) { m_width = width; }
+
     float height() const { return m_height; }
     unsigned length() const { return m_length; }
 
@@ -61,11 +74,6 @@
     const Glyph& glyph() const { return m_glyph; }
 
 private:
-    friend class SVGTextLayoutAttributesBuilder;
-    void setWidth(float width) { m_width = width; }
-
-private:
-    SVGTextMetrics();
     SVGTextMetrics(RenderSVGInlineText*, const TextRun&);
 
     float m_width;

Added: trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp (0 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp	                        (rev 0)
+++ trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp	2012-01-11 09:16:16 UTC (rev 104683)
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGTextMetricsBuilder.h"
+
+#include "RenderSVGInlineText.h"
+#include "RenderSVGText.h"
+#include "SVGTextRunRenderingContext.h"
+#include "WidthIterator.h"
+
+namespace WebCore {
+
+SVGTextMetricsBuilder::SVGTextMetricsBuilder()
+    : m_text(0)
+    , m_characters(0)
+    , m_textLength(0)
+    , m_textPosition(0)
+    , m_finished(false)
+    , m_isComplexText(false)
+    , m_preserveWhiteSpace(false)
+    , m_totalWidth(0)
+{
+}
+
+void SVGTextMetricsBuilder::advance()
+{
+    m_textPosition += m_currentMetrics.length();
+    if (m_textPosition >= m_textLength) {
+        m_finished = true;
+        return;
+    }
+
+    bool startsSurrogatePair = U16_IS_LEAD(m_characters[m_textPosition]) && (m_textPosition + 1) < m_textLength && U16_IS_TRAIL(m_characters[m_textPosition + 1]);
+#if PLATFORM(QT)
+    advanceComplexText(startsSurrogatePair);
+#else
+    if (m_isComplexText)
+        advanceComplexText(startsSurrogatePair);
+    else
+        advanceSimpleText(startsSurrogatePair);
+#endif
+
+    if (!m_currentMetrics.length())
+        m_finished = true;
+}
+
+void SVGTextMetricsBuilder::advanceSimpleText(bool startsSurrogatePair)
+{
+#if PLATFORM(QT)
+    UNUSED_PARAM(startsSurrogatePair);
+    ASSERT_NOT_REACHED();
+#else
+    unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1);
+    if (!metricsLength) {
+        m_currentMetrics = SVGTextMetrics();
+        return;
+    }
+
+    if (startsSurrogatePair)
+        ASSERT(metricsLength == 2);
+
+    float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth;
+    m_totalWidth = m_simpleWidthIterator->runWidthSoFar();
+
+#if ENABLE(SVG_FONTS)
+    m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName());
+#else
+    m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString());
+#endif
+#endif
+}
+
+void SVGTextMetricsBuilder::advanceComplexText(bool startsSurrogatePair)
+{
+    unsigned metricsLength = startsSurrogatePair ? 2 : 1;
+    m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength);
+    m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength);
+    ASSERT(m_currentMetrics.length() == metricsLength);
+
+    // Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
+    // when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping.
+    // So whenever currentWidth != currentMetrics.width(), we are processing a text run whose length is
+    // not equal to the sum of the individual lengths of the glyphs, when measuring them isolated.
+    float currentWidth = m_complexStartToCurrentMetrics.width() - m_totalWidth;
+    if (currentWidth != m_currentMetrics.width())
+        m_currentMetrics.setWidth(currentWidth);
+
+    m_totalWidth = m_complexStartToCurrentMetrics.width();
+}
+
+void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, const UChar*& lastCharacter, Vector<SVGTextMetrics>* textMetricsValues)
+{
+    ASSERT(text);
+    ASSERT(textMetricsValues->isEmpty());
+    while (!m_finished) {
+        advance();
+
+        const UChar* currentCharacter = m_characters + m_textPosition;
+        if (*currentCharacter == ' ' && !m_preserveWhiteSpace && (!lastCharacter || *lastCharacter == ' ')) {
+            if (textMetricsValues)
+                textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
+            continue;
+        }
+
+        if (textMetricsValues)
+            textMetricsValues->append(m_currentMetrics);
+        lastCharacter = currentCharacter;
+    }
+}
+
+void SVGTextMetricsBuilder::walkTreeUntilSpecificLeafIsReached(RenderObject* start, RenderSVGInlineText* stopAtElement, const UChar*& lastCharacter, Vector<SVGTextMetrics>& textMetricsValues)
+{
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+        if (child->isSVGInlineText()) {
+            RenderSVGInlineText* text = toRenderSVGInlineText(child);
+            if (stopAtElement && stopAtElement != text) {
+                measureTextRenderer(text, lastCharacter, 0);
+                continue;
+            }
+
+            measureTextRenderer(text, lastCharacter, &textMetricsValues);
+            if (stopAtElement) {
+                ASSERT(stopAtElement == text);
+                return;
+            }
+
+            continue;
+        }
+
+        if (!child->isSVGInline())
+            continue;
+
+        walkTreeUntilSpecificLeafIsReached(child, stopAtElement, lastCharacter, textMetricsValues);
+    }
+}
+
+void SVGTextMetricsBuilder::measureAllCharactersOfRenderer(RenderSVGInlineText* text, Vector<SVGTextMetrics>& textMetricsValues)
+{
+    ASSERT(!m_finished);
+    ASSERT(text);
+    ASSERT(textMetricsValues.isEmpty());
+
+    RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
+    if (!textRoot)
+        return;
+
+    m_text = text;
+    m_characters = text->characters();
+    m_textLength = text->textLength();
+    m_preserveWhiteSpace = text->style()->whiteSpace() == PRE;
+
+    const Font& scaledFont = text->scaledFont();
+    TextRun run = SVGTextMetrics::constructTextRun(text, text->characters(), 0, text->textLength());
+    m_isComplexText = scaledFont.codePath(run) == Font::Complex;
+#if !PLATFORM(QT)
+    if (!m_isComplexText)
+        m_simpleWidthIterator = adoptPtr(new WidthIterator(&text->style()->font(), run));
+#endif
+
+    const UChar* lastCharacter = 0;
+    walkTreeUntilSpecificLeafIsReached(textRoot, text, lastCharacter, textMetricsValues);
+}
+
+}
+
+#endif // ENABLE(SVG)

Added: trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h (0 => 104683)


--- trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h	2012-01-11 09:16:16 UTC (rev 104683)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGTextMetricsBuilder_h
+#define SVGTextMetricsBuilder_h
+
+#if ENABLE(SVG)
+#include "SVGTextMetrics.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderSVGInlineText;
+struct WidthIterator;
+
+class SVGTextMetricsBuilder {
+    WTF_MAKE_NONCOPYABLE(SVGTextMetricsBuilder);
+public:
+    SVGTextMetricsBuilder();
+    void measureAllCharactersOfRenderer(RenderSVGInlineText*, Vector<SVGTextMetrics>&);
+
+private:
+    void advance();
+    void advanceSimpleText(bool startsSurrogatePair);
+    void advanceComplexText(bool startsSurrogatePair);
+    void measureTextRenderer(RenderSVGInlineText*, const UChar*& lastCharacter, Vector<SVGTextMetrics>*);
+    void walkTreeUntilSpecificLeafIsReached(RenderObject*, RenderSVGInlineText* stopAtElement, const UChar*& lastCharacter, Vector<SVGTextMetrics>&);
+
+    RenderSVGInlineText* m_text;
+    const UChar* m_characters;
+    unsigned m_textLength;
+    unsigned m_textPosition;
+    bool m_finished;
+    bool m_isComplexText;
+    bool m_preserveWhiteSpace;
+    SVGTextMetrics m_currentMetrics;
+    float m_totalWidth;
+
+    // Simple text only.
+    OwnPtr<WidthIterator> m_simpleWidthIterator;
+
+    // Complex text only.
+    SVGTextMetrics m_complexStartToCurrentMetrics;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to