| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. |    2  * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 
|    3  * |    3  * | 
|    4  * This library is free software; you can redistribute it and/or |    4  * This library is free software; you can redistribute it and/or | 
|    5  * modify it under the terms of the GNU Library General Public |    5  * modify it under the terms of the GNU Library General Public | 
|    6  * License as published by the Free Software Foundation; either |    6  * License as published by the Free Software Foundation; either | 
|    7  * version 2 of the License, or (at your option) any later version. |    7  * version 2 of the License, or (at your option) any later version. | 
|    8  * |    8  * | 
|    9  * This library is distributed in the hope that it will be useful, |    9  * This library is distributed in the hope that it will be useful, | 
|   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|   12  * Library General Public License for more details. |   12  * Library General Public License for more details. | 
|   13  * |   13  * | 
|   14  * You should have received a copy of the GNU Library General Public License |   14  * You should have received a copy of the GNU Library General Public License | 
|   15  * along with this library; see the file COPYING.LIB.  If not, write to |   15  * along with this library; see the file COPYING.LIB.  If not, write to | 
|   16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |   16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 
|   17  * Boston, MA 02110-1301, USA. |   17  * Boston, MA 02110-1301, USA. | 
|   18  */ |   18  */ | 
|   19  |   19  | 
|   20 #include "config.h" |   20 #include "config.h" | 
|   21 #include "core/layout/svg/SVGTextLayoutEngine.h" |   21 #include "core/layout/svg/SVGTextLayoutEngine.h" | 
|   22  |   22  | 
|   23 #include "core/layout/svg/LayoutSVGInlineText.h" |   23 #include "core/layout/svg/LayoutSVGInlineText.h" | 
|   24 #include "core/layout/svg/LayoutSVGTextPath.h" |   24 #include "core/layout/svg/LayoutSVGTextPath.h" | 
 |   25 #include "core/layout/svg/SVGTextChunkBuilder.h" | 
|   25 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h" |   26 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h" | 
|   26 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h" |   27 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h" | 
|   27 #include "core/layout/svg/line/SVGInlineTextBox.h" |   28 #include "core/layout/svg/line/SVGInlineTextBox.h" | 
|   28 #include "core/svg/SVGElement.h" |   29 #include "core/svg/SVGElement.h" | 
|   29 #include "core/svg/SVGLengthContext.h" |   30 #include "core/svg/SVGLengthContext.h" | 
|   30 #include "core/svg/SVGTextContentElement.h" |   31 #include "core/svg/SVGTextContentElement.h" | 
|   31  |   32  | 
|   32 // Set to a value > 0 to dump the text fragments |  | 
|   33 #define DUMP_TEXT_FRAGMENTS 0 |  | 
|   34  |  | 
|   35 namespace blink { |   33 namespace blink { | 
|   36  |   34  | 
|   37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
     tAttributes) |   35 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
     tAttributes) | 
|   38     : m_layoutAttributes(layoutAttributes) |   36     : m_layoutAttributes(layoutAttributes) | 
|   39     , m_layoutAttributesPosition(0) |   37     , m_layoutAttributesPosition(0) | 
|   40     , m_logicalCharacterOffset(0) |   38     , m_logicalCharacterOffset(0) | 
|   41     , m_logicalMetricsListOffset(0) |   39     , m_logicalMetricsListOffset(0) | 
|   42     , m_visualCharacterOffset(0) |   40     , m_visualCharacterOffset(0) | 
|   43     , m_visualMetricsListOffset(0) |   41     , m_visualMetricsListOffset(0) | 
|   44     , m_x(0) |   42     , m_x(0) | 
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  175         return; |  173         return; | 
|  176     m_textPathCalculator = new Path::PositionCalculator(path); |  174     m_textPathCalculator = new Path::PositionCalculator(path); | 
|  177     m_textPathStartOffset = textPath->startOffset(); |  175     m_textPathStartOffset = textPath->startOffset(); | 
|  178     m_textPathLength = path.length(); |  176     m_textPathLength = path.length(); | 
|  179     if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) |  177     if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) | 
|  180         m_textPathStartOffset *= m_textPathLength; |  178         m_textPathStartOffset *= m_textPathLength; | 
|  181  |  179  | 
|  182     float totalLength = 0; |  180     float totalLength = 0; | 
|  183     unsigned totalCharacters = 0; |  181     unsigned totalCharacters = 0; | 
|  184  |  182  | 
|  185     lineLayout.m_chunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes
     ); |  183     SVGTextChunkBuilder textPathChunkLayoutBuilder; | 
