1 /*
2  * This file is part of NumptyPhysics
3  * Copyright (C) 2008 Tim Edmonds
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 3 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  */
16 
17 #include <string>
18 #include "Common.h"
19 #include "Config.h"
20 #include "Canvas.h"
21 #include "Path.h"
22 
23 #include <SDL/SDL.h>
24 #include <SDL/SDL_image.h>
25 
26 #define Window X11Window //oops
27 #include <SDL/SDL_syswm.h>
28 #ifndef WIN32
29 #include <X11/X.h>
30 #include <X11/Xlib.h>
31 #endif
32 #undef Window
33 
34 // zoomer.cpp
35 extern SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy);
36 
37 
38 // extract RGB colour components as 8bit values from RGB888
39 #define R32(p) (((p)>>16)&0xff)
40 #define G32(p) (((p)>>8)&0xff)
41 #define B32(p) ((p)&0xff)
42 
43 // extract RGB colour components as 8bit values from RGB565
44 #define R16(p) (((p)>>8)&0xf8)
45 #define G16(p) (((p)>>3)&0xfc)
46 #define B16(p) (((p)<<3)&0xf8)
47 
48 #define R16G16B16_TO_RGB888(r,g,b) \
49   ((((r)<<8)&0xff0000) | ((g)&0x00ff00) | (((b)>>8)))
50 
51 #define R16G16B16_TO_RGB565(r,g,b) \
52   ((Uint16)( (((r)&0xf800) | (((g)>>5)&0x07e0) | (((b)>>11))&0x001f) ))
53 
54 #define RGB888_TO_RGB565(p) \
55   ((Uint16)( (((p)>>8)&0xf800) | (((p)>>5)&0x07e0) | (((p)>>3)&0x001f) ))
56 
57 
ExtractRgb(uint32 c,int & r,int & g,int & b)58 void ExtractRgb( uint32 c, int& r, int &g, int &b )
59 {
60   r = R32(c); g = G32(c); b = B32(c);
61 }
62 
ExtractRgb(uint16 c,int & r,int & g,int & b)63 void ExtractRgb( uint16 c, int& r, int &g, int &b )
64 {
65   r = R16(c); g = G16(c); b = B16(c);
66 }
67 
68 
69 template <typename PIX>
AlphaBlend(PIX & p,int cr,int cg,int cb,int a,int ia)70 inline void AlphaBlend( PIX& p, int cr, int cg, int cb, int a, int ia )
71 {
72   throw "not implemented";
73 }
74 
AlphaBlend(Uint16 & p,int cr,int cg,int cb,int a,int ia)75 inline void AlphaBlend( Uint16& p, int cr, int cg, int cb, int a, int ia )
76 { //565
77   p = R16G16B16_TO_RGB565( a * cr + ia * R16(p),
78 			   a * cg + ia * G16(p),
79 			   a * cb + ia * B16(p) );
80 }
81 
AlphaBlend(Uint32 & p,int cr,int cg,int cb,int a,int ia)82 inline void AlphaBlend( Uint32& p, int cr, int cg, int cb, int a, int ia )
83 
84 { //888
85   p = R16G16B16_TO_RGB888( a * cr + ia * R32(p),
86 			   a * cg + ia * G32(p),
87 			   a * cb + ia * B32(p) );
88 }
89 
90 #define ALPHA_MAX 0xff
91 
92 template <typename PIX, unsigned W>
93 struct AlphaBrush
94 {
95   int m_r, m_g, m_b, m_c;
AlphaBrushAlphaBrush96   inline AlphaBrush( PIX c )
97   {
98     m_c = c;
99     ExtractRgb( c, m_r, m_g, m_b );
100   }
inkAlphaBrush101   inline void ink( PIX* pix, int step, int a )
102   {
103     int ia = ALPHA_MAX - a;
104     int o=-W/2+1;
105     AlphaBlend( *(pix+o*step), m_r, m_g, m_b, a, ia );
106     for ( ; o<=W/2; o++ ) {
107       *(pix+o*step) = m_c;
108     }
109     AlphaBlend( *(pix+o*step), m_r, m_g, m_b, ia, a );
110   }
111 };
112 
113 template <typename PIX>
114 struct AlphaBrush<PIX,1>
115 {
116   int m_r, m_g, m_b, m_c;
AlphaBrushAlphaBrush117   inline AlphaBrush( PIX c )
118   {
119     m_c = c;
120     ExtractRgb( c, m_r, m_g, m_b );
121   }
inkAlphaBrush122   inline void ink( PIX* pix, int step, int a )
123   {
124     int ia = ALPHA_MAX - a;
125     AlphaBlend( *(pix-step), m_r, m_g, m_b, a, ia );
126     AlphaBlend( *(pix), m_r, m_g, m_b, ia, a );
127   }
128 };
129 
130 template <typename PIX>
131 struct AlphaBrush<PIX,3>
132 {
133   int m_r, m_g, m_b, m_c;
AlphaBrushAlphaBrush134   inline AlphaBrush( PIX c )
135   {
136     m_c = c;
137     ExtractRgb( c, m_r, m_g, m_b );
138   }
inkAlphaBrush139   inline void ink( PIX* pix, int step, int a )
140   {
141     int ia = ALPHA_MAX - a;
142     AlphaBlend( *(pix-step), m_r, m_g, m_b, a, ia );
143     *(pix) = m_c;
144     AlphaBlend( *(pix+step), m_r, m_g, m_b, ia, a );
145   }
146 };
147 
148 
149 
150 template <typename PIX, unsigned THICK>
renderLine(void * buf,int byteStride,int x1,int y1,int x2,int y2,PIX color)151 inline void renderLine( void *buf,
152 			int byteStride,
153 			int x1, int y1, int x2, int y2,
154 			PIX color )
155 {
156   PIX *pix = (PIX*)((char*)buf+byteStride*y1) + x1;
157   int lg_delta, sh_delta, cycle, lg_step, sh_step;
158   int alpha, alpha_step, alpha_reset;
159   int pixStride = byteStride/sizeof(PIX);
160   AlphaBrush<PIX,THICK> brush( color );
161 
162   lg_delta = x2 - x1;
163   sh_delta = y2 - y1;
164   lg_step = Sgn(lg_delta);
165   lg_delta = Abs(lg_delta);
166   sh_step = Sgn(sh_delta);
167   sh_delta = Abs(sh_delta);
168   if ( sh_step < 0 )  pixStride = -pixStride;
169 
170   // in theory should be able to do this with just a single step
171   // variable - ie: combine cycle and alpha as in wu algorithm
172   if (sh_delta < lg_delta) {
173     cycle = lg_delta >> 1;
174     alpha = ALPHA_MAX >> 1;
175     alpha_step = -(ALPHA_MAX * sh_delta/(lg_delta+1));
176     alpha_reset = alpha_step < 0 ? ALPHA_MAX : 0;
177     int count = lg_step>0 ? x2-x1 : x1-x2;
178     while ( count-- ) {
179       brush.ink( pix, pixStride, alpha );
180       cycle += sh_delta;
181       alpha += alpha_step;
182       pix += lg_step;
183       if (cycle > lg_delta) {
184 	cycle -= lg_delta;
185 	alpha = alpha_reset;
186 	pix += pixStride;
187       }
188     }
189   } else {
190     cycle = sh_delta >> 1;
191     alpha = ALPHA_MAX >> 1;
192     alpha_step = -lg_step * Abs(ALPHA_MAX * lg_delta/(sh_delta+1));
193     alpha_reset = alpha_step < 0 ? ALPHA_MAX : 0;
194     int count = sh_step>0 ? y2-y1 : y1-y2;
195     while ( count-- ) {
196       brush.ink( pix, 1, alpha );
197       cycle += lg_delta;
198       alpha += alpha_step;
199       pix += pixStride;
200       if (cycle > sh_delta) {
201 	cycle -= sh_delta;
202 	alpha = alpha_reset;
203 	pix += lg_step;
204       }
205     }
206   }
207 }
208 
209 
210 #define SURFACE(cANVASpTR) ((SDL_Surface*)((cANVASpTR)->m_state))
211 
Canvas(int w,int h)212 Canvas::Canvas( int w, int h )
213   : m_state(NULL),
214     m_bgColour(0),
215     m_bgImage(NULL)
216 {
217   switch (SDL_GetVideoInfo()->vfmt->BitsPerPixel) {
218   case 16:
219   case 32:
220     m_state = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h,
221 				    SDL_GetVideoInfo()->vfmt->BitsPerPixel,
222 				    SDL_GetVideoInfo()->vfmt->Rmask,
223 				    SDL_GetVideoInfo()->vfmt->Gmask,
224 				    SDL_GetVideoInfo()->vfmt->Bmask,
225 				    SDL_GetVideoInfo()->vfmt->Amask );
226     break;
227   default:
228     // eg: dummy vid driver reports 8bpp
229     m_state = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32,
230 				    0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000 );
231     break;
232   }
233   resetClip();
234 }
235 
236 
Canvas(State state)237 Canvas::Canvas( State state )
238   : m_state(state),
239     m_bgColour(0),
240     m_bgImage(NULL)
241 {
242   resetClip();
243 }
244 
~Canvas()245 Canvas::~Canvas()
246 {
247 }
248 
width() const249 int Canvas::width() const
250 {
251   return SURFACE(this)->w;
252 }
253 
height() const254 int Canvas::height() const
255 {
256   return SURFACE(this)->h;
257 }
258 
makeColour(int r,int g,int b) const259 int Canvas::makeColour( int r, int g, int b ) const
260 {
261   return SDL_MapRGB( SURFACE(this)->format, r, g, b );
262 }
263 
makeColour(int c) const264 int Canvas::makeColour( int c ) const
265 {
266   return SDL_MapRGB( SURFACE(this)->format,
267 		     (c>>16)&0xff, (c>>8)&0xff, (c>>0)&0xff );
268 }
269 
resetClip()270 void Canvas::resetClip()
271 {
272   if ( m_state ) {
273     setClip( 0, 0, width(), height() );
274   } else {
275     setClip( 0, 0, 0, 0 );
276   }
277 }
278 
setClip(int x,int y,int w,int h)279 void Canvas::setClip( int x, int y, int w, int h )
280 {
281   m_clip = Rect(x,y,x+w-1,y+h-1);
282 }
283 
setBackground(int c)284 void Canvas::setBackground( int c )
285 {
286   m_bgColour = c;
287 }
288 
setBackground(Canvas * bg)289 void Canvas::setBackground( Canvas* bg )
290 {
291   m_bgImage = bg;
292 }
293 
clear()294 void Canvas::clear()
295 {
296   if ( m_bgImage ) {
297     SDL_BlitSurface( SURFACE(m_bgImage), NULL, SURFACE(this), NULL );
298   } else {
299     SDL_FillRect( SURFACE(this), NULL, m_bgColour );
300   }
301 }
302 
fade(const Rect & rr)303 void Canvas::fade( const Rect& rr )
304 {
305   Uint32 bpp;
306   Rect r = rr;
307   r.clipTo( m_clip );
308   bpp = SURFACE(this)->format->BytesPerPixel;
309   char* row = (char*)SURFACE(this)->pixels;
310   int pixStride = width();
311   int w = r.br.x - r.tl.x + 1;
312   int h = r.br.y - r.tl.y + 1;
313   row += (r.tl.x + r.tl.y * pixStride) * bpp;
314 
315   SDL_LockSurface(SURFACE(this));
316   switch ( bpp ) {
317   case 2:
318     for ( int r=h; r>0; r-- ) {
319       for ( int i=0;i<w;i++) {
320 	((Uint16*)row)[i] = (((Uint16*)row)[i]>>1) & 0x7bef;
321       }
322       row += pixStride * bpp;
323     }
324     break;
325   case 4:
326     for ( int r=h; r>0; r-- ) {
327       for ( int i=0;i<w;i++) {
328 	((Uint32*)row)[i] = (((Uint32*)row)[i]>>1) & 0x7f7f7f;
329       }
330       row += pixStride * bpp;
331     }
332     break;
333   }
334   SDL_UnlockSurface(SURFACE(this));
335 }
336 
scale(int factor) const337 Canvas* Canvas::scale( int factor ) const
338 {
339   Canvas *c = new Canvas( width()/factor, height()/factor );
340   if ( c ) {
341     if ( factor==4 && SURFACE(this)->format->BytesPerPixel==2 ) {
342       const uint16 MASK2LSB = 0xe79c;
343       int dpitch = SURFACE(c)->pitch / sizeof(uint16_t);
344       int spitch = SURFACE(this)->pitch / sizeof(uint16_t);
345       uint16_t *drow = (uint16_t*)SURFACE(c)->pixels;
346       for ( int y=0;y<c->height();y++ ) {
347 	for ( int x=0;x<c->width();x++ ) {
348           uint16 p = 0;
349 	  uint16_t *srow = (uint16_t*)SURFACE(this)->pixels
350   	                    + (y*spitch+x)*factor;
351 	  for ( int yy=0;yy<factor;yy++ ) {
352             uint16 q = 0;
353 	    for ( int xx=0;xx<factor;xx++ ) {
354 	      q += (srow[xx]&MASK2LSB)>>2;
355 	    }
356             p += (q&MASK2LSB)>>2;
357             srow += spitch;
358 	  }
359           drow[x] = p;
360 	}
361 	drow += dpitch;
362       }
363     } else {
364       for ( int y=0;y<c->height();y++ ) {
365 	for ( int x=0;x<c->width();x++ ) {
366 	  int r=0,g=0,b=0;
367 	  Uint8 rr,gg,bb;
368 	  for ( int yy=0;yy<factor;yy++ ) {
369 	    for ( int xx=0;xx<factor;xx++ ) {
370 	      SDL_GetRGB( readPixel( x*factor+xx, y*factor+yy ),
371 			  SURFACE(this)->format, &rr,&gg,&bb );
372 	      r += rr;
373 	      g += gg;
374 	      b += bb;
375 	    }
376 	  }
377 	  int div = factor*factor;
378 	  c->drawPixel( x, y, makeColour(r/div,g/div,b/div) );
379 	}
380       }
381     }
382   }
383   return c;
384 }
385 
386 
scale(int w,int h)387 void Canvas::scale( int w, int h )
388 {
389   if ( w!=width() && h!=height() ) {
390     SDL_Surface *s = zoomSurface( SURFACE(this),
391 				  (double)w/(double)width(),
392 				  (double)h/(double)height() );
393     if ( s ) {
394       SDL_FreeSurface( SURFACE(this) );
395       m_state = s;
396     }
397   }
398 }
399 
400 
clear(const Rect & r)401 void Canvas::clear( const Rect& r )
402 {
403   if ( m_bgImage ) {
404     SDL_Rect srcRect = { r.tl.x, r.tl.y, r.br.x-r.tl.x+1, r.br.y-r.tl.y+1 };
405     SDL_BlitSurface( SURFACE(m_bgImage), &srcRect, SURFACE(this), &srcRect );
406   } else {
407     drawRect( r, m_bgColour );
408   }
409 }
410 
drawImage(Canvas * canvas,int x,int y)411 void Canvas::drawImage( Canvas *canvas, int x, int y )
412 {
413   SDL_Rect dest = { x, y, 0, 0 };
414   SDL_BlitSurface( SURFACE(canvas), NULL, SURFACE(this), &dest );
415 }
416 
drawPixel(int x,int y,int c)417 void Canvas::drawPixel( int x, int y, int c )
418 {
419   Uint32 bpp, ofs;
420 
421   bpp = SURFACE(this)->format->BytesPerPixel;
422   ofs = SURFACE(this)->pitch*y;
423   char* row = (char*)SURFACE(this)->pixels + ofs;
424 
425   SDL_LockSurface(SURFACE(this));
426   switch ( bpp ) {
427   case 2: ((Uint16*)row)[x] = c; break;
428   case 4: ((Uint32*)row)[x] = c; break;
429   }
430   SDL_UnlockSurface(SURFACE(this));
431 }
432 
readPixel(int x,int y) const433 int Canvas::readPixel( int x, int y ) const
434 {
435   Uint32 bpp, ofs;
436   int c;
437 
438   bpp = SURFACE(this)->format->BytesPerPixel;
439   ofs = SURFACE(this)->pitch*y;
440   char* row = (char*)SURFACE(this)->pixels + ofs;
441 
442   SDL_LockSurface(SURFACE(this));
443   switch ( bpp ) {
444   case 2: c = ((Uint16*)row)[x]; break;
445   case 4: c = ((Uint32*)row)[x]; break;
446   default: c=0; break;
447   }
448   SDL_UnlockSurface(SURFACE(this));
449   return c;
450 }
451 
drawLine(int x1,int y1,int x2,int y2,int color)452 void Canvas::drawLine( int x1, int y1, int x2, int y2, int color )
453 {
454   int lg_delta, sh_delta, cycle, lg_step, sh_step;
455   lg_delta = x2 - x1;
456   sh_delta = y2 - y1;
457   lg_step = Sgn(lg_delta);
458   lg_delta = Abs(lg_delta);
459   sh_step = Sgn(sh_delta);
460   sh_delta = Abs(sh_delta);
461   if (sh_delta < lg_delta) {
462     cycle = lg_delta >> 1;
463     while (x1 != x2) {
464       drawPixel( x1, y1, color);
465       cycle += sh_delta;
466       if (cycle > lg_delta) {
467 	cycle -= lg_delta;
468 	y1 += sh_step;
469       }
470       x1 += lg_step;
471     }
472     drawPixel( x1, y1, color);
473   }
474   cycle = sh_delta >> 1;
475   while (y1 != y2) {
476     drawPixel( x1, y1, color);
477     cycle += lg_delta;
478     if (cycle > sh_delta) {
479       cycle -= sh_delta;
480       x1 += lg_step;
481     }
482     y1 += sh_step;
483   }
484   drawPixel( x1, y1, color);
485 }
486 
drawPath(const Path & path,int color,bool thick)487 void Canvas::drawPath( const Path& path, int color, bool thick )
488 {
489   // allow for thick lines in clipping
490   Rect clip = m_clip;
491   clip.tl.x++; clip.tl.y++;
492   clip.br.x--; clip.br.y--;
493 
494   int i=0;
495   const int n = path.numPoints();
496 
497   for ( ; i<n && !clip.contains( path.point(i) ); i++ ) {
498     //skip clipped start pt
499   }
500   i++;
501   SDL_LockSurface(SURFACE(this));
502   for ( ; i<n; i++ ) {
503     // pt i-1 is guranteed to be inside clipping
504     const Vec2& p2 = path.point(i);
505     if ( clip.contains( p2 ) ) {
506       const Vec2& p1 = path.point(i-1);
507       switch ( SURFACE(this)->format->BytesPerPixel ) {
508       case 2:
509 	if ( thick ) {
510 	  renderLine<Uint16,3>( SURFACE(this)->pixels,
511 				SURFACE(this)->pitch,
512 				p1.x, p1.y, p2.x, p2.y, color );
513 	} else {
514 	  renderLine<Uint16,1>( SURFACE(this)->pixels,
515 				SURFACE(this)->pitch,
516 				p1.x, p1.y, p2.x, p2.y, color );
517 	}
518 	break;
519       case 4:
520 	if ( thick ) {
521 	  renderLine<Uint32,3>( SURFACE(this)->pixels,
522 				SURFACE(this)->pitch,
523 				p1.x, p1.y, p2.x, p2.y, color );
524 	} else {
525 	  renderLine<Uint32,1>( SURFACE(this)->pixels,
526 				SURFACE(this)->pitch,
527 				p1.x, p1.y, p2.x, p2.y, color );
528 	}
529 	break;
530       }
531     } else {
532       for ( ; i<n && !clip.contains( path.point(i) ); i++ ) {
533 	//skip until we find a unclipped pt - this will be p1 next
534 	//time around
535       }
536     }
537   }
538   SDL_UnlockSurface(SURFACE(this));
539 
540 }
541 
drawRect(int x,int y,int w,int h,int c,bool fill)542 void Canvas::drawRect( int x, int y, int w, int h, int c, bool fill )
543 {
544   if ( fill ) {
545     SDL_Rect r = { x, y, w, h };
546     SDL_FillRect( SURFACE(this), &r, c );
547   } else {
548     SDL_Rect f = { x, y, w, h };
549     SDL_Rect r;
550     r=f; r.h=1; SDL_FillRect( SURFACE(this), &r, c );
551     r.y+=f.h-1; SDL_FillRect( SURFACE(this), &r, c );
552     r=f; r.w=1; SDL_FillRect( SURFACE(this), &r, c );
553     r.x+=f.w-1; SDL_FillRect( SURFACE(this), &r, c );
554   }
555 }
556 
drawRect(const Rect & r,int c,bool fill)557 void Canvas::drawRect( const Rect& r, int c, bool fill )
558 {
559   drawRect( r.tl.x, r.tl.y, r.br.x-r.tl.x, r.br.y-r.tl.y, c, fill );
560 }
561 
562 
563 
Window(int w,int h,const char * title,const char * winclass)564 Window::Window( int w, int h, const char* title, const char* winclass )
565 {
566   if ( winclass ) {
567     char s[80];
568     snprintf(s,80,"SDL_VIDEO_X11_WMCLASS=%s",winclass);
569     putenv(s);
570   }
571   if ( title ) {
572     SDL_WM_SetCaption( title, title );
573   }
574 #ifdef USE_HILDON
575   m_state = SDL_SetVideoMode( w, h, 16, SDL_SWSURFACE);//SDL_FULLSCREEN);
576   SDL_WM_ToggleFullScreen( SURFACE(this) );
577   SDL_ShowCursor( SDL_DISABLE );
578 #else
579   m_state = SDL_SetVideoMode( w, h, 0, SDL_SWSURFACE);
580 #endif
581   if ( SURFACE(this) == NULL ) {
582     throw "Unable to set video mode";
583   }
584   resetClip();
585 
586 #ifdef USE_HILDON
587   SDL_SysWMinfo sys;
588   SDL_VERSION( &sys.version );
589   SDL_GetWMInfo( &sys );
590   printf("X11 window =%08x\n",sys.info.x11.window);
591   printf("X11 fswindow =%08x\n",sys.info.x11.fswindow);
592   printf("X11 wmwindow =%08x\n",sys.info.x11.wmwindow);
593 
594   uint32_t pid = getpid();
595   XChangeProperty( sys.info.x11.display,
596 		   sys.info.x11.wmwindow,
597 		   XInternAtom (sys.info.x11.display, "_NET_WM_PID", False),
598 		   XA_CARDINAL, 32, PropModeReplace,
599 		   (unsigned char*)&pid, 1 );
600 #endif
601 }
602 
603 
update(const Rect & r)604 void Window::update( const Rect& r )
605 {
606   if ( r.tl.x < width() && r.tl.y < height() ) {
607     int x1 = Max( 0, r.tl.x );
608     int y1 = Max( 0, r.tl.y );
609     int x2 = Min( width()-1, r.br.x );
610     int y2 = Min( height()-1, r.br.y );
611     int w  = Max( 0, x2-x1 );
612     int h  = Max( 0, y2-y1 );
613     if ( w > 0 && h > 0 ) {
614       SDL_UpdateRect( SURFACE(this), x1, y1, w, h );
615     }
616   }
617 }
618 
raise()619 void Window::raise()
620 {
621   SDL_SysWMinfo sys;
622   SDL_VERSION( &sys.version );
623   SDL_GetWMInfo( &sys );
624 
625 #ifndef WIN32
626   // take focus...
627   XEvent ev = { 0 };
628   ev.xclient.type         = ClientMessage;
629   ev.xclient.window       = sys.info.x11.wmwindow;
630   ev.xclient.message_type = XInternAtom (sys.info.x11.display,
631 					 "_NET_ACTIVE_WINDOW", False);
632   ev.xclient.format       = 32;
633   //all xewv.xclient.data==0 -> older spec?
634 
635   XSendEvent (sys.info.x11.display,
636 	      DefaultRootWindow(sys.info.x11.display),
637 	      False,
638 	      NoEventMask, //SubstructureRedirectMask,
639 	      &ev);
640   XSync( sys.info.x11.display, False );
641 #endif
642   //XRaiseWindow( sys.info.x11.display, sys.info.x11.window );
643 }
644 
645 
setSubName(const char * sub)646 void Window::setSubName( const char *sub )
647 {
648 #ifdef USE_HILDON
649   SDL_SysWMinfo sys;
650   SDL_VERSION( &sys.version );
651   SDL_GetWMInfo( &sys );
652 
653   XChangeProperty( sys.info.x11.display,
654 		   sys.info.x11.fswindow,
655 		   XInternAtom (sys.info.x11.display, "_MB_WIN_SUB_NAME", False),
656 		   XA_STRING, 8, PropModeReplace,
657 		   (unsigned char*)sub, strlen(sub) );
658 #endif
659 }
660 
661 
Image(const char * file,bool alpha)662 Image::Image( const char* file, bool alpha )
663 {
664   alpha = false;
665   std::string f( "data/" );
666   SDL_Surface* img = IMG_Load((f+file).c_str());
667   if ( !img ) {
668     f = std::string( DEFAULT_RESOURCE_PATH "/" );
669     img = IMG_Load((f+file).c_str());
670   }
671   if ( img ) {
672     printf("loaded image %s\n",(f+file).c_str());
673     if ( alpha ) {
674       m_state = SDL_DisplayFormatAlpha( img );
675     } else {
676       m_state = SDL_DisplayFormat( img );
677 //       SDL_SetColorKey( SURFACE(this),
678 // 		       SDL_SRCCOLORKEY|SDL_RLEACCEL,
679 // 		       makeColour( 0x00ff00ff ) );
680     }
681     if ( m_state ) {
682       SDL_FreeSurface( img );
683     } else {
684       printf("warning image %s not converted to display format\n",(f+file).c_str());
685       m_state = img;
686     }
687   } else {
688     throw "image not found";
689   }
690   resetClip();
691 }
692 
693 
694 
writeBMP(const char * filename) const695 int Canvas::writeBMP( const char* filename ) const
696 {
697   typedef struct {
698     unsigned short int type;                 /* Magic identifier            */
699     unsigned int size;                       /* File size in bytes          */
700     unsigned short int reserved1, reserved2;
701     unsigned int offset;                     /* Offset to image data, bytes */
702   } BMPHEADER;
703 
704   typedef struct {
705     unsigned int size;               /* Header size in bytes      */
706     int width,height;                /* Width and height of image */
707     unsigned short int planes;       /* Number of colour planes   */
708     unsigned short int bits;         /* Bits per pixel            */
709     unsigned int compression;        /* Compression type          */
710     unsigned int imagesize;          /* Image size in bytes       */
711     int xresolution,yresolution;     /* Pixels per meter          */
712     unsigned int ncolours;           /* Number of colours         */
713     unsigned int importantcolours;   /* Important colours         */
714   } BMPINFOHEADER;
715 
716   int w = width();
717   int h = height();
718   BMPHEADER     head = { 'B'|('M'<<8), 14+40+w*h*3, 0, 0, 0 };
719   BMPINFOHEADER info = { 40, w, h, 1, 24, 0, w*h*3, 100, 100, 0, 0 };
720 
721   FILE *f = fopen( filename, "wb" );
722   if ( f ) {
723     Uint32 bpp;
724     bpp = SURFACE(this)->format->BytesPerPixel;
725 
726     fwrite( &head, 14, 1, f );
727     fwrite( &info, 40, 1, f );
728     for ( int y=h-1; y>=0; y-- ) {
729       for ( int x=0; x<w; x++ ) {
730 	int p = readPixel( x, y );
731 	if ( bpp==2 ) {
732 	  p = R16G16B16_TO_RGB888( R16(p), G16(p), B16(p) );
733 	}
734 	fwrite( &p, 3, 1, f );
735       }
736     }
737     fclose(f);
738     return 1;
739   }
740   return 0;
741 }
742