5 #include "../gfxdevice.h"
6 #include "../gfxtools.h"
14 #define ZSTEP (1/65536.0)
16 typedef struct _fontlist {
19 struct _fontlist*next;
22 typedef struct _internal {
29 GLUtesselator *tesselator;
30 GLUtesselator *tesselator_tex;
35 static void dbg(char*format, ...)
42 va_start(arglist, format);
43 vsprintf(buf, format, arglist);
46 while(l && buf[l-1]=='\n') {
50 printf("(device-opengl) %s\n", buf);
58 typedef void(*callbackfunction_t)();
60 void CALLBACK errorCallback(GLenum errorCode)
62 const GLubyte *estring;
63 estring = gluErrorString(errorCode);
64 dbg("Tessellation Error: %s\n", estring);
67 void CALLBACK beginCallback(GLenum which)
71 void CALLBACK endCallback(void)
75 void CALLBACK vertexCallback(GLvoid *vertex)
77 double*xyz = (GLdouble*)vertex;
78 glVertex3d(xyz[0],xyz[1],xyz[2]);
80 void CALLBACK vertexCallbackTex(GLvoid *vertex)
82 double*v = (GLdouble*)vertex;
83 glTexCoord2f(v[3],v[4]);
84 glVertex3d(v[0],v[1],v[2]);
86 void CALLBACK combineCallbackTex(GLdouble coords[3], GLdouble *data[4], GLfloat w[4], GLdouble **out)
88 GLdouble *vertex, *texCoord;
89 vertex = (GLdouble *) malloc(5 * sizeof(GLdouble));
90 vertex[0] = coords[0];
91 vertex[1] = coords[1];
92 vertex[2] = coords[2];
93 texCoord = &vertex[3];
94 vertex[3] = w[0]*data[0][3] + w[1]*data[1][3] + w[2]*data[2][3] + w[3]*data[3][3];
95 vertex[4] = w[0]*data[0][4] + w[1]*data[1][4] + w[2]*data[2][4] + w[3]*data[3][4];
99 int opengl_setparameter(struct _gfxdevice*dev, const char*key, const char*value)
101 dbg("setparameter %s=%s", key, value);
105 void opengl_startpage(struct _gfxdevice*dev, int width, int height)
107 dbg("startpage %d %d", width, height);
108 internal_t*i = (internal_t*)dev->internal;
114 void opengl_startclip(struct _gfxdevice*dev, gfxline_t*line)
119 void opengl_endclip(struct _gfxdevice*dev)
124 void opengl_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
126 internal_t*i = (internal_t*)dev->internal;
130 glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0);
135 if(l->type == gfx_moveTo) {
143 glBegin(GL_LINE_STRIP);
145 glVertex3d(l->x, l->y, (i->currentz*ZSTEP));
155 void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color)
157 internal_t*i = (internal_t*)dev->internal;
163 glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0);
165 gluTessBeginPolygon(i->tesselator, NULL);
172 xyz = malloc(sizeof(double)*3*len);
176 if(l->type == gfx_moveTo) {
179 gluTessEndContour(i->tesselator);
184 gluTessBeginContour(i->tesselator);
189 xyz[len*3+2] = (i->currentz*ZSTEP);
190 gluTessVertex(i->tesselator, &xyz[len*3], &xyz[len*3]);
197 gluTessEndContour(i->tesselator);
199 gluTessEndPolygon(i->tesselator);
204 void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
206 internal_t*i = (internal_t*)dev->internal;
211 glColor4f(1.0,0,0,1.0);
214 glGenTextures(1, texIDs);
218 while(1<<width_bits < img->width)
220 while(1<<height_bits < img->height)
222 int newwidth = 1<<width_bits;
223 int newheight = 1<<height_bits;
225 unsigned char*data = malloc(newwidth*newheight*4);
227 for(y=0;y<img->height;y++) {
228 for(x=0;x<img->width;x++) {
229 data[(y*newwidth+x)*4+0] = img->data[y*img->width+x].r;
230 data[(y*newwidth+x)*4+1] = img->data[y*img->width+x].g;
231 data[(y*newwidth+x)*4+2] = img->data[y*img->width+x].b;
232 data[(y*newwidth+x)*4+3] = img->data[y*img->width+x].a;
237 gfxmatrix_invert(matrix, &m2);
245 glEnable(GL_TEXTURE_2D);
246 glBindTexture(GL_TEXTURE_2D, texIDs[0]);
247 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newwidth, newheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
249 glEnable(GL_TEXTURE_2D);
250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
256 gluTessBeginPolygon(i->tesselator_tex, NULL);
263 xyz = malloc(sizeof(double)*5*len);
267 if(l->type == gfx_moveTo) {
270 gluTessEndContour(i->tesselator_tex);
275 gluTessBeginContour(i->tesselator_tex);
280 xyz[len*5+2] = (i->currentz*ZSTEP);
283 gfxmatrix_transform(&m2, /*src*/&xyz[len*5+0], /*dest*/&xyz[len*5+3]);
285 gluTessVertex(i->tesselator_tex, &xyz[len*5], &xyz[len*5]);
292 gluTessEndContour(i->tesselator_tex);
294 gluTessEndPolygon(i->tesselator_tex);
298 glDisable(GL_TEXTURE_2D);
301 void opengl_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
306 void opengl_addfont(gfxdevice_t*dev, char*fontid, gfxfont_t*font)
308 internal_t*i = (internal_t*)dev->internal;
310 fontlist_t*last=0,*l = i->fontlist;
313 if(!strcmp((char*)l->id, fontid)) {
314 return; // we already know this font
318 l = (fontlist_t*)rfx_calloc(sizeof(fontlist_t));
320 l->id = strdup(fontid);
329 void opengl_drawchar(gfxdevice_t*dev, char*fontid, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
331 internal_t*i = (internal_t*)dev->internal;
333 if(i->font && i->fontid && !strcmp(fontid, i->fontid)) {
334 // current font is correct
336 fontlist_t*l = i->fontlist;
340 if(!strcmp((char*)l->id, fontid)) {
348 fprintf(stderr, "Unknown font id: %s", fontid);
353 gfxglyph_t*glyph = &i->font->glyphs[glyphnr];
355 gfxline_t*line2 = gfxline_clone(glyph->line);
356 gfxline_transform(line2, matrix);
357 opengl_fill(dev, line2, color);
365 void opengl_drawlink(struct _gfxdevice*dev, gfxline_t*line, char*action)
370 void opengl_endpage(struct _gfxdevice*dev)
375 int opengl_result_save(struct _gfxresult*gfx, char*filename)
380 void* opengl_result_get(struct _gfxresult*gfx, char*name)
385 void opengl_result_destroy(struct _gfxresult*gfx)
387 dbg("result:destroy");
391 gfxresult_t*opengl_finish(struct _gfxdevice*dev)
394 internal_t*i = (internal_t*)dev->internal;
395 gluDeleteTess(i->tesselator);i->tesselator=0;
396 gluDeleteTess(i->tesselator_tex);i->tesselator_tex=0;
397 gfxresult_t*result = (gfxresult_t*)malloc(sizeof(gfxresult_t));
398 memset(result, 0, sizeof(gfxresult_t));
399 result->save = opengl_result_save;
400 result->get = opengl_result_get;
401 result->destroy = opengl_result_destroy;
405 void gfxdevice_opengl_init(gfxdevice_t*dev)
408 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
409 memset(dev, 0, sizeof(gfxdevice_t));
413 dev->setparameter = opengl_setparameter;
414 dev->startpage = opengl_startpage;
415 dev->startclip = opengl_startclip;
416 dev->endclip = opengl_endclip;
417 dev->stroke = opengl_stroke;
418 dev->fill = opengl_fill;
419 dev->fillbitmap = opengl_fillbitmap;
420 dev->fillgradient = opengl_fillgradient;
421 dev->addfont = opengl_addfont;
422 dev->drawchar = opengl_drawchar;
423 dev->drawlink = opengl_drawlink;
424 dev->endpage = opengl_endpage;
425 dev->finish = opengl_finish;
427 i->tesselator = gluNewTess();
428 gluTessCallback(i->tesselator, GLU_TESS_ERROR, (callbackfunction_t)errorCallback);
429 gluTessCallback(i->tesselator, GLU_TESS_VERTEX, (callbackfunction_t)vertexCallback);
430 gluTessCallback(i->tesselator, GLU_TESS_BEGIN, (callbackfunction_t)beginCallback);
431 gluTessCallback(i->tesselator, GLU_TESS_END, (callbackfunction_t)endCallback);
433 i->tesselator_tex = gluNewTess();
434 gluTessCallback(i->tesselator_tex, GLU_TESS_ERROR, (callbackfunction_t)errorCallback);
435 gluTessCallback(i->tesselator_tex, GLU_TESS_VERTEX, (callbackfunction_t)vertexCallbackTex);
436 gluTessCallback(i->tesselator_tex, GLU_TESS_BEGIN, (callbackfunction_t)beginCallback);
437 gluTessCallback(i->tesselator_tex, GLU_TESS_END, (callbackfunction_t)endCallback);
438 gluTessCallback(i->tesselator_tex, GLU_TESS_COMBINE, (callbackfunction_t)combineCallbackTex);
440 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);