Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/svg/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 8 kB image not shown  

Quelle  SVGAnimatedViewBox.cpp

  Sprache: C
 

/* 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 "SVGAnimatedViewBox.h"

#include <utility>

#include "SVGViewBoxSMILType.h"
#include "mozAutoDocUpdate.h"
#include "mozilla/Maybe.h"
#include "mozilla/SMILValue.h"
#include "mozilla/SVGContentUtils.h"
#include "mozilla/dom/SVGRect.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsTextFormatter.h"

using namespace mozilla::dom;

namespace mozilla {

#define NUM_VIEWBOX_COMPONENTS 4

/* Implementation of SVGViewBox methods */

bool SVGViewBox::operator==(const SVGViewBox& aOther) const {
  if (&aOther == thisreturn true;

  return (none && aOther.none) ||
         (!none && !aOther.none && x == aOther.x && y == aOther.y &&
          width == aOther.width && height == aOther.height);
}

/* static */
nsresult SVGViewBox::FromString(const nsAString& aStr, SVGViewBox* aViewBox) {
  if (aStr.EqualsLiteral("none")) {
    aViewBox->none = true;
    return NS_OK;
  }

  nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace,
                                   nsTokenizerFlags::SeparatorOptional>
      tokenizer(aStr, ',');
  float vals[NUM_VIEWBOX_COMPONENTS];
  uint32_t i;
  for (i = 0; i < NUM_VIEWBOX_COMPONENTS && tokenizer.hasMoreTokens(); ++i) {
    if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), vals[i])) {
      return NS_ERROR_DOM_SYNTAX_ERR;
    }
  }

  if (i != NUM_VIEWBOX_COMPONENTS ||             // Too few values.
      tokenizer.hasMoreTokens() ||               // Too many values.
      tokenizer.separatorAfterCurrentToken()) {  // Trailing comma.
    return NS_ERROR_DOM_SYNTAX_ERR;
  }

  aViewBox->x = vals[0];
  aViewBox->y = vals[1];
  aViewBox->width = vals[2];
  aViewBox->height = vals[3];
  aViewBox->none = false;

  return NS_OK;
}

constinit static SVGAttrTearoffTable<SVGAnimatedViewBox, SVGRect>
    sBaseSVGViewBoxTearoffTable;
constinit static SVGAttrTearoffTable<SVGAnimatedViewBox, SVGRect>
    sAnimSVGViewBoxTearoffTable;
constinit SVGAttrTearoffTable<SVGAnimatedViewBox, SVGAnimatedRect>
    SVGAnimatedViewBox::sSVGAnimatedRectTearoffTable;

//----------------------------------------------------------------------
// Helper class: AutoChangeViewBoxNotifier
// Stack-based helper class to pair calls to WillChangeViewBox and
// DidChangeViewBox.
class MOZ_RAII AutoChangeViewBoxNotifier {
 public:
  AutoChangeViewBoxNotifier(SVGAnimatedViewBox* aViewBox,
                            SVGElement* aSVGElement, bool aDoSetAttr = true)
      : mViewBox(aViewBox), mSVGElement(aSVGElement), mDoSetAttr(aDoSetAttr) {
    MOZ_ASSERT(mViewBox, "Expecting non-null viewBox");
    MOZ_ASSERT(mSVGElement, "Expecting non-null element");

    if (mDoSetAttr) {
      mUpdateBatch.emplace(aSVGElement->GetComposedDoc(), true);
      mSVGElement->WillChangeViewBox(mUpdateBatch.ref());
    }
  }

  ~AutoChangeViewBoxNotifier() {
    if (mDoSetAttr) {
      mSVGElement->DidChangeViewBox(mUpdateBatch.ref());
    }
    if (mViewBox->mAnimVal) {
      mSVGElement->AnimationNeedsResample();
    }
  }

 private:
  SVGAnimatedViewBox* const mViewBox;
  SVGElement* const mSVGElement;
  Maybe<mozAutoDocUpdate> mUpdateBatch;
  bool mDoSetAttr;
};

/* Implementation of SVGAnimatedViewBox methods */

void SVGAnimatedViewBox::Init() {
  mHasBaseVal = false;
  // Default-construct to {0, 0, 0, 0, none=true} so that x/y/width/height
  // read back as 0 via SVGAnimatedRect when the viewBox attribute is unset
  // (matching the behavior other UAs expose to script).
  mBaseVal = SVGViewBox();

  mAnimVal = nullptr;
}

bool SVGAnimatedViewBox::HasRect() const {
  // Check mAnimVal if we have one; otherwise, check mBaseVal if we have one;
  // otherwise, just return false (we clearly do not have a rect).
  const SVGViewBox* rect = mAnimVal.get();
  if (!rect) {
    if (!mHasBaseVal) {
      // no anim val, no base val --> no viewbox rect
      return false;
    }
    rect = &mBaseVal;
  }

  return !rect->none && rect->width >= 0 && rect->height >= 0;
}

void SVGAnimatedViewBox::SetAnimValue(const SVGViewBox& aRect,
                                      SVGElement* aSVGElement) {
  if (!mAnimVal) {
    // it's okay if allocation fails - and no point in reporting that
    mAnimVal = std::make_unique<SVGViewBox>(aRect);
  } else {
    if (aRect == *mAnimVal) {
      return;
    }
    *mAnimVal = aRect;
  }
  aSVGElement->DidAnimateViewBox();
}

