WID comments
[Lilanci.git] / gr.c
blob8fd732ee8c89d1deb32603f72087dc078302cf2f
1 #include "config.h"
2 #include "gr.h"
3 #include <string.h>
4 #include <stdlib.h>
5 #include <limits.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <cairo.h>
9 #include <librsvg/rsvg.h>
10 #include <librsvg/rsvg-cairo.h>
11 #include "font.h"
14 #define TRECT(x,y,w,h, tw, th) glBegin(GL_TRIANGLE_STRIP);glTexCoord2f(0.0,h/th);glVertex2f(x, y+1*h);glTexCoord2f(0.0,0.0);glVertex2f(x, y);glTexCoord2f(w/tw,h/th);glVertex2f(x+1*w, y+1*h);glTexCoord2f(w/tw,0.0);glVertex2f(x+1*w, y);glEnd();
15 #define RECT(x,y,w,h) glBegin(GL_TRIANGLE_STRIP);glVertex2f(x, y+1*h);glVertex2f(x, y);glVertex2f(x+1*w, y+1*h);glVertex2f(x+1*w, y);glEnd();
17 #define TTRECT(x,y,w,h,sw,sh, tw, th) glBegin(GL_TRIANGLE_STRIP);glTexCoord2f(0.0,sh/th);glVertex2f(x, y+1*h);glTexCoord2f(0.0,0.0);glVertex2f(x, y);glTexCoord2f(sw/tw,sh/th);glVertex2f(x+1*w, y+1*h);glTexCoord2f(sw/tw,0.0);glVertex2f(x+1*w, y);glEnd();
19 unsigned int occupied=0;
21 typedef struct{
22 GLuint *surfaces;
23 unsigned int allocated;
24 }SurfaceList;
26 SurfaceList gsprite_surfaces;
27 int AddSurface(GLuint s);
28 void RemoveSurface(GLuint s);
29 void RemoveSID(int SID);
30 void FlushSpriteSurfaces();
31 int SetVideoMode(int width, int height);
32 SDL_Surface *gscreen;
34 typedef struct{
35 Sprite **sprites;
36 unsigned int allocated;
37 }SpriteList;
39 SpriteList gsprites;
40 int AddSprite(Sprite *s);
41 void RemoveSprite(Sprite *s);
43 typedef struct{
44 Sprite *sprite;
45 double x;
46 double y;
47 double xx;
48 double yy;
49 int z; //z
50 SDL_Color c;
51 }SpriteQueueItem;
53 typedef struct{
54 SpriteQueueItem *items;
55 unsigned int allocated;
56 unsigned int next_id;
57 }SpriteQueue;
58 SpriteQueue gsprite_queue;
59 SpriteQueue gsprite_queue_sorted;
60 void FlushSpriteQueue();
61 void RotateSurface(int SID, int rotation);
63 int ginvalidsprites;
65 GLuint load_svg (char *file, int width, int height, double *pdw, double *pdh);
67 int G2SX(double x);
68 int G2SY(double y);
70 int G2SX(double x){
71 return (x/(double)SCREEN_WIDTH)*GetConfig().screen_width;
73 int G2SY(double y){
74 return (y/(double)SCREEN_HEIGHT)*GetConfig().screen_height;
76 double S2GX(int x){
77 return (x*(double)SCREEN_WIDTH)/(double)GetConfig().screen_width;
79 double S2GY(int y){
80 return (y*(double)SCREEN_HEIGHT)/(double)GetConfig().screen_height;
83 int SetVideoMode(int width, int height){
84 SDL_Rect **modes;
85 int ibest;
86 int bestdif;
87 int i;
88 Uint32 flags;
90 Config config=GetConfig();
92 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
93 flags = SDL_OPENGL ;
94 if(config.fullscreen)
95 flags = flags |SDL_FULLSCREEN;
96 /* Get available fullscreen/hardware modes */
97 modes=SDL_ListModes(NULL, flags);
99 /* Check if there are any modes available */
100 if(modes == (SDL_Rect **)0){
101 printf("No modes available!\n");
102 exit(-1);
105 /* Check if our resolution is restricted */
106 if(modes == (SDL_Rect **)-1){
107 printf("All resolutions available.\n");
108 gscreen = SDL_SetVideoMode(config.screen_width, config.screen_height, 0, flags);
110 else{
111 /* Print valid modes */
112 printf("Available Modes\n");
113 bestdif = abs((modes[0]->w - config.screen_width) + (modes[0]->h - config.screen_height));
114 ibest = 0;
115 for(i=0;modes[i];++i){
116 printf(" %d x %d\n", modes[i]->w, modes[i]->h);
117 if(bestdif > abs((modes[i]->w - config.screen_width) + (modes[i]->h - config.screen_height))){
118 bestdif = abs((modes[i]->w - config.screen_width) + (modes[i]->h - config.screen_height));
119 ibest = i;
122 printf("Using: %d x %d\n", modes[ibest]->w, modes[ibest]->h);
123 gscreen = SDL_SetVideoMode(modes[ibest]->w, modes[ibest]->h, 0, flags);
124 config.screen_height = modes[ibest]->h;
125 config.screen_width = modes[ibest]->w;
126 SetConfig(config);
128 return 0;
131 int AddSurface(GLuint s){ //returns -1 on error, SID if success
132 int i;
133 GLuint *tmp;
134 for(i=0;i<gsprite_surfaces.allocated;i++)
135 if( gsprite_surfaces.surfaces[i]==s ){
136 return i;
139 for(i=0;i<gsprite_surfaces.allocated;i++)
140 if( gsprite_surfaces.surfaces[i]==0 ){
141 gsprite_surfaces.surfaces[i]=s;
142 return i;
144 i=gsprite_surfaces.allocated;
145 tmp = (GLuint*) realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*i*2); //if the allocated space is not wide enough, then allocate double space than previous
146 if(tmp==0)
147 return -1;
148 gsprite_surfaces.surfaces=tmp;
149 memset(&gsprite_surfaces.surfaces[i],0, sizeof(GLuint)*i); //zero newly allocated space
150 gsprite_surfaces.allocated=i*2;
151 gsprite_surfaces.surfaces[i]=s;
152 return i;
155 void RemoveSurface(GLuint s){
156 int i,iwannakillyoubitch;
158 iwannakillyoubitch=1;
159 for(i=0;i<gsprite_surfaces.allocated;i++){
160 if( gsprite_surfaces.surfaces[i]==s ){
161 gsprite_surfaces.surfaces[i]=0;
163 if( i>=gsprite_surfaces.allocated/2 && iwannakillyoubitch && gsprite_surfaces.surfaces[i]!=0 )
164 iwannakillyoubitch=0;
167 if(iwannakillyoubitch){
168 gsprite_surfaces.allocated /=2;
169 gsprite_surfaces.surfaces = (GLuint *)realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*gsprite_surfaces.allocated);//TODO:check return value
173 void RemoveSID(int SID){
174 int i,iwannakillyoubitch;
176 iwannakillyoubitch=1;
177 for(i=0;i<gsprite_surfaces.allocated;i++){
178 if( i==SID ){
179 gsprite_surfaces.surfaces[i]=0;
181 if( i>=gsprite_surfaces.allocated/2 && iwannakillyoubitch && gsprite_surfaces.surfaces[i]!=0 )
182 iwannakillyoubitch=0;
185 if(iwannakillyoubitch){
186 gsprite_surfaces.allocated /=2;
187 gsprite_surfaces.surfaces = (GLuint *)realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*gsprite_surfaces.allocated);//TODO:check return value
191 int AddSprite(Sprite *s){//returns 0 on error, Sprite ID on success
192 int i;
193 Sprite **tmp;
194 for(i=0;i<gsprites.allocated;i++)
195 if( gsprites.sprites[i]==s ){
196 return i;
199 for(i=0;i<gsprites.allocated;i++)
200 if( gsprites.sprites[i]==0 ){
201 gsprites.sprites[i]=s;
202 return i;
204 i=gsprites.allocated;
205 tmp=(Sprite **)realloc(gsprites.sprites, sizeof(Sprite *)*i*2); //if the allocated space is not wide enough, then allocate double space than previous
206 if(tmp==0)
207 return 0;
208 gsprites.sprites=tmp;
209 memset(&gsprites.sprites[i],0, sizeof(Sprite *)*i); //zero newly allocated space
210 gsprites.allocated=i*2;
211 gsprites.sprites[i]=s;
212 return i;
215 void RemoveSprite(Sprite *s){
216 int i,iwannakillyoubitch;
218 iwannakillyoubitch=1;
219 for(i=0;i<gsprites.allocated;i++){
220 if( gsprites.sprites[i]==s ){
221 gsprites.sprites[i]=0;
223 if( i>=gsprites.allocated/2 && iwannakillyoubitch && gsprites.sprites[i]!=0 )
224 iwannakillyoubitch=0;
227 if(iwannakillyoubitch){
228 gsprites.allocated /=2;
229 gsprites.sprites = (Sprite **) realloc(gsprites.sprites, sizeof(Sprite *)*gsprites.allocated);//TODO:check return value
233 int GrKill(){
234 Config config;
235 int i;
237 FlushSpriteQueue();
238 FlushSpriteSurfaces();
240 config=GetConfig();
241 free(gsprite_surfaces.surfaces);
242 gsprite_surfaces.surfaces=0;
245 for(i=0; i<gsprites.allocated; i++)
246 if(gsprites.sprites[i]){
247 free(gsprites.sprites[i]->fname);
248 free(gsprites.sprites[i]);
249 gsprites.sprites[i]=0;
252 gsprites.allocated = 0;
255 rsvg_term ();
256 SetVideoMode(config.screen_width, config.screen_height);
258 return 0;
261 int GrInit(){
262 Config config;
264 config=GetConfig();
265 rsvg_init();
266 gsprite_surfaces.surfaces = (GLuint*) calloc(2, sizeof(GLuint));
267 if( gsprite_surfaces.surfaces == 0 )
268 return 1;
270 gsprite_surfaces.allocated = 2;
271 memset(gsprite_surfaces.surfaces, 0, gsprite_surfaces.allocated * sizeof(GLuint));
273 gsprites.sprites = (Sprite**) calloc(2,sizeof(Sprite*));
274 if( gsprites.sprites == 0 )
275 return 2;
276 memset(gsprites.sprites, 0, gsprites.allocated * sizeof(Sprite*));
277 gsprites.allocated = 2;
278 ginvalidsprites=1;
280 gsprite_queue.allocated=2;
281 gsprite_queue.items=(SpriteQueueItem*) malloc(sizeof(SpriteQueueItem)*2);
282 gsprite_queue.next_id=0;
284 SetVideoMode(config.screen_width, config.screen_height);
286 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
287 glClearDepth(1.0);
288 glDisable(GL_DEPTH_TEST);
289 //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
290 glEnable(GL_BLEND);
291 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
292 //glEnable(GL_ALPHA_TEST);
293 //glAlphaFunc(GL_GREATER, 0);
294 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
296 glViewport(0, 0, config.screen_width, config.screen_height);
297 glMatrixMode(GL_PROJECTION);
298 glLoadIdentity();
300 glOrtho(0.0f,config.screen_width, config.screen_height,0.0f,-1.0f,1.0f);
302 glMatrixMode(GL_MODELVIEW);
303 glLoadIdentity();
305 return 0;
308 void FlushSpriteSurfaces(){
309 int i;
311 for(i=0;i<gsprite_surfaces.allocated;i++){
312 if(gsprite_surfaces.surfaces[i]){
313 glDeleteTextures(1, &gsprite_surfaces.surfaces[i]);
314 gsprite_surfaces.surfaces[i]=0;
317 occupied =0;
320 int RegenerateSprites(){
321 int i,SID;
322 Config config;
323 Sprite *tmpsprite;
324 GLuint tmpsurface;
325 int xx,yy;
327 config=GetConfig();
330 FlushSpriteSurfaces();
332 SetVideoMode(config.screen_width, config.screen_height);
335 for(i=0;i<gsprites.allocated;i++)
336 if(gsprites.sprites[i]){
337 tmpsprite=gsprites.sprites[i];
338 xx = (tmpsprite->width/SCREEN_WIDTH)*config.screen_width;
339 yy = (tmpsprite->height/SCREEN_HEIGHT)*config.screen_height;
341 tmpsurface=load_svg(tmpsprite->fname, xx, yy, &tmpsprite->twidth, &tmpsprite->theight);
343 SID=AddSurface(tmpsurface);
344 if(SID==-1){
345 return 1;
347 RotateSurface(SID,tmpsprite->rotation);
350 RegenerateFonts();
352 ginvalidsprites=0;
353 return 0;
355 void InvalidateSprites(){
356 printf("Invalid\n");
357 ginvalidsprites=1;
360 void FlushSpriteQueue(){
361 int i;
363 for(i=0;i<gsprite_queue.allocated;i++){
364 gsprite_queue.items[i].sprite = 0;
366 if(gsprite_queue.next_id < gsprite_queue.allocated/2){
367 //TODO:dopsat zmenseni fronty
369 gsprite_queue.next_id = 0;
372 void SwapSpriteQueueItems(int aid, int bid){
373 SpriteQueueItem c;
374 memcpy(&c, &gsprite_queue_sorted.items[aid], sizeof(SpriteQueueItem));
375 memcpy(&gsprite_queue_sorted.items[aid], &gsprite_queue_sorted.items[bid], sizeof(SpriteQueueItem));
376 memcpy(&gsprite_queue_sorted.items[bid], &c, sizeof(SpriteQueueItem));
379 void YSortSpriteQueue(int from, int to){
380 int i;
381 int y1, y2;
382 int TheEnd = 0;
383 //TODO:validity check
384 while(!TheEnd){
385 TheEnd = 1;
386 for(i = from; i < to ; i++){
387 y1 = gsprite_queue_sorted.items[i].sprite->height * 0.5 + gsprite_queue_sorted.items[i].y;
388 y2 = gsprite_queue_sorted.items[i+1].sprite->height * 0.5 + gsprite_queue_sorted.items[i+1].y;
389 if(y1 > y2){
390 TheEnd = 0;
391 SwapSpriteQueueItems(i+1, i);
397 void ZSortSpriteQueue(){
398 int minz, lastminz, found;
399 int i;
400 int ysortfrom, ysortto;
401 lastminz = INT_MIN;
404 found = 1;
405 gsprite_queue_sorted.next_id= 0;
406 while(found){
407 found = 0;
408 minz = INT_MAX;
409 //we seek for smallest z bigger than z in last iteration
410 for(i=0; i<gsprite_queue.next_id; i++){
411 if( gsprite_queue.items[i].z < minz && gsprite_queue.items[i].z > lastminz){
412 found = 1;
413 minz = gsprite_queue.items[i].z;
416 if(!found)
417 break;
418 //now we copy all items on z==minz
419 ysortfrom = gsprite_queue_sorted.next_id;
420 for(i=0; i < gsprite_queue.next_id; i++){
421 if(gsprite_queue.items[i].z == minz){
422 memcpy(&gsprite_queue_sorted.items[gsprite_queue_sorted.next_id], &gsprite_queue.items[i], sizeof(SpriteQueueItem));
423 ysortto = gsprite_queue_sorted.next_id;
424 gsprite_queue_sorted.next_id++;
427 YSortSpriteQueue(ysortfrom, ysortto);
428 lastminz=minz;
433 int DrawSprites(){
434 int i;
435 SDL_Rect dest;
436 SDL_Rect src;
437 GLuint ds;
438 Sprite *dspr;
439 int LastLayer, LayerI;
441 if(ginvalidsprites){
442 printf("invalid\n");
443 RegenerateSprites();
446 gsprite_queue_sorted.allocated = gsprite_queue.allocated;
447 gsprite_queue_sorted.next_id = 0;
448 gsprite_queue_sorted.items = malloc(sizeof(SpriteQueueItem)* gsprite_queue_sorted.allocated);
449 ZSortSpriteQueue();
450 PreDrawTexts();
452 // select modulate to mix texture with color for shading
453 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
454 glEnable(GL_TEXTURE_2D);
456 LastLayer=0;
457 for(i=0;i<gsprite_queue_sorted.next_id;i++)
458 if (gsprite_queue_sorted.items[i].sprite){
459 for (LayerI = LastLayer; LayerI < gsprite_queue_sorted.items[i].z; LayerI++) {
460 glDisable(GL_TEXTURE_2D);
461 DrawTextsOnLayer(LayerI);
462 glEnable(GL_TEXTURE_2D);
464 dspr = gsprite_queue_sorted.items[i].sprite;
465 ds = gsprite_surfaces.surfaces[dspr->SID];
466 dest.x = G2SX(gsprite_queue_sorted.items[i].x);
467 dest.y = G2SY(gsprite_queue_sorted.items[i].y);
468 dest.w = G2SX(gsprite_queue_sorted.items[i].xx);
469 dest.h = G2SX(gsprite_queue_sorted.items[i].yy);
470 src.x = 0;
471 src.y = 0;
472 src.w = G2SX(gsprite_queue_sorted.items[i].sprite->width);
473 src.h = G2SX(gsprite_queue_sorted.items[i].sprite->height);
476 glBindTexture(GL_TEXTURE_2D, ds);
477 glColor4ub(gsprite_queue_sorted.items[i].c.r, gsprite_queue_sorted.items[i].c.g, gsprite_queue_sorted.items[i].c.b, gsprite_queue_sorted.items[i].c.unused);
478 TTRECT(dest.x, dest.y, dest.w, dest.h, src.w, src.h, dspr->twidth, dspr->theight);
481 glDisable(GL_TEXTURE_2D);
482 DrawRestOfTexts();
484 gsprite_queue_sorted.allocated = 0;
485 gsprite_queue_sorted.next_id = 0;
486 free(gsprite_queue_sorted.items);
487 gsprite_queue_sorted.items = 0;
488 FlushSpriteQueue();
490 SDL_GL_SwapBuffers();
492 return 0;
495 int ClrScr(){
496 //SDL_FillRect(gscreen, 0, 0x0);
497 return 0;
500 Sprite* LoadSpriteSVG(char *fname, double width, double height){
501 Sprite *sprite;
502 GLuint surface;
503 int xx,yy;
504 Config conf=GetConfig();
506 xx = width*(double)conf.screen_width/SCREEN_WIDTH;
507 yy = height*(double)conf.screen_height/SCREEN_HEIGHT;
510 sprite = (Sprite*)malloc(sizeof(Sprite));
511 surface = load_svg(fname, xx, yy, &sprite->twidth, &sprite->theight);
512 sprite->fname = malloc(sizeof(char)*(strlen(fname)+2));
513 strcpy(sprite->fname, fname);
514 sprite->width = width;
515 sprite->height = height;
516 sprite->rotation = 0;
517 sprite->SID = AddSurface(surface);
518 AddSprite(sprite);
520 return sprite;
522 void DestroySprite(Sprite *sprite){
523 RemoveSprite(sprite);
524 free(sprite->fname);
525 sprite->fname=0;
526 glDeleteTextures(1, &gsprite_surfaces.surfaces[sprite->SID]);
527 RemoveSID(sprite->SID);
528 free(sprite);
531 Sprite* CopySprite(Sprite *old){
532 printf("CopySprite not Implemented\n");
534 return 0;
538 void RotateSurface(int SID, int rotation){
539 //int i,x,y;
540 //int size;
542 fprintf(stderr, "Rotation of sprites not implemented :(\n");
545 void RotateClockwise(Sprite *sprite){
546 RotateSurface(sprite->SID,1);
547 sprite->rotation=1;
550 void QueueDrawSprite(Sprite *sprite, double x, double y, int z){
551 const SDL_Color white = {255, 255, 255, 255};
552 QueueDrawSpriteColorize(sprite, x, y, z, white);
555 void QueueDrawSpriteColorize(Sprite *sprite, double x, double y, int z, SDL_Color color){
556 SpriteQueueItem *item;
557 if(!sprite){
558 printf("NULL sprite*\n");
559 return;
561 if(gsprite_queue.next_id >=gsprite_queue.allocated){
562 item = (SpriteQueueItem *) realloc(gsprite_queue.items, sizeof(SpriteQueueItem)*gsprite_queue.allocated*2);
563 if(item == 0){
564 fprintf(stderr, "Can't allocate enough memory for sprite queue\n");
565 return;
567 gsprite_queue.allocated *= 2;
568 gsprite_queue.items = item;
571 item = &gsprite_queue.items[gsprite_queue.next_id];
572 item->sprite = sprite;
573 item->x = x;
574 item->xx = sprite->width;
575 item->y = y;
576 item->yy = sprite->height;
577 item->z = z;
578 item->c = color;
580 gsprite_queue.next_id ++;
583 void QueueDrawSpriteColorizeStretch(Sprite *sprite, double x, double y, double xx, double yy, int z, SDL_Color color){
584 SpriteQueueItem *item;
585 if(!sprite){
586 printf("NULL sprite*\n");
587 return;
589 if(gsprite_queue.next_id >=gsprite_queue.allocated){
590 item = (SpriteQueueItem *) realloc(gsprite_queue.items, sizeof(SpriteQueueItem)*gsprite_queue.allocated*2);
591 if(item == 0){
592 fprintf(stderr, "Can't allocate enough memory for sprite queue\n");
593 return;
595 gsprite_queue.allocated *= 2;
596 gsprite_queue.items = item;
599 item = &gsprite_queue.items[gsprite_queue.next_id];
600 item->sprite = sprite;
601 item->x = x;
602 item->xx = xx;
603 item->y = y;
604 item->yy = yy;
605 item->z = z;
606 item->c = color;
608 gsprite_queue.next_id ++;
612 unsigned int closestpoweroftwo(unsigned int i){
613 int p;
614 p=0;
615 while(i){
616 i=i>>1;
617 p++;
619 return 1<<(p-0);
623 //load_svg borrowed from cairo demo
625 /* load_svg: This is what you're probably interested in!
626 * -----------------------------------------------------
627 * If width and height are greater than 0, the image will
628 * be scaled to that size. wscale and hscale would be ignored.
630 * If width and height are less than 1, wscale and hscale will
631 * resize the width and the height to the specified scales.
633 * If width and height are less than 1, and wscale and hscale
634 * are either 0 or 1, then the image will be loaded at it's
635 * natural size.
637 * See main() for examples.
639 GLuint load_svg (char *file, int width, int height, double *pdw, double *pdh) {
640 RsvgDimensionData g_DimensionData;
641 RsvgHandle* rsvghandle;
642 GError* pError;
644 int bpp;
645 int btpp;
646 unsigned int rwidth;
647 unsigned int rheight;
648 unsigned int pw,ph; //power of two dimensions
649 double wscale,hscale;
650 Config config=GetConfig();
652 // Create the SVG cairo stuff.
653 rsvghandle = rsvg_handle_new_from_file(file, &pError);
655 rsvg_handle_get_dimensions( rsvghandle, &g_DimensionData);
656 rwidth = g_DimensionData.width;
657 rheight = g_DimensionData.height;
658 *pdw = closestpoweroftwo(width);
659 *pdh = closestpoweroftwo(height);
660 width = width>>config.texture_lod;
661 height = height>>config.texture_lod;
662 printf("w:%u h:%u\n",width, height);
664 /*Calculate final width and height of our surface based on the parameters passed */
665 if (width > 0) {
666 wscale=(float)width/(float)rwidth;
667 } else {
668 width=(int)(rwidth*wscale);
670 if (height > 0) {
671 hscale=(float)height/(float)rheight;
672 } else {
673 height=(int)(rheight*hscale);
677 if(hscale>wscale){
678 hscale=wscale;
679 }else{
680 wscale=hscale;
683 /* We will create a CAIRO_FORMAT_ARGB32 surface. We don't need to match
684 the screen SDL format, but we are interested in the alpha bit */
685 bpp=32; /*bits per pixel*/
686 btpp=4; /*bytes per pixel*/
688 /* scanline width */
689 int stride=width * btpp;
691 /* Allocate an image */
692 unsigned char *image=calloc(stride*height, 1);
694 /* Create the cairo surface with the adjusted width and height */
695 cairo_surface_t *cairo_surface;
696 cairo_surface = cairo_image_surface_create_for_data (image,
697 CAIRO_FORMAT_ARGB32,
698 width, height, stride);
700 cairo_t *cr=cairo_create(cairo_surface);
701 cairo_scale (cr, wscale, hscale);
703 /* Render SVG to our surface */
704 rsvg_handle_render_cairo(rsvghandle, cr);
705 rsvg_handle_free(rsvghandle);
707 /* Cleanup cairo */
708 cairo_surface_destroy (cairo_surface);
709 cairo_destroy (cr);
711 /*Destroy the svg_cairo structure */
713 /*Adjust the SDL surface mask to ARGB, matching the cairo surface created.*/
714 Uint32 rmask, gmask, bmask, amask;
716 rmask = 0x00ff0000;
717 gmask = 0x0000ff00;
718 bmask = 0x000000ff;
719 amask = 0xff000000;
721 /* Create the SDL surface using the pixel data stored. It will automatically be set to use alpha using these mask values */
722 SDL_Surface *sdl_surface=SDL_CreateRGBSurfaceFrom( (void *) image, width, height, bpp, stride, rmask, gmask, bmask, amask);
723 SDL_SetAlpha(sdl_surface, 0, 255);
724 rmask = 0x000000ff;
725 gmask = 0x0000ff00;
726 bmask = 0x00ff0000;
727 amask = 0xff000000;
728 pw = closestpoweroftwo(width);
729 ph = closestpoweroftwo(height);
730 SDL_Surface *sdl_rgba_surface=SDL_CreateRGBSurface( SDL_SWSURFACE, pw, ph, bpp, rmask, gmask, bmask, amask);
731 SDL_BlitSurface(sdl_surface, 0, sdl_rgba_surface, 0);
732 SDL_FreeSurface(sdl_surface);
733 cfree(image);
735 SDL_LockSurface(sdl_rgba_surface);
737 GLuint tid;
738 glGenTextures(1, &tid);
739 glBindTexture(GL_TEXTURE_2D, tid);
740 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
741 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
742 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pw, ph, 0, GL_RGBA, GL_UNSIGNED_BYTE, sdl_rgba_surface->pixels);
743 SDL_UnlockSurface(sdl_rgba_surface);
744 SDL_FreeSurface(sdl_rgba_surface);
745 occupied += pw*ph;
746 printf("Occupied: %u\n", occupied);
748 return tid;