tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGPolyElement.cpp (3960B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SVGPolyElement.h"
      8 
      9 #include "DOMSVGPointList.h"
     10 #include "SVGContentUtils.h"
     11 #include "mozilla/dom/SVGAnimatedLength.h"
     12 #include "mozilla/gfx/2D.h"
     13 
     14 using namespace mozilla::gfx;
     15 
     16 namespace mozilla::dom {
     17 
     18 //----------------------------------------------------------------------
     19 // Implementation
     20 
     21 SVGPolyElement::SVGPolyElement(
     22    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     23    : SVGPolyElementBase(std::move(aNodeInfo)) {}
     24 
     25 already_AddRefed<DOMSVGPointList> SVGPolyElement::Points() {
     26  return DOMSVGPointList::GetDOMWrapper(mPoints.GetBaseValKey(), this);
     27 }
     28 
     29 already_AddRefed<DOMSVGPointList> SVGPolyElement::AnimatedPoints() {
     30  return DOMSVGPointList::GetDOMWrapper(mPoints.GetAnimValKey(), this);
     31 }
     32 
     33 //----------------------------------------------------------------------
     34 // SVGElement methods
     35 
     36 /* virtual */
     37 bool SVGPolyElement::HasValidDimensions() const {
     38  return !mPoints.GetAnimValue().IsEmpty();
     39 }
     40 
     41 //----------------------------------------------------------------------
     42 // SVGGeometryElement methods
     43 
     44 bool SVGPolyElement::AttributeDefinesGeometry(const nsAtom* aName) {
     45  return aName == nsGkAtoms::points || aName == nsGkAtoms::pathLength;
     46 }
     47 
     48 void SVGPolyElement::GetMarkPoints(nsTArray<SVGMark>* aMarks) {
     49  const SVGPointList& points = mPoints.GetAnimValue();
     50 
     51  if (points.IsEmpty()) {
     52    return;
     53  }
     54 
     55  float zoom = UserSpaceMetrics::GetZoom(this);
     56 
     57  float px = points[0].mX * zoom, py = points[0].mY * zoom, prevAngle = 0.0f;
     58  if (!(std::isfinite(px) && std::isfinite(py))) {
     59    return;
     60  }
     61 
     62  aMarks->AppendElement(SVGMark(px, py, 0, SVGMark::eStart));
     63 
     64  for (uint32_t i = 1; i < points.Length(); ++i) {
     65    float x = points[i].mX * zoom;
     66    float y = points[i].mY * zoom;
     67    if (!(std::isfinite(x) && std::isfinite(y))) {
     68      aMarks->Clear();
     69      return;
     70    }
     71    float angle = std::atan2(y - py, x - px);
     72 
     73    // Vertex marker.
     74    if (i == 1) {
     75      aMarks->ElementAt(0).angle = angle;
     76    } else {
     77      aMarks->LastElement().angle =
     78          SVGContentUtils::AngleBisect(prevAngle, angle);
     79    }
     80 
     81    aMarks->AppendElement(SVGMark(x, y, 0, SVGMark::eMid));
     82 
     83    prevAngle = angle;
     84    px = x;
     85    py = y;
     86  }
     87 
     88  aMarks->LastElement().angle = prevAngle;
     89  aMarks->LastElement().type = SVGMark::eEnd;
     90 }
     91 
     92 bool SVGPolyElement::GetGeometryBounds(Rect* aBounds,
     93                                       const StrokeOptions& aStrokeOptions,
     94                                       const Matrix& aToBoundsSpace,
     95                                       const Matrix* aToNonScalingStrokeSpace) {
     96  const SVGPointList& points = mPoints.GetAnimValue();
     97 
     98  if (points.IsEmpty()) {
     99    // Rendering of the element is disabled
    100    aBounds->SetEmpty();
    101    return true;
    102  }
    103 
    104  if (aStrokeOptions.mLineWidth > 0 || aToNonScalingStrokeSpace) {
    105    // We don't handle non-scaling-stroke or stroke-miterlimit etc. yet
    106    return false;
    107  }
    108 
    109  float zoom = UserSpaceMetrics::GetZoom(this);
    110 
    111  if (aToBoundsSpace.IsRectilinear()) {
    112    // We can avoid transforming each point and just transform the result.
    113    // Important for large point lists.
    114 
    115    Rect bounds(Point(points[0]) * zoom, Size());
    116    for (uint32_t i = 1; i < points.Length(); ++i) {
    117      bounds.ExpandToEnclose(Point(points[i]) * zoom);
    118    }
    119    *aBounds = aToBoundsSpace.TransformBounds(bounds);
    120  } else {
    121    *aBounds =
    122        Rect(aToBoundsSpace.TransformPoint(Point(points[0]) * zoom), Size());
    123    for (uint32_t i = 1; i < points.Length(); ++i) {
    124      aBounds->ExpandToEnclose(
    125          aToBoundsSpace.TransformPoint(Point(points[i]) * zoom));
    126    }
    127  }
    128  return aBounds->IsFinite();
    129 }
    130 }  // namespace mozilla::dom