/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ----- BEGIN LICENSE BLOCK ----- * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Mozilla SVG project. * * The Initial Developer of the Original Code is * Crocodile Clips Ltd.. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Alex Fritze (original author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ----- END LICENSE BLOCK ----- */ #include "nsISVGViewportAxis.h" #include "nsCOMPtr.h" #include "nsWeakReference.h" #include "nsISVGViewportRect.h" #include "nsSVGNumber.h" #include "nsISVGValue.h" #include "nsSVGValue.h" #include "nsISVGValueObserver.h" #include "nsISVGValueUtils.h" #include "nsDOMError.h" #include //////////////////////////////////////////////////////////////////////// // nsSVGViewportAxis : helper class implementing nsISVGViewportAxis class nsSVGViewportAxis : public nsISVGViewportAxis // ,public nsISVGValueObserver, // public nsSupportsWeakReference { protected: friend nsresult NS_NewSVGViewportAxis(nsISVGViewportAxis **result, nsIDOMSVGNumber* scale, nsIDOMSVGNumber* length); nsSVGViewportAxis(); nsresult Init(nsIDOMSVGNumber* scale, nsIDOMSVGNumber* length); public: // nsISupports interface: NS_DECL_ISUPPORTS // nsISVGViewportAxis methods: NS_IMETHOD GetMillimeterPerPixel(nsIDOMSVGNumber **scale); NS_IMETHOD GetLength(nsIDOMSVGNumber **length); // nsISVGValueObserver // NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable); // NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable); // nsISupportsWeakReference // implementation inherited from nsSupportsWeakReference private: nsCOMPtr mScale; nsCOMPtr mLength; }; //---------------------------------------------------------------------- // Implementation nsresult NS_NewSVGViewportAxis(nsISVGViewportAxis **result, nsIDOMSVGNumber* scale, nsIDOMSVGNumber* length) { *result = nsnull; nsSVGViewportAxis *va = new nsSVGViewportAxis(); NS_ENSURE_TRUE(va, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(va); nsresult rv = va->Init(scale, length); if (NS_FAILED(rv)) { NS_RELEASE(va); return rv; } *result = va; return rv; } nsSVGViewportAxis::nsSVGViewportAxis() { } nsresult nsSVGViewportAxis::Init(nsIDOMSVGNumber* scale, nsIDOMSVGNumber* length) { mScale = scale; mLength = length; return NS_OK; } //---------------------------------------------------------------------- // nsISupports methods: NS_IMPL_ADDREF(nsSVGViewportAxis) NS_IMPL_RELEASE(nsSVGViewportAxis) NS_INTERFACE_MAP_BEGIN(nsSVGViewportAxis) NS_INTERFACE_MAP_ENTRY(nsISVGViewportAxis) // NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) // NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGViewportAxis) NS_INTERFACE_MAP_END //---------------------------------------------------------------------- // nsISVGViewportAxis methods: NS_IMETHODIMP nsSVGViewportAxis::GetMillimeterPerPixel(nsIDOMSVGNumber **scale) { *scale = mScale; NS_ADDREF(*scale); return NS_OK; } NS_IMETHODIMP nsSVGViewportAxis::GetLength(nsIDOMSVGNumber **length) { *length = mLength; NS_ADDREF(*length); return NS_OK; } //---------------------------------------------------------------------- // nsISVGValueObserver methods // NS_IMETHODIMP // nsSVGViewportAxis::WillModifySVGObservable(nsISVGValue* observable) // { // return NS_OK; // } // NS_IMETHODIMP // nsSVGViewportAxis::DidModifySVGObservable(nsISVGValue* observable) // { // // we only listen in on changes to the length // UpdateLength(); // return NS_OK; // } //////////////////////////////////////////////////////////////////////// // nsSVGViewportRect class nsSVGViewportRect : public nsISVGViewportRect, public nsSVGValue, public nsISVGValueObserver, public nsSupportsWeakReference { protected: friend nsresult NS_NewSVGViewportRect(nsISVGViewportRect **result, nsIDOMSVGNumber* scalex, nsIDOMSVGNumber* scaley, nsIDOMSVGNumber* lengthx, nsIDOMSVGNumber* lengthy); nsSVGViewportRect(); ~nsSVGViewportRect(); nsresult Init(nsIDOMSVGNumber* scalex, nsIDOMSVGNumber* scaley, nsIDOMSVGNumber* lengthx, nsIDOMSVGNumber* lengthy); public: // nsISupports interface: NS_DECL_ISUPPORTS // nsISVGViewportRect interface: NS_IMETHOD GetXAxis(nsISVGViewportAxis **xaxis); NS_IMETHOD GetYAxis(nsISVGViewportAxis **yaxis); NS_IMETHOD GetUnspecifiedAxis(nsISVGViewportAxis **axis); // nsIDOMSVGRect interface: NS_DECL_NSIDOMSVGRECT // nsISVGValue interface: NS_IMETHOD SetValueString(const nsAString& aValue); NS_IMETHOD GetValueString(nsAString& aValue); // nsISVGValueObserver interface: NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable); NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable); // nsISupportsWeakReference // implementation inherited from nsSupportsWeakReference protected: void UpdateGenericAxisScale(); void UpdateGenericAxisLength(); private: virtual void OnDidModify(); nsCOMPtr mAxisX; nsCOMPtr mAxisY; nsCOMPtr mAxisUnspecified; }; //---------------------------------------------------------------------- // implementation: nsresult NS_NewSVGViewportRect(nsISVGViewportRect **result, nsIDOMSVGNumber* scalex, nsIDOMSVGNumber* scaley, nsIDOMSVGNumber* lengthx, nsIDOMSVGNumber* lengthy) { *result = nsnull; nsSVGViewportRect *vr = new nsSVGViewportRect(); if (!vr) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(vr); nsresult rv = vr->Init(scalex, scaley, lengthx, lengthy); if (NS_FAILED(rv)) { NS_RELEASE(vr); return rv; } *result = vr; return NS_OK; } nsSVGViewportRect::nsSVGViewportRect() { } nsSVGViewportRect::~nsSVGViewportRect() { if (mAxisX) { nsCOMPtr l; mAxisX->GetLength(getter_AddRefs(l)); NS_REMOVE_SVGVALUE_OBSERVER(l); nsCOMPtr s; mAxisX->GetMillimeterPerPixel(getter_AddRefs(s)); NS_REMOVE_SVGVALUE_OBSERVER(s); } if (mAxisY) { nsCOMPtr l; mAxisY->GetLength(getter_AddRefs(l)); NS_REMOVE_SVGVALUE_OBSERVER(l); nsCOMPtr s; mAxisY->GetMillimeterPerPixel(getter_AddRefs(s)); NS_REMOVE_SVGVALUE_OBSERVER(s); } } nsresult nsSVGViewportRect::Init(nsIDOMSVGNumber* scalex, nsIDOMSVGNumber* scaley, nsIDOMSVGNumber* lengthx, nsIDOMSVGNumber* lengthy) { nsresult rv; rv = NS_NewSVGViewportAxis(getter_AddRefs(mAxisX), scalex,lengthx); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGViewportAxis(getter_AddRefs(mAxisY), scaley,lengthy); NS_ENSURE_SUCCESS(rv,rv); { nsCOMPtr sqrt_scale; rv = NS_NewSVGNumber(getter_AddRefs(sqrt_scale)); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr sqrt_length; rv = NS_NewSVGNumber(getter_AddRefs(sqrt_length)); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGViewportAxis(getter_AddRefs(mAxisUnspecified), sqrt_scale,sqrt_length); NS_ENSURE_SUCCESS(rv,rv); UpdateGenericAxisScale(); UpdateGenericAxisLength(); } NS_ADD_SVGVALUE_OBSERVER(scalex); NS_ADD_SVGVALUE_OBSERVER(scaley); NS_ADD_SVGVALUE_OBSERVER(lengthx); NS_ADD_SVGVALUE_OBSERVER(lengthy); return rv; } //---------------------------------------------------------------------- // nsISupports methods: NS_IMPL_ADDREF(nsSVGViewportRect) NS_IMPL_RELEASE(nsSVGViewportRect) NS_INTERFACE_MAP_BEGIN(nsSVGViewportRect) NS_INTERFACE_MAP_ENTRY(nsISVGValue) NS_INTERFACE_MAP_ENTRY(nsIDOMSVGRect) NS_INTERFACE_MAP_ENTRY(nsISVGViewportRect) NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGRect) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue) NS_INTERFACE_MAP_END //---------------------------------------------------------------------- // nsISVGViewportRect methods: NS_IMETHODIMP nsSVGViewportRect::GetXAxis(nsISVGViewportAxis **xaxis) { *xaxis = mAxisX; NS_ADDREF(*xaxis); return NS_OK; } NS_IMETHODIMP nsSVGViewportRect::GetYAxis(nsISVGViewportAxis **yaxis) { *yaxis = mAxisY; NS_ADDREF(*yaxis); return NS_OK; } NS_IMETHODIMP nsSVGViewportRect::GetUnspecifiedAxis(nsISVGViewportAxis **axis) { *axis = mAxisUnspecified; NS_ADDREF(*axis); return NS_OK; } //---------------------------------------------------------------------- // nsIDOMSVGRect methods: /* attribute float x; */ NS_IMETHODIMP nsSVGViewportRect::GetX(float *aX) { *aX = 0.0f; return NS_OK; } NS_IMETHODIMP nsSVGViewportRect::SetX(float aX) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; // XXX return different error } /* attribute float y; */ NS_IMETHODIMP nsSVGViewportRect::GetY(float *aY) { *aY = 0.0f; return NS_OK; } NS_IMETHODIMP nsSVGViewportRect::SetY(float aY) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } /* attribute float width; */ NS_IMETHODIMP nsSVGViewportRect::GetWidth(float *aWidth) { nsCOMPtr l; mAxisX->GetLength(getter_AddRefs(l)); return l->GetValue(aWidth); } NS_IMETHODIMP nsSVGViewportRect::SetWidth(float aWidth) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } /* attribute float height; */ NS_IMETHODIMP nsSVGViewportRect::GetHeight(float *aHeight) { nsCOMPtr l; mAxisY->GetLength(getter_AddRefs(l)); return l->GetValue(aHeight); } NS_IMETHODIMP nsSVGViewportRect::SetHeight(float aHeight) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } //---------------------------------------------------------------------- // nsISVGValue methods: NS_IMETHODIMP nsSVGViewportRect::SetValueString(const nsAString& aValue) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsSVGViewportRect::GetValueString(nsAString& aValue) { return NS_ERROR_NOT_IMPLEMENTED; } //---------------------------------------------------------------------- // nsISVGValueObserver methods: NS_IMETHODIMP nsSVGViewportRect::WillModifySVGObservable(nsISVGValue* observable) { WillModify(); return NS_OK; } NS_IMETHODIMP nsSVGViewportRect::DidModifySVGObservable (nsISVGValue* observable) { DidModify(); return NS_OK; } //---------------------------------------------------------------------- // helpers: void nsSVGViewportRect::UpdateGenericAxisLength() { float x; { nsCOMPtr l_x; mAxisX->GetLength(getter_AddRefs(l_x)); l_x->GetValue(&x); } float y; { nsCOMPtr l_y; mAxisY->GetLength(getter_AddRefs(l_y)); l_y->GetValue(&y); } nsCOMPtr l_sqrt; mAxisUnspecified->GetLength (getter_AddRefs(l_sqrt)); l_sqrt->SetValue((float)sqrt((x*x + y*y)/2.0f)); } void nsSVGViewportRect::UpdateGenericAxisScale() { float x; { nsCOMPtr s_x; mAxisX->GetMillimeterPerPixel(getter_AddRefs(s_x)); s_x->GetValue(&x); } float y; { nsCOMPtr s_y; mAxisY->GetMillimeterPerPixel(getter_AddRefs(s_y)); s_y->GetValue(&y); } nsCOMPtr s_sqrt; mAxisUnspecified->GetMillimeterPerPixel(getter_AddRefs(s_sqrt)); s_sqrt->SetValue((float)sqrt(x*x + y*y)); } void nsSVGViewportRect::OnDidModify() { UpdateGenericAxisLength(); UpdateGenericAxisScale(); }