root/trunk/cairo/cairooo/path.d

Revision 119, 7.7 kB (checked in by DRK, 6 years ago)

* Added bindings for the Glitz and Xlib backends.
* Checked in cairooo: an OO layer on top of the cairo binding.
* Added snippets directory for cairooo
* Added basic tutorial on how to use cairooo
* Added a simple demo program.
* Added scripts for building import libraries.
* Fixed several bugs.
* Drank WAAY too much coffee.

Line 
1 /**
2     XXX
3     
4 Authors: Daniel Keep
5 Copyright: 2006, Daniel Keep
6 License: BSD v2 (http://opensource.org/licenses/bsd-license.php).
7 **/
8 /**
9     Copyright © 2006 Daniel Keep
10     All rights reserved.
11     
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions are
14     met:
15     
16     * Redistributions of source code must retain the above copyright
17       notice, this list of conditions and the following disclaimer.
18       
19     * Redistributions in binary form must reproduce the above copyright
20       notice, this list of conditions and the following disclaimer in the
21       documentation and/or other materials provided with the distribution.
22     
23     * Neither the name of this software, nor the names of its contributors
24       may be used to endorse or promote products derived from this software
25       without specific prior written permission.
26     
27     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 **/
39 module cairooo.path;
40
41 // TODO: Add support for PathElement[]s.
42 // TODO: Should this be changed over to copy by value?  It looks like some
43 // people on the cairo ML think that's the way cairomm should go...
44
45 private
46 {
47     import cairo.cairo;
48     import cairooo.enums;
49     import cairooo.exceptions;
50     import cairooo.context;
51     import cairooo.glyph;
52 }
53
54 union PathData
55 {
56     struct
57     {
58         PathDataType type;
59         int length = 0;
60     }
61     struct
62     {
63         double x, y;
64     }
65 }
66
67 /+struct PathElement
68 {
69     PathDataType type;
70     union
71     {
72         MoveToElement moveTo;
73         LineToElement lineTo;
74         CurveToElement curveTo;
75         ClosePathElement closePath;
76     }
77 }
78
79 struct MoveToElement
80 {
81     double x, y;
82 }
83
84 struct LineToElement
85 {
86     double x, y
87 }
88
89 struct CurveToElement
90 {
91     double x1, y1, x2, y2, x3, y3;
92 }
93
94 struct ClosePathElement
95 {
96 }+/
97
98 class Path
99 {
100 private:
101     cairo_path_t* _handle = null;
102     uint* _refcount = null;
103     bool _selfAllocated = false;
104
105 public:
106     /**
107      * Creates a new, empty path.
108      */
109     this()
110     {
111         this._handle = new cairo_path_t;
112         this._refcount = new uint;
113         this._selfAllocated = true;
114
115         // Get initial reference
116         (*this._refcount) = 1;
117     }
118
119     /**
120         This constructor will wrap a raw cairo_path_t* handle in a Path
121         instance.  However, user code should $(I not) use this method if you
122         can help it.  Since this class maintains its own reference counting
123         information, creating multiple wrappers around a single cairo_path_t*
124         will cause the handle to be freed prematurely!
125     **/
126     this(cairo_path_t* handle)
127     {
128         // This constructor wraps an existing cairo_path_t* handle.  It simply
129         // saves the handle, creates a new refcount (defaulting to 1), and
130         // then sets selfAllocated to false.  This constructor will NOT accept
131         // user-created handles that cairo does not own.  This is more for my
132         // own sanity then any other reason at this point...
133         this._handle = handle;
134         this._refcount = new uint;
135         this._selfAllocated = false;
136
137         // Get initial reference
138         (*this._refcount) = 1;
139     }
140
141     this(PathData[] data)
142     {
143         // This constructor runs the default constructor to give us an empty
144         // cairo_path_t structure.  We then update its cairo_path_data_t
145         // pointer, and element length.
146         this();
147         this.handle.data = cast(cairo_path_data_t*) data.dup;
148         this.handle.num_data = data.length;
149     }
150
151     this(Path path)
152     {
153         // This constructor simply copies the pointer to the existing path
154         // object's handle, copies the pointer to the reference counter, and
155         // then adds a reference.
156         this._handle = path._handle;
157         this._refcount = path._refcount;
158         this._selfAllocated = path._selfAllocated;
159
160         // Increment references by one
161         (*this._refcount) ++;
162     }
163    
164     ~this()
165     {
166         // Drop a reference
167         (*this._refcount) --;
168        
169         // If there are no more references, destroy the object
170         if( (*this._refcount) == 0 )
171         {
172             if( selfAllocated )
173             {
174                 // If we allocated this path ourselves, we need to explicitly
175                 // delete it.
176                 delete this._handle;
177             }
178             else
179             {
180                 // Otherwise, let cairo deal with it.
181                 cairo_path_destroy(this._handle);
182             }
183
184             // Free the reference counter
185             delete this._refcount;
186         }
187     }
188
189     //
190     // miscellaneous members
191     //
192     cairo_path_t*
193     handle()
194     {
195         return this._handle;
196     }
197    
198     Path
199     dup()
200     {
201         return new Path(this);
202     }
203    
204     bool
205     selfAllocated()
206     {
207         return this._selfAllocated;
208     }
209
210     PathData[]
211     data()
212     {
213         return (cast(PathData*) this.handle.data)[0..this.handle.num_data];
214     }
215
216     /+PathElement[]
217     elements()
218     {
219         PathElement[] result;
220         foreach( element ; this )
221         {
222             result.length = result.length + 1;
223             result[$-1] = element;
224         }
225         return result;
226     }+/
227
228     /+int
229     opApply(int delegate(inout PathElement) dg)
230     {
231         int result = 0;
232         PathElement current;
233         PathData[] data = this.data;
234
235         for( int i=0; i<data.length; )
236         {
237             current.type = data[i].type;
238             
239             switch( current.type )
240             {
241                 case PathDataType.MoveTo:
242                     current.moveTo.x = data[i+1].x;
243                     current.moveTo.y = data[i+1].y;
244                     i += 2;
245                     break;
246
247                 case PathDataType.LineTo:
248                     current.lineTo.x = data[i+1].x;
249                     current.lineTo.y = data[i+1].y;
250                     i += 2;
251                     break;
252
253                 case PathDataType.CurveTo:
254                     current.curveTo.x1 = data[i+1].x;
255                     current.curveTo.y1 = data[i+1].y;
256                     current.curveTo.x2 = data[i+2].x;
257                     current.curveTo.y2 = data[i+2].y;
258                     current.curveTo.x3 = data[i+3].x;
259                     current.curveTo.y3 = data[i+3].y;
260                     i += 4;
261                     break;
262
263                 case PathDataType.ClosePath:
264                     i += 1;
265                     break;
266             }
267
268             result = dg(current);
269             if( result )
270                 break;
271         }
272
273         return result;
274     }+/
275
276 protected:
277     void
278     checkStatus()
279     {
280         .checkStatus(this.handle.status);
281     }
282
283     void
284     checkStatus(cairo_path_t* handle)
285     {
286         .checkStatus(handle.status);
287     }
288 }
Note: See TracBrowser for help on using the browser.