root/trunk/cairo/cairooo/surface.d

Revision 119, 7.9 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.surface;
40
41 private
42 {
43     import cairo.cairo;
44     import cairooo.enums;
45     import cairooo.exceptions;
46     import cairooo.fontoptions;
47 }
48
49 /**
50  * A cairo surface.
51  */
52 class Surface
53 {
54 private:
55     cairo_surface_t* _handle;
56
57 public:
58     /**
59      * Wraps the low-level cairo surface in a new object.  This method is most
60      * useful for wrapping pointers returned from cairo api functions that are
61      * not yet supported by the OO api.  Please note that this function is
62      * slightly dangerous and can lead to memory leaks if misused (see below).
63      *
64      * Please note that it is $(I vitally) important that you use the takeref
65      * parameter correctly.  If takeref is set to true, then the
66      * object will $(I not) add to the handle's reference count.  This means
67      * that if you do not pass the correct value for takeref, then you could
68      * end up with handles either not being destroyed, or being destroyed too
69      * early!
70      *
71      * Params:
72      *      handle      = Pointer to a cairo_surface_t context
73      *      takeref     = Should the object take a reference to the handle?
74      */
75     this(cairo_surface_t* handle, bool takeref)
76     {
77         checkStatus(handle);
78         this._handle = handle;
79         if( takeref )
80         {
81             cairo_surface_reference(this._handle);
82             checkStatus(this.handle);
83         }
84     }
85
86     /**
87      * Duplicates a surface, providing a new, independant reference to it.
88      */
89     this(Surface surface)
90     {
91         this(surface.handle, true);
92     }
93
94     ~this()
95     {
96         cairo_surface_destroy(this.handle);
97     }
98
99     //
100     // cairo api members
101     //
102
103     Surface
104     createSimilar(Content content, int width, int height)
105     {
106         scope(success) checkStatus();
107         cairo_surface_t* new_handle =
108             cairo_surface_create_similar(this.handle,
109                     cast(cairo_content_t) content, width, height);
110         return new Surface(new_handle, false);
111     }
112
113     void
114     finish()
115     {
116         scope(success) checkStatus();
117         cairo_surface_finish(this.handle);
118     }
119
120     void
121     flush()
122     {
123         scope(success) checkStatus();
124         cairo_surface_flush(this.handle);
125     }
126
127     FontOptions
128     fontOptions()
129     {
130         scope(success) checkStatus();
131         auto FontOptions temp = new FontOptions();
132         cairo_surface_get_font_options(this.handle, temp.handle);
133         return temp.dup;
134     }
135
136     void
137     markDirty()
138     {
139         scope(success) checkStatus();
140         cairo_surface_mark_dirty(this.handle);
141     }
142
143     void markDirtyRectangle(int x, int y, int width, int height)
144     {
145         scope(success) checkStatus();
146         cairo_surface_mark_dirty_rectangle(this.handle, x, y, width, height);
147     }
148
149     void setDeviceOffset(double x, double y)
150     {
151         scope(success) checkStatus();
152         cairo_surface_set_device_offset(this.handle, x, y);
153     }
154
155     //
156     // miscellaneous members
157     //
158
159     Surface
160     dup()
161     {
162         return new Surface(this);
163     }
164
165     cairo_surface_t*
166     handle()
167     {
168         return this._handle;
169     }
170
171     int
172     opEquals(Surface other)
173     {
174         return this.handle == other.handle;
175     }
176
177     /**
178         This method will take a surface handle that has been returned from a
179         function like cairo_get_target, and attempts to reconstruct the
180         original wrapper type.
181
182         This is done using cairo's internal user data functions.  If the
183         handle was not wrapped by an object, then it will return a regular
184         Surface object.
185
186         Also note that this will always recast the handle to the type of the
187         first object that it was wrapped in.  Therefore, if you wrap a handle
188         first using a Win32Surface, and then a GlitzSurface, this method will
189         always return a Win32Surface.
190     **/
191     package
192     static
193     Surface
194     rewrapSurfaceHandle(cairo_surface_t* handle)
195     {
196         // First, try to get the function pointer from the surface itself.
197         void* wrapfunc = cairo_surface_get_user_data(handle, WRAPFUNC_KEY);
198
199         // If we got null, that means that key wasn't attached: just wrap in a
200         // regular surface object.
201         if( wrapfunc == null )
202             return new Surface(handle, true);
203
204         // Otherwise, cast to a SurfaceWrapFunc, and return the result of
205         // calling that.
206         else
207             return (cast(SurfaceWrapFunc) wrapfunc)(handle);
208     }
209
210     //
211     // Internal stuff
212     //
213 protected:
214     void
215     checkStatus()
216     {
217         .checkStatus(cairo_surface_status(this._handle));
218     }
219    
220     void
221     checkStatus(cairo_surface_t* handle)
222     {
223         .checkStatus(cairo_surface_status(handle));
224     }
225
226     void
227     setWrapFunction(SurfaceWrapFunc func, cairo_surface_t* handle)
228     {
229         // First, check to see if the user data has already been set.
230         void* wrapfunc = cairo_surface_get_user_data(handle,
231                 WRAPFUNC_KEY);
232
233         // Only continue if the cast function hasn't been set yet.
234         if( wrapfunc == null )
235         {
236             cairo_surface_set_user_data(handle, WRAPFUNC_KEY,
237                     cast(void*) func, dummy_surface_delete_func);
238             checkStatus(handle);
239         }
240     }
241 }
242
243 // The following are used to implement correct surface-from-handle casting.
244 package
245 {
246     // The following implements a dummy delete function.  This is handy
247     // because we *really* don't want to try deleting stuff from the code
248     // segment...
249     private void _func(void* data) {}
250     static dummy_surface_delete_func = cast(cairo_destroy_func_t) &_func;
251
252     // This is the function pointer type that we'll store in our user data
253     // field.  It should return a new instance of a Surface subclass wrapping
254     // the given handle.
255     alias Surface function(cairo_surface_t*) SurfaceWrapFunc;
256    
257     // This hideous little hack is to get a unique user data key on which to
258     // store our casting function.
259     private static cairo_user_data_key_t _WRAPFUNC_KEY;
260     static WRAPFUNC_KEY = &_WRAPFUNC_KEY;
261 }
Note: See TracBrowser for help on using the browser.