| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:ui/ui.dart' as ui; |
| |
| import '../browser_detection.dart'; |
| import '../dom.dart'; |
| import '../svg.dart'; |
| import 'path/path.dart'; |
| import 'path/path_to_svg.dart'; |
| |
| /// Counter used for generating clip path id inside an svg <defs> tag. |
| int _clipIdCounter = 0; |
| |
| /// Used for clipping and filter svg resources. |
| /// |
| /// Position needs to be absolute since these svgs are sandwiched between |
| /// canvas elements and can cause layout shifts otherwise. |
| final SVGSVGElement kSvgResourceHeader = createSVGSVGElement() |
| ..setAttribute('width', 0) |
| ..setAttribute('height', 0) |
| ..style.position = 'absolute'; |
| |
| /// Converts Path to svg element that contains a clip-path definition. |
| /// |
| /// Calling this method updates [_clipIdCounter]. The HTML id of the generated |
| /// clip is set to "svgClip${_clipIdCounter}", e.g. "svgClip123". |
| SVGSVGElement pathToSvgClipPath(ui.Path path, |
| {double offsetX = 0, |
| double offsetY = 0, |
| double scaleX = 1.0, |
| double scaleY = 1.0}) { |
| _clipIdCounter += 1; |
| final SVGSVGElement root = kSvgResourceHeader.cloneNode(false) as SVGSVGElement; |
| final SVGDefsElement defs = createSVGDefsElement(); |
| root.append(defs); |
| |
| final String clipId = 'svgClip$_clipIdCounter'; |
| final SVGClipPathElement clipPath = createSVGClipPathElement(); |
| defs.append(clipPath); |
| clipPath.id = clipId; |
| |
| final SVGPathElement svgPath = createSVGPathElement(); |
| clipPath.append(svgPath); |
| svgPath.setAttribute('fill', '#FFFFFF'); |
| |
| // Firefox objectBoundingBox fails to scale to 1x1 units, instead use |
| // no clipPathUnits but write the path in target units. |
| if (browserEngine != BrowserEngine.firefox) { |
| clipPath.setAttribute('clipPathUnits', 'objectBoundingBox'); |
| svgPath.setAttribute('transform', 'scale($scaleX, $scaleY)'); |
| } |
| |
| svgPath.setAttribute('d', pathToSvg((path as SurfacePath).pathRef, offsetX: offsetX, offsetY: offsetY)); |
| return root; |
| } |
| |
| String createSvgClipUrl() => 'url(#svgClip$_clipIdCounter)'; |
| |
| /// Resets clip ids. Used for testing by [debugForgetFrameScene] API. |
| void resetSvgClipIds() { |
| _clipIdCounter = 0; |
| } |