|  186     const Vector<SVGTextChunk>& textChunks = lineLayout.m_chunkLayoutBuilder.tex
     tChunks(); |  184     textPathChunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes); | 
 |  185     const Vector<SVGTextChunk>& textChunks = textPathChunkLayoutBuilder.textChun
     ks(); | 
|  187  |  186  | 
|  188     unsigned size = textChunks.size(); |  187     unsigned size = textChunks.size(); | 
|  189     for (unsigned i = 0; i < size; ++i) { |  188     for (unsigned i = 0; i < size; ++i) { | 
|  190         const SVGTextChunk& chunk = textChunks.at(i); |  189         const SVGTextChunk& chunk = textChunks.at(i); | 
|  191  |  190  | 
|  192         float length = 0; |  191         float length = 0; | 
|  193         unsigned characters = 0; |  192         unsigned characters = 0; | 
|  194         chunk.calculateLength(length, characters); |  193         chunk.calculateLength(length, characters); | 
|  195  |  194  | 
|  196         // Handle text-anchor as additional start offset for text paths. |  195         // Handle text-anchor as additional start offset for text paths. | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  252     layoutTextOnLineOrPath(textBox, text, style); |  251     layoutTextOnLineOrPath(textBox, text, style); | 
|  253  |  252  | 
|  254     if (m_inPathLayout) { |  253     if (m_inPathLayout) { | 
|  255         m_pathLayoutBoxes.append(textBox); |  254         m_pathLayoutBoxes.append(textBox); | 
|  256         return; |  255         return; | 
|  257     } |  256     } | 
|  258  |  257  | 
|  259     m_lineLayoutBoxes.append(textBox); |  258     m_lineLayoutBoxes.append(textBox); | 
|  260 } |  259 } | 
|  261  |  260  | 
|  262 #if DUMP_TEXT_FRAGMENTS > 0 |  | 
|  263 static inline void dumpTextBoxes(Vector<SVGInlineTextBox*>& boxes) |  | 
|  264 { |  | 
|  265     unsigned boxCount = boxes.size(); |  | 
|  266     fprintf(stderr, "Dumping all text fragments in text sub tree, %i boxes\n", b
     oxCount); |  | 
|  267  |  | 
|  268     for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { |  | 
|  269         SVGInlineTextBox* textBox = boxes.at(boxPosition); |  | 
|  270         Vector<SVGTextFragment>& fragments = textBox->textFragments(); |  | 
|  271         fprintf(stderr, "-> Box %i: Dumping text fragments for SVGInlineTextBox,
      textBox=%p, textLayoutObject=%p\n", boxPosition, textBox, textBox->textLayoutOb
     ject()); |  | 
|  272         fprintf(stderr, "        textBox properties, start=%i, len=%i, box direc
     tion=%i\n", textBox->start(), textBox->len(), textBox->direction()); |  | 
|  273         fprintf(stderr, "   textLayoutObject properties, textLength=%i\n", textB
     ox->textLayoutObject()->textLength()); |  | 
|  274  |  | 
|  275         String characters = textBox->textLayoutObject()->text(); |  | 
|  276  |  | 
|  277         unsigned fragmentCount = fragments.size(); |  | 
|  278         for (unsigned i = 0; i < fragmentCount; ++i) { |  | 
|  279             SVGTextFragment& fragment = fragments.at(i); |  | 
|  280             String fragmentString = characters.substring(fragment.characterOffse
     t, fragment.length); |  | 
|  281             fprintf(stderr, "    -> Fragment %i, x=%lf, y=%lf, width=%lf, height
     =%lf, characterOffset=%i, length=%i, characters='%s'\n", |  | 
|  282                 i, fragment.x, fragment.y, fragment.width, fragment.height, frag
     ment.characterOffset, fragment.length, fragmentString.utf8().data()); |  | 
|  283         } |  | 
|  284     } |  | 
|  285 } |  | 
|  286 #endif |  | 
|  287  |  | 
|  288 void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b
     oxes) |  | 
