applied MSVC compatibility patch from Dwight Kelly
[swftools.git] / lib / devices / opengl.c
index a789f54..c8efc05 100644 (file)
@@ -5,6 +5,8 @@
 
 #include "../gfxdevice.h"
 #include "../gfxtools.h"
+#include "../MD5.h"
+#include "../types.h"
 
 #include <math.h>
 #include <time.h>
@@ -14,7 +16,8 @@
 #include <stdarg.h>
 
 //#define ZSTEP (1/65536.0)
-#define ZSTEP (1/8.0)
+#define ZSTEP (1/32.0)
+//#define ZSTEP (1/4.0)
 
 typedef struct _fontlist {
     gfxfont_t*font;
@@ -65,12 +68,12 @@ void CALLBACK errorCallback(GLenum errorCode)
 {
    const GLubyte *estring;
    estring = gluErrorString(errorCode);
-   dbg("Tessellation Error: %s\n", estring);
+   printf("Tessellation Error: %s\n", estring);
    exit(0);
 }
 void CALLBACK beginCallback(GLenum which)
 {
-   glBegin(which);
+    glBegin(which);
 }
 void CALLBACK endCallback(void)
 {
@@ -179,6 +182,8 @@ void opengl_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxc
     glLineWidth(1.0);
 }
 
+#define SPLINE_SUBDIVISION 2
+
 void tesselatePolygon(GLUtesselator*tesselator, double z, gfxline_t*line)
 {
     int len = 0;
@@ -191,7 +196,7 @@ void tesselatePolygon(GLUtesselator*tesselator, double z, gfxline_t*line)
     len = 0;
     while(l) {
        if(l->type == gfx_splineTo) {
-            double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))/2;
+            double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))*SPLINE_SUBDIVISION;
            int steps = (int)c;
            if(steps<1) steps = 1;
            len += steps;
@@ -218,7 +223,7 @@ void tesselatePolygon(GLUtesselator*tesselator, double z, gfxline_t*line)
 
        if(l->type == gfx_splineTo) {
            int j;
-            double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))/2;
+            double c = sqrt(abs(l->x-2*l->sx+lastx) + abs(l->y-2*l->sy+lasty))*SPLINE_SUBDIVISION;
            int steps = (int)c;
            if(steps<1) steps = 1;
            //printf("c=%f d1=%f (%f/%f) d2=%f (%f/%f)\n", c,d1,l->x-l->sx,l->y-l->sy,d2,lastx-l->sx,lasty-l->sy);
@@ -259,7 +264,8 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color)
     double z;
     dbg("fill");
     internal_t*i = (internal_t*)dev->internal;
-    
+  
+    glDisable(GL_TEXTURE_2D);
     glColor4f(color->r/255.0, color->g/255.0, color->b/255.0, color->a/255.0);
     
     i->currentz ++;
@@ -269,21 +275,41 @@ void opengl_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color)
     //tesselatePolygon(i->tesselator_line, z, line);
 }
 
-void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
+typedef struct _gfxhash
 {
-    dbg("fillbitmap");
-    internal_t*i = (internal_t*)dev->internal;
-    char running = 0;
-    int len = 0;
-    double*xyz=0;
-    gfxline_t*l=0;
-    glColor4f(1.0,0,0,1.0);
-    
-    i->currentz ++;
-    
-    GLuint texIDs[1];
-    glGenTextures(1, texIDs);
+    unsigned char d[16];
+} gfxhash_t;
+
+char gfxhash_compare(gfxhash_t*h1, gfxhash_t*h2)
+{
+    return !memcmp(h1->d, h2->d, 16);
+}
+
+typedef struct _imgopengl
+{
+    gfxhash_t hash;
+    GLuint texID;
+    int width, height;
+    struct _imgopengl*next;
+} imgopengl_t;
+
+imgopengl_t*img2texid = 0;
 
