Back to index

lightning-sunbird  0.9+nobinonly
nsSVGStroke.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 "nsSVGStroke.h"
00040 #include "nsCOMPtr.h"
00041 #include "nsIServiceManager.h"
00042 #include "nsMemory.h"
00043 #include "nsISVGPathGeometrySource.h"
00044 #include "prdtoa.h"
00045 #include "nsIDOMSVGMatrix.h"
00046 #include <math.h>
00047 
00048 #define SVG_STROKE_FLATNESS 0.5
00049 
00050 void
00051 nsSVGStroke::Build(ArtVpath* path, nsISVGPathGeometrySource* source)
00052 {
00053   if (mSvp)
00054     art_svp_free(mSvp);
00055 
00056   float width;
00057   source->GetStrokeWidth(&width);
00058 
00059   // XXX since we construct the stroke from a pre-transformed path, we
00060   // adjust the stroke width according to the expansion part of
00061   // transformation. This is not true anamorphic scaling, but the best
00062   // we can do given the circumstances...
00063   float expansion; 
00064   {
00065     double matrix[6];
00066     nsCOMPtr<nsIDOMSVGMatrix> ctm;
00067     source->GetCanvasTM(getter_AddRefs(ctm));
00068     NS_ASSERTION(ctm, "graphic source didn't have a ctm");
00069     
00070     float val;
00071     ctm->GetA(&val);
00072     matrix[0] = val;
00073     
00074     ctm->GetB(&val);
00075     matrix[1] = val;
00076     
00077     ctm->GetC(&val);  
00078     matrix[2] = val;  
00079     
00080     ctm->GetD(&val);  
00081     matrix[3] = val;  
00082     
00083     ctm->GetE(&val);
00084     matrix[4] = val;
00085     
00086     ctm->GetF(&val);
00087     matrix[5] = val;
00088     
00089     expansion = sqrt((float)fabs(matrix[0]*matrix[3]-matrix[2]*matrix[1]));
00090   }
00091 
00092   width*=expansion;
00093   if (width==0.0) return;
00094   
00095   PRUint16 strokelinecap;
00096   source->GetStrokeLinecap(&strokelinecap);  
00097   ArtPathStrokeCapType captype;
00098   switch(strokelinecap) {
00099     case nsISVGGeometrySource::STROKE_LINECAP_BUTT:
00100       captype = ART_PATH_STROKE_CAP_BUTT;
00101       break;
00102     case nsISVGGeometrySource::STROKE_LINECAP_ROUND:
00103       captype = ART_PATH_STROKE_CAP_ROUND;
00104       break;
00105     case nsISVGGeometrySource::STROKE_LINECAP_SQUARE:
00106       captype = ART_PATH_STROKE_CAP_SQUARE;
00107       break;
00108     default:
00109       NS_ERROR("not reached");
00110   }
00111 
00112   PRUint16 strokelinejoin;
00113   source->GetStrokeLinejoin(&strokelinejoin);
00114 
00115   ArtPathStrokeJoinType jointype;
00116   switch(strokelinejoin) {
00117     case nsISVGGeometrySource::STROKE_LINEJOIN_MITER:
00118       jointype = ART_PATH_STROKE_JOIN_MITER;
00119       break;
00120     case nsISVGGeometrySource::STROKE_LINEJOIN_ROUND:
00121       jointype = ART_PATH_STROKE_JOIN_ROUND;
00122       break;
00123     case nsISVGGeometrySource::STROKE_LINEJOIN_BEVEL:
00124       jointype = ART_PATH_STROKE_JOIN_BEVEL;
00125       break;
00126     default:
00127       NS_ERROR("not reached");
00128   }
00129 
00130   float *dashArray;
00131   PRUint32 dashCount;
00132   source->GetStrokeDashArray(&dashArray, &dashCount);
00133   if (dashCount>0) {
00134     ArtVpathDash dashes;
00135 
00136     float offset;
00137     source->GetStrokeDashoffset(&offset);
00138     dashes.offset = offset;
00139 
00140     dashes.n_dash = dashCount;
00141     dashes.dash = new double[dashCount];
00142     while (dashCount--)
00143       dashes.dash[dashCount] = dashArray[dashCount];
00144 
00145     nsMemory::Free(dashArray);
00146 
00147     // create a dashed vpath:
00148 
00149     ArtVpathArrayIterator src_iter;
00150 //      ArtVpathClipFilter clip_filter;
00151     ArtVpathDashFilter dash_filter;
00152       
00153     art_vpath_array_iterator_init((ArtVpath*)path, &src_iter);
00154 //      art_vpath_clip_filter_init((ArtVpathIterator*)&src_iter, canvasSpecs->GetClipRect(), &clip_filter);
00155 //      art_vpath_dash_filter_init((ArtVpathIterator*)&clip_filter, &dash, &dash_filter);
00156     art_vpath_dash_filter_init((ArtVpathIterator*)&src_iter, &dashes, &dash_filter);
00157     
00158     path = art_vpath_new_vpath_array((ArtVpathIterator*)&dash_filter);
00159     
00160     // clean up
00161     delete[] dashes.dash;
00162   }
00163   else
00164   {
00165     // no dash pattern - just clip & contract with moveto_open
00166       ArtVpathArrayIterator src_iter;
00167 //      ArtVpathClipFilter clip_filter;
00168 //      ArtVpathContractFilter contract_filter;
00169       
00170       art_vpath_array_iterator_init((ArtVpath*)path, &src_iter);
00171 //      art_vpath_clip_filter_init((ArtVpathIterator*)&src_iter, canvasSpecs->GetClipRect(), &clip_filter);
00172 //      art_vpath_contract_filter_init((ArtVpathIterator*)&clip_filter,
00173 //                                     ART_LINETO_CLIPPED,
00174 //                                     ART_MOVETO_OPEN,
00175 //                                     &contract_filter);
00176       
00177 //      path = art_vpath_new_vpath_array((ArtVpathIterator*)&contract_filter);
00178       path = art_vpath_new_vpath_array((ArtVpathIterator*)&src_iter);
00179   }    
00180 
00181   float miterlimit;
00182   source->GetStrokeMiterlimit(&miterlimit);
00183 
00184   mSvp = art_svp_vpath_stroke(path,
00185                               jointype,
00186                               captype,
00187                               width,
00188                               miterlimit,
00189                               SVG_STROKE_FLATNESS);
00190   art_free(path);
00191 }
00192