mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
202
dom/svg/SVGFragmentIdentifier.cpp
Normal file
202
dom/svg/SVGFragmentIdentifier.cpp
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/* -*- 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 "SVGFragmentIdentifier.h"
|
||||
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "mozilla/dom/SVGViewElement.h"
|
||||
#include "nsContentUtils.h" // for nsCharSeparatedTokenizerTemplate
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
static bool
|
||||
IsMatchingParameter(const nsAString& aString, const nsAString& aParameterName)
|
||||
{
|
||||
// The first two tests ensure aString.Length() > aParameterName.Length()
|
||||
// so it's then safe to do the third test
|
||||
return StringBeginsWith(aString, aParameterName) &&
|
||||
aString.Last() == ')' &&
|
||||
aString.CharAt(aParameterName.Length()) == '(';
|
||||
}
|
||||
|
||||
inline bool
|
||||
IgnoreWhitespace(char16_t aChar)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static SVGViewElement*
|
||||
GetViewElement(nsIDocument* aDocument, const nsAString& aId)
|
||||
{
|
||||
Element* element = aDocument->GetElementById(aId);
|
||||
return (element && element->IsSVGElement(nsGkAtoms::view)) ?
|
||||
static_cast<SVGViewElement*>(element) : nullptr;
|
||||
}
|
||||
|
||||
// Handles setting/clearing the root's mSVGView pointer.
|
||||
class MOZ_RAII AutoSVGViewHandler
|
||||
{
|
||||
public:
|
||||
explicit AutoSVGViewHandler(SVGSVGElement* aRoot
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mRoot(aRoot), mValid(false) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
mWasOverridden = mRoot->UseCurrentView();
|
||||
mRoot->mSVGView = nullptr;
|
||||
mRoot->mCurrentViewID = nullptr;
|
||||
}
|
||||
|
||||
~AutoSVGViewHandler() {
|
||||
if (!mWasOverridden && !mValid) {
|
||||
// we weren't overridden before and we aren't
|
||||
// overridden now so nothing has changed.
|
||||
return;
|
||||
}
|
||||
if (mValid) {
|
||||
mRoot->mSVGView = mSVGView;
|
||||
}
|
||||
mRoot->InvalidateTransformNotifyFrame();
|
||||
}
|
||||
|
||||
void CreateSVGView() {
|
||||
MOZ_ASSERT(!mSVGView, "CreateSVGView should not be called multiple times");
|
||||
mSVGView = new SVGView();
|
||||
}
|
||||
|
||||
bool ProcessAttr(const nsAString& aToken, const nsAString &aParams) {
|
||||
|
||||
MOZ_ASSERT(mSVGView, "CreateSVGView should have been called");
|
||||
|
||||
// SVGViewAttributes may occur in any order, but each type may only occur
|
||||
// at most one time in a correctly formed SVGViewSpec.
|
||||
// If we encounter any attribute more than once or get any syntax errors
|
||||
// we're going to return false and cancel any changes.
|
||||
|
||||
if (IsMatchingParameter(aToken, NS_LITERAL_STRING("viewBox"))) {
|
||||
if (mSVGView->mViewBox.IsExplicitlySet() ||
|
||||
NS_FAILED(mSVGView->mViewBox.SetBaseValueString(
|
||||
aParams, mRoot, false))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("preserveAspectRatio"))) {
|
||||
if (mSVGView->mPreserveAspectRatio.IsExplicitlySet() ||
|
||||
NS_FAILED(mSVGView->mPreserveAspectRatio.SetBaseValueString(
|
||||
aParams, mRoot, false))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("transform"))) {
|
||||
if (mSVGView->mTransforms) {
|
||||
return false;
|
||||
}
|
||||
mSVGView->mTransforms = new nsSVGAnimatedTransformList();
|
||||
if (NS_FAILED(mSVGView->mTransforms->SetBaseValueString(aParams))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("zoomAndPan"))) {
|
||||
if (mSVGView->mZoomAndPan.IsExplicitlySet()) {
|
||||
return false;
|
||||
}
|
||||
nsIAtom* valAtom = NS_GetStaticAtom(aParams);
|
||||
if (!valAtom ||
|
||||
NS_FAILED(mSVGView->mZoomAndPan.SetBaseValueAtom(
|
||||
valAtom, mRoot))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// We don't support viewTarget currently
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetValid() {
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
private:
|
||||
SVGSVGElement* mRoot;
|
||||
nsAutoPtr<SVGView> mSVGView;
|
||||
bool mValid;
|
||||
bool mWasOverridden;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
bool
|
||||
SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString& aViewSpec,
|
||||
SVGSVGElement* aRoot)
|
||||
{
|
||||
AutoSVGViewHandler viewHandler(aRoot);
|
||||
|
||||
if (!IsMatchingParameter(aViewSpec, NS_LITERAL_STRING("svgView"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Each token is a SVGViewAttribute
|
||||
int32_t bracketPos = aViewSpec.FindChar('(');
|
||||
uint32_t lengthOfViewSpec = aViewSpec.Length() - bracketPos - 2;
|
||||
nsCharSeparatedTokenizerTemplate<IgnoreWhitespace> tokenizer(
|
||||
Substring(aViewSpec, bracketPos + 1, lengthOfViewSpec), ';');
|
||||
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
return false;
|
||||
}
|
||||
viewHandler.CreateSVGView();
|
||||
|
||||
do {
|
||||
|
||||
nsAutoString token(tokenizer.nextToken());
|
||||
|
||||
bracketPos = token.FindChar('(');
|
||||
if (bracketPos < 1 || token.Last() != ')') {
|
||||
// invalid SVGViewAttribute syntax
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsAString ¶ms =
|
||||
Substring(token, bracketPos + 1, token.Length() - bracketPos - 2);
|
||||
|
||||
if (!viewHandler.ProcessAttr(token, params)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} while (tokenizer.hasMoreTokens());
|
||||
|
||||
viewHandler.SetValid();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument* aDocument,
|
||||
const nsAString& aAnchorName)
|
||||
{
|
||||
MOZ_ASSERT(aDocument->GetRootElement()->IsSVGElement(nsGkAtoms::svg),
|
||||
"expecting an SVG root element");
|
||||
|
||||
SVGSVGElement* rootElement =
|
||||
static_cast<SVGSVGElement*>(aDocument->GetRootElement());
|
||||
|
||||
const SVGViewElement* viewElement = GetViewElement(aDocument, aAnchorName);
|
||||
|
||||
if (viewElement) {
|
||||
if (!rootElement->mCurrentViewID) {
|
||||
rootElement->mCurrentViewID = new nsString();
|
||||
}
|
||||
*rootElement->mCurrentViewID = aAnchorName;
|
||||
rootElement->mSVGView = nullptr;
|
||||
rootElement->InvalidateTransformNotifyFrame();
|
||||
// not an svgView()-style fragment identifier, return false so the caller
|
||||
// continues processing to match any :target pseudo elements
|
||||
return false;
|
||||
}
|
||||
|
||||
return ProcessSVGViewSpec(aAnchorName, rootElement);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
Loading…
Add table
Add a link
Reference in a new issue