Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp |
| index 32073042bd914cd8999f8fd2c593feade0f70a23..68fc9b7c5fe565e2e6108e151c57c8ed2b4752f2 100644 |
| --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp |
| +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp |
| @@ -44,6 +44,18 @@ |
| namespace blink { |
| +struct SearchCandidate { |
| +public: |
| + SearchCandidate() {} |
| + SearchCandidate(LayoutObject* layoutObject, float dist) |
| + : candidateLayoutObject(layoutObject) |
| + , distance(dist) |
| + { |
| + } |
| + LayoutObject* candidateLayoutObject; |
| + float distance; |
| +}; |
| + |
| static inline LayoutRect adjustedEnclosingIntRect(const FloatRect& rect, |
| const AffineTransform& rootTransform, float strokeWidthForHairlinePadding) |
| { |
| @@ -476,4 +488,67 @@ float SVGLayoutSupport::calculateScreenFontSizeScalingFactor(const LayoutObject* |
| return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); |
| } |
| +static inline bool compareCandidateDistance(const SearchCandidate& r1, const SearchCandidate& r2) |
| +{ |
| + return r1.distance < r2.distance; |
| +} |
| + |
| +static inline bool isPossibleToCalculateDistance(LayoutObject* layoutObject) |
|
fs
2016/01/21 16:05:54
Yeah, this is not quite what I had in mind when I
|
| +{ |
| + if (!layoutObject->isSVGHiddenContainer() && layoutObject->localToParentTransform().isInvertible()) |
| + return true; |
| + return false; |
| +} |
| + |
| +LayoutObject* SVGLayoutSupport::findClosestLayoutSVGText(LayoutObject* layoutObject, const FloatPoint& point) |
| +{ |
| + // Try to find the closest LayoutSVGText. If not find this level, try to search on candidates. |
| + LayoutObject* closestLayoutObject = nullptr; |
| + float closestDistance = std::numeric_limits<float>::max(); |
| + Vector<SearchCandidate> candidates; |
| + for (LayoutObject* child = layoutObject->slowLastChild(); child; child = child->previousSibling()) { |
| + if (!isPossibleToCalculateDistance(child)) |
| + continue; |
| + |
| + FloatRect boundingBox = child->objectBoundingBox(); |
| + FloatPoint childLocalPoint = child->localToParentTransform().inverse().mapPoint(point); |
| + float distance = boundingBox.squaredDistanceTo(childLocalPoint); |
| + |
| + if (child->isSVGText()) { |
| + if (distance >= closestDistance) |
| + continue; |
| + candidates.clear(); |
| + closestLayoutObject = child; |
| + closestDistance = distance; |
| + continue; |
| + } |
| + |
| + if (child->isSVGContainer()) { |
| + FloatRect boundingBox = child->objectBoundingBox(); |
| + FloatPoint childLocalPoint = child->localToParentTransform().inverse().mapPoint(point); |
| + float distance = boundingBox.squaredDistanceTo(childLocalPoint); |
| + if (distance > closestDistance) |
| + continue; |
| + candidates.append(SearchCandidate(child, distance)); |
| + } |
| + } |
| + |
| + if (closestLayoutObject && closestLayoutObject->isSVGText()) |
| + return closestLayoutObject; |
| + |
| + // Sort using the distance between the mouse point and a candidate. |
| + // Because if the distance is close, It is high priority to search LayoutSVGText. |
| + std::stable_sort(candidates.begin(), candidates.end(), compareCandidateDistance); |
| + |
| + // If not find LayoutSVGText on this level of tree, try to search it on sub-tree of |condidate|. |
| + for (SearchCandidate& searchCandidate : candidates) { |
| + LayoutObject* candidateLayoutObject = searchCandidate.candidateLayoutObject; |
| + FloatPoint candidateLocalPoint = candidateLayoutObject->localToParentTransform().inverse().mapPoint(point); |
| + if (LayoutObject* result = findClosestLayoutSVGText(candidateLayoutObject, candidateLocalPoint)) |
| + return result; |
| + } |
| + |
| + return nullptr; |
| +} |
| + |
| } |