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