Chromium Code Reviews| 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 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 return false; | 249 return false; |
| 250 } | 250 } |
| 251 | 251 |
| 252 float SVGTextQuery::textLength() const | 252 float SVGTextQuery::textLength() const |
| 253 { | 253 { |
| 254 TextLengthData data; | 254 TextLengthData data; |
| 255 logicalQuery(m_queryRootLayoutObject, &data, textLengthCallback); | 255 logicalQuery(m_queryRootLayoutObject, &data, textLengthCallback); |
| 256 return data.textLength; | 256 return data.textLength; |
| 257 } | 257 } |
| 258 | 258 |
| 259 const SVGTextMetrics& findMetricsForCharacter(const Vector<SVGTextMetrics>& text MetricsValues, const SVGTextFragment& fragment, unsigned startInFragment) | |
| 260 { | |
| 261 // Find the text metrics cell that starts at or contains the character at |s tartInFragment|. | |
| 262 unsigned textMetricsOffset = fragment.metricsListOffset; | |
| 263 unsigned fragmentOffset = 0; | |
| 264 while (fragmentOffset < fragment.length) { | |
| 265 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset++]; | |
| 266 unsigned glyphEnd = fragmentOffset + metrics.length(); | |
| 267 if (startInFragment < glyphEnd) | |
| 268 break; | |
| 269 fragmentOffset = glyphEnd; | |
| 270 } | |
| 271 return textMetricsValues[textMetricsOffset - 1]; | |
| 272 } | |
| 273 | |
| 274 static float calculateGlyphRange(const QueryData* queryData, const SVGTextFragme nt& fragment, unsigned start, unsigned end) | |
| 275 { | |
| 276 float glyphRange = 0; | |
| 277 if (end <= start) | |
|
fs
2016/03/09 09:55:42
Nit: I believe this should be uncommon enough here
pdr.
2016/03/09 19:13:50
SGTM, done.
| |
| 278 return glyphRange; | |
| 279 | |
| 280 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout. layoutAttributes()->textMetricsValues(); | |
| 281 for (unsigned character = start; character < end; character++) { | |
| 282 SVGTextMetrics metrics = findMetricsForCharacter(textMetricsValues, frag ment, character); | |
|
fs
2016/03/09 09:55:42
Nit: const SVGTextMetrics&
pdr.
2016/03/09 19:13:50
Done.
| |
| 283 glyphRange += queryData->isVerticalText ? metrics.height() : metrics.wid th(); | |
| 284 } | |
| 285 return glyphRange; | |
| 286 } | |
| 287 | |
| 259 // subStringLength() implementation | 288 // subStringLength() implementation |
| 260 struct SubStringLengthData : QueryData { | 289 struct SubStringLengthData : QueryData { |
| 261 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) | 290 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) |
| 262 : startPosition(queryStartPosition) | 291 : startPosition(queryStartPosition) |
| 263 , length(queryLength) | 292 , length(queryLength) |
| 264 , subStringLength(0) | 293 , subStringLength(0) |
| 265 { | 294 { |
| 266 } | 295 } |
| 267 | 296 |
| 268 unsigned startPosition; | 297 unsigned startPosition; |
| 269 unsigned length; | 298 unsigned length; |
| 270 | 299 |
| 271 float subStringLength; | 300 float subStringLength; |
| 272 }; | 301 }; |
| 273 | 302 |
| 274 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment) | 303 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment) |
| 275 { | 304 { |
| 276 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); | 305 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); |
| 277 | 306 |
| 278 int startPosition = data->startPosition; | 307 int startPosition = data->startPosition; |
| 279 int endPosition = startPosition + data->length; | 308 int endPosition = startPosition + data->length; |
| 280 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) | 309 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) |
| 281 return false; | 310 return false; |
| 282 | 311 |
| 283 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te xtLineLayout, fragment.characterOffset + startPosition, endPosition - startPosit ion, queryData->textBox->direction()); | 312 data->subStringLength += calculateGlyphRange(queryData, fragment, startPosit ion, endPosition); |
| 284 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr ics.width(); | |
| 285 return false; | 313 return false; |
| 286 } | 314 } |
| 287 | 315 |
| 288 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st | 316 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st |
| 289 { | 317 { |
| 290 SubStringLengthData data(startPosition, length); | 318 SubStringLengthData data(startPosition, length); |
| 291 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); | 319 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); |
| 292 return data.subStringLength; | 320 return data.subStringLength; |
| 293 } | 321 } |
| 294 | 322 |
| 295 // startPositionOfCharacter() implementation | 323 // startPositionOfCharacter() implementation |
| 296 struct StartPositionOfCharacterData : QueryData { | 324 struct StartPositionOfCharacterData : QueryData { |
| 297 StartPositionOfCharacterData(unsigned queryPosition) | 325 StartPositionOfCharacterData(unsigned queryPosition) |
| 298 : position(queryPosition) | 326 : position(queryPosition) |
| 299 { | 327 { |
| 300 } | 328 } |
| 301 | 329 |
| 302 unsigned position; | 330 unsigned position; |
| 303 FloatPoint startPosition; | 331 FloatPoint startPosition; |
| 304 }; | 332 }; |
| 305 | 333 |
| 306 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, int offsetInFragment) | 334 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, int offsetInFragment) |
| 307 { | 335 { |
| 308 float glyphOffsetInDirection = 0; | 336 float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, o ffsetInFragment); |
| 309 if (offsetInFragment) { | |
| 310 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData ->textLineLayout, fragment.characterOffset, offsetInFragment, queryData->textBox ->direction()); | |
| 311 if (queryData->isVerticalText) | |
| 312 glyphOffsetInDirection = metrics.height(); | |
| 313 else | |
| 314 glyphOffsetInDirection = metrics.width(); | |
| 315 } | |
| 316 | 337 |
| 317 if (!queryData->textBox->isLeftToRightDirection()) { | 338 if (!queryData->textBox->isLeftToRightDirection()) { |
| 318 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width; | 339 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width; |
| 319 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; | 340 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; |
| 320 } | 341 } |
| 321 | 342 |
| 322 FloatPoint glyphPosition(fragment.x, fragment.y); | 343 FloatPoint glyphPosition(fragment.x, fragment.y); |
| 323 if (queryData->isVerticalText) | 344 if (queryData->isVerticalText) |
| 324 glyphPosition.move(0, glyphOffsetInDirection); | 345 glyphPosition.move(0, glyphOffsetInDirection); |
| 325 else | 346 else |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 434 struct ExtentOfCharacterData : QueryData { | 455 struct ExtentOfCharacterData : QueryData { |
| 435 ExtentOfCharacterData(unsigned queryPosition) | 456 ExtentOfCharacterData(unsigned queryPosition) |
| 436 : position(queryPosition) | 457 : position(queryPosition) |
| 437 { | 458 { |
| 438 } | 459 } |
| 439 | 460 |
| 440 unsigned position; | 461 unsigned position; |
| 441 FloatRect extent; | 462 FloatRect extent; |
| 442 }; | 463 }; |
| 443 | 464 |
| 444 const SVGTextMetrics& findMetricsForCharacter(const Vector<SVGTextMetrics>& text MetricsValues, const SVGTextFragment& fragment, unsigned startInFragment) | |
| 445 { | |
| 446 // Find the text metrics cell that start at or contain the character at |sta rtInFragment|. | |
| 447 unsigned textMetricsOffset = fragment.metricsListOffset; | |
| 448 unsigned fragmentOffset = 0; | |
| 449 while (fragmentOffset < fragment.length) { | |
| 450 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset++]; | |
| 451 unsigned glyphEnd = fragmentOffset + metrics.length(); | |
| 452 if (startInFragment < glyphEnd) | |
| 453 break; | |
| 454 fragmentOffset = glyphEnd; | |
| 455 } | |
| 456 return textMetricsValues[textMetricsOffset - 1]; | |
| 457 } | |
| 458 | |
| 459 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV GTextFragment& fragment, int startPosition, FloatRect& extent) | 465 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV GTextFragment& fragment, int startPosition, FloatRect& extent) |
| 460 { | 466 { |
| 461 float scalingFactor = queryData->textLineLayout.scalingFactor(); | 467 float scalingFactor = queryData->textLineLayout.scalingFactor(); |
| 462 ASSERT(scalingFactor); | 468 ASSERT(scalingFactor); |
| 463 | 469 |
| 464 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); | 470 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); |
| 465 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().fontMetrics(). floatAscent() / scalingFactor); | 471 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().fontMetrics(). floatAscent() / scalingFactor); |
| 466 extent.setLocation(glyphPosition); | 472 extent.setLocation(glyphPosition); |
| 467 | 473 |
| 468 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends | 474 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 } | 608 } |
| 603 | 609 |
| 604 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 610 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
| 605 { | 611 { |
| 606 CharacterNumberAtPositionData data(position); | 612 CharacterNumberAtPositionData data(position); |
| 607 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck); | 613 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck); |
| 608 return data.characterNumberWithin(m_queryRootLayoutObject); | 614 return data.characterNumberWithin(m_queryRootLayoutObject); |
| 609 } | 615 } |
| 610 | 616 |
| 611 } // namespace blink | 617 } // namespace blink |
| OLD | NEW |