OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> | 2 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> |
3 * Copyright (C) 2006 Apple Computer Inc. | 3 * Copyright (C) 2006 Apple Computer Inc. |
4 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 4 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
6 * Copyright (C) 2011 Torch Mobile (Beijing) CO. Ltd. All rights reserved. | 6 * Copyright (C) 2011 Torch Mobile (Beijing) CO. Ltd. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 18 * You should have received a copy of the GNU Library General Public License |
19 * along with this library; see the file COPYING.LIB. If not, write to | 19 * along with this library; see the file COPYING.LIB. If not, write to |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 */ | 22 */ |
23 | 23 |
24 #include "core/layout/svg/line/SVGRootInlineBox.h" | 24 #include "core/layout/svg/line/SVGRootInlineBox.h" |
25 | 25 |
26 #include "core/layout/api/LineLayoutAPIShim.h" | 26 #include "core/layout/api/LineLayoutAPIShim.h" |
27 #include "core/layout/api/LineLayoutBlockFlow.h" | 27 #include "core/layout/api/LineLayoutBlockFlow.h" |
28 #include "core/layout/api/LineLayoutSVGInlineText.h" | 28 #include "core/layout/api/LineLayoutSVGInlineText.h" |
29 #include "core/layout/svg/LayoutSVGText.h" | 29 #include "core/layout/svg/LayoutSVGText.h" |
| 30 #include "core/layout/svg/SVGTextLayoutEngine.h" |
30 #include "core/layout/svg/line/SVGInlineFlowBox.h" | 31 #include "core/layout/svg/line/SVGInlineFlowBox.h" |
31 #include "core/layout/svg/line/SVGInlineTextBox.h" | 32 #include "core/layout/svg/line/SVGInlineTextBox.h" |
32 #include "core/paint/SVGRootInlineBoxPainter.h" | 33 #include "core/paint/SVGRootInlineBoxPainter.h" |
33 #include "core/svg/SVGTextPathElement.h" | |
34 | 34 |
35 namespace blink { | 35 namespace blink { |
36 | 36 |
37 void SVGRootInlineBox::paint(const PaintInfo& paintInfo, const LayoutPoint& pain
tOffset, LayoutUnit, LayoutUnit) const | 37 void SVGRootInlineBox::paint(const PaintInfo& paintInfo, const LayoutPoint& pain
tOffset, LayoutUnit, LayoutUnit) const |
38 { | 38 { |
39 SVGRootInlineBoxPainter(*this).paint(paintInfo, paintOffset); | 39 SVGRootInlineBoxPainter(*this).paint(paintInfo, paintOffset); |
40 } | 40 } |
41 | 41 |
42 void SVGRootInlineBox::markDirty() | 42 void SVGRootInlineBox::markDirty() |
43 { | 43 { |
44 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) | 44 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) |
45 child->markDirty(); | 45 child->markDirty(); |
46 RootInlineBox::markDirty(); | 46 RootInlineBox::markDirty(); |
47 } | 47 } |
48 | 48 |
49 void SVGRootInlineBox::computePerCharacterLayoutInformation() | 49 void SVGRootInlineBox::computePerCharacterLayoutInformation() |
50 { | 50 { |
51 LayoutSVGText& textRoot = toLayoutSVGText(*LineLayoutAPIShim::layoutObjectFr
om(block())); | 51 LayoutSVGText& textRoot = toLayoutSVGText(*LineLayoutAPIShim::layoutObjectFr
om(block())); |
52 | 52 |
53 Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttribut
es(); | 53 Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttribut
es(); |
54 if (layoutAttributes.isEmpty()) | 54 if (layoutAttributes.isEmpty()) |
55 return; | 55 return; |
56 | 56 |
57 if (textRoot.needsReordering()) | 57 if (textRoot.needsReordering()) |
58 reorderValueLists(layoutAttributes); | 58 reorderValueLists(); |
59 | 59 |
60 // Perform SVG text layout phase two (see SVGTextLayoutEngine for details). | 60 // Perform SVG text layout phase two (see SVGTextLayoutEngine for details). |
61 SVGTextLayoutEngine characterLayout(layoutAttributes); | 61 SVGTextLayoutEngine characterLayout(layoutAttributes); |
62 characterLayout.layoutCharactersInTextBoxes(this); | 62 characterLayout.layoutCharactersInTextBoxes(this); |
63 | 63 |
64 // Perform SVG text layout phase three (see SVGTextChunkBuilder for details)
. | 64 // Perform SVG text layout phase three (see SVGTextChunkBuilder for details)
. |
65 characterLayout.finishLayout(); | 65 characterLayout.finishLayout(); |
66 | 66 |
67 // Perform SVG text layout phase four | 67 // Perform SVG text layout phase four |
68 // Position & resize all SVGInlineText/FlowBoxes in the inline box tree, res
ize the root box as well as the LayoutSVGText parent block. | 68 // Position & resize all SVGInlineText/FlowBoxes in the inline box tree, res
ize the root box as well as the LayoutSVGText parent block. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 continue; | 146 continue; |
147 | 147 |
148 closestLeaf = leaf; | 148 closestLeaf = leaf; |
149 if (point.x() < leaf->left() + leaf->logicalWidth()) | 149 if (point.x() < leaf->left() + leaf->logicalWidth()) |
150 return leaf; | 150 return leaf; |
151 } | 151 } |
152 | 152 |
153 return closestLeaf ? closestLeaf : lastLeaf; | 153 return closestLeaf ? closestLeaf : lastLeaf; |
154 } | 154 } |
155 | 155 |
156 static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAtt
ributes, SVGTextLayoutAttributes* lastAttributes, unsigned firstPosition, unsign
ed lastPosition) | 156 static inline void swapPositioningValuesInTextBoxes(SVGInlineTextBox* firstTextB
ox, SVGInlineTextBox* lastTextBox) |
157 { | 157 { |
158 SVGCharacterDataMap::iterator itFirst = firstAttributes->characterDataMap().
find(firstPosition + 1); | 158 LineLayoutSVGInlineText firstTextNode = LineLayoutSVGInlineText(firstTextBox
->getLineLayoutItem()); |
159 SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().fi
nd(lastPosition + 1); | 159 SVGCharacterDataMap& firstCharacterDataMap = firstTextNode.layoutAttributes(
).characterDataMap(); |
160 bool firstPresent = itFirst != firstAttributes->characterDataMap().end(); | 160 SVGCharacterDataMap::iterator itFirst = firstCharacterDataMap.find(firstText
Box->start() + 1); |
161 bool lastPresent = itLast != lastAttributes->characterDataMap().end(); | 161 if (itFirst == firstCharacterDataMap.end()) |
| 162 return; |
| 163 LineLayoutSVGInlineText lastTextNode = LineLayoutSVGInlineText(lastTextBox->
getLineLayoutItem()); |
| 164 SVGCharacterDataMap& lastCharacterDataMap = lastTextNode.layoutAttributes().
characterDataMap(); |
| 165 SVGCharacterDataMap::iterator itLast = lastCharacterDataMap.find(lastTextBox
->start() + 1); |
| 166 if (itLast == lastCharacterDataMap.end()) |
| 167 return; |
162 // We only want to perform the swap if both inline boxes are absolutely | 168 // We only want to perform the swap if both inline boxes are absolutely |
163 // positioned. | 169 // positioned. |
164 if (!firstPresent || !lastPresent) | |
165 return; | |
166 std::swap(itFirst->value, itLast->value); | 170 std::swap(itFirst->value, itLast->value); |
167 } | 171 } |
168 | 172 |
169 static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttrib
utes*>& attributes, LineLayoutSVGInlineText firstContext, LineLayoutSVGInlineTex
t lastContext, SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last) | 173 static inline void reverseInlineBoxRangeAndValueListsIfNeeded(Vector<InlineBox*>
::iterator first, Vector<InlineBox*>::iterator last) |
170 { | 174 { |
171 first = 0; | 175 // This is a copy of std::reverse(first, last). It additionally assures |
172 last = 0; | 176 // that the metrics map within the layoutObjects belonging to the |
173 | 177 // InlineBoxes are reordered as well. |
174 unsigned attributesSize = attributes.size(); | |
175 for (unsigned i = 0; i < attributesSize; ++i) { | |
176 SVGTextLayoutAttributes* current = attributes[i]; | |
177 if (!first && firstContext.isEqual(current->context())) | |
178 first = current; | |
179 if (!last && lastContext.isEqual(current->context())) | |
180 last = current; | |
181 if (first && last) | |
182 break; | |
183 } | |
184 | |
185 ASSERT(first); | |
186 ASSERT(last); | |
187 } | |
188 | |
189 static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
ctor<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last) | |
190 { | |
191 ASSERT(userData); | |
192 Vector<SVGTextLayoutAttributes*>& attributes = *reinterpret_cast<Vector<SVGT
extLayoutAttributes*>*>(userData); | |
193 | |
194 // This is a copy of std::reverse(first, last). It additionally assures that
the metrics map within the layoutObjects belonging to the InlineBoxes are reord
ered as well. | |
195 while (true) { | 178 while (true) { |
196 if (first == last || first == --last) | 179 if (first == last || first == --last) |
197 return; | 180 return; |
198 | 181 |
199 if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) { | 182 if ((*last)->isSVGInlineTextBox() && (*first)->isSVGInlineTextBox()) { |
200 InlineBox* temp = *first; | 183 SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first); |
201 *first = *last; | 184 SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last); |
202 *last = temp; | |
203 ++first; | |
204 continue; | |
205 } | |
206 | 185 |
207 SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first); | 186 // Reordering is only necessary for BiDi text that is _absolutely_ p
ositioned. |
208 SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last); | 187 if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->
len()) |
209 | 188 swapPositioningValuesInTextBoxes(firstTextBox, lastTextBox); |
210 // Reordering is only necessary for BiDi text that is _absolutely_ posit
ioned. | |
211 if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len(
)) { | |
212 LineLayoutSVGInlineText firstContext = LineLayoutSVGInlineText(first
TextBox->getLineLayoutItem()); | |
213 LineLayoutSVGInlineText lastContext = LineLayoutSVGInlineText(lastTe
xtBox->getLineLayoutItem()); | |
214 | |
215 SVGTextLayoutAttributes* firstAttributes = nullptr; | |
216 SVGTextLayoutAttributes* lastAttributes = nullptr; | |
217 findFirstAndLastAttributesInVector(attributes, firstContext, lastCon
text, firstAttributes, lastAttributes); | |
218 swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTe
xtBox->start(), lastTextBox->start()); | |
219 } | 189 } |
220 | 190 |
221 InlineBox* temp = *first; | 191 InlineBox* temp = *first; |
222 *first = *last; | 192 *first = *last; |
223 *last = temp; | 193 *last = temp; |
224 | |
225 ++first; | 194 ++first; |
226 } | 195 } |
227 } | 196 } |
228 | 197 |
229 void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes*>& attri
butes) | 198 void SVGRootInlineBox::reorderValueLists() |
230 { | 199 { |
231 Vector<InlineBox*> leafBoxesInLogicalOrder; | 200 Vector<InlineBox*> leafBoxesInLogicalOrder; |
232 collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRang
eAndValueListsIfNeeded, &attributes); | 201 collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRang
eAndValueListsIfNeeded); |
233 } | 202 } |
234 | 203 |
235 bool SVGRootInlineBox::nodeAtPoint(HitTestResult& result, const HitTestLocation&
locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop,
LayoutUnit lineBottom) | 204 bool SVGRootInlineBox::nodeAtPoint(HitTestResult& result, const HitTestLocation&
locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop,
LayoutUnit lineBottom) |
236 { | 205 { |
237 for (InlineBox* leaf = firstLeafChild(); leaf; leaf = leaf->nextLeafChild())
{ | 206 for (InlineBox* leaf = firstLeafChild(); leaf; leaf = leaf->nextLeafChild())
{ |
238 if (!leaf->isSVGInlineTextBox()) | 207 if (!leaf->isSVGInlineTextBox()) |
239 continue; | 208 continue; |
240 if (leaf->nodeAtPoint(result, locationInContainer, accumulatedOffset, li
neTop, lineBottom)) | 209 if (leaf->nodeAtPoint(result, locationInContainer, accumulatedOffset, li
neTop, lineBottom)) |
241 return true; | 210 return true; |
242 } | 211 } |
243 | 212 |
244 return false; | 213 return false; |
245 } | 214 } |
246 | 215 |
247 } // namespace blink | 216 } // namespace blink |
OLD | NEW |