1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
// This include is meant to be the body of the function CreateTilemapXX,
// which is implemented exactly the same for different resolutions. For
// compatibility reasons this is controlled by Defines instead of templates.
// Therefor the following type definitions are set to the required values,
// while compiling that function:
//
// #define DATA_TYPE unsigned char
// #define DATA_PAD 1
#define IMAX 1000
XImage *ximage;
Vec2 wcenter;
Vec2 dirx,diry,edge;
if (page) {
if (pm->IsTwinPixmap())
wcenter=Vec2( center.X(), pm->XHeight()+center.Y() );
else wcenter=Vec2( center.X(), center.Y() );
}
else wcenter=center;
ximage = img_buf->Init(width,height,DATA_PAD);
if (!itm) {
if (page) {
dirx=Vec2(-1,0).TurnAngleDeg(windir);
diry=Vec2(1,0).TurnLeft().TurnAngleDeg(windir);
}
else {
dirx=Vec2(1,0).TurnAngleDeg(-windir);
diry=Vec2(1,0).TurnLeft().TurnAngleDeg(-windir);
}
edge=wcenter-offx*dirx-offy*diry;
}
else {
dirx=(*itm)*Vec2(1,0);
diry=(*itm)*Vec2(0,1);
edge=wcenter+(*itm)*Vec2(-offx,-offy);
}
#if (0)
//
// the traditional routine to copy each pixel from one image to the other
// with the generic routines. range checking is done in pm's GetPixel() and
// there's nothing to worry about (except the time...)
//
pm->GetImage(); // to make sure the pixmap is valid
for (int y=0;y<height;y++) {
Vec2 pt=edge+y*diry;
/* x,y, dx,dy bestimmen ... */
register DATA_TYPE *dest = (DATA_TYPE*)(ximage->data + y * ximage->bytes_per_line);
for (int x=0;x<width;x++) {
*dest++ = pm->GetPixel( XPix(pt.X()), YPix(pt.Y()) );
pt+=dirx;
}
}
#else
//
// optimized mapping
// in a loop in brezenham fashion, each pixel is copied from one buffer to the
// other with direct access to the data structure. Since it would be inefficient
// to an access outside of the source image on every pixel, only the 4 edges are
// check, if the boundary is crossed, a traditional copy with range checking is
// done. This happens very seldom, since the buffer for the picture is
// large than it has to be, so that only a few flip's will really fall
// outside ...
XImage *src_image=pm->GetImage();
#ifndef RANGE_CHECK
{
char *src;
char *pic_addr=src_image->data; // image start
char *min_addr=pic_addr-pm->offset_bytes; // memory start (including offset)
char *max_addr=pic_addr+src_image->bytes_per_line*src_image->height
+pm->offset_bytes; // memory end (behind offset)
int count=0;
Vec2 t=edge;
src = (char*)((DATA_TYPE*)(pic_addr+YPix(t.Y())*src_image->bytes_per_line)+XPix(t.X()));
if (src<min_addr||src>=max_addr) count++;
t=edge+height*diry;
src = (char*)((DATA_TYPE*)(pic_addr+YPix(t.Y())*src_image->bytes_per_line)+XPix(t.X()));
if (src<min_addr||src>=max_addr) count++;
t=edge+width*dirx;
src = (char*)((DATA_TYPE*)(pic_addr+YPix(t.Y())*src_image->bytes_per_line)+XPix(t.X()));
if (src<min_addr||src>=max_addr) count++;
t=edge+height*diry+width*dirx;
src = (char*)((DATA_TYPE*)(pic_addr+YPix(t.Y())*src_image->bytes_per_line)+XPix(t.X()));
if (src<min_addr||src>=max_addr) count++;
if (count) {
DBG0( "*** range overflow -> trying slow mapping\n" );
for (int y=0;y<height;y++) {
Vec2 pt=edge+y*diry;
/* x,y, dx,dy bestimmen ... */
register DATA_TYPE *dest = (DATA_TYPE*)(ximage->data + y * ximage->bytes_per_line);
for (int x=0;x<width;x++) {
*dest++ = (DATA_TYPE)pm->GetPixel( XPix(pt.X()), YPix(pt.Y()) );
pt+=dirx;
}
}
img_buf->PutImage(dpy,tilemap,DefaultGC(dpy,scr),0,0,0,0,width,height);
return;
}
}
#endif
int pixels_per_line=src_image->bytes_per_line/sizeof(DATA_TYPE);
register int dx=(int)(dirx.X()*IMAX);
register int dy=(int)(dirx.Y()*IMAX);
for (int y=0;y<height;y++) {
Vec2 pt=edge+y*diry;
/* x,y, dx,dy bestimmen ... */
register int dx_c = ((dx>0)?dx:-dx)/2;
register int dy_c = ((dy>0)?dy:-dy)/2;
#ifdef RANGE_CHECK
register int src_x = XPix(pt.X());
register int src_y = YPix(pt.Y());
# define INC_X src_x++
# define DEC_X src_x--
# define INC_Y src_y++
# define DEC_Y src_y--
#else
# define INC_X
# define DEC_X
# define INC_Y
# define DEC_Y
#endif
register DATA_TYPE *src = (DATA_TYPE*)(src_image->data + YPix(pt.Y()) * src_image->bytes_per_line)+XPix(pt.X());
register DATA_TYPE *dest= (DATA_TYPE*)(ximage->data + y * ximage->bytes_per_line);
if (dx>=0) {
if (dy>=0) {
for (int x=0;x<width;x++) {
#ifdef RANGE_CHECK
if (src_x<0||src_x>=src_image->width||src_y<0||src_y>=src_image->height) {
*dest++ = 0;
}
else
#endif
*dest++ = *src;
dx_c-=dx;
while (dx_c<0) { dx_c+=IMAX; INC_X; src++; }
dy_c-=dy;
while (dy_c<0) { dy_c+=IMAX; INC_Y; src+=pixels_per_line; }
}
}
else {
for (int x=0;x<width;x++) {
#ifdef RANGE_CHECK
if (src_x<0||src_x>=src_image->width||src_y<0||src_y>=src_image->height) {
*dest++ = 0;
}
else
#endif
*dest++ = *src;
dx_c-=dx;
while (dx_c<0) { dx_c+=IMAX; INC_X; src++; }
dy_c+=dy;
while (dy_c<0) { dy_c+=IMAX; DEC_Y; src-=pixels_per_line; }
}
}
}
else {
if (dy>=0) {
for (int x=0;x<width;x++) {
#ifdef RANGE_CHECK
if (src_x<0||src_x>=src_image->width||src_y<0||src_y>=src_image->height) {
*dest++ = 0;
}
else
#endif
*dest++ = *src;
dx_c+=dx;
while (dx_c<0) { dx_c+=IMAX; DEC_X; src--; }
dy_c-=dy;
while (dy_c<0) { dy_c+=IMAX; INC_Y; src+=pixels_per_line; }
}
}
else {
for (int x=0;x<width;x++) {
#ifdef RANGE_CHECK
if (src_x<0||src_x>=src_image->width||src_y<0||src_y>=src_image->height) {
*dest++ = 0;
}
else
#endif
*dest++ = *src;
dx_c+=dx;
while (dx_c<0) { dx_c+=IMAX; DEC_X; src--; }
dy_c+=dy;
while (dy_c<0) { dy_c+=IMAX; DEC_Y; src-=pixels_per_line; }
}
}
}
}
#endif
img_buf->PutImage(dpy,tilemap,DefaultGC(dpy,scr),0,0,0,0,width,height);
#undef IMAX
|