• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KHTML

SVGSVGElement.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
00003                   2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
00004                   2007 Apple Inc.  All rights reserved.
00005 
00006     This file is part of the KDE project
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "config.h"
00025 #include <wtf/Platform.h>
00026 
00027 #if ENABLE(SVG)
00028 #include "SVGSVGElement.h"
00029 
00030 #include "AffineTransform.h"
00031 /*#include "CSSHelper.h"*/
00032 #include "css/csshelper.h"
00033 /*#include "CSSPropertyNames.h"*/
00034 #include "Document.h"
00035 //#include "EventListener.h"
00036 #include "dom/dom2_events.h"
00037 /*#include "EventNames.h"*/
00038 #include "FloatConversion.h"
00039 #include "FloatRect.h"
00040 /*#include "Frame.h"
00041 #include "HTMLNames.h"
00042 #include "RenderSVGViewportContainer.h"*/
00043 #include "RenderSVGRoot.h"
00044 #include "SVGAngle.h"
00045 #include "SVGLength.h"
00046 #include "SVGNames.h"
00047 #include "SVGPreserveAspectRatio.h"
00048 #include "SVGTransform.h"
00049 #include "SVGTransformList.h"
00050 /*#include "SVGViewElement.h"*/
00051 #include "SVGViewSpec.h"
00052 /*#include "SVGZoomEvent.h"
00053 #include "SelectionController.h"
00054 #include "SMILTimeContainer.h"*/
00055 #include "khtml_part.h"
00056 
00057 namespace WebCore {
00058 
00059 /*using namespace HTMLNames;
00060 using namespace EventNames;*/
00061 using namespace SVGNames;
00062 
00063 SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document* doc)
00064     : SVGStyledLocatableElement(tagName, doc)
00065     , SVGTests()
00066     , SVGLangSpace()
00067     , SVGExternalResourcesRequired()
00068     , SVGFitToViewBox()
00069     , SVGZoomAndPan()
00070     , m_x(this, LengthModeWidth)
00071     , m_y(this, LengthModeHeight)
00072     , m_width(this, LengthModeWidth)
00073     , m_height(this, LengthModeHeight)
00074     , m_useCurrentView(false)
00075     /*, m_timeContainer(SMILTimeContainer::create(this))
00076     , m_viewSpec(0)*/
00077 {
00078     setWidthBaseValue(SVGLength(this, LengthModeWidth, "100%"));
00079     setHeightBaseValue(SVGLength(this, LengthModeHeight, "100%"));
00080     //doc->registerForCacheCallbacks(this);
00081 }
00082 
00083 SVGSVGElement::~SVGSVGElement()
00084 {
00085     /*document()->unregisterForCacheCallbacks(this);
00086     // There are cases where removedFromDocument() is not called.
00087     // see ContainerNode::removeAllChildren, called by it's destructor.
00088     document()->accessSVGExtensions()->removeTimeContainer(this);*/
00089 }
00090 
00091 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
00092 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
00093 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
00094 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
00095 
00096 DOMString SVGSVGElement::contentScriptType() const
00097 {
00098     static const DOMString defaultValue("text/ecmascript");
00099     DOMString n = getAttribute(contentScriptTypeAttr);
00100     return n.isNull() ? defaultValue : n;
00101 }
00102 
00103 void SVGSVGElement::setContentScriptType(const DOMString& type)
00104 {
00105     setAttribute(SVGNames::contentScriptTypeAttr, type);
00106 }
00107 
00108 DOMString SVGSVGElement::contentStyleType() const
00109 {
00110     static const DOMString defaultValue("text/css");
00111     const DOMString n = getAttribute(contentStyleTypeAttr);
00112     return n.isNull() ? defaultValue : n;
00113 }
00114 
00115 void SVGSVGElement::setContentStyleType(const DOMString& type)
00116 {
00117     setAttribute(SVGNames::contentStyleTypeAttr, type);
00118 }
00119 
00120 bool SVGSVGElement::hasSetContainerSize() const
00121 {
00122     // For now, we interpret % dimensions only if we're a top-level SVG element nested inside
00123     // an another part. ### might even want to check if we're the documentElement; this
00124     // will also need changes with <img> handling
00125     return isOutermostSVG() && document()->part()->parentPart();
00126 }
00127 
00128 IntSize SVGSVGElement::containerSize() const
00129 {
00130     if (KHTMLView* v = document()->view())
00131         return IntSize(v->visibleWidth(), v->visibleHeight());
00132     else
00133         return IntSize(300, 150);
00134 }
00135 
00136 FloatRect SVGSVGElement::viewport() const
00137 {
00138     double _x = 0.0;
00139     double _y = 0.0;
00140     if (!isOutermostSVG()) {
00141         _x = x().value();
00142         _y = y().value();
00143     }
00144     float w = width().value();
00145     float h = height().value();
00146     AffineTransform viewBox = viewBoxToViewTransform(w, h);
00147     double wDouble = w;
00148     double hDouble = h;
00149     viewBox.map(_x, _y, &_x, &_y);
00150     viewBox.map(w, h, &wDouble, &hDouble);
00151     return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble);
00152 }
00153 
00154 int SVGSVGElement::relativeWidthValue() const
00155 {
00156     SVGLength w = width();
00157     if (w.unitType() != LengthTypePercentage)
00158         return 0;
00159 
00160     return static_cast<int>(w.valueAsPercentage() * containerSize().width());
00161 }
00162 
00163 int SVGSVGElement::relativeHeightValue() const
00164 {
00165     SVGLength h = height();
00166     if (h.unitType() != LengthTypePercentage)
00167         return 0;
00168 
00169     return static_cast<int>(h.valueAsPercentage() * containerSize().height());
00170 }
00171 
00172 float SVGSVGElement::pixelUnitToMillimeterX() const
00173 {
00174     // 2.54 / cssPixelsPerInch gives CM.
00175     return (2.54f / cssPixelsPerInch) * 10.0f;
00176 }
00177 
00178 float SVGSVGElement::pixelUnitToMillimeterY() const
00179 {
00180     // 2.54 / cssPixelsPerInch gives CM.
00181     return (2.54f / cssPixelsPerInch) * 10.0f;
00182 }
00183 
00184 float SVGSVGElement::screenPixelToMillimeterX() const
00185 {
00186     return pixelUnitToMillimeterX();
00187 }
00188 
00189 float SVGSVGElement::screenPixelToMillimeterY() const
00190 {
00191     return pixelUnitToMillimeterY();
00192 }
00193 
00194 bool SVGSVGElement::useCurrentView() const
00195 {
00196     return m_useCurrentView;
00197 }
00198 
00199 void SVGSVGElement::setUseCurrentView(bool currentView)
00200 {
00201     m_useCurrentView = currentView;
00202 }
00203 
00204 SVGViewSpec* SVGSVGElement::currentView() const
00205 {
00206     if (!m_viewSpec)
00207         m_viewSpec.set(new SVGViewSpec(this));
00208 
00209     return m_viewSpec.get();
00210 }
00211 
00212 float SVGSVGElement::currentScale() const
00213 {
00214     /*if (document() && document()->frame())
00215         return document()->frame()->zoomFactor();*/
00216     return 1.0f;
00217 }
00218 
00219 void SVGSVGElement::setCurrentScale(float scale)
00220 {
00221     Q_UNUSED(scale);
00222     /*if (document() && document()->frame())
00223         document()->frame()->setZoomFactor(scale, true);*/
00224 }
00225 
00226 FloatPoint SVGSVGElement::currentTranslate() const
00227 {
00228     return m_translation;
00229 }
00230 
00231 void SVGSVGElement::setCurrentTranslate(const FloatPoint &translation)
00232 {
00233     m_translation = translation;
00234     if (parentNode() == document() && document()->renderer())
00235         document()->renderer()->repaint();
00236 }
00237 
00238 void SVGSVGElement::addSVGWindowEventListener(const AtomicString& eventType, const Attribute* attr)
00239 {
00240     Q_UNUSED(eventType);
00241     // FIXME: None of these should be window events long term.
00242     // Once we propertly support SVGLoad, etc.
00243     RefPtr<EventListener> listener = document()->accessSVGExtensions()->
00244         createSVGEventListener(attr->localName().string(), attr->value(), this);
00245     //document()->setHTMLWindowEventListener(eventType, listener.release());
00246 }
00247 
00248 void SVGSVGElement::parseMappedAttribute(MappedAttribute* attr)
00249 {
00250     kDebug() << "parse attribute: " << attr->localName() << attr->value() << endl;
00251     if (!nearestViewportElement()) {
00252         // Only handle events if we're the outermost <svg> element
00253         /*if (attr->name() == onunloadAttr)
00254             addSVGWindowEventListener(unloadEvent, attr);
00255         else if (attr->name() == onabortAttr)
00256             addSVGWindowEventListener(abortEvent, attr);
00257         else if (attr->name() == onerrorAttr)
00258             addSVGWindowEventListener(errorEvent, attr);
00259         else if (attr->name() == onresizeAttr)
00260             addSVGWindowEventListener(resizeEvent, attr);
00261         else if (attr->name() == onscrollAttr)
00262             addSVGWindowEventListener(scrollEvent, attr);
00263         else if (attr->name() == SVGNames::onzoomAttr)
00264             addSVGWindowEventListener(zoomEvent, attr);*/
00265     }
00266     if (attr->name() == SVGNames::xAttr)
00267         setXBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00268     else if (attr->name() == SVGNames::yAttr)
00269         setYBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00270     else if (attr->name() == SVGNames::widthAttr) {
00271         kDebug() << "set width" << attr->value() << endl;
00272         setWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00273         addCSSProperty(attr, CSSPropertyWidth, attr->value());
00274         /*if (width().value() < 0.0)
00275             document()->accessSVGExtensions()->reportError("A negative value for svg attribute <width> is not allowed");*/
00276     } else if (attr->name() == SVGNames::heightAttr) {
00277         kDebug() << "set height" << attr->value() << endl;
00278         setHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00279         addCSSProperty(attr, CSSPropertyHeight, attr->value());
00280         /*if (height().value() < 0.0)
00281             document()->accessSVGExtensions()->reportError("A negative value for svg attribute <height> is not allowed");*/
00282     } else {
00283         /*if (SVGTests::parseMappedAttribute(attr))
00284             return;
00285         if (SVGLangSpace::parseMappedAttribute(attr))
00286             return;
00287         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
00288             return;
00289         if (SVGFitToViewBox::parseMappedAttribute(attr))
00290             return;
00291         if (SVGZoomAndPan::parseMappedAttribute(attr))
00292             return;*/
00293 
00294         SVGStyledLocatableElement::parseMappedAttribute(attr);
00295     }
00296 }
00297 
00298 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
00299 {
00300     SVGStyledElement::svgAttributeChanged(attrName);
00301 
00302     if (!renderer())
00303         return;
00304 
00305     /*if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
00306         attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||
00307         SVGTests::isKnownAttribute(attrName) ||
00308         SVGLangSpace::isKnownAttribute(attrName) ||
00309         SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
00310         SVGFitToViewBox::isKnownAttribute(attrName) ||
00311         SVGZoomAndPan::isKnownAttribute(attrName) ||
00312         SVGStyledLocatableElement::isKnownAttribute(attrName))
00313         renderer()->setNeedsLayout(true);*/
00314 }
00315 
00316 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
00317 {
00318     // FIXME: Implement me (see bug 11275)
00319     return 0;
00320 }
00321 
00322 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode& /*ec*/)
00323 {
00324     // if suspend_handle_id is not found, throw exception
00325     // FIXME: Implement me (see bug 11275)
00326 }
00327 
00328 void SVGSVGElement::unsuspendRedrawAll()
00329 {
00330     // FIXME: Implement me (see bug 11275)
00331 }
00332 
00333 void SVGSVGElement::forceRedraw()
00334 {
00335     // FIXME: Implement me (see bug 11275)
00336 }
00337 
00338 DOM::NodeListImpl* SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement*)
00339 {
00340     Q_UNUSED(rect);
00341     // FIXME: Implement me (see bug 11274)
00342     return 0;
00343 }
00344 
00345 DOM::NodeListImpl* SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement*)
00346 {
00347     Q_UNUSED(rect);
00348     // FIXME: Implement me (see bug 11274)
00349     return 0;
00350 }
00351 
00352 bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect)
00353 {
00354     Q_UNUSED(element);
00355     // TODO : take into account pointer-events?
00356     // FIXME: Why is element ignored??
00357     // FIXME: Implement me (see bug 11274)
00358     return rect.intersects(getBBox());
00359 }
00360 
00361 bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect)
00362 {
00363     Q_UNUSED(element);
00364     // TODO : take into account pointer-events?
00365     // FIXME: Why is element ignored??
00366     // FIXME: Implement me (see bug 11274)
00367     return rect.contains(getBBox());
00368 }
00369 
00370 void SVGSVGElement::deselectAll()
00371 {
00372     //document()->frame()->selectionController()->clear();
00373 }
00374 
00375 float SVGSVGElement::createSVGNumber()
00376 {
00377     return 0.0f;
00378 }
00379 
00380 SVGLength SVGSVGElement::createSVGLength()
00381 {
00382     return SVGLength();
00383 }
00384 
00385 SVGAngle* SVGSVGElement::createSVGAngle()
00386 {
00387     return new SVGAngle();
00388 }
00389 
00390 FloatPoint SVGSVGElement::createSVGPoint()
00391 {
00392     return FloatPoint();
00393 }
00394 
00395 AffineTransform SVGSVGElement::createSVGMatrix()
00396 {
00397     return AffineTransform();
00398 }
00399 
00400 FloatRect SVGSVGElement::createSVGRect()
00401 {
00402     return FloatRect();
00403 }
00404 
00405 SVGTransform SVGSVGElement::createSVGTransform()
00406 {
00407     return SVGTransform();
00408 }
00409 
00410 SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const AffineTransform& matrix)
00411 {
00412     return SVGTransform(matrix);
00413 }
00414 
00415 AffineTransform SVGSVGElement::getCTM() const
00416 {
00417     AffineTransform mat;
00418     if (!isOutermostSVG())
00419         mat.translate(x().value(), y().value());
00420 
00421     if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
00422         AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
00423         mat = viewBox * mat;
00424     }
00425 
00426     return mat;
00427 }
00428 
00429 AffineTransform SVGSVGElement::getScreenCTM() const
00430 {
00431     /*document()->updateLayoutIgnorePendingStylesheets();
00432     float rootX = 0.0f;
00433     float rootY = 0.0f;
00434 
00435     if (RenderObject* renderer = this->renderer()) {
00436         renderer = renderer->parent();
00437         if (isOutermostSVG()) {
00438             int tx = 0;
00439             int ty = 0;
00440             if (renderer)
00441                 renderer->absolutePosition(tx, ty, true);
00442             rootX += tx;
00443             rootY += ty;
00444         } else {
00445             rootX += x().value();
00446             rootY += y().value();
00447         }
00448     }
00449 
00450     AffineTransform mat = SVGStyledLocatableElement::getScreenCTM();
00451     mat.translate(rootX, rootY);
00452 
00453     if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
00454         AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
00455         mat = viewBox * mat;
00456     }
00457 
00458     return mat;*/
00459     ASSERT(false);
00460     return AffineTransform();
00461 }
00462 
00463 RenderObject* SVGSVGElement::createRenderer(RenderArena* arena, RenderStyle*)
00464 {
00465     kDebug() << "create RenderSVGRoot from <svg> element" << endl;
00466     return new (arena) RenderSVGRoot(this);
00467     /*if (isOutermostSVG())
00468         return new (arena) RenderSVGRoot(this);
00469     else
00470         return new (arena) RenderSVGViewportContainer(this);*/
00471 }
00472 
00473 void SVGSVGElement::insertedIntoDocument()
00474 {
00475     document()->accessSVGExtensions()->addTimeContainer(this);
00476     SVGStyledLocatableElement::insertedIntoDocument();
00477 }
00478 
00479 void SVGSVGElement::removedFromDocument()
00480 {
00481     document()->accessSVGExtensions()->removeTimeContainer(this);
00482     SVGStyledLocatableElement::removedFromDocument();
00483 }
00484 
00485 void SVGSVGElement::pauseAnimations()
00486 {
00487     /*if (!m_timeContainer->isPaused())
00488         m_timeContainer->pause();*/
00489 }
00490 
00491 void SVGSVGElement::unpauseAnimations()
00492 {
00493     /*if (m_timeContainer->isPaused())
00494         m_timeContainer->resume();*/
00495 }
00496 
00497 bool SVGSVGElement::animationsPaused() const
00498 {
00499     //return m_timeContainer->isPaused();
00500     ASSERT(false);
00501     return false;
00502 }
00503 
00504 float SVGSVGElement::getCurrentTime() const
00505 {
00506     //return narrowPrecisionToFloat(m_timeContainer->elapsed().value());
00507     ASSERT(false);
00508     return 0.0;
00509 }
00510 
00511 void SVGSVGElement::setCurrentTime(float /* seconds */)
00512 {
00513     // FIXME: Implement me, bug 12073
00514 }
00515 
00516 bool SVGSVGElement::hasRelativeValues() const
00517 {
00518     return (x().isRelative() || width().isRelative() ||
00519             y().isRelative() || height().isRelative());
00520 }
00521 
00522 bool SVGSVGElement::isOutermostSVG() const
00523 {
00524     // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
00525     return !parentNode()->isSVGElement();
00526 }
00527 
00528 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
00529 {
00530     FloatRect viewBoxRect;
00531     if (useCurrentView()) {
00532         if (currentView()) // what if we should use it but it is not set?
00533             viewBoxRect = currentView()->viewBox();
00534     } else
00535         viewBoxRect = viewBox();
00536     if (!viewBoxRect.width() || !viewBoxRect.height())
00537         return AffineTransform();
00538 
00539     AffineTransform ctm = preserveAspectRatio()->getCTM(viewBoxRect.x(),
00540             viewBoxRect.y(), viewBoxRect.width(), viewBoxRect.height(),
00541             0, 0, viewWidth, viewHeight);
00542 
00543     if (useCurrentView() && currentView())
00544         return currentView()->transform()->concatenate().matrix() * ctm;
00545 
00546     return ctm;
00547 }
00548 
00549 /*void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement)
00550 {
00551     setUseCurrentView(true);
00552     if (viewElement->hasAttribute(SVGNames::viewBoxAttr))
00553         currentView()->setViewBox(viewElement->viewBox());
00554     else
00555         currentView()->setViewBox(viewBox());
00556     if (viewElement->hasAttribute(SVGNames::preserveAspectRatioAttr)) {
00557         currentView()->preserveAspectRatio()->setAlign(viewElement->preserveAspectRatio()->align());
00558         currentView()->preserveAspectRatio()->setMeetOrSlice(viewElement->preserveAspectRatio()->meetOrSlice());
00559     } else {
00560         currentView()->preserveAspectRatio()->setAlign(preserveAspectRatio()->align());
00561         currentView()->preserveAspectRatio()->setMeetOrSlice(preserveAspectRatio()->meetOrSlice());
00562     }
00563     if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr))
00564         currentView()->setZoomAndPan(viewElement->zoomAndPan());
00565     renderer()->setNeedsLayout(true);
00566 }*/
00567 
00568 void SVGSVGElement::willSaveToCache()
00569 {
00570     //pauseAnimations();
00571 }
00572 
00573 void SVGSVGElement::willRestoreFromCache()
00574 {
00575     //unpauseAnimations();
00576 }
00577 
00578 // KHTML stuff
00579 quint32 SVGSVGElement::id() const { return SVGNames::svgTag.id(); }
00580 
00581 }
00582 
00583 #endif // ENABLE(SVG)
00584 
00585 // vim:ts=4:noet

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal