Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp

Issue 1417203006: [Line Layout API] Convert QueryData and descendants to line layout API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/layout/api/LineLayoutText.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 21 matching lines...) Expand all
32 #include "wtf/MathExtras.h" 32 #include "wtf/MathExtras.h"
33 #include "wtf/Vector.h" 33 #include "wtf/Vector.h"
34 34
35 namespace blink { 35 namespace blink {
36 36
37 // Base structure for callback user data 37 // Base structure for callback user data
38 struct QueryData { 38 struct QueryData {
39 QueryData() 39 QueryData()
40 : isVerticalText(false) 40 : isVerticalText(false)
41 , currentOffset(0) 41 , currentOffset(0)
42 , textLayoutObject(nullptr) 42 , textLineLayout(nullptr)
43 , textBox(nullptr) 43 , textBox(nullptr)
44 { 44 {
45 } 45 }
46 46
47 bool isVerticalText; 47 bool isVerticalText;
48 unsigned currentOffset; 48 unsigned currentOffset;
49 LayoutSVGInlineText* textLayoutObject; 49 LineLayoutSVGInlineText textLineLayout;
50 const SVGInlineTextBox* textBox; 50 const SVGInlineTextBox* textBox;
51 }; 51 };
52 52
53 static inline InlineFlowBox* flowBoxForLayoutObject(LayoutObject* layoutObject) 53 static inline InlineFlowBox* flowBoxForLayoutObject(LayoutObject* layoutObject)
54 { 54 {
55 if (!layoutObject) 55 if (!layoutObject)
56 return nullptr; 56 return nullptr;
57 57
58 if (layoutObject->isLayoutBlock()) { 58 if (layoutObject->isLayoutBlock()) {
59 // If we're given a block element, it has to be a LayoutSVGText. 59 // If we're given a block element, it has to be a LayoutSVGText.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 if (child->isSVGInlineTextBox()) 98 if (child->isSVGInlineTextBox())
99 textBoxes.append(toSVGInlineTextBox(child)); 99 textBoxes.append(toSVGInlineTextBox(child));
100 } 100 }
101 } 101 }
102 102
103 typedef bool ProcessTextFragmentCallback(QueryData*, const SVGTextFragment&); 103 typedef bool ProcessTextFragmentCallback(QueryData*, const SVGTextFragment&);
104 104
105 static bool queryTextBox(QueryData* queryData, const SVGInlineTextBox* textBox, ProcessTextFragmentCallback fragmentCallback) 105 static bool queryTextBox(QueryData* queryData, const SVGInlineTextBox* textBox, ProcessTextFragmentCallback fragmentCallback)
106 { 106 {
107 queryData->textBox = textBox; 107 queryData->textBox = textBox;
108 queryData->textLayoutObject = &toLayoutSVGInlineText(textBox->layoutObject() ); 108 queryData->textLineLayout = LineLayoutSVGInlineText(&toLayoutSVGInlineText(t extBox->layoutObject()));
109 109
110 queryData->isVerticalText = !textBox->layoutObject().style()->isHorizontalWr itingMode(); 110 queryData->isVerticalText = !textBox->layoutObject().style()->isHorizontalWr itingMode();
111 111
112 // Loop over all text fragments in this text box, firing a callback for each . 112 // Loop over all text fragments in this text box, firing a callback for each .
113 for (const SVGTextFragment& fragment : textBox->textFragments()) { 113 for (const SVGTextFragment& fragment : textBox->textFragments()) {
114 if (fragmentCallback(queryData, fragment)) 114 if (fragmentCallback(queryData, fragment))
115 return true; 115 return true;
116 } 116 }
117 return false; 117 return false;
118 } 118 }
119 119
120 // Execute a query in "spatial" order starting at |queryRoot|. This means 120 // Execute a query in "spatial" order starting at |queryRoot|. This means
121 // walking the lines boxes in the order they would get painted. 121 // walking the lines boxes in the order they would get painted.
122 static void spatialQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessT extFragmentCallback fragmentCallback) 122 static void spatialQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessT extFragmentCallback fragmentCallback)
123 { 123 {
124 Vector<SVGInlineTextBox*> textBoxes; 124 Vector<SVGInlineTextBox*> textBoxes;
125 collectTextBoxesInFlowBox(flowBoxForLayoutObject(queryRoot), textBoxes); 125 collectTextBoxesInFlowBox(flowBoxForLayoutObject(queryRoot), textBoxes);
126 126
127 // Loop over all text boxes 127 // Loop over all text boxes
128 for (const SVGInlineTextBox* textBox : textBoxes) { 128 for (const SVGInlineTextBox* textBox : textBoxes) {
129 if (queryTextBox(queryData, textBox, fragmentCallback)) 129 if (queryTextBox(queryData, textBox, fragmentCallback))
130 return; 130 return;
131 } 131 }
132 } 132 }
133 133
134 static void collectTextBoxesInLogicalOrder(const LayoutSVGInlineText& textLayout Object, Vector<SVGInlineTextBox*>& textBoxes) 134 static void collectTextBoxesInLogicalOrder(LineLayoutSVGInlineText textLineLayou t, Vector<SVGInlineTextBox*>& textBoxes)
135 { 135 {
136 textBoxes.shrink(0); 136 textBoxes.shrink(0);
137 for (InlineTextBox* textBox = textLayoutObject.firstTextBox(); textBox; text Box = textBox->nextTextBox()) 137 for (InlineTextBox* textBox = textLineLayout.firstTextBox(); textBox; textBo x = textBox->nextTextBox())
138 textBoxes.append(toSVGInlineTextBox(textBox)); 138 textBoxes.append(toSVGInlineTextBox(textBox));
139 std::sort(textBoxes.begin(), textBoxes.end(), InlineTextBox::compareByStart) ; 139 std::sort(textBoxes.begin(), textBoxes.end(), InlineTextBox::compareByStart) ;
140 } 140 }
141 141
142 // Execute a query in "logical" order starting at |queryRoot|. This means 142 // Execute a query in "logical" order starting at |queryRoot|. This means
143 // walking the lines boxes for each layout object in layout tree (pre)order. 143 // walking the lines boxes for each layout object in layout tree (pre)order.
144 static void logicalQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessT extFragmentCallback fragmentCallback) 144 static void logicalQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessT extFragmentCallback fragmentCallback)
145 { 145 {
146 if (!queryRoot) 146 if (!queryRoot)
147 return; 147 return;
148 148
149 // Walk the layout tree in pre-order, starting at the specified root, and 149 // Walk the layout tree in pre-order, starting at the specified root, and
150 // run the query for each text node. 150 // run the query for each text node.
151 Vector<SVGInlineTextBox*> textBoxes; 151 Vector<SVGInlineTextBox*> textBoxes;
152 for (LayoutObject* layoutObject = queryRoot->slowFirstChild(); layoutObject; layoutObject = layoutObject->nextInPreOrder(queryRoot)) { 152 for (LayoutObject* layoutObject = queryRoot->slowFirstChild(); layoutObject; layoutObject = layoutObject->nextInPreOrder(queryRoot)) {
153 if (!layoutObject->isSVGInlineText()) 153 if (!layoutObject->isSVGInlineText())
154 continue; 154 continue;
155 155
156 LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*layoutObj ect); 156 LineLayoutSVGInlineText textLineLayout = LineLayoutSVGInlineText(toLayou tSVGInlineText(layoutObject));
157 ASSERT(textLayoutObject.style()); 157 ASSERT(textLineLayout.style());
158 158
159 // TODO(fs): Allow filtering the search earlier, since we should be 159 // TODO(fs): Allow filtering the search earlier, since we should be
160 // able to trivially reject (prune) at least some of the queries. 160 // able to trivially reject (prune) at least some of the queries.
161 collectTextBoxesInLogicalOrder(textLayoutObject, textBoxes); 161 collectTextBoxesInLogicalOrder(textLineLayout, textBoxes);
162 162
163 for (const SVGInlineTextBox* textBox : textBoxes) { 163 for (const SVGInlineTextBox* textBox : textBoxes) {
164 if (queryTextBox(queryData, textBox, fragmentCallback)) 164 if (queryTextBox(queryData, textBox, fragmentCallback))
165 return; 165 return;
166 queryData->currentOffset += textBox->len(); 166 queryData->currentOffset += textBox->len();
167 } 167 }
168 } 168 }
169 } 169 }
170 170
171 static void modifyStartEndPositionsRespectingLigatures(const QueryData* queryDat a, const SVGTextFragment& fragment, int& startPosition, int& endPosition) 171 static void modifyStartEndPositionsRespectingLigatures(const QueryData* queryDat a, const SVGTextFragment& fragment, int& startPosition, int& endPosition)
172 { 172 {
173 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObjec t->layoutAttributes()->textMetricsValues(); 173 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout. layoutAttributes()->textMetricsValues();
174 174
175 unsigned textMetricsOffset = fragment.metricsListOffset; 175 unsigned textMetricsOffset = fragment.metricsListOffset;
176 int fragmentOffset = 0; 176 int fragmentOffset = 0;
177 int fragmentEnd = static_cast<int>(fragment.length); 177 int fragmentEnd = static_cast<int>(fragment.length);
178 178
179 // Find the text metrics cell that start at or contain the character startPo sition. 179 // Find the text metrics cell that start at or contain the character startPo sition.
180 while (fragmentOffset < fragmentEnd) { 180 while (fragmentOffset < fragmentEnd) {
181 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; 181 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset];
182 int glyphEnd = fragmentOffset + metrics.length(); 182 int glyphEnd = fragmentOffset + metrics.length();
183 if (startPosition < glyphEnd) 183 if (startPosition < glyphEnd)
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 273
274 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment) 274 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment)
275 { 275 {
276 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); 276 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData);
277 277
278 int startPosition = data->startPosition; 278 int startPosition = data->startPosition;
279 int endPosition = startPosition + data->length; 279 int endPosition = startPosition + data->length;
280 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 280 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
281 return false; 281 return false;
282 282
283 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(LineLayoutSVG InlineText(queryData->textLayoutObject), fragment.characterOffset + startPositio n, endPosition - startPosition, queryData->textBox->direction()); 283 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te xtLineLayout, fragment.characterOffset + startPosition, endPosition - startPosit ion, queryData->textBox->direction());
284 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr ics.width(); 284 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr ics.width();
285 return false; 285 return false;
286 } 286 }
287 287
288 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st 288 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st
289 { 289 {
290 SubStringLengthData data(startPosition, length); 290 SubStringLengthData data(startPosition, length);
291 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); 291 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback);
292 return data.subStringLength; 292 return data.subStringLength;
293 } 293 }
294 294
295 // startPositionOfCharacter() implementation 295 // startPositionOfCharacter() implementation
296 struct StartPositionOfCharacterData : QueryData { 296 struct StartPositionOfCharacterData : QueryData {
297 StartPositionOfCharacterData(unsigned queryPosition) 297 StartPositionOfCharacterData(unsigned queryPosition)
298 : position(queryPosition) 298 : position(queryPosition)
299 { 299 {
300 } 300 }
301 301
302 unsigned position; 302 unsigned position;
303 FloatPoint startPosition; 303 FloatPoint startPosition;
304 }; 304 };
305 305
306 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, int offsetInFragment) 306 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, int offsetInFragment)
307 { 307 {
308 float glyphOffsetInDirection = 0; 308 float glyphOffsetInDirection = 0;
309 if (offsetInFragment) { 309 if (offsetInFragment) {
310 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(LineLayou tSVGInlineText(queryData->textLayoutObject), fragment.characterOffset, offsetInF ragment, queryData->textBox->direction()); 310 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData ->textLineLayout, fragment.characterOffset, offsetInFragment, queryData->textBox ->direction());
311 if (queryData->isVerticalText) 311 if (queryData->isVerticalText)
312 glyphOffsetInDirection = metrics.height(); 312 glyphOffsetInDirection = metrics.height();
313 else 313 else
314 glyphOffsetInDirection = metrics.width(); 314 glyphOffsetInDirection = metrics.width();
315 } 315 }
316 316
317 if (!queryData->textBox->isLeftToRightDirection()) { 317 if (!queryData->textBox->isLeftToRightDirection()) {
318 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width; 318 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width;
319 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; 319 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection;
320 } 320 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 unsigned glyphEnd = fragmentOffset + metrics.length(); 454 unsigned glyphEnd = fragmentOffset + metrics.length();
455 if (startInFragment < glyphEnd) 455 if (startInFragment < glyphEnd)
456 break; 456 break;
457 fragmentOffset = glyphEnd; 457 fragmentOffset = glyphEnd;
458 } 458 }
459 return textMetricsValues[textMetricsOffset - 1]; 459 return textMetricsValues[textMetricsOffset - 1];
460 } 460 }
461 461
462 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV GTextFragment& fragment, int startPosition, FloatRect& extent) 462 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV GTextFragment& fragment, int startPosition, FloatRect& extent)
463 { 463 {
464 float scalingFactor = queryData->textLayoutObject->scalingFactor(); 464 float scalingFactor = queryData->textLineLayout.scalingFactor();
465 ASSERT(scalingFactor); 465 ASSERT(scalingFactor);
466 466
467 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); 467 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition);
468 glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics ().floatAscent() / scalingFactor); 468 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().fontMetrics(). floatAscent() / scalingFactor);
469 extent.setLocation(glyphPosition); 469 extent.setLocation(glyphPosition);
470 470
471 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends 471 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends
472 // time attempting to compute more correct glyph bounds already, handling 472 // time attempting to compute more correct glyph bounds already, handling
473 // cursive scripts to some degree.) 473 // cursive scripts to some degree.)
474 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObjec t->layoutAttributes()->textMetricsValues(); 474 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout. layoutAttributes()->textMetricsValues();
475 const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, f ragment, startPosition); 475 const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, f ragment, startPosition);
476 476
477 // TODO(fs): Negative glyph extents seems kind of weird to have, but 477 // TODO(fs): Negative glyph extents seems kind of weird to have, but
478 // presently it can occur in some cases (like Arabic.) 478 // presently it can occur in some cases (like Arabic.)
479 FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(met rics.height(), 0)); 479 FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(met rics.height(), 0));
480 extent.setSize(glyphSize); 480 extent.setSize(glyphSize);
481 481
482 // If RTL, adjust the starting point to align with the LHS of the glyph boun ding box. 482 // If RTL, adjust the starting point to align with the LHS of the glyph boun ding box.
483 if (!queryData->textBox->isLeftToRightDirection()) { 483 if (!queryData->textBox->isLeftToRightDirection()) {
484 if (queryData->isVerticalText) 484 if (queryData->isVerticalText)
485 extent.move(0, -glyphSize.height()); 485 extent.move(0, -glyphSize.height());
486 else 486 else
487 extent.move(-glyphSize.width(), 0); 487 extent.move(-glyphSize.width(), 0);
488 } 488 }
489 489
490 AffineTransform fragmentTransform; 490 AffineTransform fragmentTransform;
491 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength); 491 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength);
492 492
493 extent = fragmentTransform.mapRect(extent); 493 extent = fragmentTransform.mapRect(extent);
494 } 494 }
495 495
496 static inline FloatRect calculateFragmentBoundaries(const LayoutSVGInlineText& t extLayoutObject, const SVGTextFragment& fragment) 496 static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText text LineLayout, const SVGTextFragment& fragment)
497 { 497 {
498 float scalingFactor = textLayoutObject.scalingFactor(); 498 float scalingFactor = textLineLayout.scalingFactor();
499 ASSERT(scalingFactor); 499 ASSERT(scalingFactor);
500 float baseline = textLayoutObject.scaledFont().fontMetrics().floatAscent() / scalingFactor; 500 float baseline = textLineLayout.scaledFont().fontMetrics().floatAscent() / s calingFactor;
501 501
502 AffineTransform fragmentTransform; 502 AffineTransform fragmentTransform;
503 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fr agment.height); 503 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fr agment.height);
504 fragment.buildFragmentTransform(fragmentTransform); 504 fragment.buildFragmentTransform(fragmentTransform);
505 return fragmentTransform.mapRect(fragmentRect); 505 return fragmentTransform.mapRect(fragmentRect);
506 } 506 }
507 507
508 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen t& fragment) 508 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen t& fragment)
509 { 509 {
510 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ; 510 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ;
(...skipping 11 matching lines...) Expand all
522 { 522 {
523 ExtentOfCharacterData data(position); 523 ExtentOfCharacterData data(position);
524 logicalQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback); 524 logicalQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback);
525 return data.extent; 525 return data.extent;
526 } 526 }
527 527
528 // characterNumberAtPosition() implementation 528 // characterNumberAtPosition() implementation
529 struct CharacterNumberAtPositionData : QueryData { 529 struct CharacterNumberAtPositionData : QueryData {
530 CharacterNumberAtPositionData(const FloatPoint& queryPosition) 530 CharacterNumberAtPositionData(const FloatPoint& queryPosition)
531 : position(queryPosition) 531 : position(queryPosition)
532 , hitLayoutObject(nullptr) 532 , hitLayoutItem(nullptr)
533 , offsetInTextNode(0) 533 , offsetInTextNode(0)
534 { 534 {
535 } 535 }
536 536
537 int characterNumberWithin(const LayoutObject* queryRoot) const; 537 int characterNumberWithin(const LayoutObject* queryRoot) const;
538 538
539 FloatPoint position; 539 FloatPoint position;
540 LayoutObject* hitLayoutObject; 540 LineLayoutItem hitLayoutItem;
541 int offsetInTextNode; 541 int offsetInTextNode;
542 }; 542 };
543 543
544 int CharacterNumberAtPositionData::characterNumberWithin(const LayoutObject* que ryRoot) const 544 int CharacterNumberAtPositionData::characterNumberWithin(const LayoutObject* que ryRoot) const
545 { 545 {
546 // http://www.w3.org/TR/SVG/single-page.html#text-__svg__SVGTextContentEleme nt__getCharNumAtPosition 546 // http://www.w3.org/TR/SVG/single-page.html#text-__svg__SVGTextContentEleme nt__getCharNumAtPosition
547 // "If no such character exists, a value of -1 is returned." 547 // "If no such character exists, a value of -1 is returned."
548 if (!hitLayoutObject) 548 if (!hitLayoutItem)
549 return -1; 549 return -1;
550 ASSERT(queryRoot); 550 ASSERT(queryRoot);
551 int characterNumber = offsetInTextNode; 551 int characterNumber = offsetInTextNode;
552 552
553 // Accumulate the lengths of all the text nodes preceding the target layout 553 // Accumulate the lengths of all the text nodes preceding the target layout
554 // object within the queried root, to get the complete character number. 554 // object within the queried root, to get the complete character number.
555 for (const LayoutObject* layoutObject = hitLayoutObject->previousInPreOrder( queryRoot); 555 for (LineLayoutItem layoutItem = hitLayoutItem.previousInPreOrder(queryRoot) ;
556 layoutObject; layoutObject = layoutObject->previousInPreOrder(queryRoot) ) { 556 layoutItem; layoutItem = layoutItem.previousInPreOrder(queryRoot)) {
557 if (!layoutObject->isSVGInlineText()) 557 if (!layoutItem.isSVGInlineText())
558 continue; 558 continue;
559 characterNumber += toLayoutSVGInlineText(layoutObject)->resolvedTextLeng th(); 559 characterNumber += LineLayoutSVGInlineText(layoutItem).resolvedTextLengt h();
560 } 560 }
561 return characterNumber; 561 return characterNumber;
562 } 562 }
563 563
564 static unsigned logicalOffsetInTextNode(const LayoutSVGInlineText& textLayoutObj ect, const SVGInlineTextBox* startTextBox, unsigned fragmentOffset) 564 static unsigned logicalOffsetInTextNode(LineLayoutSVGInlineText textLineLayout, const SVGInlineTextBox* startTextBox, unsigned fragmentOffset)
565 { 565 {
566 Vector<SVGInlineTextBox*> textBoxes; 566 Vector<SVGInlineTextBox*> textBoxes;
567 collectTextBoxesInLogicalOrder(textLayoutObject, textBoxes); 567 collectTextBoxesInLogicalOrder(textLineLayout, textBoxes);
568 568
569 ASSERT(startTextBox); 569 ASSERT(startTextBox);
570 size_t index = textBoxes.find(startTextBox); 570 size_t index = textBoxes.find(startTextBox);
571 ASSERT(index != kNotFound); 571 ASSERT(index != kNotFound);
572 572
573 unsigned offset = fragmentOffset; 573 unsigned offset = fragmentOffset;
574 while (index) { 574 while (index) {
575 --index; 575 --index;
576 offset += textBoxes[index]->len(); 576 offset += textBoxes[index]->len();
577 } 577 }
578 return offset; 578 return offset;
579 } 579 }
580 580
581 static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex tFragment& fragment) 581 static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex tFragment& fragment)
582 { 582 {
583 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData); 583 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData);
584 584
585 // Test the query point against the bounds of the entire fragment first. 585 // Test the query point against the bounds of the entire fragment first.
586 FloatRect fragmentExtents = calculateFragmentBoundaries(*queryData->textLayo utObject, fragment); 586 FloatRect fragmentExtents = calculateFragmentBoundaries(queryData->textLineL ayout, fragment);
587 if (!fragmentExtents.contains(data->position)) 587 if (!fragmentExtents.contains(data->position))
588 return false; 588 return false;
589 589
590 // Iterate through the glyphs in this fragment, and check if their extents 590 // Iterate through the glyphs in this fragment, and check if their extents
591 // contain the query point. 591 // contain the query point.
592 FloatRect extent; 592 FloatRect extent;
593 const Vector<SVGTextMetrics>& textMetrics = queryData->textLayoutObject->lay outAttributes()->textMetricsValues(); 593 const Vector<SVGTextMetrics>& textMetrics = queryData->textLineLayout.layout Attributes()->textMetricsValues();
594 unsigned textMetricsOffset = fragment.metricsListOffset; 594 unsigned textMetricsOffset = fragment.metricsListOffset;
595 unsigned fragmentOffset = 0; 595 unsigned fragmentOffset = 0;
596 while (fragmentOffset < fragment.length) { 596 while (fragmentOffset < fragment.length) {
597 calculateGlyphBoundaries(queryData, fragment, fragmentOffset, extent); 597 calculateGlyphBoundaries(queryData, fragment, fragmentOffset, extent);
598 if (extent.contains(data->position)) { 598 if (extent.contains(data->position)) {
599 // Compute the character offset of the glyph within the text node. 599 // Compute the character offset of the glyph within the text node.
600 unsigned offsetInBox = fragment.characterOffset - queryData->textBox ->start() + fragmentOffset; 600 unsigned offsetInBox = fragment.characterOffset - queryData->textBox ->start() + fragmentOffset;
601 data->offsetInTextNode = logicalOffsetInTextNode(*queryData->textLay outObject, queryData->textBox, offsetInBox); 601 data->offsetInTextNode = logicalOffsetInTextNode(queryData->textLine Layout, queryData->textBox, offsetInBox);
602 data->hitLayoutObject = data->textLayoutObject; 602 data->hitLayoutItem = LineLayoutItem(data->textLineLayout);
603 return true; 603 return true;
604 } 604 }
605 fragmentOffset += textMetrics[textMetricsOffset].length(); 605 fragmentOffset += textMetrics[textMetricsOffset].length();
606 textMetricsOffset++; 606 textMetricsOffset++;
607 } 607 }
608 return false; 608 return false;
609 } 609 }
610 610
611 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const 611 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
612 { 612 {
613 CharacterNumberAtPositionData data(position); 613 CharacterNumberAtPositionData data(position);
614 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck); 614 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck);
615 return data.characterNumberWithin(m_queryRootLayoutObject); 615 return data.characterNumberWithin(m_queryRootLayoutObject);
616 } 616 }
617 617
618 } 618 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/api/LineLayoutText.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698