FreeBASIC  0.91.0
gfx_put.c
Go to the documentation of this file.
1 /* PUT statement */
2 
3 #include "fb_gfx.h"
4 
5 
6 #ifdef HOST_X86
7 
8 #include "x86/fb_gfx_mmx.h"
9 
10 extern void fb_hPutAlphaMaskMMX(unsigned char *src, unsigned char *dest, int w, int h, int src_pitch, int dest_pitch, int alpha, BLENDER *blender, void *param);
11 
12 #endif
13 
14 
15 /*:::::*/
16 static void fb_hPutAlphaMask(unsigned char *src, unsigned char *dest, int w, int h, int src_pitch, int dest_pitch, int alpha, BLENDER *blender, void *param)
17 {
18  unsigned char *s;
19  unsigned int *d;
20  unsigned int dc, sc;
21  int x;
22 
23 #ifdef HOST_X86
24  if (__fb_gfx->flags & HAS_MMX) {
25  fb_hPutAlphaMaskMMX(src, dest, w, h, src_pitch, dest_pitch, alpha, blender, param);
26  return;
27  }
28 #endif
29 
30  s = src;
31  d = (unsigned int *)dest;
32  src_pitch -= w;
33  dest_pitch = (dest_pitch >> 2) - w;
34  for (; h; h--) {
35  for (x = w; x; x--) {
36  dc = *d;
37  sc = *s++;
38  *d++ = (dc & ~MASK_A_32) | (sc << 24);
39  }
40  s += src_pitch;
41  d += dest_pitch;
42  }
43 }
44 
45 
46 /*:::::*/
47 FBCALL int fb_GfxPut(void *target, float fx, float fy, unsigned char *src, int x1, int y1, int x2, int y2, int coord_type, int put_mode, PUTTER *putter, int alpha, BLENDER *blender, void *param)
48 {
50  int x, y, w, h, pitch, bpp;
51  int lhs, rhs;
52  PUT_HEADER *header;
53 
54  if ((!__fb_gfx) || (!src))
56 
57  fb_hPrepareTarget(context, target);
59 
60  // quirky but good
61  switch (coord_type) {
62  case COORD_TYPE_RA:
63  lhs = COORD_TYPE_R;
64  rhs = COORD_TYPE_A;
65  break;
66  case COORD_TYPE_RR:
67  lhs = COORD_TYPE_R;
68  rhs = COORD_TYPE_R;
69  break;
70  case COORD_TYPE_AA:
71  lhs = COORD_TYPE_A;
72  rhs = COORD_TYPE_A;
73  break;
74  case COORD_TYPE_AR:
75  lhs = COORD_TYPE_A;
76  rhs = COORD_TYPE_R;
77  break;
78  default:
80  }
81 
82  fb_hFixRelative(context, lhs, &fx, &fy, NULL, NULL);
83 
84  if( rhs == COORD_TYPE_R ) {
85  x2 += x1;
86  y2 += y1;
87  }
88  fb_hTranslateCoord(context, fx, fy, &x, &y);
89 
90  header = (PUT_HEADER *)src;
91  if (header->type == PUT_HEADER_NEW) {
92  bpp = header->bpp;
93  w = header->width;
94  h = header->height;
95  pitch = header->pitch;
96  src += sizeof(PUT_HEADER);
97  }
98  else {
99  bpp = header->old.bpp;
100  if (!bpp)
101  bpp = context->target_bpp;
102  w = header->old.width;
103  h = header->old.height;
104  pitch = w * bpp;
105  src += 4;
106  }
107 
108  if (bpp != context->target_bpp) {
109  if ((put_mode == PUT_MODE_ALPHA) && (bpp == 1) && (context->target_bpp == 4))
110  putter = fb_hPutAlphaMask;
111  else
113  }
114 
115  if (x1 != 0xFFFF0000) {
116  fb_hFixCoordsOrder(&x1, &y1, &x2, &y2);
117 
118  x1 = MID(0, x1, w-1);
119  x2 = MID(0, x2, w-1);
120  y1 = MID(0, y1, h-1);
121  y2 = MID(0, y2, h-1);
122 
123  w = x2 - x1 + 1;
124  h = y2 - y1 + 1;
125  src += (y1 * pitch) + (x1 * bpp);
126  }
127 
128  if ((w == 0) || (h == 0) ||
129  (x + w <= context->view_x) || (x >= context->view_x + context->view_w) ||
130  (y + h <= context->view_y) || (y >= context->view_y + context->view_h))
131  return fb_ErrorSetNum( FB_RTERROR_OK );
132 
133  if (y < context->view_y) {
134  src += ((context->view_y - y) * pitch);
135  h -= (context->view_y - y);
136  y = context->view_y;
137  }
138  if (y + h > context->view_y + context->view_h)
139  h -= ((y + h) - (context->view_y + context->view_h));
140  if (x < context->view_x) {
141  src += ((context->view_x - x) * bpp);
142  w -= (context->view_x - x);
143  x = context->view_x;
144  }
145  if (x + w > context->view_x + context->view_w)
146  w -= ((x + w) - (context->view_x + context->view_w));
147 
148  DRIVER_LOCK();
149  putter(src, context->line[y] + (x * context->target_bpp), w, h, pitch, context->target_pitch, alpha, blender, param);
150  SET_DIRTY(context, y, h);
151  DRIVER_UNLOCK();
152 
153  return fb_ErrorSetNum( FB_RTERROR_OK );
154 }