// Set to a value > 0 to dump the text fragments
#define DUMP_TEXT_FRAGMENTS 0
-namespace WebCore {
+namespace blink {
SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layoutAttributes)
: m_layoutAttributes(layoutAttributes)
ASSERT(!m_layoutAttributes.isEmpty());
}
-void SVGTextLayoutEngine::updateCharacerPositionIfNeeded(float& x, float& y)
+void SVGTextLayoutEngine::updateCharacterPositionIfNeeded(float& x, float& y)
{
if (m_inPathLayout)
return;
m_dy = dy;
}
-void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& textMetricsValues)
+void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, const Vector<SVGTextMetrics>& textMetricsValues)
{
ASSERT(!m_currentTextFragment.length);
ASSERT(m_visualMetricsListOffset > 0);
m_currentTextFragment.length = m_visualCharacterOffset - m_currentTextFragment.characterOffset;
// Figure out fragment metrics.
- SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m_visualMetricsListOffset - 1);
+ const SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m_visualMetricsListOffset - 1);
m_currentTextFragment.width = lastCharacterMetrics.width();
m_currentTextFragment.height = lastCharacterMetrics.height();
while (currentParent) {
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(currentParent)) {
SVGLengthContext lengthContext(textContentElement);
- if (textContentElement->lengthAdjustCurrentValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser())
+ if (textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser())
return true;
}
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
SVGLengthContext lengthContext(textContentElement);
- lengthAdjust = textContentElement->lengthAdjustCurrentValue();
+ lengthAdjust = textContentElement->lengthAdjust()->currentValue()->enumValue();
if (textContentElement->textLengthIsSpecifiedByUser())
desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
else
{
ASSERT(textBox);
- RenderSVGInlineText* text = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(text);
- ASSERT(text->parent());
- ASSERT(text->parent()->node());
- ASSERT(text->parent()->node()->isSVGElement());
+ RenderSVGInlineText& text = toRenderSVGInlineText(textBox->renderer());
+ ASSERT(text.parent());
+ ASSERT(text.parent()->node());
+ ASSERT(text.parent()->node()->isSVGElement());
- const RenderStyle* style = text->style();
+ const RenderStyle* style = text.style();
ASSERT(style);
textBox->clearTextFragments();
- m_isVerticalText = style->svgStyle()->isVerticalWritingMode();
- layoutTextOnLineOrPath(textBox, text, style);
+ m_isVerticalText = style->svgStyle().isVerticalWritingMode();
+ layoutTextOnLineOrPath(textBox, text, *style);
if (m_inPathLayout) {
m_pathLayoutBoxes.append(textBox);
if (!boxCount)
return;
- AffineTransform textBoxTransformation;
for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
SVGInlineTextBox* textBox = boxes.at(boxPosition);
- Vector<SVGTextFragment>& fragments = textBox->textFragments();
+ AffineTransform textBoxTransformation = m_chunkLayoutBuilder.transformationForTextBox(textBox);
+ if (textBoxTransformation.isIdentity())
+ continue;
+ Vector<SVGTextFragment>& fragments = textBox->textFragments();
unsigned fragmentCount = fragments.size();
for (unsigned i = 0; i < fragmentCount; ++i) {
- m_chunkLayoutBuilder.transformationForTextBox(textBox, textBoxTransformation);
- if (textBoxTransformation.isIdentity())
- continue;
ASSERT(fragments[i].lengthAdjustTransform.isIdentity());
fragments[i].lengthAdjustTransform = textBoxTransformation;
}
bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes*& logicalAttributes, SVGTextMetrics& logicalMetrics)
{
- Vector<SVGTextMetrics>* textMetricsValues = &logicalAttributes->textMetricsValues();
+ const Vector<SVGTextMetrics>* textMetricsValues = &logicalAttributes->textMetricsValues();
unsigned textMetricsSize = textMetricsValues->size();
while (true) {
if (m_logicalMetricsListOffset == textMetricsSize) {
return true;
}
-bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics)
+bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBox, const Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics)
{
ASSERT(!visualMetricsValues.isEmpty());
unsigned textMetricsSize = visualMetricsValues.size();
m_visualCharacterOffset += visualMetrics.length();
}
-void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style)
+void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, const RenderSVGInlineText& text, const RenderStyle& style)
{
if (m_inPathLayout && !m_textPathCalculator)
return;
- SVGElement* lengthContext = toSVGElement(text->parent()->node());
+ SVGElement* lengthContext = toSVGElement(text.parent()->node());
- RenderObject* textParent = text->parent();
+ RenderObject* textParent = text.parent();
bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false;
- const SVGRenderStyle* svgStyle = style->svgStyle();
- ASSERT(svgStyle);
+ const SVGRenderStyle& svgStyle = style.svgStyle();
m_visualMetricsListOffset = 0;
m_visualCharacterOffset = 0;
- Vector<SVGTextMetrics>& visualMetricsValues = text->layoutAttributes()->textMetricsValues();
+ const Vector<SVGTextMetrics>& visualMetricsValues = text.layoutAttributes()->textMetricsValues();
ASSERT(!visualMetricsValues.isEmpty());
- const Font& font = style->font();
+ const Font& font = style.font();
- SVGTextLayoutEngineSpacing spacingLayout(font);
+ SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom());
SVGTextLayoutEngineBaseline baselineLayout(font);
bool didStartTextFragment = false;
float lastAngle = 0;
float baselineShift = baselineLayout.calculateBaselineShift(svgStyle, lengthContext);
- baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVerticalText, text);
+ baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVerticalText, &text);
// Main layout algorithm.
while (true) {
float angle = data.rotate == SVGTextLayoutAttributes::emptyValue() ? 0 : data.rotate;
// Calculate glyph orientation angle.
- UChar currentCharacter = text->characterAt(m_visualCharacterOffset);
+ UChar currentCharacter = text.characterAt(m_visualCharacterOffset);
float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, svgStyle, currentCharacter);
// Calculate glyph advance & x/y orientation shifts.
float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation(m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientationShift);
// Assign current text position to x/y values, if needed.
- updateCharacerPositionIfNeeded(x, y);
+ updateCharacterPositionIfNeeded(x, y);
// Apply dx/dy value adjustments to current text position, if needed.
updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy);
- // Calculate SVG Fonts kerning, if needed.
- float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph());
-
- // Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed.
- float spacing = spacingLayout.calculateCSSKerningAndSpacing(svgStyle, lengthContext, currentCharacter);
+ // Calculate CSS 'letter-spacing' and 'word-spacing' for next character, if needed.
+ float spacing = spacingLayout.calculateCSSSpacing(currentCharacter);
float textPathOffset = 0;
if (m_inPathLayout) {
if (y != SVGTextLayoutAttributes::emptyValue())
m_textPathCurrentOffset = y + m_textPathStartOffset;
- m_textPathCurrentOffset += m_dy - kerning;
+ m_textPathCurrentOffset += m_dy;
m_dy = 0;
// Apply dx/dy correction and setup translations that move to the glyph midpoint.
if (x != SVGTextLayoutAttributes::emptyValue())
m_textPathCurrentOffset = x + m_textPathStartOffset;
- m_textPathCurrentOffset += m_dx - kerning;
+ m_textPathCurrentOffset += m_dx;
m_dx = 0;
// Apply dx/dy correction and setup translations that move to the glyph midpoint.
angle -= 90;
} else {
// Apply all previously calculated shift values.
- if (m_isVerticalText) {
+ if (m_isVerticalText)
x += baselineShift;
- y -= kerning;
- } else {
- x -= kerning;
+ else
y -= baselineShift;
- }
x += m_dx;
y += m_dy;
// Determine whether we have to start a new fragment.
bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPathLayout || angle || angle != lastAngle
- || orientationAngle || kerning || applySpacingToNextCharacter || definesTextLength;
+ || orientationAngle || applySpacingToNextCharacter || definesTextLength;
// If we already started a fragment, close it now.
if (didStartTextFragment && shouldStartNewFragment) {