Back to index

lightning-sunbird  0.9+nobinonly
nsSVGPolylineFrame.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla SVG project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Crocodile Clips Ltd..
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsSVGPathGeometryFrame.h"
00040 #include "nsIDOMSVGAnimatedPoints.h"
00041 #include "nsIDOMSVGPointList.h"
00042 #include "nsIDOMSVGPoint.h"
00043 //#include "nsASVGPathBuilder.h"
00044 #include "nsISVGRendererPathBuilder.h"
00045 #include "nsISVGMarkable.h"
00046 #include "nsSVGMarkerFrame.h"
00047 #include "nsLayoutAtoms.h"
00048 
00049 class nsSVGPolylineFrame : public nsSVGPathGeometryFrame,
00050                            public nsISVGMarkable
00051 {
00052 protected:
00053   friend nsresult
00054   NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00055 
00056   virtual ~nsSVGPolylineFrame();
00057   NS_IMETHOD InitSVG();
00058 
00059 public:
00065   virtual nsIAtom* GetType() const;
00066 
00067 #ifdef DEBUG
00068   NS_IMETHOD GetFrameName(nsAString& aResult) const
00069   {
00070     return MakeFrameName(NS_LITERAL_STRING("SVGPolyline"), aResult);
00071   }
00072 #endif
00073 
00074   // nsISVGValueObserver interface:
00075   NS_IMETHOD DidModifySVGObservable(nsISVGValue* observable,
00076                                     nsISVGValue::modificationType aModType);
00077 
00078   // nsISVGPathGeometrySource interface:
00079   NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder);
00080 
00081 //  virtual void ConstructPath(nsASVGPathBuilder* pathBuilder);
00082 
00083   nsCOMPtr<nsIDOMSVGPointList> mPoints;
00084 
00085   // nsISVGMarkable interface
00086   void GetMarkPoints(nsVoidArray *aMarks);
00087 
00088    // nsISupports interface:
00089   NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
00090 
00091 private:
00092   NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
00093   NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }  
00094 };
00095 
00096 NS_INTERFACE_MAP_BEGIN(nsSVGPolylineFrame)
00097   NS_INTERFACE_MAP_ENTRY(nsISVGMarkable)
00098 NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrame)
00099 
00100 //----------------------------------------------------------------------
00101 // Implementation
00102 
00103 nsresult
00104 NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame)
00105 {
00106   nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(aContent);
00107   if (!anim_points) {
00108 #ifdef DEBUG
00109     printf("warning: trying to construct an SVGPolylineFrame for a content element that doesn't support the right interfaces\n");
00110 #endif
00111     return NS_ERROR_FAILURE;
00112   }
00113   
00114   nsSVGPolylineFrame* it = new (aPresShell) nsSVGPolylineFrame;
00115   if (nsnull == it)
00116     return NS_ERROR_OUT_OF_MEMORY;
00117 
00118   *aNewFrame = it;
00119   return NS_OK;
00120 }
00121 
00122 nsSVGPolylineFrame::~nsSVGPolylineFrame()
00123 {
00124   nsCOMPtr<nsISVGValue> value;
00125   if (mPoints && (value = do_QueryInterface(mPoints)))
00126       value->RemoveObserver(this);
00127 }
00128 
00129 NS_IMETHODIMP
00130 nsSVGPolylineFrame::InitSVG()
00131 {
00132   nsresult rv = nsSVGPathGeometryFrame::InitSVG();
00133   if (NS_FAILED(rv)) return rv;
00134   
00135   nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(mContent);
00136   NS_ASSERTION(anim_points,"wrong content element");
00137   anim_points->GetPoints(getter_AddRefs(mPoints));
00138   NS_ASSERTION(mPoints, "no points");
00139   if (!mPoints) return NS_ERROR_FAILURE;
00140   nsCOMPtr<nsISVGValue> value = do_QueryInterface(mPoints);
00141   if (value)
00142     value->AddObserver(this);
00143   return NS_OK; 
00144 }  
00145 
00146 nsIAtom *
00147 nsSVGPolylineFrame::GetType() const
00148 {
00149   return nsLayoutAtoms::svgPolylineFrame;
00150 }
00151 
00152 //----------------------------------------------------------------------
00153 // nsISVGValueObserver methods:
00154 
00155 NS_IMETHODIMP
00156 nsSVGPolylineFrame::DidModifySVGObservable(nsISVGValue* observable,
00157                                            nsISVGValue::modificationType aModType)
00158 {
00159   nsCOMPtr<nsIDOMSVGPointList> l = do_QueryInterface(observable);
00160   if (l && mPoints==l) {
00161     UpdateGraphic(nsISVGPathGeometrySource::UPDATEMASK_PATH);
00162     return NS_OK;
00163   }
00164   // else
00165   return nsSVGPathGeometryFrame::DidModifySVGObservable(observable, aModType);
00166 }
00167 
00168 //----------------------------------------------------------------------
00169 // nsISVGPathGeometrySource methods:
00170 
00171 /* void constructPath (in nsISVGRendererPathBuilder pathBuilder); */
00172 NS_IMETHODIMP nsSVGPolylineFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuilder)
00173 {
00174   if (!mPoints) return NS_OK;
00175 
00176   PRUint32 count;
00177   mPoints->GetNumberOfItems(&count);
00178   if (count == 0) return NS_OK;
00179   
00180   PRUint32 i;
00181   for (i = 0; i < count; ++i) {
00182     nsCOMPtr<nsIDOMSVGPoint> point;
00183     mPoints->GetItem(i, getter_AddRefs(point));
00184 
00185     float x, y;
00186     point->GetX(&x);
00187     point->GetY(&y);
00188     if (i == 0)
00189       pathBuilder->Moveto(x, y);
00190     else
00191       pathBuilder->Lineto(x, y);
00192   }
00193 
00194   return NS_OK;
00195 }
00196 
00197 //----------------------------------------------------------------------
00198 // nsISVGMarkable methods:
00199 
00200 void
00201 nsSVGPolylineFrame::GetMarkPoints(nsVoidArray *aMarks) {
00202 
00203   if (!mPoints)
00204     return;
00205 
00206   PRUint32 count;
00207   mPoints->GetNumberOfItems(&count);
00208   if (count == 0)
00209     return;
00210   
00211   float px = 0.0, py = 0.0, prevAngle;
00212 
00213   for (PRUint32 i = 0; i < count; ++i) {
00214     nsCOMPtr<nsIDOMSVGPoint> point;
00215     mPoints->GetItem(i, getter_AddRefs(point));
00216 
00217     float x, y;
00218     point->GetX(&x);
00219     point->GetY(&y);
00220 
00221     float angle = atan2(y-py, x-px);
00222     if (i == 1)
00223       ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = angle;
00224     else if (i > 1)
00225       ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
00226         nsSVGMarkerFrame::bisect(prevAngle, angle);
00227 
00228     nsSVGMark *mark;
00229     mark = new nsSVGMark;
00230     mark->x = x;
00231     mark->y = y;
00232     aMarks->AppendElement(mark);
00233 
00234     prevAngle = angle;
00235     px = x;
00236     py = y;
00237   }
00238 
00239   ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
00240 }