root/trunk/import/htmlayout/graphin.d

Revision 24, 17.0 kB (checked in by yidabu, 1 year ago)

some changes for works with tango 0.99.9, dmd 1.056

Line 
1 module htmlayout.graphin;
2
3 import htmlayout.capi;
4 import tango.sys.win32.Types;
5 import tango.stdc.stringz;
6 import tango.text.convert.Utf;
7 import tango.io.model.IConduit;
8 import tango.io.device.File;
9 import htmlayout.htmlayout; //bug, not import this
10 class HImage
11 {
12     protected this(HIMG h,UINT sizex,UINT sizey)
13     {
14         mHandle=h;
15         mWidth=sizex;
16         mHeight=sizey;
17     }
18
19     ~this()
20     {
21         if(mHandle) mGraphin.imageRelease(mHandle);
22     }
23
24     static HImage opCall(UINT sizex,UINT sizey)
25     {
26         if(mGraphin is null) mGraphin=gApi();
27         HIMG himg;
28         if(mGraphin.imageCreate(sizex,sizey,&himg)==GRAPHIN_OK && himg) return new HImage(himg,sizex,sizey);
29         else return null;
30     }
31
32     static HImage opCall(char[] data) // loads image from png or jpeg enoded data
33     {
34         if(mGraphin is null) mGraphin=gApi();
35         HIMG himg;
36         if(mGraphin.imageLoad(cast(ubyte*)data.ptr,data.length,&himg)==GRAPHIN_OK && himg)
37         {
38             BYTE* ddata;UINT width;UINT height;INT stride;UINT pixel_format;
39             mGraphin.imageGetInfo(himg,&ddata,&width,&height,&stride,&pixel_format);
40             return new HImage(himg,width,height);
41         }
42         else return null;
43     }
44
45     bool save(OutputStream strm,uint quality = 0 /*JPEG qquality: 20..100,if 0 - PNG */) // save image as png or jpeg enoded data
46     {
47         static uint lastsaver=0;
48         auto id=++lastsaver;
49         mSavers[id]=strm;
50         scope(exit) mSavers.remove(id);
51         if(quality >= 1 && quality <= 100) // jpeg
52             return (lastResult = mGraphin.imageSave(mHandle,&mWriteImage,cast(void*)id,24,1,quality))==GRAPHIN_OK;
53         else // png
54             return (lastResult = mGraphin.imageSave(mHandle,&mWriteImage,cast(void*)id,32,0,0))==GRAPHIN_OK;
55     }
56
57     bool save(char[] file,uint quality=0)
58     {
59         File f;
60         try
61             f=new File(file,File.WriteCreate);
62         catch(Object o)
63             return false;
64         scope(exit) f.close;
65         return save(f,quality);
66     }
67
68     uint width() {return mWidth;}
69     uint height() {return mHeight;}
70     HIMG handle() {return mHandle;}
71
72     bool clear(){return (lastResult=mGraphin.imageClear(mHandle))==GRAPHIN_OK;}
73
74     // bitblit it to the hdc
75     bool blit(HPLATFORMGFX hdc,INT dx,INT dy,INT sx=0,INT sy=0,INT w=-1,INT h=-1,bool blend=true){return (lastResult=mGraphin.imageBlit(hdc,dx,dy,mHandle,sx,sy,w<0?mWidth:w,h<0?mHeight:h,blend?1:0))==GRAPHIN_OK;}
76
77     bool renderElement(htmlayout.element.HElement e,int x,int y,bool now=true){return (lastResult=HTMLayoutRenderElement(mHandle,POINT(x,y),e.handle,now?1:0))==GRAPHIN_OK;}
78
79     GRAPHIN_RESULT lastResult;
80     char[] lastResultMsg() {return graphinResultMsg(lastResult);}
81
82 protected:
83     HIMG mHandle;
84     UINT mWidth;
85     UINT mHeight;
86     static Graphin *mGraphin;
87
88     static tango.io.model.IConduit.OutputStream[uint] mSavers;
89
90     extern(Windows) static BOOL mWriteImage(LPVOID prm, LPBYTE data, UINT data_length)
91     {
92         auto saver=cast(uint)prm in mSavers;
93         if(saver && *saver) return saver.write(data[0..data_length])==data_length;
94         else return false;
95     }
96 }
97
98 class HGraphics
99 {
100     HGFX handle() {return mHandle;}
101
102     this(HImage img)
103     {
104         if(!img || !img.handle) throw new Exception("Bad image handle!");
105         if(mGraphin is null) mGraphin=gApi();
106         mGraphin.gCreate(img.handle,&mHandle);
107     }
108     ~this() {if(mHandle) mGraphin.gRelease(mHandle);}
109
110     static HGraphics opCall(HImage img)
111     {
112         if(img && img.handle) return new HGraphics(img);
113         else return null;
114     }
115
116     // Draws line from x1,y1 to x2,y2 using current line_color and line_gradient.
117     bool line(POS x1,POS y1,POS x2,POS y2){return (lastResult=mGraphin.gLine(mHandle,x1,y1,x2,y2))==GRAPHIN_OK;}
118
119     // Draws triangle using current lineColor/lineGradient and fillColor/fillGradient.
120     bool triangle(POS x1,POS y1,POS x2,POS y2,POS x3,POS y3){return (lastResult=mGraphin.gTriangle(mHandle,x1,y1,x2,y2,x3,y3))==GRAPHIN_OK;}
121
122     // Draws rectangle using current lineColor/lineGradient and fillColor/fillGradient
123     bool rectangle(POS x1,POS y1,POS x2,POS y2){return (lastResult=mGraphin.gRectangle(mHandle,x1,y1,x2,y2))==GRAPHIN_OK;}
124
125     // Draws rounded rectangle using current lineColor/lineGradient and fillColor/fillGradient with rounded corners.
126     bool rectangle(POS x1,POS y1,POS x2,POS y2,DIM rAll)
127     {
128         scope DIM[8] rad = [rAll,rAll,rAll,rAll,rAll,rAll,rAll,rAll];
129         return (lastResult=mGraphin.gRoundedRectangle(mHandle,x1,y1,x2,y2,rad.ptr))==GRAPHIN_OK;
130     }
131
132     bool rectangle(POS x1,POS y1,POS x2,POS y2,DIM rTopLeft,DIM rTopRight,DIM rBottomRight,DIM rBottomLeft)
133     {
134         scope DIM[8] rad = [rTopLeft,rTopLeft,rTopRight,rTopRight,rBottomRight,rBottomRight,rBottomLeft,rBottomLeft];
135         return (lastResult=mGraphin.gRoundedRectangle(mHandle,x1,y1,x2,y2,rad.ptr))==GRAPHIN_OK;
136     }
137
138
139     // Draws circle or ellipse using current lineColor/lineGradient and fillColor/fillGradient.
140     bool ellipse(POS x,POS y,POS rx,POS ry){return (lastResult=mGraphin.gEllipse(mHandle,x,y,rx,ry))==GRAPHIN_OK;}
141     bool circle(POS x,POS y,POS radii){return (lastResult=mGraphin.gEllipse(mHandle,x,y,radii,radii))==GRAPHIN_OK;}
142
143     // Draws closed arc using current lineColor/lineGradient and fillColor/fillGradient.
144     bool arc(POS x,POS y,POS rx,POS ry,ANGLE start,ANGLE sweep){return (lastResult=mGraphin.gArc(mHandle,x,y,rx,ry,start,sweep))==GRAPHIN_OK;}
145
146     // Draws star.
147     bool star(POS x,POS y,POS r1,POS r2,ANGLE start,UINT rays){return (lastResult=mGraphin.gStar(mHandle,x,y,r1,r2,start,rays))==GRAPHIN_OK;}
148
149     // Draws closed polygon using current lineColor/lineGradient and fillColor/fillGradient.
150     bool polygon(POS* xy,UINT num_points){return (lastResult=mGraphin.gPolygon(mHandle,xy,num_points))==GRAPHIN_OK;}
151
152     // you bet
153     bool polyline(POS* xy,uint num_points){return (lastResult=mGraphin.gPolyline(mHandle,xy,num_points))==GRAPHIN_OK;}
154
155     // SECTION: Path operations
156
157     bool openPath(){return (lastResult=mGraphin.gOpenPath(mHandle))==GRAPHIN_OK;}
158
159     bool moveTo(POS x,POS y,bool relative){return (lastResult=mGraphin.gMoveTo(mHandle,x,y,relative))==GRAPHIN_OK;}
160
161     bool lineTo(POS x,POS y,bool relative){return (lastResult=mGraphin.gLineTo(mHandle,x,y,relative))==GRAPHIN_OK;}
162
163     bool hlineTo(POS x,bool relative){return (lastResult=mGraphin.gHLineTo(mHandle,x,relative))==GRAPHIN_OK;}
164
165     bool vlineTo(POS y,bool relative){return (lastResult=mGraphin.gVLineTo(mHandle,y,relative))==GRAPHIN_OK;}
166
167     bool arcTo(POS x,POS y,ANGLE angle,POS rx,POS ry,bool is_large_arc,bool sweep_flag,bool relative){return (lastResult=mGraphin.gArcTo(mHandle,x,y,angle,rx,ry,is_large_arc,sweep_flag,relative))==GRAPHIN_OK;}
168
169     bool ellipseTo(POS x,POS y,POS rx,POS ry,bool clockwise){return (lastResult=mGraphin.gEllipseTo(mHandle,x,y,rx,ry,clockwise))==GRAPHIN_OK;}
170
171     bool quadraticCurveTo(POS xc,POS yc,POS x,POS y,bool relative){return (lastResult=mGraphin.gQuadraticCurveTo(mHandle,xc,yc,x,y,relative))==GRAPHIN_OK;}
172
173     bool bezierCurveTo(POS xc1,POS yc1,POS xc2,POS yc2,POS x,POS y,bool relative){return (lastResult=mGraphin.gBezierCurveTo(mHandle,xc1,yc1,xc2,yc2,x,y,relative))==GRAPHIN_OK;}
174
175     bool closePath(){return (lastResult=mGraphin.gClosePath(mHandle))==GRAPHIN_OK;}
176
177     bool drawPath(DRAW_PATH_MODE dpm){return (lastResult=mGraphin.gDrawPath(mHandle,dpm))==GRAPHIN_OK;}
178
179     // end of path opearations
180
181     // SECTION: affine tranformations:
182
183     bool rotate(ANGLE radians){return (lastResult=mGraphin.gRotate(mHandle,radians,null,null))==GRAPHIN_OK;}
184
185     bool rotate(ANGLE radians,POS center_x,POS center_y){return (lastResult=mGraphin.gRotate(mHandle,radians,&center_x,&center_y))==GRAPHIN_OK;}
186
187     bool translate(POS cx,POS cy){return (lastResult=mGraphin.gTranslate(mHandle,cx,cy))==GRAPHIN_OK;}
188
189     bool scale(REAL x,REAL y){return (lastResult=mGraphin.gScale(mHandle,x,y))==GRAPHIN_OK;}
190
191     bool skew(REAL dx,REAL dy){return (lastResult=mGraphin.gSkew(mHandle,dx,dy))==GRAPHIN_OK;}
192
193     // all above in one shot
194     bool transform(POS m11,POS m12,POS m21,POS m22,POS dx,POS dy){return (lastResult=mGraphin.gTransform(mHandle,m11,m12,m21,m22,dx,dy))==GRAPHIN_OK;}
195
196     // end of affine tranformations.
197
198     // SECTION: state save/restore
199
200     bool stateSave(){return (lastResult=mGraphin.gStateSave(mHandle))==GRAPHIN_OK;}
201
202     bool stateRestore(){return (lastResult=mGraphin.gStateRestore(mHandle))==GRAPHIN_OK;}
203
204     // end of state save/restore
205
206     // SECTION: drawing attributes
207
208     // set line width for subsequent drawings.
209     bool lineWidth(DIM width){return (lastResult=mGraphin.gLineWidth(mHandle,width))==GRAPHIN_OK;}
210
211     bool noLine() {return lineWidth(0.0);}
212
213     bool lineColor(HColor c) {return (lastResult=mGraphin.gLineColor(mHandle,graphinColor(c)))==GRAPHIN_OK;}
214
215     bool lineCap(LINE_CAP_TYPE ct){return (lastResult=mGraphin.gLineCap(mHandle,ct))==GRAPHIN_OK;}
216
217     bool lineJoin(LINE_JOIN_TYPE jt){return (lastResult=mGraphin.gLineJoin(mHandle,jt))==GRAPHIN_OK;}
218
219     // color for solid fills
220     bool fillColor(HColor c){return (lastResult=mGraphin.gFillColor(mHandle,graphinColor(c)))==GRAPHIN_OK;}
221
222     bool noFill(){return fillColor(*HColor(0,0,0,0xff));}
223
224     // setup parameters of linear gradient of lines.
225     bool lineLinearGradient(POS x1,POS y1,POS x2,POS y2,HColorStop[] stops){return (lastResult=mGraphin.gLineGradientLinear(mHandle,x1,y1,x2,y2,stops.ptr,stops.length))==GRAPHIN_OK;}
226     bool lineLinearGradient(POS x1,POS y1,POS x2,POS y2,HColor c1,HColor c2){auto stops = [ *HColorStop(graphinColor(c1),0.0),*HColorStop(graphinColor(c2),1.0) ];return fillLinearGradient(x1,y1,x2,y2,stops);
227     }
228
229     // setup parameters of linear gradient of fills.
230     bool fillLinearGradient(POS x1,POS y1,POS x2,POS y2,HColorStop[] stops){return (lastResult=mGraphin.gFillGradientLinear(mHandle,x1,y1,x2,y2,stops.ptr,stops.length))==GRAPHIN_OK;}
231
232     bool fillLinearGradient(POS x1,POS y1,POS x2,POS y2,HColor c1,HColor c2){auto stops = [ *HColorStop(graphinColor(c1),0.0),*HColorStop(graphinColor(c2),1.0) ];return fillLinearGradient(x1,y1,x2,y2,stops);
233     }
234
235     // setup parameters of line gradient radial fills.
236     bool lineRadialGradient(POS x,POS y,DIM radii,HColorStop[] stops){return (lastResult=mGraphin.gFillGradientRadial(mHandle,x,y,radii,stops.ptr,stops.length))==GRAPHIN_OK;}
237
238     bool lineRadialGradient(POS x,POS y,DIM radii,HColor c1,HColor c2){auto stops = [ *HColorStop(graphinColor(c1),0.0),*HColorStop(graphinColor(c2),1.0) ];return lineRadialGradient(x,y,radii,stops);
239     }
240
241     // setup parameters of gradient radial fills.
242     bool fillRadialGradient(POS x,POS y,DIM radii,HColorStop[] stops){return (lastResult=mGraphin.gFillGradientRadial(mHandle,x,y,radii,stops.ptr,stops.length))==GRAPHIN_OK;}
243
244     bool fillRadialGradient(POS x,POS y,DIM radii,HColor c1,HColor c2){auto stops = [ *HColorStop(graphinColor(c1),0.0),*HColorStop(graphinColor(c2),1.0) ];return fillRadialGradient(x,y,radii,stops);
245     }
246
247
248     bool fillMode(bool even_odd /* false - fill_non_zero */){return (lastResult=mGraphin.gFillMode(mHandle,even_odd))==GRAPHIN_OK;}
249
250     // SECTION: text
251
252     // define font attributes for all subsequent text operations.
253     bool font(char[] name,DIM size,bool bold = false,bool italic = false,ANGLE angle = 0){return (lastResult=mGraphin.gSetFont(mHandle,toStringz(name),size,bold,italic,angle))==GRAPHIN_OK;}
254
255     // draw text at x,y with text alignment
256     bool text(POS x,POS y,char[] t){auto str=toString16(t);return (lastResult=mGraphin.gText(mHandle,x,y,str.ptr,str.length))==GRAPHIN_OK;
257     }
258
259     // calculates width of the text string
260     DIM textWidth(char[] t)
261     {
262         DIM width;
263         auto str=toString16(t);
264         if((lastResult=mGraphin.gTextWidth(mHandle,str.ptr,str.length,&width))==GRAPHIN_OK) return width;
265         else return -1;
266     }
267
268     // returns height and ascent of the font.
269     bool fontMetrics(ref DIM height,ref DIM ascent){return (lastResult=mGraphin.gFontMetrics(mHandle,&height,&ascent))==GRAPHIN_OK;}
270
271     // set text alignments
272     bool textAlignment(TEXT_ALIGNMENT x,TEXT_ALIGNMENT y){return (lastResult=mGraphin.gTextAlignment(mHandle,x,y))==GRAPHIN_OK;}
273
274     // SECTION: image rendering
275
276     // draws img onto the graphics surface with current transformation applied(scale,rotation). expensive
277     bool drawImage(HImage pimg,POS x,POS y,DIM w,DIM h,UINT ix,UINT iy,UINT iw,UINT ih){return (lastResult=mGraphin.gDrawImage(mHandle,pimg.handle,x,y,&w,&h,&ix,&iy,&iw,&ih))==GRAPHIN_OK;}
278     // draws whole img onto the graphics surface with current transformation applied(scale,rotation). expensive
279     bool drawImage(HImage pimg,POS x,POS y){return (lastResult=mGraphin.gDrawImage(mHandle,pimg.handle,x,y,null,null,null,null,null,null))==GRAPHIN_OK;}
280     // blends image bits with bits of the surface. no affine transformations. less expensive
281     bool blendImage(HImage pimg,POS x,POS y,UINT opacity,UINT ix,UINT iy,UINT iw,UINT ih){return (lastResult=mGraphin.gBlendImage(mHandle,pimg.handle,x,y,opacity,&ix,&iy,&iw,&ih))==GRAPHIN_OK;}
282     // blends image bits with bits of the surface. no affine transformations. less expensive
283     bool blendImage(HImage pimg,POS x,POS y,UINT opacity){return (lastResult=mGraphin.gBlendImage(mHandle,pimg.handle,x,y,opacity,null,null,null,null))==GRAPHIN_OK;}
284     // blits image bits onto underlying pixel buffer. no affine transformations.
285     bool blitImage(HImage pimg,POS x,POS y,UINT ix,UINT iy,UINT iw,UINT ih){return (lastResult=mGraphin.gBlitImage(mHandle,pimg.handle,x,y,&ix,&iy,&iw,&ih))==GRAPHIN_OK;}
286     // blits image bits onto underlying pixel buffer. no affine transformations.
287     bool blitImage(HImage pimg,POS x,POS y){return (lastResult=mGraphin.gBlitImage(mHandle,pimg.handle,x,y,null,null,null,null))==GRAPHIN_OK;}
288
289     // SECTION: coordinate space
290
291     bool worldToScreen(ref POS inout_x,ref POS inout_y){return (lastResult=mGraphin.gWorldToScreen(mHandle,&inout_x,&inout_y))==GRAPHIN_OK;}
292
293     bool worldToScreen(ref DIM inout_length){return (lastResult=mGraphin.gWorldToScreen(mHandle,&inout_length,null))==GRAPHIN_OK;}
294
295     bool screenToWorld(ref POS inout_x,ref POS inout_y){return (lastResult=mGraphin.gScreenToWorld(mHandle,&inout_x,&inout_y))==GRAPHIN_OK;}
296
297     bool screenToWorld(ref DIM inout_length){return (lastResult=mGraphin.gScreenToWorld(mHandle,&inout_length,null))==GRAPHIN_OK;}
298
299     // SECTION: clipping
300
301     bool setClipBox(POS x1,POS y1,POS x2,POS y2){return (lastResult=mGraphin.gSetClipBox(mHandle,x1,y1,x2,y2))==GRAPHIN_OK;}
302
303     bool getClipBox(ref POS x1,ref POS y1,ref POS x2,ref POS y2){return (lastResult=mGraphin.gGetClipBox(mHandle,&x1,&y1,&x2,&y2))==GRAPHIN_OK;}
304
305     bool visible(POS x,POS y)
306     {
307         BOOL is_in = 0;
308         return (lastResult=mGraphin.gPointInClipBox(mHandle,x,y,&is_in))==GRAPHIN_OK;
309         return is_in != 0;
310     }
311
312     bool visible(POS x1,POS y1,POS x2,POS y2)
313     {
314         BOOL is_in = 0;
315         return (lastResult=mGraphin.gRectInClipBox(mHandle,x1,y1,x2,y2,&is_in))==GRAPHIN_OK;
316         return is_in != 0;
317     }
318
319     GRAPHIN_RESULT lastResult;
320     char[] lastResultMsg() {return graphinResultMsg(lastResult);}
321
322 protected:
323     HGFX mHandle;
324     static Graphin *mGraphin;
325 }
326
327 struct HColor
328 {
329     byte r,g,b,a;
330
331     static HColor* opCall()
332     {
333         auto ret=new HColor;
334         ret.a=cast(byte)0xff;
335         return ret;
336     }
337
338     static HColor* opCall(uint rgbt=0x000000ff)
339     {
340         auto ret=new HColor;
341         ret.r=rgbt & 0xff;
342         ret.g=(rgbt & 0xff00) >> 8;
343         ret.b=(rgbt & 0xff0000) >> 16;
344         ret.a=(rgbt & 0xff000000) >> 24;
345         return ret;
346     }
347
348     static HColor* opCall(uint red,uint green,uint blue,uint alpha=0)
349     {
350         auto ret=new HColor;
351         ret.r=cast(byte)red;
352         ret.g=cast(byte)green;
353         ret.b=cast(byte)blue;
354         ret.a=cast(byte)alpha;
355         return ret;
356     }
357
358     HColor* clone()
359     {
360         auto ret=new HColor;
361         *ret=*this;
362         return ret;
363     }
364    
365     bool transparent() {return a == 0xff;}
366
367     /*HColor* parse(char[] text,HColor *default_value = HColor())
368     {
369         if(text.length == 0)
370             return default_value;
371         if(text[0] == '#') // #xxx,#xxxx,#xxxxxx,#xxxxxxxx
372         {
373             int R = 0,G = 0,B = 0,T = 0;
374             switch(text.length)
375             {
376                 case 4: swscanf(text.start+1 ,L"%1x%1x%1x",&R,&G,&B);R <<= 4;G <<= 4;B <<= 4;break;
377                 case 5: swscanf(text.start+1 ,L"%1x%1x%1x%1x",&R,&G,&B,&T);R <<= 4;G <<= 4;B <<= 4;T <<= 4;break;
378                 case 7: swscanf(text.start+1 ,L"%2x%2x%2x",&R,&G,&B);break;
379                 case 9: swscanf(text.start+1 ,L"%2x%2x%2x%2x",&R,&G,&B,&T);break;
380                 default: return default_value;
381             }
382             return color(R,G,B,T);
383         }
384         else if(text.like(L"rgb(*)")) // rgb(r,g,b),rgb(r,g,b,a)
385         {
386             text.start += 4;text.length -= 5;
387             unsigned ca[4] = {0};aux::wchars tok;aux::wtokens toks(text,L",");
388             for(int n = 0;n < 4;++n)
389             {
390                 if(!toks.next(tok)) break;
391                 ca[n] = aux::to_uint(tok);
392                 if(tok.start[tok.length] == '%')    ca[n] =(ca[n] * 255) / 100;
393             }
394             return color(aux::limit(ca[0],0U,255U),aux::limit(ca[1],0U,255U),aux::limit(ca[2],0U,255U),aux::limit(ca[3],0U,255U));
395         }
396         return default_value;
397     }*/
398 }
399
400 private Graphin* gApi()
401 {
402     static Graphin *mGraphin;
403     if(mGraphin is null) mGraphin=HTMLayoutGetGraphin();
404     return mGraphin;
405 }
406
407 COLOR graphinColor(HColor c) {return gApi.RGBT(c.r,c.g,c.b,c.a);}
408 COLOR graphinColor(uint r,uint g,uint b,uint a = 0) {return gApi.RGBT(r,g,b,a);}
409
410 char[] graphinResultMsg(GRAPHIN_RESULT res)
411 {
412     if(res==GRAPHIN_PANIC) return "GRAPHIN_PANIC - e.g. not enough memory";
413     else if(res==GRAPHIN_OK) return "GRAPHIN_OK";
414     else if(res==GRAPHIN_BAD_PARAM) return "GRAPHIN_BAD_PARAM - bad parameter";
415     else if(res==GRAPHIN_FAILURE) return "GRAPHIN_FAILURE - operation failed,e.g. restore() without save()";
416     else if(res==GRAPHIN_NOTSUPPORTED) return "GRAPHIN_NOTSUPPORTED - the platform does not support requested feature";
417     else return null;
418 }
Note: See TracBrowser for help on using the browser.