pause
[Lilanci.git] / gr.c
blobb0ec0cb4472a0a56b8c2cdc55c1944914fea6cdf
1 #include "config.h"
2 #include "gr.h"
3 #include <string.h>
4 #include <stdlib.h>
5 #include <limits.h>
7 #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();
8 #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();
10 #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();
12 unsigned int occupied=0;
14 typedef struct{
15 GLuint *surfaces;
16 unsigned int allocated;
17 }SurfaceList;
19 SurfaceList gsprite_surfaces;
20 int AddSurface(GLuint s);
21 void RemoveSurface(GLuint s);
22 void RemoveSID(int SID);
23 void FlushSpriteSurfaces();
24 int SetVideoMode(int width, int height);
25 SDL_Surface *gscreen;
27 typedef struct{
28 Sprite **sprites;
29 unsigned int allocated;
30 }SpriteList;
32 SpriteList gsprites;
33 int AddSprite(Sprite *s);
34 void RemoveSprite(Sprite *s);
36 typedef struct{
37 Sprite *sprite;
38 double x;
39 double y;
40 double xx;
41 double yy;
42 int z; //z
43 SDL_Color c;
44 }SpriteQueueItem;
46 typedef struct{
47 SpriteQueueItem *items;
48 unsigned int allocated;
49 unsigned int next_id;
50 }SpriteQueue;
51 SpriteQueue gsprite_queue;
52 SpriteQueue gsprite_queue_sorted;
53 void FlushSpriteQueue();
54 void RotateSurface(int SID, int rotation);
56 int ginvalidsprites;
58 GLuint load_svg (char *file, int width, int height, double *pdw, double *pdh);
60 int G2SX(double x);
61 int G2SY(double y);
63 int G2SX(double x){
64 return (x/(double)SCREEN_WIDTH)*GetConfig().screen_width;
66 int G2SY(double y){
67 return (y/(double)SCREEN_HEIGHT)*GetConfig().screen_height;
70 int SetVideoMode(int width, int height){
71 SDL_Rect **modes;
72 int ibest;
73 int bestdif;
74 int i;
75 Uint32 flags;
77 Config config=GetConfig();
79 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
80 flags = SDL_OPENGL ;
81 if(config.fullscreen)
82 flags = flags |SDL_FULLSCREEN;
83 /* Get available fullscreen/hardware modes */
84 modes=SDL_ListModes(NULL, flags);
86 /* Check if there are any modes available */
87 if(modes == (SDL_Rect **)0){
88 printf("No modes available!\n");
89 exit(-1);
92 /* Check if our resolution is restricted */
93 if(modes == (SDL_Rect **)-1){
94 printf("All resolutions available.\n");
95 gscreen = SDL_SetVideoMode(config.screen_width, config.screen_height, 0, flags);
97 else{
98 /* Print valid modes */
99 printf("Available Modes\n");
100 bestdif = abs((modes[0]->w - config.screen_width) + (modes[0]->h - config.screen_height));
101 ibest = 0;
102 for(i=0;modes[i];++i){
103 printf(" %d x %d\n", modes[i]->w, modes[i]->h);
104 if(bestdif > abs((modes[i]->w - config.screen_width) + (modes[i]->h - config.screen_height))){
105 bestdif = abs((modes[i]->w - config.screen_width) + (modes[i]->h - config.screen_height));
106 ibest = i;
109 printf("Using: %d x %d\n", modes[ibest]->w, modes[ibest]->h);
110 gscreen = SDL_SetVideoMode(modes[ibest]->w, modes[ibest]->h, 0, flags);
111 config.screen_height = modes[ibest]->h;
112 config.screen_width = modes[ibest]->w;
113 SetConfig(config);
115 return 0;
118 int AddSurface(GLuint s){ //returns -1 on error, SID if success
119 int i;
120 GLuint *tmp;
121 for(i=0;i<gsprite_surfaces.allocated;i++)
122 if( gsprite_surfaces.surfaces[i]==s ){
123 return i;
126 for(i=0;i<gsprite_surfaces.allocated;i++)
127 if( gsprite_surfaces.surfaces[i]==0 ){
128 gsprite_surfaces.surfaces[i]=s;
129 return i;
131 i=gsprite_surfaces.allocated;
132 tmp = (GLuint*) realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*i*2); //if the allocated space is not wide enough, then allocate double space than previous
133 if(tmp==0)
134 return -1;
135 gsprite_surfaces.surfaces=tmp;
136 memset(&gsprite_surfaces.surfaces[i],0, sizeof(GLuint)*i); //zero newly allocated space
137 gsprite_surfaces.allocated=i*2;
138 gsprite_surfaces.surfaces[i]=s;
139 return i;
142 void RemoveSurface(GLuint s){
143 int i,iwannakillyoubitch;
145 iwannakillyoubitch=1;
146 for(i=0;i<gsprite_surfaces.allocated;i++){
147 if( gsprite_surfaces.surfaces[i]==s ){
148 gsprite_surfaces.surfaces[i]=0;
150 if( i>=gsprite_surfaces.allocated/2 && iwannakillyoubitch && gsprite_surfaces.surfaces[i]!=0 )
151 iwannakillyoubitch=0;
154 if(iwannakillyoubitch){
155 gsprite_surfaces.allocated /=2;
156 gsprite_surfaces.surfaces = (GLuint *)realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*gsprite_surfaces.allocated);//TODO:check return value
160 void RemoveSID(int SID){
161 int i,iwannakillyoubitch;
163 iwannakillyoubitch=1;
164 for(i=0;i<gsprite_surfaces.allocated;i++){
165 if( i==SID ){
166 gsprite_surfaces.surfaces[i]=0;
168 if( i>=gsprite_surfaces.allocated/2 && iwannakillyoubitch && gsprite_surfaces.surfaces[i]!=0 )
169 iwannakillyoubitch=0;
172 if(iwannakillyoubitch){
173 gsprite_surfaces.allocated /=2;
174 gsprite_surfaces.surfaces = (GLuint *)realloc(gsprite_surfaces.surfaces, sizeof(GLuint)*gsprite_surfaces.allocated);//TODO:check return value
178 int AddSprite(Sprite *s){//returns 0 on error, Sprite ID on success
179 int i;
180 Sprite **tmp;
181 for(i=0;i<gsprites.allocated;i++)
182 if( gsprites.sprites[i]==s ){
183 return i;
186 for(i=0;i<gsprites.allocated;i++)
187 if( gsprites.sprites[i]==0 ){
188 gsprites.sprites[i]=s;
189 return i;
191 i=gsprites.allocated;
192 tmp=(Sprite **)realloc(gsprites.sprites, sizeof(Sprite *)*i*2); //if the allocated space is not wide enough, then allocate double space than previous
193 if(tmp==0)
194 return 0;
195 gsprites.sprites=tmp;
196 memset(&gsprites.sprites[i],0, sizeof(Sprite *)*i); //zero newly allocated space
197 gsprites.allocated=i*2;
198 gsprites.sprites[i]=s;
199 return i;
202 void RemoveSprite(Sprite *s){
203 int i,iwannakillyoubitch;
205 iwannakillyoubitch=1;
206 for(i=0;i<gsprites.allocated;i++){
207 if( gsprites.sprites[i]==s ){
208 gsprites.sprites[i]=0;
210 if( i>=gsprites.allocated/2 && iwannakillyoubitch && gsprites.sprites[i]!=0 )
211 iwannakillyoubitch=0;
214 if(iwannakillyoubitch){
215 gsprites.allocated /=2;
216 gsprites.sprites = (Sprite **) realloc(gsprites.sprites, sizeof(Sprite *)*gsprites.allocated);//TODO:check return value
220 int GrKill(){
221 Config config;
222 int i;
224 FlushSpriteQueue();
225 FlushSpriteSurfaces();
227 config=GetConfig();
228 free(gsprite_surfaces.surfaces);
229 gsprite_surfaces.surfaces=0;
232 for(i=0; i<gsprites.allocated; i++)
233 if(gsprites.sprites[i]){
234 free(gsprites.sprites[i]->fname);
235 free(gsprites.sprites[i]);
236 gsprites.sprites[i]=0;
239 gsprites.allocated = 0;
242 SetVideoMode(config.screen_width, config.screen_height);
244 return 0;
247 int GrInit(){
248 Config config;
250 config=GetConfig();
251 gsprite_surfaces.surfaces = (GLuint*) calloc(2, sizeof(GLuint));
252 if( gsprite_surfaces.surfaces == 0 )
253 return 1;
255 gsprite_surfaces.allocated = 2;
256 memset(gsprite_surfaces.surfaces, 0, gsprite_surfaces.allocated * sizeof(GLuint));
258 gsprites.sprites = (Sprite**) calloc(2,sizeof(Sprite*));
259 if( gsprites.sprites == 0 )
260 return 2;
261 memset(gsprites.sprites, 0, gsprites.allocated * sizeof(Sprite*));
262 gsprites.allocated = 2;
263 ginvalidsprites=1;
265 gsprite_queue.allocated=2;
266 gsprite_queue.items=(SpriteQueueItem*) malloc(sizeof(SpriteQueueItem)*2);
267 gsprite_queue.next_id=0;
269 SetVideoMode(config.screen_width, config.screen_height);
271 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
272 glClearDepth(1.0);
273 glDisable(GL_DEPTH_TEST);
274 //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
275 glEnable(GL_BLEND);
276 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
277 //glEnable(GL_ALPHA_TEST);
278 //glAlphaFunc(GL_GREATER, 0);
279 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
281 glViewport(0, 0, config.screen_width, config.screen_height);
282 glMatrixMode(GL_PROJECTION);
283 glLoadIdentity();
285 glOrtho(0.0f,config.screen_width, config.screen_height,0.0f,-1.0f,1.0f);
287 glMatrixMode(GL_MODELVIEW);
288 glLoadIdentity();
290 return 0;
293 void FlushSpriteSurfaces(){
294 int i;
296 for(i=0;i<gsprite_surfaces.allocated;i++){
297 if(gsprite_surfaces.surfaces[i]){
298 glDeleteTextures(1, &gsprite_surfaces.surfaces[i]);
299 gsprite_surfaces.surfaces[i]=0;
302 occupied =0;
305 int RegenerateSprites(){
306 int i,SID;
307 Config config;
308 Sprite *tmpsprite;
309 GLuint tmpsurface;
310 int xx,yy;
312 config=GetConfig();
315 FlushSpriteSurfaces();
317 SetVideoMode(config.screen_width, config.screen_height);
320 for(i=0;i<gsprites.allocated;i++)
321 if(gsprites.sprites[i]){
322 tmpsprite=gsprites.sprites[i];
323 xx = (tmpsprite->width/SCREEN_WIDTH)*config.screen_width;
324 yy = (tmpsprite->height/SCREEN_HEIGHT)*config.screen_height;
326 tmpsurface=load_svg(tmpsprite->fname, xx, yy, &tmpsprite->twidth, &tmpsprite->theight);
328 SID=AddSurface(tmpsurface);
329 if(SID==-1){
330 return 1;
332 RotateSurface(SID,tmpsprite->rotation);
336 ginvalidsprites=0;
337 return 0;
339 void InvalidateSprites(){
340 printf("Invalid\n");
341 ginvalidsprites=1;
344 void FlushSpriteQueue(){
345 int i;
347 for(i=0;i<gsprite_queue.allocated;i++){
348 gsprite_queue.items[i].sprite = 0;
350 if(gsprite_queue.next_id < gsprite_queue.allocated/2){
351 //TODO:dopsat zmenseni fronty
353 gsprite_queue.next_id = 0;
356 void SwapSpriteQueueItems(int aid, int bid){
357 SpriteQueueItem c;
358 memcpy(&c, &gsprite_queue_sorted.items[aid], sizeof(SpriteQueueItem));
359 memcpy(&gsprite_queue_sorted.items[aid], &gsprite_queue_sorted.items[bid], sizeof(SpriteQueueItem));
360 memcpy(&gsprite_queue_sorted.items[bid], &c, sizeof(SpriteQueueItem));
361 /*c.sprite = gsprite_queue_sorted.items[aid].sprite;
362 c.x = gsprite_queue_sorted.items[aid].x;
363 c.xx = gsprite_queue_sorted.items[aid].xx;
364 c.y = gsprite_queue_sorted.items[aid].y;
365 c.yy = gsprite_queue_sorted.items[aid].yy;
366 c.z = gsprite_queue_sorted.items[aid].z;
367 c.c = gsprite_queue_sorted.items[aid].c;
369 gsprite_queue_sorted.items[aid].sprite = gsprite_queue_sorted.items[bid].sprite ;
370 gsprite_queue_sorted.items[aid].x = gsprite_queue_sorted.items[bid].x ;
371 gsprite_queue_sorted.items[aid].xx = gsprite_queue_sorted.items[bid].xx ;
372 gsprite_queue_sorted.items[aid].y = gsprite_queue_sorted.items[bid].y ;
373 gsprite_queue_sorted.items[aid].yy = gsprite_queue_sorted.items[bid].yy ;
374 gsprite_queue_sorted.items[aid].z = gsprite_queue_sorted.items[bid].z ;
375 gsprite_queue_sorted.items[aid].c = gsprite_queue_sorted.items[bid].c ;
377 gsprite_queue_sorted.items[bid].sprite = c.sprite;
378 gsprite_queue_sorted.items[bid].x = c.x;
379 gsprite_queue_sorted.items[bid].xx = c.xx;
380 gsprite_queue_sorted.items[bid].y = c.y;
381 gsprite_queue_sorted.items[bid].yy = c.yy;
382 gsprite_queue_sorted.items[bid].z = c.z;
383 gsprite_queue_sorted.items[bid].c = c.c;*/
386 void YSortSpriteQueue(int from, int to){
387 int i;
388 int y1, y2;
389 int TheEnd = 0;
390 //TODO:validity check
391 while(!TheEnd){
392 TheEnd = 1;
393 for(i = from; i < to ; i++){
394 y1 = gsprite_queue_sorted.items[i].sprite->height * 0.5 + gsprite_queue_sorted.items[i].y;
395 y2 = gsprite_queue_sorted.items[i+1].sprite->height * 0.5 + gsprite_queue_sorted.items[i+1].y;
396 if(y1 > y2){
397 TheEnd = 0;
398 SwapSpriteQueueItems(i+1, i);
404 void ZSortSpriteQueue(){
405 int minz, lastminz, found;
406 int i;
407 int ysortfrom, ysortto;
408 lastminz = INT_MIN;
411 found = 1;
412 gsprite_queue_sorted.next_id= 0;
413 while(found){
414 found = 0;
415 minz = INT_MAX;
416 //we seek for smallest z bigger than z in last iteration
417 for(i=0; i<gsprite_queue.next_id; i++){
418 if( gsprite_queue.items[i].z < minz && gsprite_queue.items[i].z > lastminz){
419 found = 1;
420 minz = gsprite_queue.items[i].z;
423 if(!found)
424 break;
425 //now we copy all items on z==minz
426 ysortfrom = gsprite_queue_sorted.next_id;
427 for(i=0; i < gsprite_queue.next_id; i++){
428 if(gsprite_queue.items[i].z == minz){
429 memcpy(&gsprite_queue_sorted.items[gsprite_queue_sorted.next_id], &gsprite_queue.items[i], sizeof(SpriteQueueItem));
430 ysortto = gsprite_queue_sorted.next_id;
431 gsprite_queue_sorted.next_id++;
434 YSortSpriteQueue(ysortfrom, ysortto);
435 lastminz=minz;
440 int DrawSprites(){
441 int i;
442 SDL_Rect dest;
443 SDL_Rect src;
444 GLuint ds;
445 Sprite *dspr;
447 if(ginvalidsprites){
448 printf("invalid\n");
449 RegenerateSprites();
452 gsprite_queue_sorted.allocated = gsprite_queue.allocated;
453 gsprite_queue_sorted.next_id = 0;
454 gsprite_queue_sorted.items = malloc(sizeof(SpriteQueueItem)* gsprite_queue_sorted.allocated);
455 ZSortSpriteQueue();
457 // select modulate to mix texture with color for shading
458 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
459 glEnable(GL_TEXTURE_2D);
461 for(i=0;i<gsprite_queue_sorted.next_id;i++)
462 if(gsprite_queue_sorted.items[i].sprite){
463 dspr = gsprite_queue_sorted.items[i].sprite;
464 ds = gsprite_surfaces.surfaces[dspr->SID];
465 dest.x = G2SX(gsprite_queue_sorted.items[i].x);
466 dest.y = G2SY(gsprite_queue_sorted.items[i].y);
467 dest.w = G2SX(gsprite_queue_sorted.items[i].xx);
468 dest.h = G2SX(gsprite_queue_sorted.items[i].yy);
469 src.x = 0;
470 src.y = 0;
471 src.w = G2SX(gsprite_queue_sorted.items[i].sprite->width);
472 src.h = G2SX(gsprite_queue_sorted.items[i].sprite->height);
475 glBindTexture(GL_TEXTURE_2D, ds);
476 glColor3ub(gsprite_queue_sorted.items[i].c.r, gsprite_queue_sorted.items[i].c.g, gsprite_queue_sorted.items[i].c.b);
477 TTRECT(dest.x, dest.y, dest.w, dest.h, src.w, src.h, dspr->twidth, dspr->theight);
480 glDisable(GL_TEXTURE_2D);
482 gsprite_queue_sorted.allocated = 0;
483 gsprite_queue_sorted.next_id = 0;
484 free(gsprite_queue_sorted.items);
485 gsprite_queue_sorted.items = 0;
486 FlushSpriteQueue();
488 SDL_GL_SwapBuffers();
490 return 0;
493 int ClrScr(){
494 //SDL_FillRect(gscreen, 0, 0x0);
495 return 0;
498 Sprite* LoadSpriteSVG(char *fname, double width, double height){
499 Sprite *sprite;
500 GLuint surface;
501 int xx,yy;
502 Config conf=GetConfig();
504 xx = width*(double)conf.screen_width/SCREEN_WIDTH;
505 yy = height*(double)conf.screen_height/SCREEN_HEIGHT;
508 sprite = (Sprite*)malloc(sizeof(Sprite));
509 surface = load_svg(fname, xx, yy, &sprite->twidth, &sprite->theight);
510 sprite->fname = malloc(sizeof(char)*(strlen(fname)+2));
511 strcpy(sprite->fname, fname);
512 sprite->width = width;
513 sprite->height = height;
514 sprite->rotation = 0;
515 sprite->SID = AddSurface(surface);
516 AddSprite(sprite);
518 return sprite;
520 void DestroySprite(Sprite *sprite){
521 RemoveSprite(sprite);
522 free(sprite->fname);
523 sprite->fname=0;
524 glDeleteTextures(1, &gsprite_surfaces.surfaces[sprite->SID]);
525 RemoveSID(sprite->SID);
526 free(sprite);
529 Sprite* CopySprite(Sprite *old){
530 printf("CopySprite not Implemented\n");
532 return 0;
536 void RotateSurface(int SID, int rotation){
537 //int i,x,y;
538 //int size;
540 fprintf(stderr, "Rotation of sprites not implemented :(\n");
543 void RotateClockwise(Sprite *sprite){
544 RotateSurface(sprite->SID,1);
545 sprite->rotation=1;
548 void QueueDrawSprite(Sprite *sprite, double x, double y, int z){
549 SDL_Color white = {255, 255, 255};
550 QueueDrawSpriteColorize(sprite, x, y, z, white);
553 void QueueDrawSpriteColorize(Sprite *sprite, double x, double y, int z, SDL_Color color){
554 SpriteQueueItem *item;
555 if(!sprite){
556 printf("NULL sprite*\n");
557 return;
559 if(gsprite_queue.next_id >=gsprite_queue.allocated){
560 item = (SpriteQueueItem *) realloc(gsprite_queue.items, sizeof(SpriteQueueItem)*gsprite_queue.allocated*2);
561 if(item == 0){
562 fprintf(stderr, "Can't allocate enough memory for sprite queue\n");
563 return;
565 gsprite_queue.allocated *= 2;
566 gsprite_queue.items = item;
569 item = &gsprite_queue.items[gsprite_queue.next_id];
570 item->sprite = sprite;
571 item->x = x;
572 item->xx = sprite->width;
573 item->y = y;
574 item->yy = sprite->height;
575 item->z = z;
576 item->c = color;
578 gsprite_queue.next_id ++;
581 void QueueDrawSpriteColorizeStretch(Sprite *sprite, double x, double y, double xx, double yy, int z, SDL_Color color){
582 SpriteQueueItem *item;
583 if(!sprite){
584 printf("NULL sprite*\n");
585 return;
587 if(gsprite_queue.next_id >=gsprite_queue.allocated){
588 item = (SpriteQueueItem *) realloc(gsprite_queue.items, sizeof(SpriteQueueItem)*gsprite_queue.allocated*2);
589 if(item == 0){
590 fprintf(stderr, "Can't allocate enough memory for sprite queue\n");
591 return;
593 gsprite_queue.allocated *= 2;
594 gsprite_queue.items = item;
597 item = &gsprite_queue.items[gsprite_queue.next_id];
598 item->sprite = sprite;
599 item->x = x;
600 item->xx = xx;
601 item->y = y;
602 item->yy = yy;
603 item->z = z;
604 item->c = color;
606 gsprite_queue.next_id ++;
610 unsigned int closestpoweroftwo(unsigned int i){
611 int p;
612 p=0;
613 while(i){
614 i=i>>1;
615 p++;
617 return 1<<(p-0);
621 //load_svg borrowed from cairo demo
622 #include <stdio.h>
623 #include <stdlib.h>
624 #include <sys/types.h>
625 #include <cairo.h>
626 #include <svg.h>
627 #include <svg-cairo.h>
629 /* load_svg: This is what you're probably interested in!
630 * -----------------------------------------------------
631 * If width and height are greater than 0, the image will
632 * be scaled to that size. wscale and hscale would be ignored.
634 * If width and height are less than 1, wscale and hscale will
635 * resize the width and the height to the specified scales.
637 * If width and height are less than 1, and wscale and hscale
638 * are either 0 or 1, then the image will be loaded at it's
639 * natural size.
641 * See main() for examples.
643 GLuint load_svg (char *file, int width, int height, double *pdw, double *pdh) {
644 svg_cairo_t *scr;
645 int bpp;
646 int btpp;
647 unsigned int rwidth;
648 unsigned int rheight;
649 unsigned int pw,ph; //power of two dimensions
650 double wscale,hscale;
651 Config config=GetConfig();
653 // Create the SVG cairo stuff.
654 svg_cairo_create(&scr);
655 svg_cairo_parse (scr, file);
657 svg_cairo_get_size (scr, &rwidth, &rheight);
658 *pdw = closestpoweroftwo(width);
659 *pdh = closestpoweroftwo(height);
660 width = width>>config.texture_lod;
661 height = height>>config.texture_lod;
663 /*Calculate final width and height of our surface based on the parameters passed */
664 if (width > 0) {
665 wscale=(float)width/(float)rwidth;
666 } else {
667 width=(int)(rwidth*wscale);
669 if (height > 0) {
670 hscale=(float)height/(float)rheight;
671 } else {
672 height=(int)(rheight*hscale);
676 if(hscale>wscale){
677 hscale=wscale;
678 }else{
679 wscale=hscale;
682 /* We will create a CAIRO_FORMAT_ARGB32 surface. We don't need to match
683 the screen SDL format, but we are interested in the alpha bit */
684 bpp=32; /*bits per pixel*/
685 btpp=4; /*bytes per pixel*/
687 /* scanline width */
688 int stride=width * btpp;
690 /* Allocate an image */
691 unsigned char *image=calloc(stride*height, 1);
693 /* Create the cairo surface with the adjusted width and height */
694 cairo_surface_t *cairo_surface;
695 cairo_surface = cairo_image_surface_create_for_data (image,
696 CAIRO_FORMAT_ARGB32,
697 width, height, stride);
699 cairo_t *cr=cairo_create(cairo_surface);
700 cairo_scale (cr, wscale, hscale);
702 /* Render SVG to our surface */
703 svg_cairo_render (scr, cr);
705 /* Cleanup cairo */
706 cairo_surface_destroy (cairo_surface);
707 cairo_destroy (cr);
709 /*Destroy the svg_cairo structure */
710 svg_cairo_destroy (scr);
712 /*Adjust the SDL surface mask to ARGB, matching the cairo surface created.*/
713 Uint32 rmask, gmask, bmask, amask;
715 rmask = 0x00ff0000;
716 gmask = 0x0000ff00;
717 bmask = 0x000000ff;
718 amask = 0xff000000;
720 /* Create the SDL surface using the pixel data stored. It will automatically be set to use alpha using these mask values */
721 SDL_Surface *sdl_surface=SDL_CreateRGBSurfaceFrom( (void *) image, width, height, bpp, stride, rmask, gmask, bmask, amask);
722 SDL_SetAlpha(sdl_surface, 0, 255);
723 rmask = 0x000000ff;
724 gmask = 0x0000ff00;
725 bmask = 0x00ff0000;
726 amask = 0xff000000;
727 pw = closestpoweroftwo(width);
728 ph = closestpoweroftwo(height);
729 SDL_Surface *sdl_rgba_surface=SDL_CreateRGBSurface( SDL_SWSURFACE, pw, ph, bpp, rmask, gmask, bmask, amask);
730 SDL_BlitSurface(sdl_surface, 0, sdl_rgba_surface, 0);
731 SDL_FreeSurface(sdl_surface);
732 cfree(image);
734 SDL_LockSurface(sdl_rgba_surface);
736 GLuint tid;
737 glGenTextures(1, &tid);
738 glBindTexture(GL_TEXTURE_2D, tid);
739 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
740 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
741 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pw, ph, 0, GL_RGBA, GL_UNSIGNED_BYTE, sdl_rgba_surface->pixels);
742 SDL_UnlockSurface(sdl_rgba_surface);
743 SDL_FreeSurface(sdl_rgba_surface);
744 occupied += pw*ph;
745 printf("Occupied: %u\n", occupied);
747 return tid;