| /* |
| * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h" |
| |
| #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" |
| #include "third_party/blink/renderer/core/svg/svg_path_element.h" |
| #include "third_party/blink/renderer/core/svg/svg_text_path_element.h" |
| #include "third_party/blink/renderer/platform/graphics/path.h" |
| |
| namespace blink { |
| |
| PathPositionMapper::PathPositionMapper(const Path& path, |
| float computed_path_length, |
| float start_offset) |
| : position_calculator_(path), |
| path_length_(computed_path_length), |
| path_start_offset_(start_offset) {} |
| |
| PathPositionMapper::PositionType PathPositionMapper::PointAndNormalAtLength( |
| float length, |
| FloatPoint& point, |
| float& angle) { |
| if (length < 0) |
| return kBeforePath; |
| if (length > path_length_) |
| return kAfterPath; |
| DCHECK_GE(length, 0); |
| DCHECK_LE(length, path_length_); |
| |
| position_calculator_.PointAndNormalAtLength(length, point, angle); |
| return kOnPath; |
| } |
| |
| LayoutSVGTextPath::LayoutSVGTextPath(Element* element) |
| : LayoutSVGInline(element) {} |
| |
| bool LayoutSVGTextPath::IsChildAllowed(LayoutObject* child, |
| const ComputedStyle&) const { |
| if (child->IsText()) |
| return SVGLayoutSupport::IsLayoutableTextNode(child); |
| |
| return child->IsSVGInline() && !child->IsSVGTextPath(); |
| } |
| |
| std::unique_ptr<PathPositionMapper> LayoutSVGTextPath::LayoutPath() const { |
| const SVGTextPathElement& text_path_element = |
| ToSVGTextPathElement(*GetNode()); |
| Element* target_element = SVGURIReference::TargetElementFromIRIString( |
| text_path_element.HrefString(), |
| text_path_element.TreeScopeForIdResolution()); |
| |
| if (!IsSVGPathElement(target_element)) |
| return nullptr; |
| |
| const SVGPathElement& path_element = ToSVGPathElement(*target_element); |
| Path path_data = path_element.AsPath(); |
| if (path_data.IsEmpty()) |
| return nullptr; |
| |
| // Spec: The 'transform' attribute on the referenced 'path' ... |
| // element represents a supplemental transformation relative to the current |
| // user coordinate system for the current 'text' element, including any |
| // adjustments to the current user coordinate system due to a possible |
| // 'transform' property on the current 'text' element. |
| // https://svgwg.org/svg2-draft/text.html#TextPathElement |
| path_data.Transform( |
| path_element.CalculateTransform(SVGElement::kIncludeMotionTransform)); |
| |
| // Determine the length to resolve any percentage 'startOffset' |
| // against - either 'pathLength' (author path length) or the |
| // computed length of the path. |
| float computed_path_length = path_data.length(); |
| float author_path_length = path_element.AuthorPathLength(); |
| float offset_scale = 1; |
| if (!std::isnan(author_path_length)) { |
| offset_scale = SVGGeometryElement::PathLengthScaleFactor( |
| computed_path_length, author_path_length); |
| } else { |
| author_path_length = computed_path_length; |
| } |
| |
| const SVGLength& start_offset = |
| *text_path_element.startOffset()->CurrentValue(); |
| float path_start_offset = start_offset.ValueAsPercentage(); |
| if (start_offset.TypeWithCalcResolved() == |
| CSSPrimitiveValue::UnitType::kPercentage) |
| path_start_offset *= author_path_length; |
| |
| path_start_offset *= offset_scale; |
| |
| return PathPositionMapper::Create(path_data, computed_path_length, |
| path_start_offset); |
| } |
| |
| } // namespace blink |