OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org> | 2 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org> |
3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
5 * Copyright (C) 2009 Google, Inc. All rights reserved. | 5 * Copyright (C) 2009 Google, Inc. All rights reserved. |
6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
7 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 7 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "core/layout/svg/LayoutSVGViewportContainer.h" | 37 #include "core/layout/svg/LayoutSVGViewportContainer.h" |
38 #include "core/layout/svg/SVGResources.h" | 38 #include "core/layout/svg/SVGResources.h" |
39 #include "core/layout/svg/SVGResourcesCache.h" | 39 #include "core/layout/svg/SVGResourcesCache.h" |
40 #include "core/paint/PaintLayer.h" | 40 #include "core/paint/PaintLayer.h" |
41 #include "core/svg/SVGElement.h" | 41 #include "core/svg/SVGElement.h" |
42 #include "platform/geometry/TransformState.h" | 42 #include "platform/geometry/TransformState.h" |
43 #include "platform/graphics/StrokeData.h" | 43 #include "platform/graphics/StrokeData.h" |
44 | 44 |
45 namespace blink { | 45 namespace blink { |
46 | 46 |
| 47 struct SearchCandidate { |
| 48 SearchCandidate() |
| 49 : candidateLayoutObject(nullptr) |
| 50 , candidateDistance(std::numeric_limits<float>::max()) |
| 51 { |
| 52 } |
| 53 SearchCandidate(LayoutObject* layoutObject, float distance) |
| 54 : candidateLayoutObject(layoutObject) |
| 55 , candidateDistance(distance) |
| 56 { |
| 57 } |
| 58 LayoutObject* candidateLayoutObject; |
| 59 float candidateDistance; |
| 60 }; |
| 61 |
47 static inline LayoutRect adjustedEnclosingIntRect(const FloatRect& rect, | 62 static inline LayoutRect adjustedEnclosingIntRect(const FloatRect& rect, |
48 const AffineTransform& rootTransform, float strokeWidthForHairlinePadding) | 63 const AffineTransform& rootTransform, float strokeWidthForHairlinePadding) |
49 { | 64 { |
50 FloatRect adjustedRect = rect; | 65 FloatRect adjustedRect = rect; |
51 | 66 |
52 if (strokeWidthForHairlinePadding) { | 67 if (strokeWidthForHairlinePadding) { |
53 // For hairline strokes (stroke-width < 1 in device space), Skia rasteri
zes up to 0.4(9) off | 68 // For hairline strokes (stroke-width < 1 in device space), Skia rasteri
zes up to 0.4(9) off |
54 // the stroke center. That means enclosingIntRect is not enough - we mus
t also pad to 0.5. | 69 // the stroke center. That means enclosingIntRect is not enough - we mus
t also pad to 0.5. |
55 // This is still fragile as it misses out on CC/DSF CTM components. | 70 // This is still fragile as it misses out on CC/DSF CTM components. |
56 const FloatSize strokeSize = rootTransform.mapSize( | 71 const FloatSize strokeSize = rootTransform.mapSize( |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 ASSERT(layoutObject); | 495 ASSERT(layoutObject); |
481 | 496 |
482 // FIXME: trying to compute a device space transform at record time is wrong
. All clients | 497 // FIXME: trying to compute a device space transform at record time is wrong
. All clients |
483 // should be updated to avoid relying on this information, and the method sh
ould be removed. | 498 // should be updated to avoid relying on this information, and the method sh
ould be removed. |
484 AffineTransform ctm = deprecatedCalculateTransformToLayer(layoutObject) * Su
btreeContentTransformScope::currentContentTransformation(); | 499 AffineTransform ctm = deprecatedCalculateTransformToLayer(layoutObject) * Su
btreeContentTransformScope::currentContentTransformation(); |
485 ctm.scale(layoutObject->document().frameHost()->deviceScaleFactor()); | 500 ctm.scale(layoutObject->document().frameHost()->deviceScaleFactor()); |
486 | 501 |
487 return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(),
2)) / 2)); | 502 return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(),
2)) / 2)); |
488 } | 503 } |
489 | 504 |
| 505 static inline bool compareCandidateDistance(const SearchCandidate& r1, const Sea
rchCandidate& r2) |
| 506 { |
| 507 return r1.candidateDistance < r2.candidateDistance; |
| 508 } |
| 509 |
| 510 static inline float distanceToChildLayoutObject(LayoutObject* child, const Float
Point& point) |
| 511 { |
| 512 const AffineTransform& localToParentTransform = child->localToParentTransfor
m(); |
| 513 if (!localToParentTransform.isInvertible()) |
| 514 return std::numeric_limits<float>::max(); |
| 515 FloatPoint childLocalPoint = localToParentTransform.inverse().mapPoint(point
); |
| 516 return child->objectBoundingBox().squaredDistanceTo(childLocalPoint); |
| 517 } |
| 518 |
| 519 static SearchCandidate searchTreeForFindClosestLayoutSVGText(LayoutObject* layou
tObject, const FloatPoint& point) |
| 520 { |
| 521 // Try to find the closest LayoutSVGText. |
| 522 SearchCandidate closestText; |
| 523 Vector<SearchCandidate> candidates; |
| 524 |
| 525 // Find the closest LayoutSVGText on this tree level, and also collect any |
| 526 // containers that could contain LayoutSVGTexts that are closer. |
| 527 for (LayoutObject* child = layoutObject->slowLastChild(); child; child = chi
ld->previousSibling()) { |
| 528 if (child->isSVGText()) { |
| 529 float distance = distanceToChildLayoutObject(child, point); |
| 530 if (distance >= closestText.candidateDistance) |
| 531 continue; |
| 532 candidates.clear(); |
| 533 closestText.candidateLayoutObject = child; |
| 534 closestText.candidateDistance = distance; |
| 535 continue; |
| 536 } |
| 537 |
| 538 if (child->isSVGContainer() && !layoutObject->isSVGHiddenContainer()) { |
| 539 float distance = distanceToChildLayoutObject(child, point); |
| 540 if (distance > closestText.candidateDistance) |
| 541 continue; |
| 542 candidates.append(SearchCandidate(child, distance)); |
| 543 } |
| 544 } |
| 545 |
| 546 // If a LayoutSVGText was found and there are no potentially closer sub-tree
s, |
| 547 // just return |closestText|. |
| 548 if (closestText.candidateLayoutObject && candidates.isEmpty()) |
| 549 return closestText; |
| 550 |
| 551 std::stable_sort(candidates.begin(), candidates.end(), compareCandidateDista
nce); |
| 552 |
| 553 // Find the closest LayoutSVGText in the sub-trees in |candidates|. |
| 554 // If a LayoutSVGText is found that is strictly closer than any previous can
didate, then end the search. |
| 555 for (const SearchCandidate& searchCandidate : candidates) { |
| 556 if (closestText.candidateDistance < searchCandidate.candidateDistance) |
| 557 break; |
| 558 LayoutObject* candidateLayoutObject = searchCandidate.candidateLayoutObj
ect; |
| 559 FloatPoint candidateLocalPoint = candidateLayoutObject->localToParentTra
nsform().inverse().mapPoint(point); |
| 560 |
| 561 SearchCandidate candidateText = searchTreeForFindClosestLayoutSVGText(ca
ndidateLayoutObject, candidateLocalPoint); |
| 562 |
| 563 if (candidateText.candidateDistance < closestText.candidateDistance) |
| 564 closestText = candidateText; |
| 565 } |
| 566 |
| 567 return closestText; |
| 568 } |
| 569 |
| 570 LayoutObject* SVGLayoutSupport::findClosestLayoutSVGText(LayoutObject* layoutObj
ect, const FloatPoint& point) |
| 571 { |
| 572 return searchTreeForFindClosestLayoutSVGText(layoutObject, point).candidateL
ayoutObject; |
| 573 } |
| 574 |
490 } // namespace blink | 575 } // namespace blink |
OLD | NEW |