| 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 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout.
layoutAttributes()->textMetricsValues(); |
| 278 for (unsigned character = start; character < end; character++) { |
| 279 const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValue
s, fragment, character); |
| 280 glyphRange += queryData->isVerticalText ? metrics.height() : metrics.wid
th(); |
| 281 } |
| 282 return glyphRange; |
| 283 } |
| 284 |
| 259 // subStringLength() implementation | 285 // subStringLength() implementation |
| 260 struct SubStringLengthData : QueryData { | 286 struct SubStringLengthData : QueryData { |
| 261 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) | 287 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) |
| 262 : startPosition(queryStartPosition) | 288 : startPosition(queryStartPosition) |
| 263 , length(queryLength) | 289 , length(queryLength) |
| 264 , subStringLength(0) | 290 , subStringLength(0) |
| 265 { | 291 { |
| 266 } | 292 } |
| 267 | 293 |
| 268 unsigned startPosition; | 294 unsigned startPosition; |
| 269 unsigned length; | 295 unsigned length; |
| 270 | 296 |
| 271 float subStringLength; | 297 float subStringLength; |
| 272 }; | 298 }; |
| 273 | 299 |
| 274 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment&
fragment) | 300 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment&
fragment) |
| 275 { | 301 { |
| 276 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); | 302 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); |
| 277 | 303 |
| 278 int startPosition = data->startPosition; | 304 int startPosition = data->startPosition; |
| 279 int endPosition = startPosition + data->length; | 305 int endPosition = startPosition + data->length; |
| 280 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 306 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
| 281 return false; | 307 return false; |
| 282 | 308 |
| 283 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtLineLayout, fragment.characterOffset + startPosition, endPosition - startPosit
ion, queryData->textBox->direction()); | 309 data->subStringLength += calculateGlyphRange(queryData, fragment, startPosit
ion, endPosition); |
| 284 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr
ics.width(); | |
| 285 return false; | 310 return false; |
| 286 } | 311 } |
| 287 | 312 |
| 288 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con
st | 313 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con
st |
| 289 { | 314 { |
| 290 SubStringLengthData data(startPosition, length); | 315 SubStringLengthData data(startPosition, length); |
| 291 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); | 316 logicalQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); |
| 292 return data.subStringLength; | 317 return data.subStringLength; |
| 293 } | 318 } |
| 294 | 319 |
| 295 // startPositionOfCharacter() implementation | 320 // startPositionOfCharacter() implementation |
| 296 struct StartPositionOfCharacterData : QueryData { | 321 struct StartPositionOfCharacterData : QueryData { |
| 297 StartPositionOfCharacterData(unsigned queryPosition) | 322 StartPositionOfCharacterData(unsigned queryPosition) |
| 298 : position(queryPosition) | 323 : position(queryPosition) |
| 299 { | 324 { |
| 300 } | 325 } |
| 301 | 326 |
| 302 unsigned position; | 327 unsigned position; |
| 303 FloatPoint startPosition; | 328 FloatPoint startPosition; |
| 304 }; | 329 }; |
| 305 | 330 |
| 306 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD
ata, const SVGTextFragment& fragment, int offsetInFragment) | 331 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD
ata, const SVGTextFragment& fragment, int offsetInFragment) |
| 307 { | 332 { |
| 308 float glyphOffsetInDirection = 0; | 333 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 | 334 |
| 317 if (!queryData->textBox->isLeftToRightDirection()) { | 335 if (!queryData->textBox->isLeftToRightDirection()) { |
| 318 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra
gment.width; | 336 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra
gment.width; |
| 319 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; | 337 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; |
| 320 } | 338 } |
| 321 | 339 |
| 322 FloatPoint glyphPosition(fragment.x, fragment.y); | 340 FloatPoint glyphPosition(fragment.x, fragment.y); |
| 323 if (queryData->isVerticalText) | 341 if (queryData->isVerticalText) |
| 324 glyphPosition.move(0, glyphOffsetInDirection); | 342 glyphPosition.move(0, glyphOffsetInDirection); |
| 325 else | 343 else |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 struct ExtentOfCharacterData : QueryData { | 452 struct ExtentOfCharacterData : QueryData { |
| 435 ExtentOfCharacterData(unsigned queryPosition) | 453 ExtentOfCharacterData(unsigned queryPosition) |
| 436 : position(queryPosition) | 454 : position(queryPosition) |
| 437 { | 455 { |
| 438 } | 456 } |
| 439 | 457 |
| 440 unsigned position; | 458 unsigned position; |
| 441 FloatRect extent; | 459 FloatRect extent; |
| 442 }; | 460 }; |
| 443 | 461 |
| 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) | 462 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV
GTextFragment& fragment, int startPosition, FloatRect& extent) |
| 460 { | 463 { |
| 461 float scalingFactor = queryData->textLineLayout.scalingFactor(); | 464 float scalingFactor = queryData->textLineLayout.scalingFactor(); |
| 462 ASSERT(scalingFactor); | 465 ASSERT(scalingFactor); |
| 463 | 466 |
| 464 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, startPosition); | 467 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, startPosition); |
| 465 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().fontMetrics().
floatAscent() / scalingFactor); | 468 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().fontMetrics().
floatAscent() / scalingFactor); |
| 466 extent.setLocation(glyphPosition); | 469 extent.setLocation(glyphPosition); |
| 467 | 470 |
| 468 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends | 471 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 } | 605 } |
| 603 | 606 |
| 604 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 607 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
| 605 { | 608 { |
| 606 CharacterNumberAtPositionData data(position); | 609 CharacterNumberAtPositionData data(position); |
| 607 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba
ck); | 610 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba
ck); |
| 608 return data.characterNumberWithin(m_queryRootLayoutObject); | 611 return data.characterNumberWithin(m_queryRootLayoutObject); |
| 609 } | 612 } |
| 610 | 613 |
| 611 } // namespace blink | 614 } // namespace blink |
| OLD | NEW |