_________ __                 __
        /   _____//  |_____________ _/  |______     ____  __ __  ______
        \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
        /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ \
       /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
               \/                  \/          \//_____/            \/
    ______________________                           ______________________
                          T H E   W A R   B E G I N S
                   Stratagus - A free fantasy real time strategy game engine

renderer.h
Go to the documentation of this file.
1 #ifndef __RENDERER_H__
2 #define __RENDERER_H__
3 
4 #include <assert.h>
5 
6 struct CPrimitives {
7  virtual void DrawPixel(Uint32 color, int x, int y) = 0;
8  virtual void DrawTransPixel(Uint32 color, int x, int y,
9  unsigned char alpha) = 0;
10 
11  virtual void DrawLine(Uint32 color, int sx, int sy, int dx, int dy) = 0;
12  virtual void DrawTransLine(Uint32 color, int sx, int sy,
13  int dx, int dy, unsigned char alpha) = 0;
14 
15  virtual void DrawRectangle(Uint32 color, int x, int y, int w, int h) = 0;
16  virtual void DrawTransRectangle(Uint32 color, int x, int y,
17  int w, int h, unsigned char alpha) = 0;
18 
19  virtual void FillTransRectangle(Uint32 color, int x, int y,
20  int w, int h, unsigned char alpha) = 0;
21 
22  virtual void DrawCircle(Uint32 color, int x, int y, int r) = 0;
23  virtual void DrawTransCircle(Uint32 color, int x, int y,
24  int r, unsigned char alpha) = 0;
25 
26  virtual void FillCircle(Uint32 color, int x, int y, int r) = 0;
27  virtual void FillTransCircle(Uint32 color, int x, int y,
28  int r, unsigned char alpha) = 0;
29 };
30 
31 namespace DRAW
32 {
33 template <const int BPP>
34 static inline Uint32 GetPixel(const void *const pixels, unsigned int index)
35 {
36  if (BPP == 1) {
37  return (((Uint8 *)pixels)[index]);
38  } else if (BPP == 2) {
39  return (((Uint16 *)pixels)[index]);
40  } else if (BPP == 4) {
41  return (((Uint32 *)pixels)[index]);
42  } else {
43  assert(0);
44  }
45  return 0;
46 };// __attribute__ ((nothrow,nonnull (1)));
47 
48 template <const int BPP>
49 static inline void PutPixel(void *const pixels,
50  unsigned int index, Uint32 color)
51 {
52  if (BPP == 1) {
53  ((Uint8 *)pixels)[index] = color;
54  } else if (BPP == 2) {
55  ((Uint16 *)pixels)[index] = color;
56  } else if (BPP == 4) {
57  ((Uint32 *)pixels)[index] = color;
58  } else {
59  assert(0);
60  }
61 };// __attribute__ ((nothrow,nonnull (1)));
62 
63 template <const int BPP>
64 static inline void
65 PutPixelDouble(void *pixels, const unsigned int index, Uint32 color)
66 {
67  if (BPP == 1) {
68  color &= 0xFF;
69  color |= color << 8;
70  *((Uint16 *)(((Uint8 *)pixels) + index)) = color;
71  } else if (BPP == 2) {
72  color &= 0xFFFF;
73  color |= color << 16;
74  *((Uint32 *)(((Uint16 *)pixels) + index)) = color;
75  } else if (BPP == 4) {
76  Uint32 *ptr = ((Uint32 *)pixels) + index;
77 #ifdef __x86_64__
78  Uint64 tmp = color;
79  tmp <<= 32;
80  //tmp |= color;
81  *((Uint64 *)ptr) = tmp | color;
82 #else
83  *ptr++ = color;
84  *ptr = color;
85 #endif
86  } else {
87  assert(0);
88  }
89 };// __attribute__ ((nothrow,nonnull (1)));
90 
91 template <const int BPP>
92 static inline void
93 PutPixelQuatro(void *pixels, unsigned int index, Uint32 color)
94 {
95  if (BPP == 1) {
96  color &= 0xFF;
97  color |= color << 8;
98  color |= color << 16;
99  *((Uint32 *)(((Uint8 *)pixels) + index)) = color;
100  } else if (BPP == 2) {
101  Uint32 *ptr = (Uint32 *)(((Uint16 *)pixels) + index);
102  color &= 0xFFFF;
103  color |= color << 16;
104 #ifdef __x86_64__
105  Uint64 tmp = color;
106  tmp <<= 32;
107  //tmp |= color;
108  *((Uint64 *)ptr) = tmp | color;
109 #else
110  *ptr++ = color;
111  *ptr = color;
112 #endif
113  } else if (BPP == 4) {
114  Uint32 *ptr = ((Uint32 *)pixels) + index;
115 #ifdef __x86_64__
116  Uint64 tmp = color;
117  tmp <<= 32;
118  tmp |= color;
119  *((Uint64 *)ptr) = tmp;
120  *((Uint64 *)(ptr + 2)) = tmp;
121 #else
122  *ptr++ = color;
123  *ptr++ = color;
124  *ptr++ = color;
125  *ptr = color;
126 #endif
127  } else {
128  assert(0);
129  }
130 };// __attribute__ ((nothrow,nonnull (1)));
131 
132 template <const int BPP>
133 static inline void DrawHLine(void *pixels, unsigned int index,
134  int width, Uint32 color)
135 {
136 #if 0
137  //if(width < 1) return;
138  do {
139  PutPixel(pixels, index, color);
140  index++;
141  } while (--width);
142 #else
143  if (BPP == 1) {
144  memset((void *)(((Uint8 *)pixels) + index), color, width);
145  } else if (BPP == 2) {
146 #ifdef __x86_64__
147  switch (((uintptr_t)pixels) & 6) {
148  case 6:
149  PutPixel<BPP>(pixels, index, color);
150  index++;
151  --width;
152  case 4:
153  PutPixel<BPP>(pixels, index, color);
154  index++;
155  --width;
156  case 2:
157  PutPixel<BPP>(pixels, index, color);
158  index++;
159  --width;
160  default:
161  break;
162  }
163 #else
164  if (((uintptr_t)pixels) & BPP) {
165  PutPixel<BPP>(pixels, index, color);
166  index++;
167  --width;
168  }
169 #endif
170  }
171 #ifdef __x86_64__
172  else if (BPP == 4 && ((uintptr_t)pixels) & BPP) {
173  PutPixel<BPP>(pixels, index, color);
174  index++;
175  --width;
176  }
177 #endif
178  while (width > 3) {
179  PutPixelQuatro<BPP>(pixels, index, color);
180  index += 4;
181  width -= 4;
182  };
183  switch (width & 3) {
184  case 3:
185  PutPixel<BPP>(pixels, index, color);
186  index++;
187  //--width;
188  case 2:
189  PutPixel<BPP>(pixels, index, color);
190  index++;
191  //--width;
192  case 1:
193  PutPixel<BPP>(pixels, index, color);
194  index++;
195  //--width;
196  default:
197  break;
198  }
199 
200 #endif
201 };
202 
203 };
204 
205 //RGB565 -> MASK = 0xf7de
206 //RGB555 -> MASK = 0xfbde
207 //RGB888 -> MASK = 0
208 template <const int BPP, const int MASK>
209 class CRenderer : public CPrimitives
210 {
211 
212  static inline void PutTransPixel(void *pixels, unsigned int index,
213  Uint32 color, unsigned int alpha)
214  {
215  unsigned int dp;
216  if (BPP == 2) {
217  Uint16 *p = (((Uint16 *)pixels) + index);
218  // Loses precision for speed
219  alpha >>= 3;
220  if (MASK == 0xf7de) {
221  /* RGB565 */
222  color = (((color << 16) | color) & 0x07E0F81F);
223  dp = *p;
224  dp = ((dp << 16) | dp) & 0x07E0F81F;
225  dp += (((color - dp) * alpha) >> 5);
226  dp &= 0x07E0F81F;
227  } else {
228  if (MASK == 0xfbde) {
229  /* RGB555 */
230  color = (((color << 16) | color) & 0x03e07c1f);
231  dp = *p;
232  dp = ((dp << 16) | dp) & 0x03e07c1f;
233  dp += (((color - dp) * alpha) >> 5);
234  dp &= 0x03e07c1f;
235  } else {
236  assert(0);
237  }
238  }
239  *p = (dp >> 16) | dp;
240  } else if (BPP == 4) {
241  /* RGB888(8) */
242  Uint32 *p = (((Uint32 *)pixels) + index);
243  unsigned int sp2 = (color & 0xFF00FF00) >> 8;
244  unsigned int dp2;
245 
246  color &= 0x00FF00FF;
247 
248  dp = *p;
249  dp2 = (dp & 0xFF00FF00) >> 8;
250  dp &= 0x00FF00FF;
251 
252  dp += (((color - dp) * alpha) >> 8);
253  dp &= 0x00FF00FF;
254  dp2 += (((sp2 - dp2) * alpha) >> 8);
255  dp2 &= 0x00FF00FF;
256  *p = (dp | (dp2 << 8));
257  } else {
258  assert(0);
259  }
260  } // __attribute__ ((nothrow,nonnull (1)));
261 
262  static inline void PutTransPixelDouble(void *pixels, unsigned int index,
263  Uint32 color, unsigned int alpha)
264  {
265 
266  if (BPP == 2) {
267  /*
268  #ifdef __x86_64__
269  //FIXME
270  unsigned int dp;
271  Uint16 *p = (((Uint16 *)pixels) + index);
272 
273  #else
274  */
275  PutTransPixel(pixels, index, color, alpha);
276  PutTransPixel(pixels, index + 1, color, alpha);
277  //#endif
278  } else if (BPP == 4) {
279 #ifdef __x86_64__
280  Uint64 *const p = (Uint64 *)(((Uint32 *)pixels) + index);
281  const Uint64 A = alpha;
282  Uint64 src0 = color;
283  Uint64 src1 = (src0 | (src0 << 32));
284  Uint64 dst0 = *p;
285  Uint64 dst1 = (dst0 >> 8);
286 
287  src0 = src1;
288  src1 >>= 8;
289 
290  src0 &= 0x00FF00FF00FF00FF;
291  src1 &= 0x00FF00FF00FF00FF;
292 
293  dst0 &= 0x00FF00FF00FF00FF;
294  dst1 &= 0x00FF00FF00FF00FF;
295 
296  dst0 += ((src0 - dst0) * A >> 8);
297  dst0 &= 0x00FF00FF00FF00FF;
298 
299  dst1 += ((src1 - dst1) * A >> 8);
300  dst1 &= 0x00FF00FF00FF00FF;
301 
302  *p = dst0 | (dst1 << 8)
303 #else
304  Uint32 * p = (((Uint32 *)pixels) + index);
305  /*
306  * FIXME:
307  * Two Pixels Blend for litle endian and
308  * big endian may be broken.
309  */
310  unsigned int d1, s1 = color & 0xff00ff;
311  unsigned int dp = *p;
312  d1 = dp & 0xff00ff;
313 
314  color &= 0xff00;
315  color = (color >> 8) | (color << 8);
316 
317  d1 += (s1 - d1) * alpha >> 8;
318  d1 &= 0xff00ff;
319 
320  dp = ((dp & 0xff00) >> 8) |
321  ((p[1] & 0xff00) << 8);
322 
323  dp += (color - dp) * alpha >> 8;
324  dp &= 0x00ff00ff;
325 
326  *p++ = d1 | ((dp << 8) & 0xff00) | 0xff000000;
327 
328  d1 = *p;
329  d1 &= 0xff00ff;
330  d1 += (s1 - d1) * alpha >> 8;
331  d1 &= 0xff00ff;
332 
333  *p = d1 | ((dp >> 8) & 0xff00) | 0xff000000;
334 #endif
335  } else {
336  assert(0);
337  }
338  } // __attribute__ ((nothrow,nonnull (1)));
339 
340 
341  static inline void PutTransPixel128(void *pixels, unsigned int index, Uint32 color)
342  {
343  if (BPP == 2) {
344  /* blend a single 16 bit pixel at 50% */
345 #define BLEND16_50(d, s, mask) \
346  ((((s & mask) + (d & mask)) >> 1) + (s & d & (~mask & 0xffff)))
347 
348  Uint16 *p = (((Uint16 *)pixels) + index);
349  Uint16 d = *p;
350  Uint16 s = color & 0xFFFF; // I hope that caler secure it;
351 
352  *p = BLEND16_50(d, s, MASK);
353 
354 #undef BLEND16_50
355  } else if (BPP == 4) {
356  Uint32 *p = (((Uint32 *)pixels) + index);
357  unsigned int d = *p;
358 
359  *p = ((((color & 0x00fefefe) + (d & 0x00fefefe)) >> 1)
360  + (color & d & 0x00010101)) | 0xff000000;
361 
362  } else {
363  assert(0);
364  }
365  };
366 
367  static inline void PutTransPixel128Double(void *pixels, const unsigned int index,
368  const Uint32 color)
369  {
370  if (BPP == 2) {
371  /* blend two 16 bit pixels at 50% */
372 #define BLEND2x16_50(d, s, mask) \
373  (((s & (mask | mask << 16)) >> 1) + ((d & (mask | mask << 16)) >> 1) \
374  + (s & d & (~(mask | mask << 16))))
375 
376  Uint32 *p = (Uint32 *)(((Uint16 *)pixels) + index);
377  Uint32 d = *p;
378  const Uint32 s = (color & 0xFFFF) | color << 16; // I hope that caler secure it;
379 
380  *p = BLEND2x16_50(d, s, MASK);
381 
382 #undef BLEND2x16_50
383  } else if (BPP == 4) {
384  Uint32 *p = (((Uint32 *)pixels) + index);
385 #ifdef __x86_64__
386  unsigned long long int d = *(unsigned long long int *)p;
387  unsigned long long int s, c = color;
388 
389  s = c | c << 32;
390  c = s & 0x00fefefe00fefefe;
391 
392  *(unsigned long long int *)p =
393  (((c + (d & 0x00fefefe00fefefe)) >> 1)
394  + (s & d & 0x0001010100010101)) |
395  0xff000000ff000000;
396 #else
397  Uint32 d = *p;
398  const Uint32 c = color & 0x00fefefe;
399  *p++ = (((c + (d & 0x00fefefe)) >> 1)
400  + (color & d & 0x00010101)) | 0xff000000;
401  d = *p;
402  *p = (((c + (d & 0x00fefefe)) >> 1)
403  + (color & d & 0x00010101)) | 0xff000000;
404 #endif
405  } else {
406  assert(0);
407  }
408  } // __attribute__ ((nothrow,nonnull (1)));
409 
410  static void DrawVLine(void *pixels, const unsigned int pitch,
411  unsigned int index, int height, Uint32 color)
412  {
413  if (height < 1) { return; }
414  do {
415  DRAW::PutPixel<BPP>(pixels, index, color);
416  index += pitch;
417  } while (--height);
418  } // __attribute__ ((nothrow,nonnull (1)));
419 
420  static void DrawTransVLine(void *pixels, const unsigned int pitch,
421  unsigned int index, int height, Uint32 color, unsigned int alpha)
422  {
423  if (height < 1) { return; }
424  if (alpha == 128) {
425  do {
426  PutTransPixel128(pixels, index, color);
427  index += pitch;
428  } while (--height);
429  } else {
430  do {
431  PutTransPixel(pixels, index, color, alpha);
432  index += pitch;
433  } while (--height);
434  }
435  } // __attribute__ ((nothrow,nonnull (1)));
436 
437  static inline void DrawTransHLine128(void *pixels,
438  unsigned int index, int width, Uint32 color)
439  {
440 #ifdef __x86_64__
441  //FIXME: this may not work on 16 bpp
442  if (((uintptr_t)pixels) & BPP) {
443 #else
444  if (width & 1) {
445 #endif
446  PutTransPixel128(pixels, index, color);
447  --width;
448  index++;
449  }
450  while (width > 1) {
451  PutTransPixel128Double(pixels, index, color);
452  index += 2;
453  width -= 2;
454  };
455 #ifdef __x86_64__
456  if (width) { PutTransPixel128(pixels, index, color); }
457 #endif
458 
459  } // __attribute__ ((nothrow,nonnull (1)));
460 
461 
462  static inline void DrawTransHLineNon128(void *pixels,
463  unsigned int index, int width, Uint32 color, unsigned int alpha)
464  {
465 #ifdef __x86_64__
466  if (((uintptr_t)pixels) & BPP) {
467 #else
468  if (width & 1) {
469 #endif
470  PutTransPixel(pixels, index, color, alpha);
471  --width;
472  index++;
473  }
474  while (width > 1) {
475  PutTransPixelDouble(pixels, index, color, alpha);
476  index += 2;
477  width -= 2;
478  };
479 #ifdef __x86_64__
480  if (width) { PutTransPixel(pixels, index, color, alpha); }
481 #endif
482  } // __attribute__ ((nothrow,nonnull (1)));
483 
484  static inline void DrawTransHLine(void *pixels,
485  unsigned int index, int width, Uint32 color, unsigned int alpha)
486  {
487  //if(width < 1) return;
488  if (alpha == 128) {
489  DrawTransHLine128(pixels, index, width, color);
490  } else {
491  DrawTransHLineNon128(pixels, index, width, color, alpha);
492  }
493  };
494 
495  void DrawPixel(Uint32 color, int x, int y)
496  {
497  unsigned int index = TheScreen->pitch / BPP;
498  index *= y;
499  index += x;
500  DRAW::PutPixel<BPP>(TheScreen->pixels, index, color);
501  };
502 
503  void DrawTransPixel(Uint32 color, int x, int y, unsigned char alpha)
504  {
505  unsigned int index = TheScreen->pitch / BPP;
506  index *= y;
507  index += x;
508  if (alpha == 128) {
509  PutTransPixel128(TheScreen->pixels, index, color);
510  } else {
511  PutTransPixel(TheScreen->pixels, index, color, alpha);
512  }
513  };
514 
515  void DrawLine(Uint32 color, int sx, int sy, int dx, int dy)
516  {
517  unsigned int index;
518  const unsigned int pitch = TheScreen->pitch / BPP;
519 
520  if (sx == dx) {
521  unsigned int len = 1;
522  if (sy < dy) {
523  index = sx + sy * pitch;
524  len += dy - sy;
525  } else {
526  index = dx + dy * pitch;
527  len += sy - dy;
528  }
529  DrawVLine(TheScreen->pixels, pitch, index, len, color);
530  return;
531  }
532 
533  if (sy == dy) {
534  unsigned int len = 1;
535  if (sx < dx) {
536  index = sx + sy * pitch;
537  len += dx - sx;
538  } else {
539  index = dx + dy * pitch;
540  len += sx - dx;
541  }
542  DRAW::DrawHLine<BPP>(TheScreen->pixels, index, len, color);
543  return;
544  }
545 
546  // exchange coordinates
547  if (sy > dy) {
548  int t;
549  t = dx;
550  dx = sx;
551  sx = t;
552  t = dy;
553  dy = sy;
554  sy = t;
555  }
556 
557  int ylen = dy - sy;
558  int incr;
559  int xlen;
560 
561  if (sx > dx) {
562  xlen = sx - dx;
563  incr = -1;
564  } else {
565  xlen = dx - sx;
566  incr = 1;
567  }
568 
569  int y = sy;
570  int x = sx;
571 
572  if (xlen > ylen) {
573  int p;
574 
575  if (sx > dx) {
576  int t;
577  t = sx;
578  sx = dx;
579  dx = t;
580  y = dy;
581  }
582 
583  p = (ylen << 1) - xlen;
584 
585  index = y * pitch;
586  incr *= pitch;
587  for (x = sx; x < dx; ++x) {
588  DRAW::PutPixel<BPP>(TheScreen->pixels, x + index, color);
589  if (p >= 0) {
590  //y += incr;
591  index += incr;
592  p += (ylen - xlen) << 1;
593  } else {
594  p += (ylen << 1);
595  }
596  }
597  return;
598  }
599 
600  if (ylen > xlen) {
601  int p;
602 
603  p = (xlen << 1) - ylen;
604  index = sy * pitch;
605  for (y = sy; y < dy; ++y) {
606  DRAW::PutPixel<BPP>(TheScreen->pixels, x + index, color);
607  if (p >= 0) {
608  x += incr;
609  p += (xlen - ylen) << 1;
610  } else {
611  p += (xlen << 1);
612  }
613  index += pitch;
614  }
615 
616  return;
617  }
618 
619  // Draw a diagonal line
620  if (ylen == xlen) {
621  index = y * pitch;
622  while (y != dy) {
623  DRAW::PutPixel<BPP>(TheScreen->pixels, x + index, color);
624  x += incr;
625  ++y;
626  index += pitch;
627  }
628  }
629  };
630 
631  void DrawTransLine(Uint32 color, int sx, int sy,
632  int dx, int dy, unsigned char alpha)
633  {
634  DrawLine(color, sx, sy, dx, dy);
635  }
636 
637 
638  void DrawRectangle(Uint32 color, int x, int y, int w, int h)
639  {
640  const unsigned int pitch = TheScreen->pitch / BPP;
641  unsigned int index = y * pitch;
642  unsigned int y_offset = (h - 1) * pitch;
643  PutTransPixel128(TheScreen->pixels, x + index, color);
644  DRAW::DrawHLine<BPP>(TheScreen->pixels, x + index + 1, w - 2, color);
645  PutTransPixel128(TheScreen->pixels, x + index + w - 1, color);
646 
647  PutTransPixel128(TheScreen->pixels, x + index + y_offset, color);
648  DRAW::DrawHLine<BPP>(TheScreen->pixels, x + index + y_offset + 1, w - 2, color); // (x, y + h - 1, w)
649  PutTransPixel128(TheScreen->pixels, x + index + y_offset + w - 1, color);
650 
651  DrawVLine(TheScreen->pixels, pitch, x + index + pitch,
652  h - 2, color); //(x, y + 1, h - 2)
653  DrawVLine(TheScreen->pixels, pitch, x + index + w - 1 + pitch,
654  h - 2, color); //x + w - 1, y + 1, h - 2
655  };
656 
657  void DrawTransRectangle(Uint32 color, int x, int y,
658  int w, int h, unsigned char alpha)
659  {
660  const unsigned int pitch = TheScreen->pitch / BPP;
661  unsigned int index = y * pitch;
662  unsigned int y_offset = (h - 1) * pitch;
663  //unsigned int a = 255 - alpha;
664 
665  PutTransPixel(TheScreen->pixels, x + index, color, alpha / 2);
666  DrawTransHLine(TheScreen->pixels, x + index + 1, w - 2, color, alpha);
667  PutTransPixel(TheScreen->pixels, x + index + w - 1, color, alpha / 2);
668 
669  PutTransPixel(TheScreen->pixels, x + index + y_offset, color, alpha / 2);
670  DrawTransHLine(TheScreen->pixels, x + index + y_offset + 1,
671  w - 2, color, alpha); // (x, y + h - 1, w)
672  PutTransPixel(TheScreen->pixels,
673  x + index + y_offset + w - 1, color, alpha / 2);
674 
675  DrawTransVLine(TheScreen->pixels, pitch, x + index + pitch,
676  h - 2, color, alpha); //(x, y + 1, h - 2)
677  DrawTransVLine(TheScreen->pixels, pitch, x + index + w - 1 + pitch,
678  h - 2, color, alpha); //x + w - 1, y + 1, h - 2
679  };
680 
681  void FillTransRectangle(Uint32 color, int x, int y,
682  int w, int h, unsigned char alpha)
683  {
684  const unsigned int pitch = TheScreen->pitch / BPP;
685  unsigned int index = y * pitch;
686  if (alpha == 128) {
687  do {
688  DrawTransHLine128(TheScreen->pixels, x + index, w, color);
689  index += pitch;
690  } while (--h);
691  } else {
692  do {
693  DrawTransHLineNon128(TheScreen->pixels, x + index, w, color, alpha);
694  index += pitch;
695  } while (--h);
696  }
697  };
698 
699  void DrawCircle(Uint32 color, int x, int y, int r)
700  {
701  const unsigned int pitch = TheScreen->pitch / BPP;
702  int p = 1 - r;
703  int px = 0;
704  int py = r;
705 
706  for (; px <= py + 1; ++px) {
707  unsigned int index_plus = (y + py) * pitch;
708  unsigned int index_minus = (y - py) * pitch;
709 
710  DRAW::PutPixel<BPP>(TheScreen->pixels, x + px + index_plus, color);
711  DRAW::PutPixel<BPP>(TheScreen->pixels, x + px + index_minus, color);
712  DRAW::PutPixel<BPP>(TheScreen->pixels, x - px + index_plus, color);
713  DRAW::PutPixel<BPP>(TheScreen->pixels, x - px + index_minus, color);
714 
715  index_plus = (y + px) * pitch;
716  index_minus = (y - px) * pitch;
717 
718  DRAW::PutPixel<BPP>(TheScreen->pixels, x + py + index_plus, color);
719  DRAW::PutPixel<BPP>(TheScreen->pixels, x + py + index_minus, color);
720  DRAW::PutPixel<BPP>(TheScreen->pixels, x - py + index_plus, color);
721  DRAW::PutPixel<BPP>(TheScreen->pixels, x - py + index_minus, color);
722 
723  if (p < 0) {
724  p += 2 * px + 3;
725  } else {
726  p += 2 * (px - py) + 5;
727  py -= 1;
728  }
729  }
730  };
731 
732  void DrawTransCircle(Uint32 color, int x, int y,
733  int r, unsigned char alpha)
734  {
735  const unsigned int pitch = TheScreen->pitch / BPP;
736  int p = 1 - r;
737  int px = 0;
738  int py = r;
739 
740  for (; px <= py + 1; ++px) {
741  unsigned int index_plus = (y + py) * pitch;
742  unsigned int index_minus = (y - py) * pitch;
743 
744  PutTransPixel(TheScreen->pixels, x + px + index_plus, color, alpha);
745  PutTransPixel(TheScreen->pixels, x + px + index_minus, color, alpha);
746  PutTransPixel(TheScreen->pixels, x - px + index_plus, color, alpha);
747  PutTransPixel(TheScreen->pixels, x - px + index_minus, color, alpha);
748 
749  index_plus = (y + px) * pitch;
750  index_minus = (y - px) * pitch;
751 
752  PutTransPixel(TheScreen->pixels, x + py + index_plus, color, alpha);
753  PutTransPixel(TheScreen->pixels, x + py + index_minus, color, alpha);
754  PutTransPixel(TheScreen->pixels, x - py + index_plus, color, alpha);
755  PutTransPixel(TheScreen->pixels, x - py + index_minus, color, alpha);
756 
757  if (p < 0) {
758  p += 2 * px + 3;
759  } else {
760  p += 2 * (px - py) + 5;
761  py -= 1;
762  }
763  }
764  };
765 
766  void FillCircle(Uint32 color, int x, int y, int r)
767  {
768  const unsigned int pitch = TheScreen->pitch / BPP;
769  int p = 1 - r;
770  int px = 0;
771  int py = r;
772 
773  for (; px <= py; ++px) {
774  //FIXME: Change it to DrawHLine for speed.
775  unsigned int y_index = y * pitch;
776  unsigned int py_index = py * pitch;
777 
778  // Fill up the middle half of the circle
779  DrawVLine(TheScreen->pixels, pitch,
780  x + px + y_index,
781  py + 1, color);
782  DrawVLine(TheScreen->pixels, pitch,
783  x + px + (y_index - py_index),
784  py, color);
785 
786  if (px) {
787  DrawVLine(TheScreen->pixels, pitch,
788  x - px + y_index,
789  py + 1, color);
790  DrawVLine(TheScreen->pixels, pitch,
791  x - px + (y_index - py_index),
792  py, color);
793  }
794 
795  if (p < 0) {
796  p += 2 * px + 3;
797  } else {
798  p += 2 * (px - py) + 5;
799  py -= 1;
800  // Fill up the left/right half of the circle
801  if (py >= px) {
802  unsigned int px_index = px * pitch;
803  DrawVLine(TheScreen->pixels, pitch,
804  x + py + 1 + y_index,
805  px + 1, color);
806  DrawVLine(TheScreen->pixels, pitch,
807  x + py + 1 + (y_index - px_index),
808  px, color);
809  DrawVLine(TheScreen->pixels, pitch,
810  x - py - 1 + y_index,
811  px + 1, color);
812  DrawVLine(TheScreen->pixels, pitch,
813  x - py - 1 + (y_index - px_index),
814  px, color);
815  }
816  }
817  }
818  };
819 
820  void FillTransCircle(Uint32 color, int x, int y,
821  int r, unsigned char alpha)
822  {
823  const unsigned int pitch = TheScreen->pitch / BPP;
824  int p = 1 - r;
825  int px = 0;
826  int py = r;
827 
828  for (; px <= py; ++px) {
829  //FIXME: Change it to DrawTransHLine for speed.
830  unsigned int y_index = y * pitch;
831  unsigned int py_index = py * pitch;
832 
833  // Fill up the middle half of the circle
834  DrawTransVLine(TheScreen->pixels, pitch,
835  x + px + y_index,
836  py + 1, color, alpha);
837  DrawTransVLine(TheScreen->pixels, pitch,
838  x + px + (y_index - py_index),
839  py, color, alpha);
840 
841  if (px) {
842  DrawTransVLine(TheScreen->pixels, pitch,
843  x - px + y_index,
844  py + 1, color, alpha);
845  DrawTransVLine(TheScreen->pixels, pitch,
846  x - px + (y_index - py_index),
847  py, color, alpha);
848  }
849 
850  if (p < 0) {
851  p += 2 * px + 3;
852  } else {
853  p += 2 * (px - py) + 5;
854  py -= 1;
855  // Fill up the left/right half of the circle
856  if (py >= px) {
857  unsigned int px_index = px * pitch;
858  DrawTransVLine(TheScreen->pixels, pitch,
859  x + py + 1 + y_index,
860  px + 1, color, alpha);
861  DrawTransVLine(TheScreen->pixels, pitch,
862  x + py + 1 + (y_index - px_index),
863  px, color, alpha);
864  DrawTransVLine(TheScreen->pixels, pitch,
865  x - py - 1 + y_index,
866  px + 1, color, alpha);
867  DrawTransVLine(TheScreen->pixels, pitch,
868  x - py - 1 + (y_index - px_index),
869  px, color, alpha);
870  }
871  }
872  }
873  };
874 
875 };
876 
880 
881 #endif
882 
Primitive16_555_t
CRenderer< 2, 0xfbde > Primitive16_555_t
Definition: renderer.h:877
CPrimitives::DrawCircle
virtual void DrawCircle(Uint32 color, int x, int y, int r)=0
CPrimitives::FillTransRectangle
virtual void FillTransRectangle(Uint32 color, int x, int y, int w, int h, unsigned char alpha)=0
CPrimitives::FillTransCircle
virtual void FillTransCircle(Uint32 color, int x, int y, int r, unsigned char alpha)=0
DRAW::PutPixelQuatro
static void PutPixelQuatro(void *pixels, unsigned int index, Uint32 color)
Definition: renderer.h:93
BLEND2x16_50
#define BLEND2x16_50(d, s, mask)
CPrimitives::DrawTransCircle
virtual void DrawTransCircle(Uint32 color, int x, int y, int r, unsigned char alpha)=0
BLEND16_50
#define BLEND16_50(d, s, mask)
CPrimitives::DrawTransPixel
virtual void DrawTransPixel(Uint32 color, int x, int y, unsigned char alpha)=0
DRAW::PutPixel
static void PutPixel(void *const pixels, unsigned int index, Uint32 color)
Definition: renderer.h:49
TheScreen
SDL_Surface * TheScreen
Internal screen.
Definition: sdl.cpp:94
CPrimitives::DrawRectangle
virtual void DrawRectangle(Uint32 color, int x, int y, int w, int h)=0
DRAW::DrawHLine
static void DrawHLine(void *pixels, unsigned int index, int width, Uint32 color)
Definition: renderer.h:133
DRAW
Definition: renderer.h:31
CPrimitives::DrawPixel
virtual void DrawPixel(Uint32 color, int x, int y)=0
update-images.w
w
Definition: update-images.py:53
CPrimitives::FillCircle
virtual void FillCircle(Uint32 color, int x, int y, int r)=0
CPrimitives::DrawTransLine
virtual void DrawTransLine(Uint32 color, int sx, int sy, int dx, int dy, unsigned char alpha)=0
DRAW::PutPixelDouble
static void PutPixelDouble(void *pixels, const unsigned int index, Uint32 color)
Definition: renderer.h:65
Primitive32_t
CRenderer< 4, 0 > Primitive32_t
Definition: renderer.h:879
CPrimitives::DrawTransRectangle
virtual void DrawTransRectangle(Uint32 color, int x, int y, int w, int h, unsigned char alpha)=0
Primitive16_565_t
CRenderer< 2, 0xf7de > Primitive16_565_t
Definition: renderer.h:878
update-images.h
h
Definition: update-images.py:53
CPrimitives
Definition: renderer.h:6
CRenderer
Definition: renderer.h:209
CPrimitives::DrawLine
virtual void DrawLine(Uint32 color, int sx, int sy, int dx, int dy)=0
DRAW::GetPixel
static Uint32 GetPixel(const void *const pixels, unsigned int index)
Definition: renderer.h:34
(C) Copyright 1998-2012 by The Stratagus Project under the GNU General Public License.
All trademarks and copyrights on this page are owned by their respective owners.