tor-browser

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

SVGMarkerElement.cpp (7378B)


      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/SVGMarkerElement.h"
      8 
      9 #include "DOMSVGAngle.h"
     10 #include "SVGAnimatedPreserveAspectRatio.h"
     11 #include "SVGContentUtils.h"
     12 #include "mozilla/dom/SVGGeometryElement.h"
     13 #include "mozilla/dom/SVGLengthBinding.h"
     14 #include "mozilla/dom/SVGMarkerElementBinding.h"
     15 #include "mozilla/gfx/Matrix.h"
     16 #include "nsError.h"
     17 #include "nsGkAtoms.h"
     18 
     19 using namespace mozilla::gfx;
     20 using namespace mozilla::dom::SVGMarkerElement_Binding;
     21 
     22 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
     23 
     24 namespace mozilla::dom {
     25 
     26 using namespace SVGAngle_Binding;
     27 
     28 JSObject* SVGMarkerElement::WrapNode(JSContext* aCx,
     29                                     JS::Handle<JSObject*> aGivenProto) {
     30  return SVGMarkerElement_Binding::Wrap(aCx, this, aGivenProto);
     31 }
     32 
     33 SVGElement::LengthInfo SVGMarkerElement::sLengthInfo[4] = {
     34    {nsGkAtoms::refX, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     35     SVGContentUtils::X},
     36    {nsGkAtoms::refY, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     37     SVGContentUtils::Y},
     38    {nsGkAtoms::markerWidth, 3, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     39     SVGContentUtils::X},
     40    {nsGkAtoms::markerHeight, 3, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
     41     SVGContentUtils::Y},
     42 };
     43 
     44 SVGEnumMapping SVGMarkerElement::sUnitsMap[] = {
     45    {nsGkAtoms::strokeWidth, SVG_MARKERUNITS_STROKEWIDTH},
     46    {nsGkAtoms::userSpaceOnUse, SVG_MARKERUNITS_USERSPACEONUSE},
     47    {nullptr, 0}};
     48 
     49 SVGElement::EnumInfo SVGMarkerElement::sEnumInfo[1] = {
     50    {nsGkAtoms::markerUnits, sUnitsMap, SVG_MARKERUNITS_STROKEWIDTH}};
     51 
     52 //----------------------------------------------------------------------
     53 // Implementation
     54 
     55 SVGMarkerElement::SVGMarkerElement(
     56    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     57    : SVGMarkerElementBase(std::move(aNodeInfo)), mCoordCtx(nullptr) {}
     58 
     59 //----------------------------------------------------------------------
     60 // nsINode methods
     61 
     62 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement)
     63 
     64 //----------------------------------------------------------------------
     65 
     66 already_AddRefed<SVGAnimatedRect> SVGMarkerElement::ViewBox() {
     67  return mViewBox.ToSVGAnimatedRect(this);
     68 }
     69 
     70 already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
     71 SVGMarkerElement::PreserveAspectRatio() {
     72  return mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(this);
     73 }
     74 
     75 //----------------------------------------------------------------------
     76 
     77 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::RefX() {
     78  return mLengthAttributes[REFX].ToDOMAnimatedLength(this);
     79 }
     80 
     81 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::RefY() {
     82  return mLengthAttributes[REFY].ToDOMAnimatedLength(this);
     83 }
     84 
     85 already_AddRefed<DOMSVGAnimatedEnumeration> SVGMarkerElement::MarkerUnits() {
     86  return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(this);
     87 }
     88 
     89 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::MarkerWidth() {
     90  return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(this);
     91 }
     92 
     93 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::MarkerHeight() {
     94  return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(this);
     95 }
     96 
     97 already_AddRefed<DOMSVGAnimatedEnumeration> SVGMarkerElement::OrientType() {
     98  return mOrient.ToDOMAnimatedEnum(this);
     99 }
    100 
    101 already_AddRefed<DOMSVGAnimatedAngle> SVGMarkerElement::OrientAngle() {
    102  return mOrient.ToDOMAnimatedAngle(this);
    103 }
    104 
    105 void SVGMarkerElement::SetOrientToAuto() {
    106  mOrient.SetBaseType(SVG_MARKER_ORIENT_AUTO, this, IgnoreErrors());
    107 }
    108 
    109 void SVGMarkerElement::SetOrientToAngle(DOMSVGAngle& aAngle) {
    110  nsAutoString angle;
    111  aAngle.GetValueAsString(angle);
    112  mOrient.SetBaseValueString(angle, this, true);
    113 }
    114 
    115 //----------------------------------------------------------------------
    116 // SVGElement methods
    117 
    118 void SVGMarkerElement::SetParentCoordCtxProvider(SVGViewportElement* aContext) {
    119  mCoordCtx = aContext;
    120  mViewBoxToViewportTransform = nullptr;
    121 }
    122 
    123 /* virtual */
    124 bool SVGMarkerElement::HasValidDimensions() const {
    125  return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() ||
    126          mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) &&
    127         (!mLengthAttributes[MARKERHEIGHT].IsExplicitlySet() ||
    128          mLengthAttributes[MARKERHEIGHT].GetAnimValInSpecifiedUnits() > 0);
    129 }
    130 
    131 SVGElement::LengthAttributesInfo SVGMarkerElement::GetLengthInfo() {
    132  return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
    133                              std::size(sLengthInfo));
    134 }
    135 
    136 SVGElement::EnumAttributesInfo SVGMarkerElement::GetEnumInfo() {
    137  return EnumAttributesInfo(mEnumAttributes, sEnumInfo, std::size(sEnumInfo));
    138 }
    139 
    140 SVGAnimatedOrient* SVGMarkerElement::GetAnimatedOrient() { return &mOrient; }
    141 
    142 SVGAnimatedViewBox* SVGMarkerElement::GetAnimatedViewBox() { return &mViewBox; }
    143 
    144 SVGAnimatedPreserveAspectRatio*
    145 SVGMarkerElement::GetAnimatedPreserveAspectRatio() {
    146  return &mPreserveAspectRatio;
    147 }
    148 
    149 //----------------------------------------------------------------------
    150 // public helpers
    151 
    152 gfx::Matrix SVGMarkerElement::GetMarkerTransform(float aStrokeWidth,
    153                                                 const SVGMark& aMark) {
    154  float scale =
    155      mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH
    156          ? aStrokeWidth
    157          : 1.0f;
    158 
    159  float angle;
    160  switch (mOrient.GetAnimType()) {
    161    case SVG_MARKER_ORIENT_AUTO:
    162      angle = aMark.angle;
    163      break;
    164    case SVG_MARKER_ORIENT_AUTO_START_REVERSE:
    165      angle = aMark.angle + (aMark.type == SVGMark::eStart ? M_PI : 0.0f);
    166      break;
    167    default:  // SVG_MARKER_ORIENT_ANGLE
    168      angle = mOrient.GetAnimValue() * M_PI / 180.0f;
    169      break;
    170  }
    171 
    172  return gfx::Matrix(cos(angle) * scale, sin(angle) * scale,
    173                     -sin(angle) * scale, cos(angle) * scale, aMark.x, aMark.y);
    174 }
    175 
    176 SVGViewBox SVGMarkerElement::GetViewBox() {
    177  if (mViewBox.HasRect()) {
    178    float zoom = UserSpaceMetrics::GetZoom(this);
    179    return mViewBox.GetAnimValue() * zoom;
    180  }
    181  return SVGViewBox(
    182      0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx),
    183      mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx));
    184 }
    185 
    186 gfx::Matrix SVGMarkerElement::GetViewBoxTransform() {
    187  if (!mViewBoxToViewportTransform) {
    188    float viewportWidth =
    189        mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx);
    190    float viewportHeight =
    191        mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx);
    192 
    193    SVGViewBox viewbox = GetViewBox();
    194 
    195    MOZ_ASSERT(viewbox.width > 0.0f && viewbox.height > 0.0f,
    196               "Rendering should be disabled");
    197 
    198    gfx::Matrix viewBoxTM = SVGContentUtils::GetViewBoxTransform(
    199        viewportWidth, viewportHeight, viewbox.x, viewbox.y, viewbox.width,
    200        viewbox.height, mPreserveAspectRatio);
    201 
    202    float refX = mLengthAttributes[REFX].GetAnimValueWithZoom(mCoordCtx);
    203    float refY = mLengthAttributes[REFY].GetAnimValueWithZoom(mCoordCtx);
    204 
    205    gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY));
    206 
    207    Matrix TM = viewBoxTM;
    208    TM.PostTranslate(-ref.x, -ref.y);
    209 
    210    mViewBoxToViewportTransform = MakeUnique<gfx::Matrix>(TM);
    211  }
    212 
    213  return *mViewBoxToViewportTransform;
    214 }
    215 
    216 }  // namespace mozilla::dom