DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/dom/SVGFETurbulenceElement.h"
#include "mozilla/dom/SVGFETurbulenceElementBinding.h"
#include "nsSVGFilterInstance.h"
#include "nsSVGUtils.h"

NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)

using namespace mozilla::gfx;

namespace mozilla {
namespace dom {

// Stitch Options
static const unsigned short SVG_STITCHTYPE_STITCH = 1;
static const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;

static const int32_t MAX_OCTAVES = 10;

JSObject* SVGFETurbulenceElement::WrapNode(JSContext* aCx,
                                           JS::Handle<JSObject*> aGivenProto) {
  return SVGFETurbulenceElement_Binding::Wrap(aCx, this, aGivenProto);
}

SVGElement::NumberInfo SVGFETurbulenceElement::sNumberInfo[1] = {
    {nsGkAtoms::seed, 0, false}};

SVGElement::NumberPairInfo SVGFETurbulenceElement::sNumberPairInfo[1] = {
    {nsGkAtoms::baseFrequency, 0, 0}};

SVGElement::IntegerInfo SVGFETurbulenceElement::sIntegerInfo[1] = {
    {nsGkAtoms::numOctaves, 1}};

SVGEnumMapping SVGFETurbulenceElement::sTypeMap[] = {
    {nsGkAtoms::fractalNoise, SVG_TURBULENCE_TYPE_FRACTALNOISE},
    {nsGkAtoms::turbulence, SVG_TURBULENCE_TYPE_TURBULENCE},
    {nullptr, 0}};

SVGEnumMapping SVGFETurbulenceElement::sStitchTilesMap[] = {
    {nsGkAtoms::stitch, SVG_STITCHTYPE_STITCH},
    {nsGkAtoms::noStitch, SVG_STITCHTYPE_NOSTITCH},
    {nullptr, 0}};

SVGElement::EnumInfo SVGFETurbulenceElement::sEnumInfo[2] = {
    {nsGkAtoms::type, sTypeMap, SVG_TURBULENCE_TYPE_TURBULENCE},
    {nsGkAtoms::stitchTiles, sStitchTilesMap, SVG_STITCHTYPE_NOSTITCH}};

SVGElement::StringInfo SVGFETurbulenceElement::sStringInfo[1] = {
    {nsGkAtoms::result, kNameSpaceID_None, true}};

//----------------------------------------------------------------------
// nsINode methods

NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement)

//----------------------------------------------------------------------

already_AddRefed<DOMSVGAnimatedNumber>
SVGFETurbulenceElement::BaseFrequencyX() {
  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(
      SVGAnimatedNumberPair::eFirst, this);
}

already_AddRefed<DOMSVGAnimatedNumber>
SVGFETurbulenceElement::BaseFrequencyY() {
  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(
      SVGAnimatedNumberPair::eSecond, this);
}

already_AddRefed<DOMSVGAnimatedInteger> SVGFETurbulenceElement::NumOctaves() {
  return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(this);
}

already_AddRefed<DOMSVGAnimatedNumber> SVGFETurbulenceElement::Seed() {
  return mNumberAttributes[SEED].ToDOMAnimatedNumber(this);
}

already_AddRefed<DOMSVGAnimatedEnumeration>
SVGFETurbulenceElement::StitchTiles() {
  return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(this);
}

already_AddRefed<DOMSVGAnimatedEnumeration> SVGFETurbulenceElement::Type() {
  return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this);
}

FilterPrimitiveDescription SVGFETurbulenceElement::GetPrimitiveDescription(
    nsSVGFilterInstance* aInstance, const IntRect& aFilterSubregion,
    const nsTArray<bool>& aInputsAreTainted,
    nsTArray<RefPtr<SourceSurface>>& aInputImages) {
  float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(
      SVGAnimatedNumberPair::eFirst);
  float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(
      SVGAnimatedNumberPair::eSecond);
  float seed = mNumberAttributes[OCTAVES].GetAnimValue();
  uint32_t octaves =
      clamped(mIntegerAttributes[OCTAVES].GetAnimValue(), 0, MAX_OCTAVES);
  uint32_t type = mEnumAttributes[TYPE].GetAnimValue();
  uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue();

  if (fX == 0 && fY == 0) {
    // A base frequency of zero results in transparent black for
    // type="turbulence" and in 50% alpha 50% gray for type="fractalNoise".
    if (type == SVG_TURBULENCE_TYPE_TURBULENCE) {
      return FilterPrimitiveDescription();
    }
    FloodAttributes atts;
    atts.mColor = Color(0.5, 0.5, 0.5, 0.5);
    return FilterPrimitiveDescription(AsVariant(std::move(atts)));
  }

  // We interpret the base frequency as relative to user space units. In other
  // words, we consider one turbulence base period to be 1 / fX user space
  // units wide and 1 / fY user space units high. We do not scale the frequency
  // depending on the filter primitive region.
  // We now convert the frequency from user space to filter space.
  // If a frequency in user space units is zero, then it will also be zero in
  // filter space. During the conversion we use a dummy period length of 1
  // for those frequencies but then ignore the converted length and use 0
  // for the converted frequency. This avoids division by zero.
  gfxRect firstPeriodInUserSpace(0, 0, fX == 0 ? 1 : (1 / fX),
                                 fY == 0 ? 1 : (1 / fY));
  gfxRect firstPeriodInFilterSpace =
      aInstance->UserSpaceToFilterSpace(firstPeriodInUserSpace);
  Size frequencyInFilterSpace(
      fX == 0 ? 0 : (1 / firstPeriodInFilterSpace.width),
      fY == 0 ? 0 : (1 / firstPeriodInFilterSpace.height));
  gfxPoint offset = firstPeriodInFilterSpace.TopLeft();

  TurbulenceAttributes atts;
  atts.mOffset = IntPoint::Truncate(offset.x, offset.y);
  atts.mBaseFrequency = frequencyInFilterSpace;
  atts.mSeed = seed;
  atts.mOctaves = octaves;
  atts.mStitchable = stitch == SVG_STITCHTYPE_STITCH;
  atts.mType = type;
  return FilterPrimitiveDescription(AsVariant(std::move(atts)));
}

bool SVGFETurbulenceElement::AttributeAffectsRendering(
    int32_t aNameSpaceID, nsAtom* aAttribute) const {
  return SVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID,
                                                               aAttribute) ||
         (aNameSpaceID == kNameSpaceID_None &&
          (aAttribute == nsGkAtoms::seed ||
           aAttribute == nsGkAtoms::baseFrequency ||
           aAttribute == nsGkAtoms::numOctaves ||
           aAttribute == nsGkAtoms::type ||
           aAttribute == nsGkAtoms::stitchTiles));
}

//----------------------------------------------------------------------
// SVGElement methods

SVGElement::NumberAttributesInfo SVGFETurbulenceElement::GetNumberInfo() {
  return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                              ArrayLength(sNumberInfo));
}

SVGElement::NumberPairAttributesInfo
SVGFETurbulenceElement::GetNumberPairInfo() {
  return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
                                  ArrayLength(sNumberPairInfo));
}

SVGElement::IntegerAttributesInfo SVGFETurbulenceElement::GetIntegerInfo() {
  return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
                               ArrayLength(sIntegerInfo));
}

SVGElement::EnumAttributesInfo SVGFETurbulenceElement::GetEnumInfo() {
  return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo));
}

SVGElement::StringAttributesInfo SVGFETurbulenceElement::GetStringInfo() {
  return StringAttributesInfo(mStringAttributes, sStringInfo,
                              ArrayLength(sStringInfo));
}

}  // namespace dom
}  // namespace mozilla