void SVGAnimatedViewBox::SetBaseField(float aValue, SVGElement* aSVGElement,
                                      float& aField) {
  if (!mHasBaseVal) {
    aField = aValue;
    return;
  }
  // If the current base value is "none", writing any field transitions the
  // viewBox to a numerical rect, so we must notify (and clear |none|) even
  // when this field's value happens to be unchanged.
  if (!mBaseVal.none && aField == aValue) {
    return;
  }
  AutoChangeViewBoxNotifier notifier(this, aSVGElement);
  aField = aValue;
  mBaseVal.none = false;
}

void SVGAnimatedViewBox::SetBaseValue(const SVGViewBox& aRect,
                                      SVGElement* aSVGElement,
                                      bool aDoSetAttr) {
  // Comparison against mBaseVal is only valid if we currently have a base val.
  if (mHasBaseVal && mBaseVal == aRect) {
    return;
  }

  AutoChangeViewBoxNotifier notifier(this, aSVGElement, aDoSetAttr);

  mBaseVal = aRect;
  mHasBaseVal = true;
}

nsresult SVGAnimatedViewBox::SetBaseValueString(const nsAString& aValue,
                                                SVGElement* aSVGElement,
                                                bool aDoSetAttr) {
  SVGViewBox viewBox;

  nsresult rv = SVGViewBox::FromString(aValue, &viewBox);
  if (NS_FAILED(rv)) {
    return rv;
  }
  SetBaseValue(viewBox, aSVGElement, aDoSetAttr);
  return NS_OK;
}

void SVGAnimatedViewBox::GetBaseValueString(nsAString& aValue) const {
  if (mBaseVal.none) {
    aValue.AssignLiteral("none");
    return;
  }
  nsTextFormatter::ssprintf(aValue, u"%g %g %g %g", (double)mBaseVal.x,
                            (double)mBaseVal.y, (double)mBaseVal.width,
                            (double)mBaseVal.height);
}

already_AddRefed<SVGAnimatedRect> SVGAnimatedViewBox::ToSVGAnimatedRect(
    SVGElement* aSVGElement) {
  RefPtr<SVGAnimatedRect> domAnimatedRect =
      sSVGAnimatedRectTearoffTable.GetTearoff(this);
  if (!domAnimatedRect) {
    domAnimatedRect = new SVGAnimatedRect(this, aSVGElement);
    sSVGAnimatedRectTearoffTable.AddTearoff(this, domAnimatedRect);
  }

  return domAnimatedRect.forget();
}

MovingNotNull<RefPtr<SVGRect>> SVGAnimatedViewBox::ToDOMBaseVal(
    SVGElement* aSVGElement) {
  RefPtr<SVGRect> domBaseVal = sBaseSVGViewBoxTearoffTable.GetTearoff(this);
  if (!domBaseVal) {
    domBaseVal = new SVGRect(this, aSVGElement, SVGRect::RectType::BaseValue);
    sBaseSVGViewBoxTearoffTable.AddTearoff(this, domBaseVal);
  }

  return WrapMovingNotNull(std::move(domBaseVal));
}

SVGRect::~SVGRect() {
  switch (mType) {
    case RectType::BaseValue:
      sBaseSVGViewBoxTearoffTable.RemoveTearoff(mVal);
      break;
    case RectType::AnimValue:
      sAnimSVGViewBoxTearoffTable.RemoveTearoff(mVal);
      break;
    default:
      break;
  }
}

MovingNotNull<RefPtr<SVGRect>> SVGAnimatedViewBox::ToDOMAnimVal(
    SVGElement* aSVGElement) {
  RefPtr<SVGRect> domAnimVal = sAnimSVGViewBoxTearoffTable.GetTearoff(this);
  if (!domAnimVal) {
    domAnimVal = new SVGRect(this, aSVGElement, SVGRect::RectType::AnimValue);
    sAnimSVGViewBoxTearoffTable.AddTearoff(this, domAnimVal);
  }

  return WrapMovingNotNull(std::move(domAnimVal));
}

std::unique_ptr<SMILAttr> SVGAnimatedViewBox::ToSMILAttr(
    SVGElement* aSVGElement) {
  return std::make_unique<SMILViewBox>(this, aSVGElement);
}

nsresult SVGAnimatedViewBox::SMILViewBox ::ValueFromString(
    const nsAString& aStr, const SVGAnimationElement* /*aSrcElement*/,
    SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
  SVGViewBox viewBox;
  nsresult res = SVGViewBox::FromString(aStr, &viewBox);
  if (NS_FAILED(res)) {
    return res;
  }
  SMILValue val(&SVGViewBoxSMILType::sSingleton);
  *static_cast<SVGViewBox*>(val.mU.mPtr) = viewBox;
  aValue = std::move(val);

  return NS_OK;
}

SMILValue SVGAnimatedViewBox::SMILViewBox::GetBaseValue() const {
  SMILValue val(&SVGViewBoxSMILType::sSingleton);
  *static_cast<SVGViewBox*>(val.mU.mPtr) = mVal->mBaseVal;
  return val;
}

void SVGAnimatedViewBox::SMILViewBox::ClearAnimValue() {
  if (mVal->mAnimVal) {
    mVal->mAnimVal = nullptr;
    mSVGElement->DidAnimateViewBox();
  }
}

nsresult SVGAnimatedViewBox::SMILViewBox::SetAnimValue(
    const SMILValue& aValue) {
  NS_ASSERTION(aValue.mType == &SVGViewBoxSMILType::sSingleton,
               "Unexpected type to assign animated value");
  if (aValue.mType == &SVGViewBoxSMILType::sSingleton) {
    SVGViewBox& vb = *static_cast<SVGViewBox*>(aValue.mU.mPtr);
    mVal->SetAnimValue(vb, mSVGElement);
  }
  return NS_OK;
}

}  // namespace mozilla

Messung V0.5 in Prozent
C=92 H=99 G=95

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-24) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.