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