/*
 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2010 Rob Buis <buis@kde.org>
 * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
 * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

// FIXME: no css::ViewCSS available!
// FIXME: Fix SVGSVGElement inheritance (css::DocumentCSS)!
// FIXME: no events::DocumentEvent available!

[
    JSGenerateToNativeObject,
    ExportMacro=WEBCORE_EXPORT,
] interface SVGSVGElement : SVGGraphicsElement {
    [SameObject] readonly attribute SVGAnimatedLength x;
    [SameObject] readonly attribute SVGAnimatedLength y;
    [SameObject] readonly attribute SVGAnimatedLength width;
    [SameObject] readonly attribute SVGAnimatedLength height;

    attribute unrestricted float currentScale;
    [SameObject] readonly attribute SVGPoint currentTranslate;
    
    readonly attribute boolean useCurrentView;
    readonly attribute SVGViewSpec currentView;

    NodeList getIntersectionList(SVGRect rect, SVGElement? referenceElement);
    NodeList getEnclosureList(SVGRect rect, SVGElement? referenceElement);
    boolean checkIntersection(SVGElement element, SVGRect rect);
    boolean checkEnclosure(SVGElement element, SVGRect rect);

    void deselectAll();

    [NewObject] SVGNumber createSVGNumber();
    [NewObject] SVGLength createSVGLength();
    [NewObject] SVGAngle createSVGAngle();
    [NewObject] SVGPoint createSVGPoint();
    [NewObject] SVGMatrix createSVGMatrix();
    [NewObject] SVGRect createSVGRect();
    [NewObject] SVGTransform createSVGTransform();
    [NewObject] SVGTransform createSVGTransformFromMatrix(optional DOMMatrix2DInit matrix);

    Element getElementById([RequiresExistingAtomString] DOMString elementId);

    // SVG animations extensions
    // https://svgwg.org/specs/animations/#InterfaceSVGSVGElement
    void pauseAnimations();
    void unpauseAnimations();
    boolean animationsPaused();
    unrestricted float getCurrentTime();
    void setCurrentTime(optional unrestricted float seconds = NaN);

    // Deprecated SVG redrawing
    unsigned long suspendRedraw(optional unsigned long maxWaitMilliseconds = 0);
    void unsuspendRedraw(optional unsigned long suspendHandleId = 0);
    void unsuspendRedrawAll();
    void forceRedraw();
};

SVGSVGElement implements SVGFitToViewBox;
SVGSVGElement implements SVGZoomAndPan;
