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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 struct StartPositionOfCharacterData : SVGTextQuery::Data { | 272 struct StartPositionOfCharacterData : SVGTextQuery::Data { |
273 StartPositionOfCharacterData(unsigned queryPosition) | 273 StartPositionOfCharacterData(unsigned queryPosition) |
274 : position(queryPosition) | 274 : position(queryPosition) |
275 { | 275 { |
276 } | 276 } |
277 | 277 |
278 unsigned position; | 278 unsigned position; |
279 FloatPoint startPosition; | 279 FloatPoint startPosition; |
280 }; | 280 }; |
281 | 281 |
| 282 static FloatPoint calculateGlyphPositionWithoutTransform(const SVGTextQuery::Dat
a* queryData, const SVGTextFragment& fragment, int offsetInFragment) |
| 283 { |
| 284 float glyphOffsetInDirection = 0; |
| 285 if (offsetInFragment) { |
| 286 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData
->textLayoutObject, fragment.characterOffset, offsetInFragment, queryData->textL
ayoutObject->styleRef().direction()); |
| 287 if (queryData->isVerticalText) |
| 288 glyphOffsetInDirection = metrics.height(); |
| 289 else |
| 290 glyphOffsetInDirection = metrics.width(); |
| 291 } |
| 292 |
| 293 FloatPoint glyphPosition(fragment.x, fragment.y); |
| 294 if (queryData->isVerticalText) |
| 295 glyphPosition.move(0, glyphOffsetInDirection); |
| 296 else |
| 297 glyphPosition.move(glyphOffsetInDirection, 0); |
| 298 |
| 299 return glyphPosition; |
| 300 } |
| 301 |
| 302 static FloatPoint calculateGlyphPosition(const SVGTextQuery::Data* queryData, co
nst SVGTextFragment& fragment, int offsetInFragment) |
| 303 { |
| 304 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, offsetInFragment); |
| 305 AffineTransform fragmentTransform; |
| 306 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); |
| 307 if (!fragmentTransform.isIdentity()) |
| 308 glyphPosition = fragmentTransform.mapPoint(glyphPosition); |
| 309 |
| 310 return glyphPosition; |
| 311 } |
| 312 |
282 bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe
xtFragment& fragment) const | 313 bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe
xtFragment& fragment) const |
283 { | 314 { |
284 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat
a*>(queryData); | 315 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat
a*>(queryData); |
285 | 316 |
286 int startPosition = data->position; | 317 int startPosition = data->position; |
287 int endPosition = startPosition + 1; | 318 int endPosition = startPosition + 1; |
288 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 319 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
289 return false; | 320 return false; |
290 | 321 |
291 data->startPosition = FloatPoint(fragment.x, fragment.y); | 322 data->startPosition = calculateGlyphPosition(queryData, fragment, startPosit
ion); |
292 | |
293 if (startPosition) { | |
294 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData
->textLayoutObject, fragment.characterOffset, startPosition, queryData->textLayo
utObject->styleRef().direction()); | |
295 if (queryData->isVerticalText) | |
296 data->startPosition.move(0, metrics.height()); | |
297 else | |
298 data->startPosition.move(metrics.width(), 0); | |
299 } | |
300 | |
301 AffineTransform fragmentTransform; | |
302 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); | |
303 if (fragmentTransform.isIdentity()) | |
304 return true; | |
305 | |
306 data->startPosition = fragmentTransform.mapPoint(data->startPosition); | |
307 return true; | 323 return true; |
308 } | 324 } |
309 | 325 |
310 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const | 326 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const |
311 { | 327 { |
312 StartPositionOfCharacterData data(position); | 328 StartPositionOfCharacterData data(position); |
313 executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); | 329 executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); |
314 return data.startPosition; | 330 return data.startPosition; |
315 } | 331 } |
316 | 332 |
(...skipping 10 matching lines...) Expand all Loading... |
327 | 343 |
328 bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText
Fragment& fragment) const | 344 bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText
Fragment& fragment) const |
329 { | 345 { |
330 EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(
queryData); | 346 EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(
queryData); |
331 | 347 |
332 int startPosition = data->position; | 348 int startPosition = data->position; |
333 int endPosition = startPosition + 1; | 349 int endPosition = startPosition + 1; |
334 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 350 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
335 return false; | 351 return false; |
336 | 352 |
337 data->endPosition = FloatPoint(fragment.x, fragment.y); | 353 // TODO(fs): mapStartEndPositionsIntoFragmentCoordinates(...) above applies |
338 | 354 // some heuristics for ligatures, so why not just use endPosition here? |
339 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtLayoutObject, fragment.characterOffset, startPosition + 1, queryData->textLayo
utObject->styleRef().direction()); | 355 // (rather than startPosition+1) |
340 if (queryData->isVerticalText) | 356 data->endPosition = calculateGlyphPosition(queryData, fragment, startPositio
n + 1); |
341 data->endPosition.move(0, metrics.height()); | |
342 else | |
343 data->endPosition.move(metrics.width(), 0); | |
344 | |
345 AffineTransform fragmentTransform; | |
346 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); | |
347 if (fragmentTransform.isIdentity()) | |
348 return true; | |
349 | |
350 data->endPosition = fragmentTransform.mapPoint(data->endPosition); | |
351 return true; | 357 return true; |
352 } | 358 } |
353 | 359 |
354 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const | 360 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const |
355 { | 361 { |
356 EndPositionOfCharacterData data(position); | 362 EndPositionOfCharacterData data(position); |
357 executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); | 363 executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); |
358 return data.endPosition; | 364 return data.endPosition; |
359 } | 365 } |
360 | 366 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 | 413 |
408 unsigned position; | 414 unsigned position; |
409 FloatRect extent; | 415 FloatRect extent; |
410 }; | 416 }; |
411 | 417 |
412 static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
SVGTextFragment& fragment, int startPosition, FloatRect& extent) | 418 static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
SVGTextFragment& fragment, int startPosition, FloatRect& extent) |
413 { | 419 { |
414 float scalingFactor = queryData->textLayoutObject->scalingFactor(); | 420 float scalingFactor = queryData->textLayoutObject->scalingFactor(); |
415 ASSERT(scalingFactor); | 421 ASSERT(scalingFactor); |
416 | 422 |
417 extent.setLocation(FloatPoint(fragment.x, fragment.y - queryData->textLayout
Object->scaledFont().fontMetrics().floatAscent() / scalingFactor)); | 423 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, startPosition); |
418 | 424 glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics
().floatAscent() / scalingFactor); |
419 if (startPosition) { | 425 extent.setLocation(glyphPosition); |
420 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData
->textLayoutObject, fragment.characterOffset, startPosition, queryData->textLayo
utObject->styleRef().direction()); | |
421 if (queryData->isVerticalText) | |
422 extent.move(0, metrics.height()); | |
423 else | |
424 extent.move(metrics.width(), 0); | |
425 } | |
426 | 426 |
427 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtLayoutObject, fragment.characterOffset + startPosition, 1, queryData->textLayo
utObject->styleRef().direction()); | 427 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtLayoutObject, fragment.characterOffset + startPosition, 1, queryData->textLayo
utObject->styleRef().direction()); |
428 extent.setSize(FloatSize(metrics.width(), metrics.height())); | 428 extent.setSize(FloatSize(metrics.width(), metrics.height())); |
429 | 429 |
430 AffineTransform fragmentTransform; | 430 AffineTransform fragmentTransform; |
431 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); | 431 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); |
432 | 432 |
433 extent = fragmentTransform.mapRect(extent); | 433 extent = fragmentTransform.mapRect(extent); |
434 } | 434 } |
435 | 435 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 508 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
509 { | 509 { |
510 CharacterNumberAtPositionData data(position); | 510 CharacterNumberAtPositionData data(position); |
511 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) | 511 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) |
512 return -1; | 512 return -1; |
513 | 513 |
514 return data.processedCharacters; | 514 return data.processedCharacters; |
515 } | 515 } |
516 | 516 |
517 } | 517 } |
OLD | NEW |