tor-browser

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

SVGCircleElement.cpp (5878B)


      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 "mozilla/dom/SVGCircleElement.h"
      8 
      9 #include "ComputedStyle.h"
     10 #include "SVGGeometryProperty.h"
     11 #include "mozilla/dom/SVGCircleElementBinding.h"
     12 #include "mozilla/dom/SVGLengthBinding.h"
     13 #include "mozilla/gfx/2D.h"
     14 #include "nsGkAtoms.h"
     15 
     16 NS_IMPL_NS_NEW_SVG_ELEMENT(Circle)
     17 
     18 using namespace mozilla::gfx;
     19 
     20 namespace mozilla::dom {
     21 
     22 JSObject* SVGCircleElement::WrapNode(JSContext* aCx,
     23                                     JS::Handle<JSObject*> aGivenProto) {
     24  return SVGCircleElement_Binding::Wrap(aCx, this, aGivenProto);
     25 }
     26 
     27 SVGElement::LengthInfo SVGCircleElement::sLengthInfo[3] = {
     28    {nsGkAtoms::cx, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     29     SVGContentUtils::X},
     30    {nsGkAtoms::cy, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     31     SVGContentUtils::Y},
     32    {nsGkAtoms::r, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     33     SVGContentUtils::XY}};
     34 
     35 //----------------------------------------------------------------------
     36 // Implementation
     37 
     38 SVGCircleElement::SVGCircleElement(
     39    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     40    : SVGCircleElementBase(std::move(aNodeInfo)) {}
     41 
     42 bool SVGCircleElement::IsAttributeMapped(const nsAtom* aAttribute) const {
     43  return IsInLengthInfo(aAttribute, sLengthInfo) ||
     44         SVGCircleElementBase::IsAttributeMapped(aAttribute);
     45 }
     46 
     47 namespace SVGT = SVGGeometryProperty::Tags;
     48 
     49 //----------------------------------------------------------------------
     50 // nsINode methods
     51 
     52 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGCircleElement)
     53 
     54 //----------------------------------------------------------------------
     55 
     56 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::Cx() {
     57  return mLengthAttributes[ATTR_CX].ToDOMAnimatedLength(this);
     58 }
     59 
     60 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::Cy() {
     61  return mLengthAttributes[ATTR_CY].ToDOMAnimatedLength(this);
     62 }
     63 
     64 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::R() {
     65  return mLengthAttributes[ATTR_R].ToDOMAnimatedLength(this);
     66 }
     67 
     68 //----------------------------------------------------------------------
     69 // SVGElement methods
     70 
     71 /* virtual */
     72 bool SVGCircleElement::HasValidDimensions() const {
     73  float r;
     74 
     75  if (SVGGeometryProperty::ResolveAll<SVGT::R>(this, &r)) {
     76    return r > 0;
     77  }
     78  // This function might be called for an element in display:none subtree
     79  // (e.g. SMIL animateMotion), we fall back to use SVG attributes.
     80  return mLengthAttributes[ATTR_R].IsExplicitlySet() &&
     81         mLengthAttributes[ATTR_R].GetAnimValInSpecifiedUnits() > 0;
     82 }
     83 
     84 SVGElement::LengthAttributesInfo SVGCircleElement::GetLengthInfo() {
     85  return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
     86                              std::size(sLengthInfo));
     87 }
     88 
     89 //----------------------------------------------------------------------
     90 // SVGGeometryElement methods
     91 
     92 bool SVGCircleElement::GetGeometryBounds(
     93    Rect* aBounds, const StrokeOptions& aStrokeOptions,
     94    const Matrix& aToBoundsSpace, const Matrix* aToNonScalingStrokeSpace) {
     95  float x, y, r;
     96 
     97  DebugOnly<bool> ok =
     98      SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x, &y,
     99                                                                   &r);
    100  MOZ_ASSERT(ok, "SVGGeometryProperty::ResolveAll failed");
    101 
    102  if (r <= 0.f) {
    103    // Rendering of the element is disabled
    104    *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
    105    return true;
    106  }
    107 
    108  if (aToBoundsSpace.IsRectilinear()) {
    109    // Optimize the case where we can treat the circle as a rectangle and
    110    // still get tight bounds.
    111    if (aStrokeOptions.mLineWidth > 0.f) {
    112      if (aToNonScalingStrokeSpace) {
    113        if (aToNonScalingStrokeSpace->IsRectilinear()) {
    114          MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
    115          Rect userBounds(x - r, y - r, 2 * r, 2 * r);
    116          SVGContentUtils::RectilinearGetStrokeBounds(
    117              userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
    118              aStrokeOptions.mLineWidth, aBounds);
    119          return true;
    120        }
    121        return false;
    122      }
    123      r += aStrokeOptions.mLineWidth / 2.f;
    124    }
    125    Rect rect(x - r, y - r, 2 * r, 2 * r);
    126    *aBounds = aToBoundsSpace.TransformBounds(rect);
    127    return true;
    128  }
    129 
    130  return false;
    131 }
    132 
    133 already_AddRefed<Path> SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
    134  float x, y, r;
    135  if (!SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x,
    136                                                                    &y, &r)) {
    137    // This function might be called for element in display:none subtree
    138    // (e.g. getTotalLength), we fall back to use SVG attributes.
    139    GetAnimatedLengthValues(&x, &y, &r, nullptr);
    140  }
    141 
    142  if (r <= 0.0f) {
    143    return nullptr;
    144  }
    145 
    146  aBuilder->Arc(Point(x, y), r, 0, Float(2 * M_PI));
    147 
    148  return aBuilder->Finish();
    149 }
    150 
    151 bool SVGCircleElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
    152                                             const ComputedStyle& aOldStyle) {
    153  const auto& newSVGReset = *aNewStyle.StyleSVGReset();
    154  const auto& oldSVGReset = *aOldStyle.StyleSVGReset();
    155 
    156  return newSVGReset.mCx != oldSVGReset.mCx ||
    157         newSVGReset.mCy != oldSVGReset.mCy || newSVGReset.mR != oldSVGReset.mR;
    158 }
    159 
    160 NonCustomCSSPropertyId SVGCircleElement::GetCSSPropertyIdForAttrEnum(
    161    uint8_t aAttrEnum) {
    162  switch (aAttrEnum) {
    163    case ATTR_CX:
    164      return eCSSProperty_cx;
    165    case ATTR_CY:
    166      return eCSSProperty_cy;
    167    case ATTR_R:
    168      return eCSSProperty_r;
    169    default:
    170      MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
    171      return eCSSProperty_UNKNOWN;
    172  }
    173 }
    174 
    175 }  // namespace mozilla::dom