|  289 { |  | 
|  290     unsigned boxCount = boxes.size(); |  | 
|  291     if (!boxCount) |  | 
|  292         return; |  | 
|  293  |  | 
|  294     for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { |  | 
|  295         SVGInlineTextBox* textBox = boxes.at(boxPosition); |  | 
|  296         AffineTransform textBoxTransformation = m_chunkLayoutBuilder.transformat
     ionForTextBox(textBox); |  | 
|  297         if (textBoxTransformation.isIdentity()) |  | 
|  298             continue; |  | 
|  299  |  | 
|  300         Vector<SVGTextFragment>& fragments = textBox->textFragments(); |  | 
|  301         unsigned fragmentCount = fragments.size(); |  | 
|  302         for (unsigned i = 0; i < fragmentCount; ++i) { |  | 
|  303             ASSERT(fragments[i].lengthAdjustTransform.isIdentity()); |  | 
|  304             fragments[i].lengthAdjustTransform = textBoxTransformation; |  | 
|  305         } |  | 
|  306     } |  | 
|  307  |  | 
|  308     boxes.clear(); |  | 
|  309 } |  | 
|  310  |  | 
|  311 void SVGTextLayoutEngine::finishLayout() |  261 void SVGTextLayoutEngine::finishLayout() | 
|  312 { |  262 { | 
|  313     // After all text fragments are stored in their correpsonding SVGInlineTextB
     oxes, we can layout individual text chunks. |  263     // After all text fragments are stored in their correpsonding SVGInlineTextB
     oxes, we can layout individual text chunks. | 
|  314     // Chunk layouting is only performed for line layout boxes, not for path lay
     out, where it has already been done. |  264     // Chunk layouting is only performed for line layout boxes, not for path lay
     out, where it has already been done. | 
|  315     m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes); |  265     SVGTextChunkBuilder chunkLayoutBuilder; | 
 |  266     chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes); | 
|  316  |  267  | 
|  317     // Finalize transform matrices, after the chunk layout corrections have been
      applied, and all fragment x/y positions are finalized. |  268     // Finalize transform matrices, after the chunk layout corrections have been
      applied, and all fragment x/y positions are finalized. | 
|  318     if (!m_lineLayoutBoxes.isEmpty()) { |  269     if (!m_lineLayoutBoxes.isEmpty()) { | 
|  319 #if DUMP_TEXT_FRAGMENTS > 0 |  270         chunkLayoutBuilder.finalizeTransformMatrices(m_lineLayoutBoxes); | 
|  320         fprintf(stderr, "Line layout: "); |  271         m_lineLayoutBoxes.clear(); | 
|  321         dumpTextBoxes(m_lineLayoutBoxes); |  | 
|  322 #endif |  | 
|  323  |  | 
|  324         finalizeTransformMatrices(m_lineLayoutBoxes); |  | 
|  325     } |  272     } | 
|  326  |  273  | 
|  327     if (!m_pathLayoutBoxes.isEmpty()) { |  274     if (!m_pathLayoutBoxes.isEmpty()) { | 
|  328 #if DUMP_TEXT_FRAGMENTS > 0 |  275         chunkLayoutBuilder.finalizeTransformMatrices(m_pathLayoutBoxes); | 
|  329         fprintf(stderr, "Path layout: "); |  276         m_pathLayoutBoxes.clear(); | 
|  330         dumpTextBoxes(m_pathLayoutBoxes); |  | 
|  331 #endif |  | 
|  332  |  | 
|  333         finalizeTransformMatrices(m_pathLayoutBoxes); |  | 
|  334     } |  277     } | 
|  335 } |  278 } | 
|  336  |  279  | 
|  337 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu
     tes*& logicalAttributes) |  280 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu
     tes*& logicalAttributes) | 
|  338 { |  281 { | 
|  339     if (m_layoutAttributesPosition == m_layoutAttributes.size()) |  282     if (m_layoutAttributesPosition == m_layoutAttributes.size()) | 
|  340         return false; |  283         return false; | 
|  341  |  284  | 
|  342     logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; |  285     logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; | 
|  343     ASSERT(logicalAttributes); |  286     ASSERT(logicalAttributes); | 
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  634     } |  577     } | 
|  635  |  578  | 
|  636     if (!didStartTextFragment) |  579     if (!didStartTextFragment) | 
|  637         return; |  580         return; | 
|  638  |  581  | 
|  639     // Close last open fragment, if needed. |  582     // Close last open fragment, if needed. | 
|  640     recordTextFragment(textBox, visualMetricsValues); |  583     recordTextFragment(textBox, visualMetricsValues); | 
|  641 } |  584 } | 
|  642  |  585  | 
|  643 } |  586 } | 
| OLD | NEW |