+gfxhash_t gfximage_hash(gfximage_t*img)
+{
+    int t;
+    int size = img->width*img->height*4;
+    U8*data = (U8*)img->data;
+    gfxhash_t hash;
+    hash_md5(data, size, hash.d);
+    return hash;
+}
+
+imgopengl_t*addTexture(gfximage_t*img)
+{
+    gfxhash_t hash = gfximage_hash(img);
+    imgopengl_t*i = img2texid;
+    
     int width_bits = 0;
     int height_bits = 0;
     while(1<<width_bits < img->width)
@@ -293,6 +319,25 @@ void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf
     int newwidth = 1<<width_bits;
     int newheight = 1<<height_bits;
 
+    while(i) {
+        if(gfxhash_compare(&hash, &i->hash) && newwidth==i->width && newheight==i->height) {
+            return i;
+        }
+        i = i->next;
+    }
+    
+    GLuint texIDs[1];
+    glGenTextures(1, texIDs);
+
+    i = malloc(sizeof(imgopengl_t));
+    i->hash = hash;
+    i->texID = texIDs[0];
+    i->next = img2texid;
+    img2texid = i;
+
+    i->width = newwidth;
+    i->height = newheight;
+
     unsigned char*data = malloc(newwidth*newheight*4);
     int x,y;
     for(y=0;y<img->height;y++) {
@@ -319,28 +364,45 @@ void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf
            data[(y*newwidth+x)*4+3] = img->data[lasty*img->width+x].a;
         }
     }
+    
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, i->texID);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, i->width, i->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+    
+    return i;
+};
+
+void opengl_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
+{
+    dbg("fillbitmap");
+    internal_t*i = (internal_t*)dev->internal;
+    char running = 0;
+    int len = 0;
+    double*xyz=0;
+    gfxline_t*l=0;
+    glColor4f(1.0,0,0,1.0);
+    
+    i->currentz ++;
+  
+    imgopengl_t* txt = addTexture(img);
 
     gfxmatrix_t m2;
     gfxmatrix_invert(matrix, &m2);
-    m2.m00 /= newwidth;
-    m2.m10 /= newwidth;
-    m2.tx /= newwidth;
-    m2.m01 /= newheight;
-    m2.m11 /= newheight;
-    m2.ty /= newheight;
+    m2.m00 /= txt->width;
+    m2.m10 /= txt->width;
+    m2.tx /= txt->width;
+    m2.m01 /= txt->height;
+    m2.m11 /= txt->height;
+    m2.ty /= txt->height;
 
     glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, texIDs[0]);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newwidth, newheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-    
-    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, txt->texID);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     
-    
     gluTessBeginPolygon(i->tesselator_tex, NULL);
     l = line;
     len = 0;
@@ -416,6 +478,8 @@ void opengl_addfont(gfxdevice_t*dev, gfxfont_t*font)
 void opengl_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
 {
     internal_t*i = (internal_t*)dev->internal;
+    if(!font)
+       return;
 
     if(i->font && i->font->id && !strcmp(font->id, i->font->id)) {
        // current font is correct
@@ -430,8 +494,10 @@ void opengl_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*co
            l = l->next;
        }
        if(i->font == 0) {
-           fprintf(stderr, "Unknown font id: %s", font->id);
-           return;
+            opengl_addfont(dev, font);
+            i->font = font;
+           //fprintf(stderr, "Unknown font id: %s", font->id);
+           //return;
        }
     }
 
@@ -518,7 +584,7 @@ void gfxdevice_opengl_init(gfxdevice_t*dev)
     gluTessCallback(i->tesselator, GLU_TESS_VERTEX, (callbackfunction_t)vertexCallback);
     gluTessCallback(i->tesselator, GLU_TESS_BEGIN, (callbackfunction_t)beginCallback);
     gluTessCallback(i->tesselator, GLU_TESS_END, (callbackfunction_t)endCallback);
-    //gluTessCallback(i->tesselator, GLU_TESS_COMBINE, (callbackfunction_t)combineCallback);
+    gluTessCallback(i->tesselator, GLU_TESS_COMBINE, (callbackfunction_t)combineCallback);
     
     i->tesselator_line = gluNewTess();
     gluTessCallback(i->tesselator_line, GLU_TESS_ERROR, (callbackfunction_t)errorCallback);