File: rotate.H

package info (click to toggle)
xjig 2.4-5
  • links: PTS
  • area: main
  • in suites: potato
  • size: 412 kB
  • ctags: 1,155
  • sloc: cpp: 4,534; makefile: 735; sh: 14; perl: 5
file content (216 lines) | stat: -rw-r--r-- 5,937 bytes parent folder | download | duplicates (10)
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