/src/leptonica/src/roplow.c
Line | Count | Source |
1 | | /*====================================================================* |
2 | | - Copyright (C) 2001 Leptonica. All rights reserved. |
3 | | - |
4 | | - Redistribution and use in source and binary forms, with or without |
5 | | - modification, are permitted provided that the following conditions |
6 | | - are met: |
7 | | - 1. Redistributions of source code must retain the above copyright |
8 | | - notice, this list of conditions and the following disclaimer. |
9 | | - 2. Redistributions in binary form must reproduce the above |
10 | | - copyright notice, this list of conditions and the following |
11 | | - disclaimer in the documentation and/or other materials |
12 | | - provided with the distribution. |
13 | | - |
14 | | - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
15 | | - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
16 | | - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
17 | | - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY |
18 | | - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | | - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | | - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | | - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | | - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
23 | | - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
24 | | - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | | *====================================================================*/ |
26 | | |
27 | | /*! |
28 | | * \file roplow.c |
29 | | * <pre> |
30 | | * Low level dest-only |
31 | | * void rasteropUniLow() |
32 | | * static void rasteropUniWordAlignedlLow() |
33 | | * static void rasteropUniGeneralLow() |
34 | | * |
35 | | * Low level src and dest |
36 | | * void rasteropLow() |
37 | | * static void rasteropWordAlignedLow() |
38 | | * static void rasteropVAlignedLow() |
39 | | * static void rasteropGeneralLow() |
40 | | * |
41 | | * Low level in-place full height vertical block transfer |
42 | | * void rasteropVipLow() |
43 | | * |
44 | | * Low level in-place full width horizontal block transfer |
45 | | * void rasteropHipLow() |
46 | | * static void shiftDataHorizontalLow() |
47 | | * </pre> |
48 | | */ |
49 | | |
50 | | #ifdef HAVE_CONFIG_H |
51 | | #include <config_auto.h> |
52 | | #endif /* HAVE_CONFIG_H */ |
53 | | |
54 | | #include <string.h> |
55 | | #include "allheaders.h" |
56 | | |
57 | | /* Static helpers */ |
58 | | static void rasteropUniWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx, |
59 | | l_int32 dy, l_int32 dw, l_int32 dh, |
60 | | l_int32 op); |
61 | | static void rasteropUniGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx, |
62 | | l_int32 dy, l_int32 dw, l_int32 dh, |
63 | | l_int32 op); |
64 | | static void rasteropWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx, |
65 | | l_int32 dy, l_int32 dw, l_int32 dh, |
66 | | l_int32 op, l_uint32 *datas, l_int32 swpl, |
67 | | l_int32 sx, l_int32 sy); |
68 | | static void rasteropVAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx, |
69 | | l_int32 dy, l_int32 dw, l_int32 dh, |
70 | | l_int32 op, l_uint32 *datas, l_int32 swpl, |
71 | | l_int32 sx, l_int32 sy); |
72 | | static void rasteropGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx, |
73 | | l_int32 dy, l_int32 dw, l_int32 dh, |
74 | | l_int32 op, l_uint32 *datas, l_int32 swpl, |
75 | | l_int32 sx, l_int32 sy); |
76 | | static void shiftDataHorizontalLow(l_uint32 *datad, l_int32 wpld, |
77 | | l_uint32 *datas, l_int32 wpls, |
78 | | l_int32 shift); |
79 | | |
80 | 36.5M | #define COMBINE_PARTIAL(d, s, m) ( ((d) & ~(m)) | ((s) & (m)) ) |
81 | | |
82 | | static const l_int32 SHIFT_LEFT = 0; |
83 | | static const l_int32 SHIFT_RIGHT = 1; |
84 | | |
85 | | static const l_uint32 lmask32[] = {0x0, |
86 | | 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, |
87 | | 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, |
88 | | 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, |
89 | | 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, |
90 | | 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, |
91 | | 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, |
92 | | 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, |
93 | | 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff}; |
94 | | |
95 | | static const l_uint32 rmask32[] = {0x0, |
96 | | 0x00000001, 0x00000003, 0x00000007, 0x0000000f, |
97 | | 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, |
98 | | 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, |
99 | | 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, |
100 | | 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, |
101 | | 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, |
102 | | 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, |
103 | | 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; |
104 | | |
105 | | |
106 | | /*--------------------------------------------------------------------* |
107 | | * Low-level dest-only rasterops * |
108 | | *--------------------------------------------------------------------*/ |
109 | | /*! |
110 | | * \brief rasteropUniLow() |
111 | | * |
112 | | * \param[in] datad ptr to dest image data |
113 | | * \param[in] dpixw width of dest |
114 | | * \param[in] dpixh height of dest |
115 | | * \param[in] depth depth of src and dest |
116 | | * \param[in] dwpl wpl of dest |
117 | | * \param[in] dx x val of UL corner of dest rectangle |
118 | | * \param[in] dy y val of UL corner of dest rectangle |
119 | | * \param[in] dw width of dest rectangle |
120 | | * \param[in] dh height of dest rectangle |
121 | | * \param[in] op op code |
122 | | * \return void |
123 | | * |
124 | | * Action: scales width, performs clipping, checks alignment, and |
125 | | * dispatches for the rasterop. |
126 | | */ |
127 | | void |
128 | | rasteropUniLow(l_uint32 *datad, |
129 | | l_int32 dpixw, |
130 | | l_int32 dpixh, |
131 | | l_int32 depth, |
132 | | l_int32 dwpl, |
133 | | l_int32 dx, |
134 | | l_int32 dy, |
135 | | l_int32 dw, |
136 | | l_int32 dh, |
137 | | l_int32 op) |
138 | 128k | { |
139 | 128k | l_int32 dhangw, dhangh; |
140 | | |
141 | | /* -------------------------------------------------------* |
142 | | * scale horizontal dimensions by depth |
143 | | * -------------------------------------------------------*/ |
144 | 128k | if (depth != 1) { |
145 | 128k | dpixw *= depth; |
146 | 128k | dx *= depth; |
147 | 128k | dw *= depth; |
148 | 128k | } |
149 | | |
150 | | /* -------------------------------------------------------* |
151 | | * clip rectangle to dest image |
152 | | * -------------------------------------------------------*/ |
153 | | /* first, clip horizontally (dx, dw) */ |
154 | 128k | if (dx < 0) { |
155 | 0 | dw += dx; /* reduce dw */ |
156 | 0 | dx = 0; |
157 | 0 | } |
158 | 128k | dhangw = dx + dw - dpixw; /* rect ovhang dest to right */ |
159 | 128k | if (dhangw > 0) |
160 | 0 | dw -= dhangw; /* reduce dw */ |
161 | | |
162 | | /* then, clip vertically (dy, dh) */ |
163 | 128k | if (dy < 0) { |
164 | 0 | dh += dy; /* reduce dh */ |
165 | 0 | dy = 0; |
166 | 0 | } |
167 | 128k | dhangh = dy + dh - dpixh; /* rect ovhang dest below */ |
168 | 128k | if (dhangh > 0) |
169 | 0 | dh -= dhangh; /* reduce dh */ |
170 | | |
171 | | /* if clipped entirely, quit */ |
172 | 128k | if ((dw <= 0) || (dh <= 0)) |
173 | 0 | return; |
174 | | |
175 | | /* -------------------------------------------------------* |
176 | | * dispatch to aligned or non-aligned blitters |
177 | | * -------------------------------------------------------*/ |
178 | 128k | if ((dx & 31) == 0) |
179 | 128k | rasteropUniWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op); |
180 | 12 | else |
181 | 12 | rasteropUniGeneralLow(datad, dwpl, dx, dy, dw, dh, op); |
182 | 128k | } |
183 | | |
184 | | |
185 | | |
186 | | /*--------------------------------------------------------------------* |
187 | | * Static low-level uni rasterop with word alignment * |
188 | | *--------------------------------------------------------------------*/ |
189 | | /*! |
190 | | * \brief rasteropUniWordAlignedLow() |
191 | | * |
192 | | * \param[in] datad ptr to dest image data |
193 | | * \param[in] dwpl wpl of dest |
194 | | * \param[in] dx x val of UL corner of dest rectangle |
195 | | * \param[in] dy y val of UL corner of dest rectangle |
196 | | * \param[in] dw width of dest rectangle |
197 | | * \param[in] dh height of dest rectangle |
198 | | * \param[in] op op code |
199 | | * \return void |
200 | | * |
201 | | * This is called when the dest rect is left aligned |
202 | | * on 32-bit word boundaries. That is: dx & 31 == 0. |
203 | | * |
204 | | * We make an optimized implementation of this because |
205 | | * it is a common case: e.g., operating on a full dest image. |
206 | | */ |
207 | | static void |
208 | | rasteropUniWordAlignedLow(l_uint32 *datad, |
209 | | l_int32 dwpl, |
210 | | l_int32 dx, |
211 | | l_int32 dy, |
212 | | l_int32 dw, |
213 | | l_int32 dh, |
214 | | l_int32 op) |
215 | 128k | { |
216 | 128k | l_int32 nfullw; /* number of full words */ |
217 | 128k | l_uint32 *pfword; /* ptr to first word */ |
218 | 128k | l_int32 lwbits; /* number of ovrhang bits in last partial word */ |
219 | 128k | l_uint32 lwmask; /* mask for last partial word */ |
220 | 128k | l_uint32 *lined; |
221 | 128k | l_int32 i, j; |
222 | | |
223 | | /*--------------------------------------------------------* |
224 | | * Preliminary calculations * |
225 | | *--------------------------------------------------------*/ |
226 | 128k | nfullw = dw >> 5; |
227 | 128k | lwbits = dw & 31; |
228 | 128k | if (lwbits) |
229 | 95.2k | lwmask = lmask32[lwbits]; |
230 | 128k | pfword = datad + dwpl * dy + (dx >> 5); |
231 | | |
232 | | |
233 | | /*--------------------------------------------------------* |
234 | | * Now we're ready to do the ops * |
235 | | *--------------------------------------------------------*/ |
236 | 128k | switch (op) |
237 | 128k | { |
238 | 60 | case PIX_CLR: |
239 | 2.68k | for (i = 0; i < dh; i++) { |
240 | 2.62k | lined = pfword + i * dwpl; |
241 | 72.2k | for (j = 0; j < nfullw; j++) |
242 | 69.6k | *lined++ = 0x0; |
243 | 2.62k | if (lwbits) |
244 | 1.17k | *lined = COMBINE_PARTIAL(*lined, 0x0, lwmask); |
245 | 2.62k | } |
246 | 60 | break; |
247 | 0 | case PIX_SET: |
248 | 0 | for (i = 0; i < dh; i++) { |
249 | 0 | lined = pfword + i * dwpl; |
250 | 0 | for (j = 0; j < nfullw; j++) |
251 | 0 | *lined++ = 0xffffffff; |
252 | 0 | if (lwbits) |
253 | 0 | *lined = COMBINE_PARTIAL(*lined, 0xffffffff, lwmask); |
254 | 0 | } |
255 | 0 | break; |
256 | 128k | case PIX_NOT(PIX_DST): |
257 | 4.75M | for (i = 0; i < dh; i++) { |
258 | 4.62M | lined = pfword + i * dwpl; |
259 | 43.9M | for (j = 0; j < nfullw; j++) { |
260 | 39.3M | *lined = ~(*lined); |
261 | 39.3M | lined++; |
262 | 39.3M | } |
263 | 4.62M | if (lwbits) |
264 | 3.42M | *lined = COMBINE_PARTIAL(*lined, ~(*lined), lwmask); |
265 | 4.62M | } |
266 | 128k | break; |
267 | 0 | default: |
268 | 0 | lept_stderr("Operation %d not permitted here!\n", op); |
269 | 128k | } |
270 | 128k | } |
271 | | |
272 | | |
273 | | /*--------------------------------------------------------------------* |
274 | | * Static low-level uni rasterop without word alignment * |
275 | | *--------------------------------------------------------------------*/ |
276 | | /*! |
277 | | * \brief rasteropUniGeneralLow() |
278 | | * |
279 | | * \param[in] datad ptr to dest image data |
280 | | * \param[in] dwpl wpl of dest |
281 | | * \param[in] dx x val of UL corner of dest rectangle |
282 | | * \param[in] dy y val of UL corner of dest rectangle |
283 | | * \param[in] dw width of dest rectangle |
284 | | * \param[in] dh height of dest rectangle |
285 | | * \param[in] op op code |
286 | | * \return void |
287 | | */ |
288 | | static void |
289 | | rasteropUniGeneralLow(l_uint32 *datad, |
290 | | l_int32 dwpl, |
291 | | l_int32 dx, |
292 | | l_int32 dy, |
293 | | l_int32 dw, |
294 | | l_int32 dh, |
295 | | l_int32 op) |
296 | 12 | { |
297 | 12 | l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */ |
298 | 12 | l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */ |
299 | 12 | l_uint32 dfwmask; /* mask for first partial dest word */ |
300 | 12 | l_int32 dfwbits; /* first word dest bits in ovrhang */ |
301 | 12 | l_uint32 *pdfwpart = NULL; /* ptr to first partial dest word */ |
302 | 12 | l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */ |
303 | 12 | l_int32 dnfullw; /* number of full words in dest */ |
304 | 12 | l_uint32 *pdfwfull = NULL; /* ptr to first full dest word */ |
305 | 12 | l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */ |
306 | 12 | l_uint32 dlwmask; /* mask for last partial dest word */ |
307 | 12 | l_int32 dlwbits; /* last word dest bits in ovrhang */ |
308 | 12 | l_uint32 *pdlwpart = NULL; /* ptr to last partial dest word */ |
309 | 12 | l_int32 i, j; |
310 | | |
311 | | |
312 | | /*--------------------------------------------------------* |
313 | | * Preliminary calculations * |
314 | | *--------------------------------------------------------*/ |
315 | | /* is the first word partial? */ |
316 | 12 | dfwmask = 0; |
317 | 12 | if ((dx & 31) == 0) { /* if not */ |
318 | 0 | dfwpartb = 0; |
319 | 0 | dfwbits = 0; |
320 | 12 | } else { /* if so */ |
321 | 12 | dfwpartb = 1; |
322 | 12 | dfwbits = 32 - (dx & 31); |
323 | 12 | dfwmask = rmask32[dfwbits]; |
324 | 12 | pdfwpart = datad + dwpl * dy + (dx >> 5); |
325 | 12 | } |
326 | | |
327 | | /* is the first word doubly partial? */ |
328 | 12 | if (dw >= dfwbits) { /* if not */ |
329 | 12 | dfwpart2b = 0; |
330 | 12 | } else { /* if so */ |
331 | 0 | dfwpart2b = 1; |
332 | 0 | dfwmask &= lmask32[32 - dfwbits + dw]; |
333 | 0 | } |
334 | | |
335 | | /* is there a full dest word? */ |
336 | 12 | if (dfwpart2b == 1) { /* not */ |
337 | 0 | dfwfullb = 0; |
338 | 0 | dnfullw = 0; |
339 | 12 | } else { |
340 | 12 | dnfullw = (dw - dfwbits) >> 5; |
341 | 12 | if (dnfullw == 0) { /* if not */ |
342 | 12 | dfwfullb = 0; |
343 | 12 | } else { /* if so */ |
344 | 0 | dfwfullb = 1; |
345 | 0 | if (dfwpartb) |
346 | 0 | pdfwfull = pdfwpart + 1; |
347 | 0 | else |
348 | 0 | pdfwfull = datad + dwpl * dy + (dx >> 5); |
349 | 0 | } |
350 | 12 | } |
351 | | |
352 | | /* is the last word partial? */ |
353 | 12 | dlwbits = (dx + dw) & 31; |
354 | 12 | if (dfwpart2b == 1 || dlwbits == 0) { /* if not */ |
355 | 0 | dlwpartb = 0; |
356 | 12 | } else { |
357 | 12 | dlwpartb = 1; |
358 | 12 | dlwmask = lmask32[dlwbits]; |
359 | 12 | if (dfwpartb) |
360 | 12 | pdlwpart = pdfwpart + 1 + dnfullw; |
361 | 0 | else |
362 | 0 | pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw; |
363 | 12 | } |
364 | | |
365 | | |
366 | | /*--------------------------------------------------------* |
367 | | * Now we're ready to do the ops * |
368 | | *--------------------------------------------------------*/ |
369 | 12 | switch (op) |
370 | 12 | { |
371 | 12 | case PIX_CLR: |
372 | | /* do the first partial word */ |
373 | 12 | if (dfwpartb) { |
374 | 1.45k | for (i = 0; i < dh; i++) { |
375 | 1.44k | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, dfwmask); |
376 | 1.44k | pdfwpart += dwpl; |
377 | 1.44k | } |
378 | 12 | } |
379 | | |
380 | | /* do the full words */ |
381 | 12 | if (dfwfullb) { |
382 | 0 | for (i = 0; i < dh; i++) { |
383 | 0 | for (j = 0; j < dnfullw; j++) |
384 | 0 | *(pdfwfull + j) = 0x0; |
385 | 0 | pdfwfull += dwpl; |
386 | 0 | } |
387 | 0 | } |
388 | | |
389 | | /* do the last partial word */ |
390 | 12 | if (dlwpartb) { |
391 | 1.45k | for (i = 0; i < dh; i++) { |
392 | 1.44k | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, dlwmask); |
393 | 1.44k | pdlwpart += dwpl; |
394 | 1.44k | } |
395 | 12 | } |
396 | 12 | break; |
397 | 0 | case PIX_SET: |
398 | | /* do the first partial word */ |
399 | 0 | if (dfwpartb) { |
400 | 0 | for (i = 0; i < dh; i++) { |
401 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0xffffffff, dfwmask); |
402 | 0 | pdfwpart += dwpl; |
403 | 0 | } |
404 | 0 | } |
405 | | |
406 | | /* do the full words */ |
407 | 0 | if (dfwfullb) { |
408 | 0 | for (i = 0; i < dh; i++) { |
409 | 0 | for (j = 0; j < dnfullw; j++) |
410 | 0 | *(pdfwfull + j) = 0xffffffff; |
411 | 0 | pdfwfull += dwpl; |
412 | 0 | } |
413 | 0 | } |
414 | | |
415 | | /* do the last partial word */ |
416 | 0 | if (dlwpartb) { |
417 | 0 | for (i = 0; i < dh; i++) { |
418 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0xffffffff, dlwmask); |
419 | 0 | pdlwpart += dwpl; |
420 | 0 | } |
421 | 0 | } |
422 | 0 | break; |
423 | 0 | case PIX_NOT(PIX_DST): |
424 | | /* do the first partial word */ |
425 | 0 | if (dfwpartb) { |
426 | 0 | for (i = 0; i < dh; i++) { |
427 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*pdfwpart), dfwmask); |
428 | 0 | pdfwpart += dwpl; |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | /* do the full words */ |
433 | 0 | if (dfwfullb) { |
434 | 0 | for (i = 0; i < dh; i++) { |
435 | 0 | for (j = 0; j < dnfullw; j++) |
436 | 0 | *(pdfwfull + j) = ~(*(pdfwfull + j)); |
437 | 0 | pdfwfull += dwpl; |
438 | 0 | } |
439 | 0 | } |
440 | | |
441 | | /* do the last partial word */ |
442 | 0 | if (dlwpartb) { |
443 | 0 | for (i = 0; i < dh; i++) { |
444 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pdlwpart), dlwmask); |
445 | 0 | pdlwpart += dwpl; |
446 | 0 | } |
447 | 0 | } |
448 | 0 | break; |
449 | 0 | default: |
450 | 0 | lept_stderr("Operation %d not permitted here!\n", op); |
451 | 12 | } |
452 | 12 | } |
453 | | |
454 | | |
455 | | /*--------------------------------------------------------------------* |
456 | | * Low-level src and dest rasterops * |
457 | | *--------------------------------------------------------------------*/ |
458 | | /*! |
459 | | * \brief rasteropLow() |
460 | | * |
461 | | * \param[in] datad ptr to dest image data |
462 | | * \param[in] dpixw width of dest |
463 | | * \param[in] dpixh height of dest |
464 | | * \param[in] depth depth of src and dest |
465 | | * \param[in] dwpl wpl of dest |
466 | | * \param[in] dx x val of UL corner of dest rectangle |
467 | | * \param[in] dy y val of UL corner of dest rectangle |
468 | | * \param[in] dw width of dest rectangle |
469 | | * \param[in] dh height of dest rectangle |
470 | | * \param[in] op op code |
471 | | * \param[in] datas ptr to src image data |
472 | | * \param[in] spixw width of src |
473 | | * \param[in] spixh height of src |
474 | | * \param[in] swpl wpl of src |
475 | | * \param[in] sx x val of UL corner of src rectangle |
476 | | * \param[in] sy y val of UL corner of src rectangle |
477 | | * \return void |
478 | | * |
479 | | * Action: Scales width, performs clipping, checks alignment and |
480 | | * dispatches for the rasterop. |
481 | | * |
482 | | * Warning: the two images must have equal depth. This is not checked. |
483 | | */ |
484 | | void |
485 | | rasteropLow(l_uint32 *datad, |
486 | | l_int32 dpixw, |
487 | | l_int32 dpixh, |
488 | | l_int32 depth, |
489 | | l_int32 dwpl, |
490 | | l_int32 dx, |
491 | | l_int32 dy, |
492 | | l_int32 dw, |
493 | | l_int32 dh, |
494 | | l_int32 op, |
495 | | l_uint32 *datas, |
496 | | l_int32 spixw, |
497 | | l_int32 spixh, |
498 | | l_int32 swpl, |
499 | | l_int32 sx, |
500 | | l_int32 sy) |
501 | 3.19M | { |
502 | 3.19M | l_int32 dhangw, shangw, dhangh, shangh; |
503 | | |
504 | | /* -------------------------------------------------------* |
505 | | * Scale horizontal dimensions by depth * |
506 | | * -------------------------------------------------------*/ |
507 | 3.19M | if (depth != 1) { |
508 | 439k | dpixw *= depth; |
509 | 439k | dx *= depth; |
510 | 439k | dw *= depth; |
511 | 439k | spixw *= depth; |
512 | 439k | sx *= depth; |
513 | 439k | } |
514 | | |
515 | | /* -------------------------------------------------------* |
516 | | * Clip to max rectangle within both src and dest * |
517 | | * -------------------------------------------------------*/ |
518 | | /* Clip horizontally (sx, dx, dw) */ |
519 | 3.19M | if (dx < 0) { |
520 | 0 | sx -= dx; /* increase sx */ |
521 | 0 | dw += dx; /* reduce dw */ |
522 | 0 | dx = 0; |
523 | 0 | } |
524 | 3.19M | if (sx < 0) { |
525 | 0 | dx -= sx; /* increase dx */ |
526 | 0 | dw += sx; /* reduce dw */ |
527 | 0 | sx = 0; |
528 | 0 | } |
529 | 3.19M | dhangw = dx + dw - dpixw; /* rect ovhang dest to right */ |
530 | 3.19M | if (dhangw > 0) |
531 | 0 | dw -= dhangw; /* reduce dw */ |
532 | 3.19M | shangw = sx + dw - spixw; /* rect ovhang src to right */ |
533 | 3.19M | if (shangw > 0) |
534 | 0 | dw -= shangw; /* reduce dw */ |
535 | | |
536 | | /* Clip vertically (sy, dy, dh) */ |
537 | 3.19M | if (dy < 0) { |
538 | 408 | sy -= dy; /* increase sy */ |
539 | 408 | dh += dy; /* reduce dh */ |
540 | 408 | dy = 0; |
541 | 408 | } |
542 | 3.19M | if (sy < 0) { |
543 | 0 | dy -= sy; /* increase dy */ |
544 | 0 | dh += sy; /* reduce dh */ |
545 | 0 | sy = 0; |
546 | 0 | } |
547 | 3.19M | dhangh = dy + dh - dpixh; /* rect ovhang dest below */ |
548 | 3.19M | if (dhangh > 0) |
549 | 408 | dh -= dhangh; /* reduce dh */ |
550 | 3.19M | shangh = sy + dh - spixh; /* rect ovhang src below */ |
551 | 3.19M | if (shangh > 0) |
552 | 0 | dh -= shangh; /* reduce dh */ |
553 | | |
554 | | /* If clipped entirely, quit */ |
555 | 3.19M | if ((dw <= 0) || (dh <= 0)) |
556 | 0 | return; |
557 | | |
558 | | #if 0 |
559 | | lept_stderr("dx = %d, dy = %d, dw = %d, dh = %d, sx = %d, sy = %d\n", |
560 | | dx, dy, dw, dh, sx, sy); |
561 | | #endif |
562 | | |
563 | | /* -------------------------------------------------------* |
564 | | * Dispatch to aligned or non-aligned blitters * |
565 | | * -------------------------------------------------------*/ |
566 | 3.19M | if (((dx & 31) == 0) && ((sx & 31) == 0)) |
567 | 732k | rasteropWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op, |
568 | 732k | datas, swpl, sx, sy); |
569 | 2.46M | else if ((dx & 31) == (sx & 31)) |
570 | 77.6k | rasteropVAlignedLow(datad, dwpl, dx, dy, dw, dh, op, |
571 | 77.6k | datas, swpl, sx, sy); |
572 | 2.38M | else |
573 | 2.38M | rasteropGeneralLow(datad, dwpl, dx, dy, dw, dh, op, |
574 | 2.38M | datas, swpl, sx, sy); |
575 | 3.19M | } |
576 | | |
577 | | |
578 | | /*--------------------------------------------------------------------* |
579 | | * Static low-level rasterop with vertical word alignment * |
580 | | *--------------------------------------------------------------------*/ |
581 | | /*! |
582 | | * \brief rasteropWordAlignedLow() |
583 | | * |
584 | | * \param[in] datad ptr to dest image data |
585 | | * \param[in] dwpl wpl of dest |
586 | | * \param[in] dx x val of UL corner of dest rectangle |
587 | | * \param[in] dy y val of UL corner of dest rectangle |
588 | | * \param[in] dw width of dest rectangle |
589 | | * \param[in] dh height of dest rectangle |
590 | | * \param[in] op op code |
591 | | * \param[in] datas ptr to src image data |
592 | | * \param[in] swpl wpl of src |
593 | | * \param[in] sx x val of UL corner of src rectangle |
594 | | * \param[in] sy y val of UL corner of src rectangle |
595 | | * \return void |
596 | | * |
597 | | * This is called when both the src and dest rects |
598 | | * are left aligned on 32-bit word boundaries. |
599 | | * That is: dx & 31 == 0 and sx & 31 == 0 |
600 | | * |
601 | | * We make an optimized implementation of this because |
602 | | * it is a common case: e.g., two images are rasterop'd |
603 | | * starting from their UL corners 0,0. |
604 | | */ |
605 | | static void |
606 | | rasteropWordAlignedLow(l_uint32 *datad, |
607 | | l_int32 dwpl, |
608 | | l_int32 dx, |
609 | | l_int32 dy, |
610 | | l_int32 dw, |
611 | | l_int32 dh, |
612 | | l_int32 op, |
613 | | l_uint32 *datas, |
614 | | l_int32 swpl, |
615 | | l_int32 sx, |
616 | | l_int32 sy) |
617 | 732k | { |
618 | 732k | l_int32 nfullw; /* number of full words */ |
619 | 732k | l_uint32 *psfword; /* ptr to first src word */ |
620 | 732k | l_uint32 *pdfword; /* ptr to first dest word */ |
621 | 732k | l_int32 lwbits; /* number of ovrhang bits in last partial word */ |
622 | 732k | l_uint32 lwmask; /* mask for last partial word */ |
623 | 732k | l_uint32 *lines, *lined; |
624 | 732k | l_int32 i, j; |
625 | | |
626 | | |
627 | | /*--------------------------------------------------------* |
628 | | * Preliminary calculations * |
629 | | *--------------------------------------------------------*/ |
630 | 732k | nfullw = dw >> 5; |
631 | 732k | lwbits = dw & 31; |
632 | 732k | if (lwbits) |
633 | 668k | lwmask = lmask32[lwbits]; |
634 | 732k | psfword = datas + swpl * sy + (sx >> 5); |
635 | 732k | pdfword = datad + dwpl * dy + (dx >> 5); |
636 | | |
637 | | /*--------------------------------------------------------* |
638 | | * Now we're ready to do the ops * |
639 | | *--------------------------------------------------------*/ |
640 | 732k | switch (op) |
641 | 732k | { |
642 | 731k | case PIX_SRC: |
643 | 12.0M | for (i = 0; i < dh; i++) { |
644 | 11.3M | lines = psfword + i * swpl; |
645 | 11.3M | lined = pdfword + i * dwpl; |
646 | 18.3M | for (j = 0; j < nfullw; j++) { |
647 | 6.99M | *lined = *lines; |
648 | 6.99M | lined++; |
649 | 6.99M | lines++; |
650 | 6.99M | } |
651 | 11.3M | if (lwbits) |
652 | 11.0M | *lined = COMBINE_PARTIAL(*lined, *lines, lwmask); |
653 | 11.3M | } |
654 | 731k | break; |
655 | 0 | case PIX_NOT(PIX_SRC): |
656 | 0 | for (i = 0; i < dh; i++) { |
657 | 0 | lines = psfword + i * swpl; |
658 | 0 | lined = pdfword + i * dwpl; |
659 | 0 | for (j = 0; j < nfullw; j++) { |
660 | 0 | *lined = ~(*lines); |
661 | 0 | lined++; |
662 | 0 | lines++; |
663 | 0 | } |
664 | 0 | if (lwbits) |
665 | 0 | *lined = COMBINE_PARTIAL(*lined, ~(*lines), lwmask); |
666 | 0 | } |
667 | 0 | break; |
668 | 420 | case (PIX_SRC | PIX_DST): |
669 | 47.2k | for (i = 0; i < dh; i++) { |
670 | 46.8k | lines = psfword + i * swpl; |
671 | 46.8k | lined = pdfword + i * dwpl; |
672 | 2.76M | for (j = 0; j < nfullw; j++) { |
673 | 2.71M | *lined = (*lines | *lined); |
674 | 2.71M | lined++; |
675 | 2.71M | lines++; |
676 | 2.71M | } |
677 | 46.8k | if (lwbits) |
678 | 46.8k | *lined = COMBINE_PARTIAL(*lined, (*lines | *lined), lwmask); |
679 | 46.8k | } |
680 | 420 | break; |
681 | 420 | case (PIX_SRC & PIX_DST): |
682 | 47.2k | for (i = 0; i < dh; i++) { |
683 | 46.8k | lines = psfword + i * swpl; |
684 | 46.8k | lined = pdfword + i * dwpl; |
685 | 2.76M | for (j = 0; j < nfullw; j++) { |
686 | 2.71M | *lined = (*lines & *lined); |
687 | 2.71M | lined++; |
688 | 2.71M | lines++; |
689 | 2.71M | } |
690 | 46.8k | if (lwbits) |
691 | 46.8k | *lined = COMBINE_PARTIAL(*lined, (*lines & *lined), lwmask); |
692 | 46.8k | } |
693 | 420 | break; |
694 | 0 | case (PIX_SRC ^ PIX_DST): |
695 | 0 | for (i = 0; i < dh; i++) { |
696 | 0 | lines = psfword + i * swpl; |
697 | 0 | lined = pdfword + i * dwpl; |
698 | 0 | for (j = 0; j < nfullw; j++) { |
699 | 0 | *lined = (*lines ^ *lined); |
700 | 0 | lined++; |
701 | 0 | lines++; |
702 | 0 | } |
703 | 0 | if (lwbits) |
704 | 0 | *lined = COMBINE_PARTIAL(*lined, (*lines ^ *lined), lwmask); |
705 | 0 | } |
706 | 0 | break; |
707 | 0 | case (PIX_NOT(PIX_SRC) | PIX_DST): |
708 | 0 | for (i = 0; i < dh; i++) { |
709 | 0 | lines = psfword + i * swpl; |
710 | 0 | lined = pdfword + i * dwpl; |
711 | 0 | for (j = 0; j < nfullw; j++) { |
712 | 0 | *lined = (~(*lines) | *lined); |
713 | 0 | lined++; |
714 | 0 | lines++; |
715 | 0 | } |
716 | 0 | if (lwbits) |
717 | 0 | *lined = COMBINE_PARTIAL(*lined, (~(*lines) | *lined), lwmask); |
718 | 0 | } |
719 | 0 | break; |
720 | 0 | case (PIX_NOT(PIX_SRC) & PIX_DST): |
721 | 0 | for (i = 0; i < dh; i++) { |
722 | 0 | lines = psfword + i * swpl; |
723 | 0 | lined = pdfword + i * dwpl; |
724 | 0 | for (j = 0; j < nfullw; j++) { |
725 | 0 | *lined = (~(*lines) & *lined); |
726 | 0 | lined++; |
727 | 0 | lines++; |
728 | 0 | } |
729 | 0 | if (lwbits) |
730 | 0 | *lined = COMBINE_PARTIAL(*lined, (~(*lines) & *lined), lwmask); |
731 | 0 | } |
732 | 0 | break; |
733 | 0 | case (PIX_SRC | PIX_NOT(PIX_DST)): |
734 | 0 | for (i = 0; i < dh; i++) { |
735 | 0 | lines = psfword + i * swpl; |
736 | 0 | lined = pdfword + i * dwpl; |
737 | 0 | for (j = 0; j < nfullw; j++) { |
738 | 0 | *lined = (*lines | ~(*lined)); |
739 | 0 | lined++; |
740 | 0 | lines++; |
741 | 0 | } |
742 | 0 | if (lwbits) |
743 | 0 | *lined = COMBINE_PARTIAL(*lined, (*lines | ~(*lined)), lwmask); |
744 | 0 | } |
745 | 0 | break; |
746 | 0 | case (PIX_SRC & PIX_NOT(PIX_DST)): |
747 | 0 | for (i = 0; i < dh; i++) { |
748 | 0 | lines = psfword + i * swpl; |
749 | 0 | lined = pdfword + i * dwpl; |
750 | 0 | for (j = 0; j < nfullw; j++) { |
751 | 0 | *lined = (*lines & ~(*lined)); |
752 | 0 | lined++; |
753 | 0 | lines++; |
754 | 0 | } |
755 | 0 | if (lwbits) |
756 | 0 | *lined = COMBINE_PARTIAL(*lined, (*lines & ~(*lined)), lwmask); |
757 | 0 | } |
758 | 0 | break; |
759 | 0 | case (PIX_NOT(PIX_SRC | PIX_DST)): |
760 | 0 | for (i = 0; i < dh; i++) { |
761 | 0 | lines = psfword + i * swpl; |
762 | 0 | lined = pdfword + i * dwpl; |
763 | 0 | for (j = 0; j < nfullw; j++) { |
764 | 0 | *lined = ~(*lines | *lined); |
765 | 0 | lined++; |
766 | 0 | lines++; |
767 | 0 | } |
768 | 0 | if (lwbits) |
769 | 0 | *lined = COMBINE_PARTIAL(*lined, ~(*lines | *lined), lwmask); |
770 | 0 | } |
771 | 0 | break; |
772 | 0 | case (PIX_NOT(PIX_SRC & PIX_DST)): |
773 | 0 | for (i = 0; i < dh; i++) { |
774 | 0 | lines = psfword + i * swpl; |
775 | 0 | lined = pdfword + i * dwpl; |
776 | 0 | for (j = 0; j < nfullw; j++) { |
777 | 0 | *lined = ~(*lines & *lined); |
778 | 0 | lined++; |
779 | 0 | lines++; |
780 | 0 | } |
781 | 0 | if (lwbits) |
782 | 0 | *lined = COMBINE_PARTIAL(*lined, ~(*lines & *lined), lwmask); |
783 | 0 | } |
784 | 0 | break; |
785 | | /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */ |
786 | 0 | case (PIX_NOT(PIX_SRC ^ PIX_DST)): |
787 | 0 | for (i = 0; i < dh; i++) { |
788 | 0 | lines = psfword + i * swpl; |
789 | 0 | lined = pdfword + i * dwpl; |
790 | 0 | for (j = 0; j < nfullw; j++) { |
791 | 0 | *lined = ~(*lines ^ *lined); |
792 | 0 | lined++; |
793 | 0 | lines++; |
794 | 0 | } |
795 | 0 | if (lwbits) |
796 | 0 | *lined = COMBINE_PARTIAL(*lined, ~(*lines ^ *lined), lwmask); |
797 | 0 | } |
798 | 0 | break; |
799 | 0 | default: |
800 | 0 | lept_stderr("Operation %d invalid\n", op); |
801 | 732k | } |
802 | 732k | } |
803 | | |
804 | | |
805 | | |
806 | | /*--------------------------------------------------------------------* |
807 | | * Static low-level rasterop with vertical word alignment * |
808 | | *--------------------------------------------------------------------*/ |
809 | | /*! |
810 | | * \brief rasteropVAlignedLow() |
811 | | * |
812 | | * \param[in] datad ptr to dest image data |
813 | | * \param[in] dwpl wpl of dest |
814 | | * \param[in] dx x val of UL corner of dest rectangle |
815 | | * \param[in] dy y val of UL corner of dest rectangle |
816 | | * \param[in] dw width of dest rectangle |
817 | | * \param[in] dh height of dest rectangle |
818 | | * \param[in] op op code |
819 | | * \param[in] datas ptr to src image data |
820 | | * \param[in] swpl wpl of src |
821 | | * \param[in] sx x val of UL corner of src rectangle |
822 | | * \param[in] sy y val of UL corner of src rectangle |
823 | | * \return void |
824 | | * |
825 | | * This is called when the left side of the src and dest |
826 | | * rects have the same alignment relative to 32-bit word |
827 | | * boundaries; i.e., dx & 31) == (sx & 31 |
828 | | */ |
829 | | static void |
830 | | rasteropVAlignedLow(l_uint32 *datad, |
831 | | l_int32 dwpl, |
832 | | l_int32 dx, |
833 | | l_int32 dy, |
834 | | l_int32 dw, |
835 | | l_int32 dh, |
836 | | l_int32 op, |
837 | | l_uint32 *datas, |
838 | | l_int32 swpl, |
839 | | l_int32 sx, |
840 | | l_int32 sy) |
841 | 77.6k | { |
842 | 77.6k | l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */ |
843 | 77.6k | l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */ |
844 | 77.6k | l_uint32 dfwmask; /* mask for first partial dest word */ |
845 | 77.6k | l_int32 dfwbits; /* first word dest bits in ovrhang */ |
846 | 77.6k | l_uint32 *pdfwpart = NULL; /* ptr to first partial dest word */ |
847 | 77.6k | l_uint32 *psfwpart = NULL; /* ptr to first partial src word */ |
848 | 77.6k | l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */ |
849 | 77.6k | l_int32 dnfullw; /* number of full words in dest */ |
850 | 77.6k | l_uint32 *pdfwfull = NULL; /* ptr to first full dest word */ |
851 | 77.6k | l_uint32 *psfwfull = NULL; /* ptr to first full src word */ |
852 | 77.6k | l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */ |
853 | 77.6k | l_uint32 dlwmask; /* mask for last partial dest word */ |
854 | 77.6k | l_int32 dlwbits; /* last word dest bits in ovrhang */ |
855 | 77.6k | l_uint32 *pdlwpart = NULL; /* ptr to last partial dest word */ |
856 | 77.6k | l_uint32 *pslwpart = NULL; /* ptr to last partial src word */ |
857 | 77.6k | l_int32 i, j; |
858 | | |
859 | | |
860 | | /*--------------------------------------------------------* |
861 | | * Preliminary calculations * |
862 | | *--------------------------------------------------------*/ |
863 | | /* is the first word partial? */ |
864 | 77.6k | dfwmask = 0; |
865 | 77.6k | if ((dx & 31) == 0) { /* if not */ |
866 | 0 | dfwpartb = 0; |
867 | 0 | dfwbits = 0; |
868 | 77.6k | } else { /* if so */ |
869 | 77.6k | dfwpartb = 1; |
870 | 77.6k | dfwbits = 32 - (dx & 31); |
871 | 77.6k | dfwmask = rmask32[dfwbits]; |
872 | 77.6k | pdfwpart = datad + dwpl * dy + (dx >> 5); |
873 | 77.6k | psfwpart = datas + swpl * sy + (sx >> 5); |
874 | 77.6k | } |
875 | | |
876 | | /* is the first word doubly partial? */ |
877 | 77.6k | if (dw >= dfwbits) { /* if not */ |
878 | 50.9k | dfwpart2b = 0; |
879 | 50.9k | } else { /* if so */ |
880 | 26.6k | dfwpart2b = 1; |
881 | 26.6k | dfwmask &= lmask32[32 - dfwbits + dw]; |
882 | 26.6k | } |
883 | | |
884 | | /* is there a full dest word? */ |
885 | 77.6k | if (dfwpart2b == 1) { /* not */ |
886 | 26.6k | dfwfullb = 0; |
887 | 26.6k | dnfullw = 0; |
888 | 50.9k | } else { |
889 | 50.9k | dnfullw = (dw - dfwbits) >> 5; |
890 | 50.9k | if (dnfullw == 0) { /* if not */ |
891 | 50.9k | dfwfullb = 0; |
892 | 50.9k | } else { /* if so */ |
893 | 0 | dfwfullb = 1; |
894 | 0 | if (dfwpartb) { |
895 | 0 | pdfwfull = pdfwpart + 1; |
896 | 0 | psfwfull = psfwpart + 1; |
897 | 0 | } else { |
898 | 0 | pdfwfull = datad + dwpl * dy + (dx >> 5); |
899 | 0 | psfwfull = datas + swpl * sy + (sx >> 5); |
900 | 0 | } |
901 | 0 | } |
902 | 50.9k | } |
903 | | |
904 | | /* is the last word partial? */ |
905 | 77.6k | dlwbits = (dx + dw) & 31; |
906 | 77.6k | if (dfwpart2b == 1 || dlwbits == 0) { /* if not */ |
907 | 54.5k | dlwpartb = 0; |
908 | 54.5k | } else { |
909 | 23.1k | dlwpartb = 1; |
910 | 23.1k | dlwmask = lmask32[dlwbits]; |
911 | 23.1k | if (dfwpartb) { |
912 | 23.1k | pdlwpart = pdfwpart + 1 + dnfullw; |
913 | 23.1k | pslwpart = psfwpart + 1 + dnfullw; |
914 | 23.1k | } else { |
915 | 0 | pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw; |
916 | 0 | pslwpart = datas + swpl * sy + (sx >> 5) + dnfullw; |
917 | 0 | } |
918 | 23.1k | } |
919 | | |
920 | | |
921 | | /*--------------------------------------------------------* |
922 | | * Now we're ready to do the ops * |
923 | | *--------------------------------------------------------*/ |
924 | 77.6k | switch (op) |
925 | 77.6k | { |
926 | 77.6k | case PIX_SRC: |
927 | | /* do the first partial word */ |
928 | 77.6k | if (dfwpartb) { |
929 | 2.87M | for (i = 0; i < dh; i++) { |
930 | 2.79M | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, dfwmask); |
931 | 2.79M | pdfwpart += dwpl; |
932 | 2.79M | psfwpart += swpl; |
933 | 2.79M | } |
934 | 77.6k | } |
935 | | |
936 | | /* do the full words */ |
937 | 77.6k | if (dfwfullb) { |
938 | 0 | for (i = 0; i < dh; i++) { |
939 | 0 | for (j = 0; j < dnfullw; j++) |
940 | 0 | *(pdfwfull + j) = *(psfwfull + j); |
941 | 0 | pdfwfull += dwpl; |
942 | 0 | psfwfull += swpl; |
943 | 0 | } |
944 | 0 | } |
945 | | |
946 | | /* do the last partial word */ |
947 | 77.6k | if (dlwpartb) { |
948 | 855k | for (i = 0; i < dh; i++) { |
949 | 832k | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, dlwmask); |
950 | 832k | pdlwpart += dwpl; |
951 | 832k | pslwpart += swpl; |
952 | 832k | } |
953 | 23.1k | } |
954 | 77.6k | break; |
955 | 0 | case PIX_NOT(PIX_SRC): |
956 | | /* do the first partial word */ |
957 | 0 | if (dfwpartb) { |
958 | 0 | for (i = 0; i < dh; i++) { |
959 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*psfwpart), dfwmask); |
960 | 0 | pdfwpart += dwpl; |
961 | 0 | psfwpart += swpl; |
962 | 0 | } |
963 | 0 | } |
964 | | |
965 | | /* do the full words */ |
966 | 0 | if (dfwfullb) { |
967 | 0 | for (i = 0; i < dh; i++) { |
968 | 0 | for (j = 0; j < dnfullw; j++) |
969 | 0 | *(pdfwfull + j) = ~(*(psfwfull + j)); |
970 | 0 | pdfwfull += dwpl; |
971 | 0 | psfwfull += swpl; |
972 | 0 | } |
973 | 0 | } |
974 | | |
975 | | /* do the last partial word */ |
976 | 0 | if (dlwpartb) { |
977 | 0 | for (i = 0; i < dh; i++) { |
978 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pslwpart), dlwmask); |
979 | 0 | pdlwpart += dwpl; |
980 | 0 | pslwpart += swpl; |
981 | 0 | } |
982 | 0 | } |
983 | 0 | break; |
984 | 0 | case (PIX_SRC | PIX_DST): |
985 | | /* do the first partial word */ |
986 | 0 | if (dfwpartb) { |
987 | 0 | for (i = 0; i < dh; i++) { |
988 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
989 | 0 | (*psfwpart | *pdfwpart), dfwmask); |
990 | 0 | pdfwpart += dwpl; |
991 | 0 | psfwpart += swpl; |
992 | 0 | } |
993 | 0 | } |
994 | | |
995 | | /* do the full words */ |
996 | 0 | if (dfwfullb) { |
997 | 0 | for (i = 0; i < dh; i++) { |
998 | 0 | for (j = 0; j < dnfullw; j++) |
999 | 0 | *(pdfwfull + j) |= *(psfwfull + j); |
1000 | 0 | pdfwfull += dwpl; |
1001 | 0 | psfwfull += swpl; |
1002 | 0 | } |
1003 | 0 | } |
1004 | | |
1005 | | /* do the last partial word */ |
1006 | 0 | if (dlwpartb) { |
1007 | 0 | for (i = 0; i < dh; i++) { |
1008 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1009 | 0 | (*pslwpart | *pdlwpart), dlwmask); |
1010 | 0 | pdlwpart += dwpl; |
1011 | 0 | pslwpart += swpl; |
1012 | 0 | } |
1013 | 0 | } |
1014 | 0 | break; |
1015 | 0 | case (PIX_SRC & PIX_DST): |
1016 | | /* do the first partial word */ |
1017 | 0 | if (dfwpartb) { |
1018 | 0 | for (i = 0; i < dh; i++) { |
1019 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1020 | 0 | (*psfwpart & *pdfwpart), dfwmask); |
1021 | 0 | pdfwpart += dwpl; |
1022 | 0 | psfwpart += swpl; |
1023 | 0 | } |
1024 | 0 | } |
1025 | | |
1026 | | /* do the full words */ |
1027 | 0 | if (dfwfullb) { |
1028 | 0 | for (i = 0; i < dh; i++) { |
1029 | 0 | for (j = 0; j < dnfullw; j++) |
1030 | 0 | *(pdfwfull + j) &= *(psfwfull + j); |
1031 | 0 | pdfwfull += dwpl; |
1032 | 0 | psfwfull += swpl; |
1033 | 0 | } |
1034 | 0 | } |
1035 | | |
1036 | | /* do the last partial word */ |
1037 | 0 | if (dlwpartb) { |
1038 | 0 | for (i = 0; i < dh; i++) { |
1039 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1040 | 0 | (*pslwpart & *pdlwpart), dlwmask); |
1041 | 0 | pdlwpart += dwpl; |
1042 | 0 | pslwpart += swpl; |
1043 | 0 | } |
1044 | 0 | } |
1045 | 0 | break; |
1046 | 0 | case (PIX_SRC ^ PIX_DST): |
1047 | | /* do the first partial word */ |
1048 | 0 | if (dfwpartb) { |
1049 | 0 | for (i = 0; i < dh; i++) { |
1050 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1051 | 0 | (*psfwpart ^ *pdfwpart), dfwmask); |
1052 | 0 | pdfwpart += dwpl; |
1053 | 0 | psfwpart += swpl; |
1054 | 0 | } |
1055 | 0 | } |
1056 | | |
1057 | | /* do the full words */ |
1058 | 0 | if (dfwfullb) { |
1059 | 0 | for (i = 0; i < dh; i++) { |
1060 | 0 | for (j = 0; j < dnfullw; j++) |
1061 | 0 | *(pdfwfull + j) ^= *(psfwfull + j); |
1062 | 0 | pdfwfull += dwpl; |
1063 | 0 | psfwfull += swpl; |
1064 | 0 | } |
1065 | 0 | } |
1066 | | |
1067 | | /* do the last partial word */ |
1068 | 0 | if (dlwpartb) { |
1069 | 0 | for (i = 0; i < dh; i++) { |
1070 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1071 | 0 | (*pslwpart ^ *pdlwpart), dlwmask); |
1072 | 0 | pdlwpart += dwpl; |
1073 | 0 | pslwpart += swpl; |
1074 | 0 | } |
1075 | 0 | } |
1076 | 0 | break; |
1077 | 0 | case (PIX_NOT(PIX_SRC) | PIX_DST): |
1078 | | /* do the first partial word */ |
1079 | 0 | if (dfwpartb) { |
1080 | 0 | for (i = 0; i < dh; i++) { |
1081 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1082 | 0 | (~(*psfwpart) | *pdfwpart), dfwmask); |
1083 | 0 | pdfwpart += dwpl; |
1084 | 0 | psfwpart += swpl; |
1085 | 0 | } |
1086 | 0 | } |
1087 | | |
1088 | | /* do the full words */ |
1089 | 0 | if (dfwfullb) { |
1090 | 0 | for (i = 0; i < dh; i++) { |
1091 | 0 | for (j = 0; j < dnfullw; j++) |
1092 | 0 | *(pdfwfull + j) |= ~(*(psfwfull + j)); |
1093 | 0 | pdfwfull += dwpl; |
1094 | 0 | psfwfull += swpl; |
1095 | 0 | } |
1096 | 0 | } |
1097 | | |
1098 | | /* do the last partial word */ |
1099 | 0 | if (dlwpartb) { |
1100 | 0 | for (i = 0; i < dh; i++) { |
1101 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1102 | 0 | (~(*pslwpart) | *pdlwpart), dlwmask); |
1103 | 0 | pdlwpart += dwpl; |
1104 | 0 | pslwpart += swpl; |
1105 | 0 | } |
1106 | 0 | } |
1107 | 0 | break; |
1108 | 0 | case (PIX_NOT(PIX_SRC) & PIX_DST): |
1109 | | /* do the first partial word */ |
1110 | 0 | if (dfwpartb) { |
1111 | 0 | for (i = 0; i < dh; i++) { |
1112 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1113 | 0 | (~(*psfwpart) & *pdfwpart), dfwmask); |
1114 | 0 | pdfwpart += dwpl; |
1115 | 0 | psfwpart += swpl; |
1116 | 0 | } |
1117 | 0 | } |
1118 | | |
1119 | | /* do the full words */ |
1120 | 0 | if (dfwfullb) { |
1121 | 0 | for (i = 0; i < dh; i++) { |
1122 | 0 | for (j = 0; j < dnfullw; j++) |
1123 | 0 | *(pdfwfull + j) &= ~(*(psfwfull + j)); |
1124 | 0 | pdfwfull += dwpl; |
1125 | 0 | psfwfull += swpl; |
1126 | 0 | } |
1127 | 0 | } |
1128 | | |
1129 | | /* do the last partial word */ |
1130 | 0 | if (dlwpartb) { |
1131 | 0 | for (i = 0; i < dh; i++) { |
1132 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1133 | 0 | (~(*pslwpart) & *pdlwpart), dlwmask); |
1134 | 0 | pdlwpart += dwpl; |
1135 | 0 | pslwpart += swpl; |
1136 | 0 | } |
1137 | 0 | } |
1138 | 0 | break; |
1139 | 0 | case (PIX_SRC | PIX_NOT(PIX_DST)): |
1140 | | /* do the first partial word */ |
1141 | 0 | if (dfwpartb) { |
1142 | 0 | for (i = 0; i < dh; i++) { |
1143 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1144 | 0 | (*psfwpart | ~(*pdfwpart)), dfwmask); |
1145 | 0 | pdfwpart += dwpl; |
1146 | 0 | psfwpart += swpl; |
1147 | 0 | } |
1148 | 0 | } |
1149 | | |
1150 | | /* do the full words */ |
1151 | 0 | if (dfwfullb) { |
1152 | 0 | for (i = 0; i < dh; i++) { |
1153 | 0 | for (j = 0; j < dnfullw; j++) |
1154 | 0 | *(pdfwfull + j) = *(psfwfull + j) | ~(*(pdfwfull + j)); |
1155 | 0 | pdfwfull += dwpl; |
1156 | 0 | psfwfull += swpl; |
1157 | 0 | } |
1158 | 0 | } |
1159 | | |
1160 | | /* do the last partial word */ |
1161 | 0 | if (dlwpartb) { |
1162 | 0 | for (i = 0; i < dh; i++) { |
1163 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1164 | 0 | (*pslwpart | ~(*pdlwpart)), dlwmask); |
1165 | 0 | pdlwpart += dwpl; |
1166 | 0 | pslwpart += swpl; |
1167 | 0 | } |
1168 | 0 | } |
1169 | 0 | break; |
1170 | 0 | case (PIX_SRC & PIX_NOT(PIX_DST)): |
1171 | | /* do the first partial word */ |
1172 | 0 | if (dfwpartb) { |
1173 | 0 | for (i = 0; i < dh; i++) { |
1174 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1175 | 0 | (*psfwpart & ~(*pdfwpart)), dfwmask); |
1176 | 0 | pdfwpart += dwpl; |
1177 | 0 | psfwpart += swpl; |
1178 | 0 | } |
1179 | 0 | } |
1180 | | |
1181 | | /* do the full words */ |
1182 | 0 | if (dfwfullb) { |
1183 | 0 | for (i = 0; i < dh; i++) { |
1184 | 0 | for (j = 0; j < dnfullw; j++) |
1185 | 0 | *(pdfwfull + j) = *(psfwfull + j) & ~(*(pdfwfull + j)); |
1186 | 0 | pdfwfull += dwpl; |
1187 | 0 | psfwfull += swpl; |
1188 | 0 | } |
1189 | 0 | } |
1190 | | |
1191 | | /* do the last partial word */ |
1192 | 0 | if (dlwpartb) { |
1193 | 0 | for (i = 0; i < dh; i++) { |
1194 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1195 | 0 | (*pslwpart & ~(*pdlwpart)), dlwmask); |
1196 | 0 | pdlwpart += dwpl; |
1197 | 0 | pslwpart += swpl; |
1198 | 0 | } |
1199 | 0 | } |
1200 | 0 | break; |
1201 | 0 | case (PIX_NOT(PIX_SRC | PIX_DST)): |
1202 | | /* do the first partial word */ |
1203 | 0 | if (dfwpartb) { |
1204 | 0 | for (i = 0; i < dh; i++) { |
1205 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1206 | 0 | ~(*psfwpart | *pdfwpart), dfwmask); |
1207 | 0 | pdfwpart += dwpl; |
1208 | 0 | psfwpart += swpl; |
1209 | 0 | } |
1210 | 0 | } |
1211 | | |
1212 | | /* do the full words */ |
1213 | 0 | if (dfwfullb) { |
1214 | 0 | for (i = 0; i < dh; i++) { |
1215 | 0 | for (j = 0; j < dnfullw; j++) |
1216 | 0 | *(pdfwfull + j) = ~(*(psfwfull + j) | *(pdfwfull + j)); |
1217 | 0 | pdfwfull += dwpl; |
1218 | 0 | psfwfull += swpl; |
1219 | 0 | } |
1220 | 0 | } |
1221 | | |
1222 | | /* do the last partial word */ |
1223 | 0 | if (dlwpartb) { |
1224 | 0 | for (i = 0; i < dh; i++) { |
1225 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1226 | 0 | ~(*pslwpart | *pdlwpart), dlwmask); |
1227 | 0 | pdlwpart += dwpl; |
1228 | 0 | pslwpart += swpl; |
1229 | 0 | } |
1230 | 0 | } |
1231 | 0 | break; |
1232 | 0 | case (PIX_NOT(PIX_SRC & PIX_DST)): |
1233 | | /* do the first partial word */ |
1234 | 0 | if (dfwpartb) { |
1235 | 0 | for (i = 0; i < dh; i++) { |
1236 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1237 | 0 | ~(*psfwpart & *pdfwpart), dfwmask); |
1238 | 0 | pdfwpart += dwpl; |
1239 | 0 | psfwpart += swpl; |
1240 | 0 | } |
1241 | 0 | } |
1242 | | |
1243 | | /* do the full words */ |
1244 | 0 | if (dfwfullb) { |
1245 | 0 | for (i = 0; i < dh; i++) { |
1246 | 0 | for (j = 0; j < dnfullw; j++) |
1247 | 0 | *(pdfwfull + j) = ~(*(psfwfull + j) & *(pdfwfull + j)); |
1248 | 0 | pdfwfull += dwpl; |
1249 | 0 | psfwfull += swpl; |
1250 | 0 | } |
1251 | 0 | } |
1252 | | |
1253 | | /* do the last partial word */ |
1254 | 0 | if (dlwpartb) { |
1255 | 0 | for (i = 0; i < dh; i++) { |
1256 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1257 | 0 | ~(*pslwpart & *pdlwpart), dlwmask); |
1258 | 0 | pdlwpart += dwpl; |
1259 | 0 | pslwpart += swpl; |
1260 | 0 | } |
1261 | 0 | } |
1262 | 0 | break; |
1263 | | /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */ |
1264 | 0 | case (PIX_NOT(PIX_SRC ^ PIX_DST)): |
1265 | | /* do the first partial word */ |
1266 | 0 | if (dfwpartb) { |
1267 | 0 | for (i = 0; i < dh; i++) { |
1268 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1269 | 0 | ~(*psfwpart ^ *pdfwpart), dfwmask); |
1270 | 0 | pdfwpart += dwpl; |
1271 | 0 | psfwpart += swpl; |
1272 | 0 | } |
1273 | 0 | } |
1274 | | |
1275 | | /* do the full words */ |
1276 | 0 | if (dfwfullb) { |
1277 | 0 | for (i = 0; i < dh; i++) { |
1278 | 0 | for (j = 0; j < dnfullw; j++) |
1279 | 0 | *(pdfwfull + j) = ~(*(psfwfull + j) ^ *(pdfwfull + j)); |
1280 | 0 | pdfwfull += dwpl; |
1281 | 0 | psfwfull += swpl; |
1282 | 0 | } |
1283 | 0 | } |
1284 | | |
1285 | | /* do the last partial word */ |
1286 | 0 | if (dlwpartb) { |
1287 | 0 | for (i = 0; i < dh; i++) { |
1288 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1289 | 0 | ~(*pslwpart ^ *pdlwpart), dlwmask); |
1290 | 0 | pdlwpart += dwpl; |
1291 | 0 | pslwpart += swpl; |
1292 | 0 | } |
1293 | 0 | } |
1294 | 0 | break; |
1295 | 0 | default: |
1296 | 0 | lept_stderr("Operation %x invalid\n", op); |
1297 | 77.6k | } |
1298 | 77.6k | } |
1299 | | |
1300 | | |
1301 | | /*--------------------------------------------------------------------* |
1302 | | * Static low-level rasterop without vertical word alignment * |
1303 | | *--------------------------------------------------------------------*/ |
1304 | | /*! |
1305 | | * \brief rasteropGeneralLow() |
1306 | | * |
1307 | | * \param[in] datad ptr to dest image data |
1308 | | * \param[in] dwpl wpl of dest |
1309 | | * \param[in] dx x val of UL corner of dest rectangle |
1310 | | * \param[in] dy y val of UL corner of dest rectangle |
1311 | | * \param[in] dw width of dest rectangle |
1312 | | * \param[in] dh height of dest rectangle |
1313 | | * \param[in] op op code |
1314 | | * \param[in] datas ptr to src image data |
1315 | | * \param[in] swpl wpl of src |
1316 | | * \param[in] sx x val of UL corner of src rectangle |
1317 | | * \param[in] sy y val of UL corner of src rectangle |
1318 | | * \return void |
1319 | | * |
1320 | | * This is called when the src and dest rects are |
1321 | | * do not have the same 32-bit word alignment. |
1322 | | * |
1323 | | * The method is a generalization of rasteropVAlignLow. |
1324 | | * There, the src image pieces were directly merged |
1325 | | * with the dest. Here, we shift the source bits |
1326 | | * to fill words that are aligned with the dest, and |
1327 | | * then use those "source words" exactly in place |
1328 | | * of the source words that were used in rasteropVAlignLow. |
1329 | | * |
1330 | | * The critical parameter is thus the shift required |
1331 | | * for the src. Consider the left edge of the rectangle. |
1332 | | * The overhang into the src and dest words are found, |
1333 | | * and the difference is exactly this shift. There are |
1334 | | * two separate cases, depending on whether the src pixels |
1335 | | * are shifted left or right. If the src overhang is |
1336 | | * larger than the dest overhang, the src is shifted to |
1337 | | * the right, and a number of pixels equal to the shift are |
1338 | | * left over for filling the next dest word, if necessary. |
1339 | | * |
1340 | | * But if the dest overhang is larger than the src overhang, |
1341 | | * the src is shifted to the left, and depending on the width of |
1342 | | * transferred pixels, it may also be necessary to shift pixels |
1343 | | * in from the next src word, in order to fill the dest word. |
1344 | | * An interesting case is where the src overhang equals the width, |
1345 | | * dw, of the block. Then all the pixels necessary to fill the first |
1346 | | * dest word can be taken from the first src word, up to the last |
1347 | | * src pixel in the word, and no pixels from the next src word are |
1348 | | * required. Consider this simple example, where a single pixel from |
1349 | | * the src is transferred to the dest: |
1350 | | * pix1 = pixCreate(32, 1, 1); |
1351 | | * pix2 = pixCreate(32, 1, 1); |
1352 | | * pixRasterop(pix1, 30, 0, 1, 1, PIX_SRC, pix2, 31, 0); |
1353 | | * Here, the pixel at the right end of the src image (sx = 31) |
1354 | | * is shifted one bit to the left (to dx = 30). The width (1) equals |
1355 | | * the src overhang (1), and no pixels from the next word are required. |
1356 | | * (This must be true because there is only one src word.) |
1357 | | */ |
1358 | | static void |
1359 | | rasteropGeneralLow(l_uint32 *datad, |
1360 | | l_int32 dwpl, |
1361 | | l_int32 dx, |
1362 | | l_int32 dy, |
1363 | | l_int32 dw, |
1364 | | l_int32 dh, |
1365 | | l_int32 op, |
1366 | | l_uint32 *datas, |
1367 | | l_int32 swpl, |
1368 | | l_int32 sx, |
1369 | | l_int32 sy) |
1370 | 2.38M | { |
1371 | 2.38M | l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */ |
1372 | 2.38M | l_int32 dfwpart2b; /* boolean (1, 0) if 1st dest word is doubly partial */ |
1373 | 2.38M | l_uint32 dfwmask; /* mask for first partial dest word */ |
1374 | 2.38M | l_int32 dfwbits; /* first word dest bits in overhang; 0-31 */ |
1375 | 2.38M | l_int32 dhang; /* dest overhang in first partial word, */ |
1376 | | /* or 0 if dest is word aligned (same as dfwbits) */ |
1377 | 2.38M | l_uint32 *pdfwpart = NULL; /* ptr to first partial dest word */ |
1378 | 2.38M | l_uint32 *psfwpart = NULL; /* ptr to first partial src word */ |
1379 | 2.38M | l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */ |
1380 | 2.38M | l_int32 dnfullw; /* number of full words in dest */ |
1381 | 2.38M | l_uint32 *pdfwfull = NULL; /* ptr to first full dest word */ |
1382 | 2.38M | l_uint32 *psfwfull = NULL; /* ptr to first full src word */ |
1383 | 2.38M | l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */ |
1384 | 2.38M | l_uint32 dlwmask; /* mask for last partial dest word */ |
1385 | 2.38M | l_int32 dlwbits; /* last word dest bits in ovrhang */ |
1386 | 2.38M | l_uint32 *pdlwpart = NULL; /* ptr to last partial dest word */ |
1387 | 2.38M | l_uint32 *pslwpart = NULL; /* ptr to last partial src word */ |
1388 | 2.38M | l_uint32 sword; /* compose src word aligned with the dest words */ |
1389 | 2.38M | l_int32 sfwbits; /* first word src bits in overhang (1-32), */ |
1390 | | /* or 32 if src is word aligned */ |
1391 | 2.38M | l_int32 shang; /* source overhang in the first partial word, */ |
1392 | | /* or 0 if src is word aligned (not same as sfwbits) */ |
1393 | 2.38M | l_int32 sleftshift; /* bits to shift left for source word to align */ |
1394 | | /* with the dest. Also the number of bits that */ |
1395 | | /* get shifted to the right to align with the dest. */ |
1396 | 2.38M | l_int32 srightshift; /* bits to shift right for source word to align */ |
1397 | | /* with dest. Also, the number of bits that get */ |
1398 | | /* shifted left to align with the dest. */ |
1399 | 2.38M | l_int32 srightmask; /* mask for selecting sleftshift bits that have */ |
1400 | | /* been shifted right by srightshift bits */ |
1401 | 2.38M | l_int32 sfwshiftdir; /* either SHIFT_LEFT or SHIFT_RIGHT */ |
1402 | 2.38M | l_int32 sfwaddb; /* boolean: do we need an additional sfw right shift? */ |
1403 | 2.38M | l_int32 slwaddb; /* boolean: do we need an additional slw right shift? */ |
1404 | 2.38M | l_int32 i, j; |
1405 | | |
1406 | | |
1407 | | /*--------------------------------------------------------* |
1408 | | * Preliminary calculations * |
1409 | | *--------------------------------------------------------*/ |
1410 | | /* To get alignment of src with dst (e.g., in the |
1411 | | * full words) the src must do a left shift of its |
1412 | | * relative overhang in the current src word, |
1413 | | * and OR that with a right shift of |
1414 | | * (31 - relative overhang) from the next src word. |
1415 | | * We find the absolute overhangs, the relative overhangs, |
1416 | | * the required shifts and the src mask */ |
1417 | 2.38M | if ((sx & 31) == 0) |
1418 | 0 | shang = 0; |
1419 | 2.38M | else |
1420 | 2.38M | shang = 32 - (sx & 31); |
1421 | 2.38M | if ((dx & 31) == 0) |
1422 | 2.38M | dhang = 0; |
1423 | 0 | else |
1424 | 0 | dhang = 32 - (dx & 31); |
1425 | | #if 0 |
1426 | | lept_stderr("shang = %d, dhang = %d\n", shang, dhang); |
1427 | | #endif |
1428 | | |
1429 | 2.38M | if (shang == 0 && dhang == 0) { /* this should be treated by an |
1430 | | aligned operation, not by |
1431 | | this general rasterop! */ |
1432 | 0 | sleftshift = 0; |
1433 | 0 | srightshift = 0; |
1434 | 0 | srightmask = rmask32[0]; |
1435 | 2.38M | } else { |
1436 | 2.38M | if (dhang > shang) |
1437 | 0 | sleftshift = dhang - shang; |
1438 | 2.38M | else |
1439 | 2.38M | sleftshift = 32 - (shang - dhang); |
1440 | 2.38M | srightshift = 32 - sleftshift; |
1441 | 2.38M | srightmask = rmask32[sleftshift]; |
1442 | 2.38M | } |
1443 | | |
1444 | | #if 0 |
1445 | | lept_stderr("sleftshift = %d, srightshift = %d\n", sleftshift, srightshift); |
1446 | | #endif |
1447 | | |
1448 | | /* Is the first dest word partial? */ |
1449 | 2.38M | dfwmask = 0; |
1450 | 2.38M | if ((dx & 31) == 0) { /* if not */ |
1451 | 2.38M | dfwpartb = 0; |
1452 | 2.38M | dfwbits = 0; |
1453 | 2.38M | } else { /* if so */ |
1454 | 0 | dfwpartb = 1; |
1455 | 0 | dfwbits = 32 - (dx & 31); |
1456 | 0 | dfwmask = rmask32[dfwbits]; |
1457 | 0 | pdfwpart = datad + dwpl * dy + (dx >> 5); |
1458 | 0 | psfwpart = datas + swpl * sy + (sx >> 5); |
1459 | 0 | sfwbits = 32 - (sx & 31); |
1460 | 0 | if (dfwbits > sfwbits) { |
1461 | 0 | sfwshiftdir = SHIFT_LEFT; /* shift by sleftshift */ |
1462 | | /* Do we have enough bits from the current src word? */ |
1463 | 0 | if (dw <= shang) |
1464 | 0 | sfwaddb = 0; /* yes: we have enough bits */ |
1465 | 0 | else |
1466 | 0 | sfwaddb = 1; /* no: rshift in next src word by srightshift */ |
1467 | 0 | } else { |
1468 | 0 | sfwshiftdir = SHIFT_RIGHT; /* shift by srightshift */ |
1469 | 0 | } |
1470 | 0 | } |
1471 | | |
1472 | | /* Is the first dest word doubly partial? */ |
1473 | 2.38M | if (dw >= dfwbits) { /* if not */ |
1474 | 2.38M | dfwpart2b = 0; |
1475 | 2.38M | } else { /* if so */ |
1476 | 0 | dfwpart2b = 1; |
1477 | 0 | dfwmask &= lmask32[32 - dfwbits + dw]; |
1478 | 0 | } |
1479 | | |
1480 | | /* Is there a full dest word? */ |
1481 | 2.38M | if (dfwpart2b == 1) { /* not */ |
1482 | 0 | dfwfullb = 0; |
1483 | 0 | dnfullw = 0; |
1484 | 2.38M | } else { |
1485 | 2.38M | dnfullw = (dw - dfwbits) >> 5; |
1486 | 2.38M | if (dnfullw == 0) { /* if not */ |
1487 | 2.35M | dfwfullb = 0; |
1488 | 2.35M | } else { /* if so */ |
1489 | 29.4k | dfwfullb = 1; |
1490 | 29.4k | pdfwfull = datad + dwpl * dy + ((dx + dhang) >> 5); |
1491 | 29.4k | psfwfull = datas + swpl * sy + ((sx + dhang) >> 5); /* yes, dhang */ |
1492 | 29.4k | } |
1493 | 2.38M | } |
1494 | | |
1495 | | /* Is the last dest word partial? */ |
1496 | 2.38M | dlwbits = (dx + dw) & 31; |
1497 | 2.38M | if (dfwpart2b == 1 || dlwbits == 0) { /* if not */ |
1498 | 2.15k | dlwpartb = 0; |
1499 | 2.38M | } else { |
1500 | 2.38M | dlwpartb = 1; |
1501 | 2.38M | dlwmask = lmask32[dlwbits]; |
1502 | 2.38M | pdlwpart = datad + dwpl * dy + ((dx + dhang) >> 5) + dnfullw; |
1503 | 2.38M | pslwpart = datas + swpl * sy + ((sx + dhang) >> 5) + dnfullw; |
1504 | 2.38M | if (dlwbits <= srightshift) /* must be <= here !!! */ |
1505 | 2.25M | slwaddb = 0; /* we got enough bits from current src word */ |
1506 | 134k | else |
1507 | 134k | slwaddb = 1; /* must rshift in next src word by srightshift */ |
1508 | 2.38M | } |
1509 | | |
1510 | | |
1511 | | /*--------------------------------------------------------* |
1512 | | * Now we're ready to do the ops * |
1513 | | *--------------------------------------------------------*/ |
1514 | 2.38M | switch (op) |
1515 | 2.38M | { |
1516 | 2.38M | case PIX_SRC: |
1517 | | /* do the first partial word */ |
1518 | 2.38M | if (dfwpartb) { |
1519 | 0 | for (i = 0; i < dh; i++) |
1520 | 0 | { |
1521 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1522 | 0 | sword = *psfwpart << sleftshift; |
1523 | 0 | if (sfwaddb) |
1524 | 0 | sword = COMBINE_PARTIAL(sword, |
1525 | 0 | *(psfwpart + 1) >> srightshift, |
1526 | 0 | srightmask); |
1527 | 0 | } else { /* shift right */ |
1528 | 0 | sword = *psfwpart >> srightshift; |
1529 | 0 | } |
1530 | |
|
1531 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, sword, dfwmask); |
1532 | 0 | pdfwpart += dwpl; |
1533 | 0 | psfwpart += swpl; |
1534 | 0 | } |
1535 | 0 | } |
1536 | | |
1537 | | /* do the full words */ |
1538 | 2.38M | if (dfwfullb) { |
1539 | 605k | for (i = 0; i < dh; i++) { |
1540 | 1.93M | for (j = 0; j < dnfullw; j++) { |
1541 | 1.35M | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1542 | 1.35M | *(psfwfull + j + 1) >> srightshift, |
1543 | 1.35M | srightmask); |
1544 | 1.35M | *(pdfwfull + j) = sword; |
1545 | 1.35M | } |
1546 | 575k | pdfwfull += dwpl; |
1547 | 575k | psfwfull += swpl; |
1548 | 575k | } |
1549 | 29.4k | } |
1550 | | |
1551 | | /* do the last partial word */ |
1552 | 2.38M | if (dlwpartb) { |
1553 | 17.9M | for (i = 0; i < dh; i++) { |
1554 | 15.5M | sword = *pslwpart << sleftshift; |
1555 | 15.5M | if (slwaddb) |
1556 | 1.42M | sword = COMBINE_PARTIAL(sword, |
1557 | 15.5M | *(pslwpart + 1) >> srightshift, |
1558 | 15.5M | srightmask); |
1559 | | |
1560 | 15.5M | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, sword, dlwmask); |
1561 | 15.5M | pdlwpart += dwpl; |
1562 | 15.5M | pslwpart += swpl; |
1563 | 15.5M | } |
1564 | 2.38M | } |
1565 | 2.38M | break; |
1566 | 0 | case PIX_NOT(PIX_SRC): |
1567 | | /* do the first partial word */ |
1568 | 0 | if (dfwpartb) { |
1569 | 0 | for (i = 0; i < dh; i++) |
1570 | 0 | { |
1571 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1572 | 0 | sword = *psfwpart << sleftshift; |
1573 | 0 | if (sfwaddb) |
1574 | 0 | sword = COMBINE_PARTIAL(sword, |
1575 | 0 | *(psfwpart + 1) >> srightshift, |
1576 | 0 | srightmask); |
1577 | 0 | } else { /* shift right */ |
1578 | 0 | sword = *psfwpart >> srightshift; |
1579 | 0 | } |
1580 | |
|
1581 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~sword, dfwmask); |
1582 | 0 | pdfwpart += dwpl; |
1583 | 0 | psfwpart += swpl; |
1584 | 0 | } |
1585 | 0 | } |
1586 | | |
1587 | | /* do the full words */ |
1588 | 0 | if (dfwfullb) { |
1589 | 0 | for (i = 0; i < dh; i++) { |
1590 | 0 | for (j = 0; j < dnfullw; j++) { |
1591 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1592 | 0 | *(psfwfull + j + 1) >> srightshift, |
1593 | 0 | srightmask); |
1594 | 0 | *(pdfwfull + j) = ~sword; |
1595 | 0 | } |
1596 | 0 | pdfwfull += dwpl; |
1597 | 0 | psfwfull += swpl; |
1598 | 0 | } |
1599 | 0 | } |
1600 | | |
1601 | | /* do the last partial word */ |
1602 | 0 | if (dlwpartb) { |
1603 | 0 | for (i = 0; i < dh; i++) { |
1604 | 0 | sword = *pslwpart << sleftshift; |
1605 | 0 | if (slwaddb) |
1606 | 0 | sword = COMBINE_PARTIAL(sword, |
1607 | 0 | *(pslwpart + 1) >> srightshift, |
1608 | 0 | srightmask); |
1609 | |
|
1610 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~sword, dlwmask); |
1611 | 0 | pdlwpart += dwpl; |
1612 | 0 | pslwpart += swpl; |
1613 | 0 | } |
1614 | 0 | } |
1615 | 0 | break; |
1616 | 0 | case (PIX_SRC | PIX_DST): |
1617 | | /* do the first partial word */ |
1618 | 0 | if (dfwpartb) { |
1619 | 0 | for (i = 0; i < dh; i++) |
1620 | 0 | { |
1621 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1622 | 0 | sword = *psfwpart << sleftshift; |
1623 | 0 | if (sfwaddb) |
1624 | 0 | sword = COMBINE_PARTIAL(sword, |
1625 | 0 | *(psfwpart + 1) >> srightshift, |
1626 | 0 | srightmask); |
1627 | 0 | } else { /* shift right */ |
1628 | 0 | sword = *psfwpart >> srightshift; |
1629 | 0 | } |
1630 | |
|
1631 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1632 | 0 | (sword | *pdfwpart), dfwmask); |
1633 | 0 | pdfwpart += dwpl; |
1634 | 0 | psfwpart += swpl; |
1635 | 0 | } |
1636 | 0 | } |
1637 | | |
1638 | | /* do the full words */ |
1639 | 0 | if (dfwfullb) { |
1640 | 0 | for (i = 0; i < dh; i++) { |
1641 | 0 | for (j = 0; j < dnfullw; j++) { |
1642 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1643 | 0 | *(psfwfull + j + 1) >> srightshift, |
1644 | 0 | srightmask); |
1645 | 0 | *(pdfwfull + j) |= sword; |
1646 | 0 | } |
1647 | 0 | pdfwfull += dwpl; |
1648 | 0 | psfwfull += swpl; |
1649 | 0 | } |
1650 | 0 | } |
1651 | | |
1652 | | /* do the last partial word */ |
1653 | 0 | if (dlwpartb) { |
1654 | 0 | for (i = 0; i < dh; i++) { |
1655 | 0 | sword = *pslwpart << sleftshift; |
1656 | 0 | if (slwaddb) |
1657 | 0 | sword = COMBINE_PARTIAL(sword, |
1658 | 0 | *(pslwpart + 1) >> srightshift, |
1659 | 0 | srightmask); |
1660 | |
|
1661 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1662 | 0 | (sword | *pdlwpart), dlwmask); |
1663 | 0 | pdlwpart += dwpl; |
1664 | 0 | pslwpart += swpl; |
1665 | 0 | } |
1666 | 0 | } |
1667 | 0 | break; |
1668 | 0 | case (PIX_SRC & PIX_DST): |
1669 | | /* do the first partial word */ |
1670 | 0 | if (dfwpartb) { |
1671 | 0 | for (i = 0; i < dh; i++) |
1672 | 0 | { |
1673 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1674 | 0 | sword = *psfwpart << sleftshift; |
1675 | 0 | if (sfwaddb) |
1676 | 0 | sword = COMBINE_PARTIAL(sword, |
1677 | 0 | *(psfwpart + 1) >> srightshift, |
1678 | 0 | srightmask); |
1679 | 0 | } else { /* shift right */ |
1680 | 0 | sword = *psfwpart >> srightshift; |
1681 | 0 | } |
1682 | |
|
1683 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1684 | 0 | (sword & *pdfwpart), dfwmask); |
1685 | 0 | pdfwpart += dwpl; |
1686 | 0 | psfwpart += swpl; |
1687 | 0 | } |
1688 | 0 | } |
1689 | | |
1690 | | /* do the full words */ |
1691 | 0 | if (dfwfullb) { |
1692 | 0 | for (i = 0; i < dh; i++) { |
1693 | 0 | for (j = 0; j < dnfullw; j++) { |
1694 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1695 | 0 | *(psfwfull + j + 1) >> srightshift, |
1696 | 0 | srightmask); |
1697 | 0 | *(pdfwfull + j) &= sword; |
1698 | 0 | } |
1699 | 0 | pdfwfull += dwpl; |
1700 | 0 | psfwfull += swpl; |
1701 | 0 | } |
1702 | 0 | } |
1703 | | |
1704 | | /* do the last partial word */ |
1705 | 0 | if (dlwpartb) { |
1706 | 0 | for (i = 0; i < dh; i++) { |
1707 | 0 | sword = *pslwpart << sleftshift; |
1708 | 0 | if (slwaddb) |
1709 | 0 | sword = COMBINE_PARTIAL(sword, |
1710 | 0 | *(pslwpart + 1) >> srightshift, |
1711 | 0 | srightmask); |
1712 | |
|
1713 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1714 | 0 | (sword & *pdlwpart), dlwmask); |
1715 | 0 | pdlwpart += dwpl; |
1716 | 0 | pslwpart += swpl; |
1717 | 0 | } |
1718 | 0 | } |
1719 | 0 | break; |
1720 | 0 | case (PIX_SRC ^ PIX_DST): |
1721 | | /* do the first partial word */ |
1722 | 0 | if (dfwpartb) { |
1723 | 0 | for (i = 0; i < dh; i++) |
1724 | 0 | { |
1725 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1726 | 0 | sword = *psfwpart << sleftshift; |
1727 | 0 | if (sfwaddb) |
1728 | 0 | sword = COMBINE_PARTIAL(sword, |
1729 | 0 | *(psfwpart + 1) >> srightshift, |
1730 | 0 | srightmask); |
1731 | 0 | } else { /* shift right */ |
1732 | 0 | sword = *psfwpart >> srightshift; |
1733 | 0 | } |
1734 | |
|
1735 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1736 | 0 | (sword ^ *pdfwpart), dfwmask); |
1737 | 0 | pdfwpart += dwpl; |
1738 | 0 | psfwpart += swpl; |
1739 | 0 | } |
1740 | 0 | } |
1741 | | |
1742 | | /* do the full words */ |
1743 | 0 | if (dfwfullb) { |
1744 | 0 | for (i = 0; i < dh; i++) { |
1745 | 0 | for (j = 0; j < dnfullw; j++) { |
1746 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1747 | 0 | *(psfwfull + j + 1) >> srightshift, |
1748 | 0 | srightmask); |
1749 | 0 | *(pdfwfull + j) ^= sword; |
1750 | 0 | } |
1751 | 0 | pdfwfull += dwpl; |
1752 | 0 | psfwfull += swpl; |
1753 | 0 | } |
1754 | 0 | } |
1755 | | |
1756 | | /* do the last partial word */ |
1757 | 0 | if (dlwpartb) { |
1758 | 0 | for (i = 0; i < dh; i++) { |
1759 | 0 | sword = *pslwpart << sleftshift; |
1760 | 0 | if (slwaddb) |
1761 | 0 | sword = COMBINE_PARTIAL(sword, |
1762 | 0 | *(pslwpart + 1) >> srightshift, |
1763 | 0 | srightmask); |
1764 | |
|
1765 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1766 | 0 | (sword ^ *pdlwpart), dlwmask); |
1767 | 0 | pdlwpart += dwpl; |
1768 | 0 | pslwpart += swpl; |
1769 | 0 | } |
1770 | 0 | } |
1771 | 0 | break; |
1772 | 0 | case (PIX_NOT(PIX_SRC) | PIX_DST): |
1773 | | /* do the first partial word */ |
1774 | 0 | if (dfwpartb) { |
1775 | 0 | for (i = 0; i < dh; i++) |
1776 | 0 | { |
1777 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1778 | 0 | sword = *psfwpart << sleftshift; |
1779 | 0 | if (sfwaddb) |
1780 | 0 | sword = COMBINE_PARTIAL(sword, |
1781 | 0 | *(psfwpart + 1) >> srightshift, |
1782 | 0 | srightmask); |
1783 | 0 | } else { /* shift right */ |
1784 | 0 | sword = *psfwpart >> srightshift; |
1785 | 0 | } |
1786 | |
|
1787 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1788 | 0 | (~sword | *pdfwpart), dfwmask); |
1789 | 0 | pdfwpart += dwpl; |
1790 | 0 | psfwpart += swpl; |
1791 | 0 | } |
1792 | 0 | } |
1793 | | |
1794 | | /* do the full words */ |
1795 | 0 | if (dfwfullb) { |
1796 | 0 | for (i = 0; i < dh; i++) { |
1797 | 0 | for (j = 0; j < dnfullw; j++) { |
1798 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1799 | 0 | *(psfwfull + j + 1) >> srightshift, |
1800 | 0 | srightmask); |
1801 | 0 | *(pdfwfull + j) |= ~sword; |
1802 | 0 | } |
1803 | 0 | pdfwfull += dwpl; |
1804 | 0 | psfwfull += swpl; |
1805 | 0 | } |
1806 | 0 | } |
1807 | | |
1808 | | /* do the last partial word */ |
1809 | 0 | if (dlwpartb) { |
1810 | 0 | for (i = 0; i < dh; i++) { |
1811 | 0 | sword = *pslwpart << sleftshift; |
1812 | 0 | if (slwaddb) |
1813 | 0 | sword = COMBINE_PARTIAL(sword, |
1814 | 0 | *(pslwpart + 1) >> srightshift, |
1815 | 0 | srightmask); |
1816 | |
|
1817 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1818 | 0 | (~sword | *pdlwpart), dlwmask); |
1819 | 0 | pdlwpart += dwpl; |
1820 | 0 | pslwpart += swpl; |
1821 | 0 | } |
1822 | 0 | } |
1823 | 0 | break; |
1824 | 0 | case (PIX_NOT(PIX_SRC) & PIX_DST): |
1825 | | /* do the first partial word */ |
1826 | 0 | if (dfwpartb) { |
1827 | 0 | for (i = 0; i < dh; i++) |
1828 | 0 | { |
1829 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1830 | 0 | sword = *psfwpart << sleftshift; |
1831 | 0 | if (sfwaddb) |
1832 | 0 | sword = COMBINE_PARTIAL(sword, |
1833 | 0 | *(psfwpart + 1) >> srightshift, |
1834 | 0 | srightmask); |
1835 | 0 | } else { /* shift right */ |
1836 | 0 | sword = *psfwpart >> srightshift; |
1837 | 0 | } |
1838 | |
|
1839 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1840 | 0 | (~sword & *pdfwpart), dfwmask); |
1841 | 0 | pdfwpart += dwpl; |
1842 | 0 | psfwpart += swpl; |
1843 | 0 | } |
1844 | 0 | } |
1845 | | |
1846 | | /* do the full words */ |
1847 | 0 | if (dfwfullb) { |
1848 | 0 | for (i = 0; i < dh; i++) { |
1849 | 0 | for (j = 0; j < dnfullw; j++) { |
1850 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1851 | 0 | *(psfwfull + j + 1) >> srightshift, |
1852 | 0 | srightmask); |
1853 | 0 | *(pdfwfull + j) &= ~sword; |
1854 | 0 | } |
1855 | 0 | pdfwfull += dwpl; |
1856 | 0 | psfwfull += swpl; |
1857 | 0 | } |
1858 | 0 | } |
1859 | | |
1860 | | /* do the last partial word */ |
1861 | 0 | if (dlwpartb) { |
1862 | 0 | for (i = 0; i < dh; i++) { |
1863 | 0 | sword = *pslwpart << sleftshift; |
1864 | 0 | if (slwaddb) |
1865 | 0 | sword = COMBINE_PARTIAL(sword, |
1866 | 0 | *(pslwpart + 1) >> srightshift, |
1867 | 0 | srightmask); |
1868 | |
|
1869 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1870 | 0 | (~sword & *pdlwpart), dlwmask); |
1871 | 0 | pdlwpart += dwpl; |
1872 | 0 | pslwpart += swpl; |
1873 | 0 | } |
1874 | 0 | } |
1875 | 0 | break; |
1876 | 0 | case (PIX_SRC | PIX_NOT(PIX_DST)): |
1877 | | /* do the first partial word */ |
1878 | 0 | if (dfwpartb) { |
1879 | 0 | for (i = 0; i < dh; i++) |
1880 | 0 | { |
1881 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1882 | 0 | sword = *psfwpart << sleftshift; |
1883 | 0 | if (sfwaddb) |
1884 | 0 | sword = COMBINE_PARTIAL(sword, |
1885 | 0 | *(psfwpart + 1) >> srightshift, |
1886 | 0 | srightmask); |
1887 | 0 | } else { /* shift right */ |
1888 | 0 | sword = *psfwpart >> srightshift; |
1889 | 0 | } |
1890 | |
|
1891 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1892 | 0 | (sword | ~(*pdfwpart)), dfwmask); |
1893 | 0 | pdfwpart += dwpl; |
1894 | 0 | psfwpart += swpl; |
1895 | 0 | } |
1896 | 0 | } |
1897 | | |
1898 | | /* do the full words */ |
1899 | 0 | if (dfwfullb) { |
1900 | 0 | for (i = 0; i < dh; i++) { |
1901 | 0 | for (j = 0; j < dnfullw; j++) { |
1902 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1903 | 0 | *(psfwfull + j + 1) >> srightshift, |
1904 | 0 | srightmask); |
1905 | 0 | *(pdfwfull + j) = sword | ~(*(pdfwfull + j)); |
1906 | 0 | } |
1907 | 0 | pdfwfull += dwpl; |
1908 | 0 | psfwfull += swpl; |
1909 | 0 | } |
1910 | 0 | } |
1911 | | |
1912 | | /* do the last partial word */ |
1913 | 0 | if (dlwpartb) { |
1914 | 0 | for (i = 0; i < dh; i++) { |
1915 | 0 | sword = *pslwpart << sleftshift; |
1916 | 0 | if (slwaddb) |
1917 | 0 | sword = COMBINE_PARTIAL(sword, |
1918 | 0 | *(pslwpart + 1) >> srightshift, |
1919 | 0 | srightmask); |
1920 | |
|
1921 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1922 | 0 | (sword | ~(*pdlwpart)), dlwmask); |
1923 | 0 | pdlwpart += dwpl; |
1924 | 0 | pslwpart += swpl; |
1925 | 0 | } |
1926 | 0 | } |
1927 | 0 | break; |
1928 | 0 | case (PIX_SRC & PIX_NOT(PIX_DST)): |
1929 | | /* do the first partial word */ |
1930 | 0 | if (dfwpartb) { |
1931 | 0 | for (i = 0; i < dh; i++) |
1932 | 0 | { |
1933 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1934 | 0 | sword = *psfwpart << sleftshift; |
1935 | 0 | if (sfwaddb) |
1936 | 0 | sword = COMBINE_PARTIAL(sword, |
1937 | 0 | *(psfwpart + 1) >> srightshift, |
1938 | 0 | srightmask); |
1939 | 0 | } else { /* shift right */ |
1940 | 0 | sword = *psfwpart >> srightshift; |
1941 | 0 | } |
1942 | |
|
1943 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1944 | 0 | (sword & ~(*pdfwpart)), dfwmask); |
1945 | 0 | pdfwpart += dwpl; |
1946 | 0 | psfwpart += swpl; |
1947 | 0 | } |
1948 | 0 | } |
1949 | | |
1950 | | /* do the full words */ |
1951 | 0 | if (dfwfullb) { |
1952 | 0 | for (i = 0; i < dh; i++) { |
1953 | 0 | for (j = 0; j < dnfullw; j++) { |
1954 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
1955 | 0 | *(psfwfull + j + 1) >> srightshift, |
1956 | 0 | srightmask); |
1957 | 0 | *(pdfwfull + j) = sword & ~(*(pdfwfull + j)); |
1958 | 0 | } |
1959 | 0 | pdfwfull += dwpl; |
1960 | 0 | psfwfull += swpl; |
1961 | 0 | } |
1962 | 0 | } |
1963 | | |
1964 | | /* do the last partial word */ |
1965 | 0 | if (dlwpartb) { |
1966 | 0 | for (i = 0; i < dh; i++) { |
1967 | 0 | sword = *pslwpart << sleftshift; |
1968 | 0 | if (slwaddb) |
1969 | 0 | sword = COMBINE_PARTIAL(sword, |
1970 | 0 | *(pslwpart + 1) >> srightshift, |
1971 | 0 | srightmask); |
1972 | |
|
1973 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
1974 | 0 | (sword & ~(*pdlwpart)), dlwmask); |
1975 | 0 | pdlwpart += dwpl; |
1976 | 0 | pslwpart += swpl; |
1977 | 0 | } |
1978 | 0 | } |
1979 | 0 | break; |
1980 | 0 | case (PIX_NOT(PIX_SRC | PIX_DST)): |
1981 | | /* do the first partial word */ |
1982 | 0 | if (dfwpartb) { |
1983 | 0 | for (i = 0; i < dh; i++) |
1984 | 0 | { |
1985 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
1986 | 0 | sword = *psfwpart << sleftshift; |
1987 | 0 | if (sfwaddb) |
1988 | 0 | sword = COMBINE_PARTIAL(sword, |
1989 | 0 | *(psfwpart + 1) >> srightshift, |
1990 | 0 | srightmask); |
1991 | 0 | } else { /* shift right */ |
1992 | 0 | sword = *psfwpart >> srightshift; |
1993 | 0 | } |
1994 | |
|
1995 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
1996 | 0 | ~(sword | *pdfwpart), dfwmask); |
1997 | 0 | pdfwpart += dwpl; |
1998 | 0 | psfwpart += swpl; |
1999 | 0 | } |
2000 | 0 | } |
2001 | | |
2002 | | /* do the full words */ |
2003 | 0 | if (dfwfullb) { |
2004 | 0 | for (i = 0; i < dh; i++) { |
2005 | 0 | for (j = 0; j < dnfullw; j++) { |
2006 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
2007 | 0 | *(psfwfull + j + 1) >> srightshift, |
2008 | 0 | srightmask); |
2009 | 0 | *(pdfwfull + j) = ~(sword | *(pdfwfull + j)); |
2010 | 0 | } |
2011 | 0 | pdfwfull += dwpl; |
2012 | 0 | psfwfull += swpl; |
2013 | 0 | } |
2014 | 0 | } |
2015 | | |
2016 | | /* do the last partial word */ |
2017 | 0 | if (dlwpartb) { |
2018 | 0 | for (i = 0; i < dh; i++) { |
2019 | 0 | sword = *pslwpart << sleftshift; |
2020 | 0 | if (slwaddb) |
2021 | 0 | sword = COMBINE_PARTIAL(sword, |
2022 | 0 | *(pslwpart + 1) >> srightshift, |
2023 | 0 | srightmask); |
2024 | |
|
2025 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
2026 | 0 | ~(sword | *pdlwpart), dlwmask); |
2027 | 0 | pdlwpart += dwpl; |
2028 | 0 | pslwpart += swpl; |
2029 | 0 | } |
2030 | 0 | } |
2031 | 0 | break; |
2032 | 0 | case (PIX_NOT(PIX_SRC & PIX_DST)): |
2033 | | /* do the first partial word */ |
2034 | 0 | if (dfwpartb) { |
2035 | 0 | for (i = 0; i < dh; i++) |
2036 | 0 | { |
2037 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
2038 | 0 | sword = *psfwpart << sleftshift; |
2039 | 0 | if (sfwaddb) |
2040 | 0 | sword = COMBINE_PARTIAL(sword, |
2041 | 0 | *(psfwpart + 1) >> srightshift, |
2042 | 0 | srightmask); |
2043 | 0 | } else { /* shift right */ |
2044 | 0 | sword = *psfwpart >> srightshift; |
2045 | 0 | } |
2046 | |
|
2047 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
2048 | 0 | ~(sword & *pdfwpart), dfwmask); |
2049 | 0 | pdfwpart += dwpl; |
2050 | 0 | psfwpart += swpl; |
2051 | 0 | } |
2052 | 0 | } |
2053 | | |
2054 | | /* do the full words */ |
2055 | 0 | if (dfwfullb) { |
2056 | 0 | for (i = 0; i < dh; i++) { |
2057 | 0 | for (j = 0; j < dnfullw; j++) { |
2058 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
2059 | 0 | *(psfwfull + j + 1) >> srightshift, |
2060 | 0 | srightmask); |
2061 | 0 | *(pdfwfull + j) = ~(sword & *(pdfwfull + j)); |
2062 | 0 | } |
2063 | 0 | pdfwfull += dwpl; |
2064 | 0 | psfwfull += swpl; |
2065 | 0 | } |
2066 | 0 | } |
2067 | | |
2068 | | /* do the last partial word */ |
2069 | 0 | if (dlwpartb) { |
2070 | 0 | for (i = 0; i < dh; i++) { |
2071 | 0 | sword = *pslwpart << sleftshift; |
2072 | 0 | if (slwaddb) |
2073 | 0 | sword = COMBINE_PARTIAL(sword, |
2074 | 0 | *(pslwpart + 1) >> srightshift, |
2075 | 0 | srightmask); |
2076 | |
|
2077 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
2078 | 0 | ~(sword & *pdlwpart), dlwmask); |
2079 | 0 | pdlwpart += dwpl; |
2080 | 0 | pslwpart += swpl; |
2081 | 0 | } |
2082 | 0 | } |
2083 | 0 | break; |
2084 | | /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */ |
2085 | 0 | case (PIX_NOT(PIX_SRC ^ PIX_DST)): |
2086 | | /* do the first partial word */ |
2087 | 0 | if (dfwpartb) { |
2088 | 0 | for (i = 0; i < dh; i++) |
2089 | 0 | { |
2090 | 0 | if (sfwshiftdir == SHIFT_LEFT) { |
2091 | 0 | sword = *psfwpart << sleftshift; |
2092 | 0 | if (sfwaddb) |
2093 | 0 | sword = COMBINE_PARTIAL(sword, |
2094 | 0 | *(psfwpart + 1) >> srightshift, |
2095 | 0 | srightmask); |
2096 | 0 | } else { /* shift right */ |
2097 | 0 | sword = *psfwpart >> srightshift; |
2098 | 0 | } |
2099 | |
|
2100 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, |
2101 | 0 | ~(sword ^ *pdfwpart), dfwmask); |
2102 | 0 | pdfwpart += dwpl; |
2103 | 0 | psfwpart += swpl; |
2104 | 0 | } |
2105 | 0 | } |
2106 | | |
2107 | | /* do the full words */ |
2108 | 0 | if (dfwfullb) { |
2109 | 0 | for (i = 0; i < dh; i++) { |
2110 | 0 | for (j = 0; j < dnfullw; j++) { |
2111 | 0 | sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift, |
2112 | 0 | *(psfwfull + j + 1) >> srightshift, |
2113 | 0 | srightmask); |
2114 | 0 | *(pdfwfull + j) = ~(sword ^ *(pdfwfull + j)); |
2115 | 0 | } |
2116 | 0 | pdfwfull += dwpl; |
2117 | 0 | psfwfull += swpl; |
2118 | 0 | } |
2119 | 0 | } |
2120 | | |
2121 | | /* do the last partial word */ |
2122 | 0 | if (dlwpartb) { |
2123 | 0 | for (i = 0; i < dh; i++) { |
2124 | 0 | sword = *pslwpart << sleftshift; |
2125 | 0 | if (slwaddb) |
2126 | 0 | sword = COMBINE_PARTIAL(sword, |
2127 | 0 | *(pslwpart + 1) >> srightshift, |
2128 | 0 | srightmask); |
2129 | |
|
2130 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, |
2131 | 0 | ~(sword ^ *pdlwpart), dlwmask); |
2132 | 0 | pdlwpart += dwpl; |
2133 | 0 | pslwpart += swpl; |
2134 | 0 | } |
2135 | 0 | } |
2136 | 0 | break; |
2137 | 0 | default: |
2138 | 0 | lept_stderr("Operation %x invalid\n", op); |
2139 | 2.38M | } |
2140 | 2.38M | } |
2141 | | |
2142 | | |
2143 | | /*--------------------------------------------------------------------* |
2144 | | * Low level in-place full height vertical block transfer * |
2145 | | *--------------------------------------------------------------------*/ |
2146 | | /*! |
2147 | | * \brief rasteropVipLow() |
2148 | | * |
2149 | | * \param[in] data ptr to image data |
2150 | | * \param[in] pixw width |
2151 | | * \param[in] pixh height |
2152 | | * \param[in] depth depth |
2153 | | * \param[in] wpl wpl |
2154 | | * \param[in] x x val of UL corner of rectangle |
2155 | | * \param[in] w width of rectangle |
2156 | | * \param[in] shift + shifts data downward in vertical column |
2157 | | * \return 0 if OK; 1 on error. |
2158 | | * |
2159 | | * <pre> |
2160 | | * Notes: |
2161 | | * (1) This clears the pixels that are left exposed after the |
2162 | | * translation. You can consider them as pixels that are |
2163 | | * shifted in from outside the image. This can be later |
2164 | | * overridden by the incolor parameter in higher-level functions |
2165 | | * that call this. For example, for images with depth > 1, |
2166 | | * these pixels are cleared to black; to be white they |
2167 | | * must later be SET to white. See, e.g., pixRasteropVip(). |
2168 | | * (2) This function scales the width to accommodate any depth, |
2169 | | * performs clipping, and then does the in-place rasterop. |
2170 | | * </pre> |
2171 | | */ |
2172 | | void |
2173 | | rasteropVipLow(l_uint32 *data, |
2174 | | l_int32 pixw, |
2175 | | l_int32 pixh, |
2176 | | l_int32 depth, |
2177 | | l_int32 wpl, |
2178 | | l_int32 x, |
2179 | | l_int32 w, |
2180 | | l_int32 shift) |
2181 | 0 | { |
2182 | 0 | l_int32 fwpartb; /* boolean (1, 0) if first word is partial */ |
2183 | 0 | l_int32 fwpart2b; /* boolean (1, 0) if first word is doubly partial */ |
2184 | 0 | l_uint32 fwmask; /* mask for first partial word */ |
2185 | 0 | l_int32 fwbits; /* first word bits in ovrhang */ |
2186 | 0 | l_uint32 *pdfwpart = NULL; /* ptr to first partial dest word */ |
2187 | 0 | l_uint32 *psfwpart = NULL; /* ptr to first partial src word */ |
2188 | 0 | l_int32 fwfullb; /* boolean (1, 0) if there exists a full word */ |
2189 | 0 | l_int32 nfullw; /* number of full words */ |
2190 | 0 | l_uint32 *pdfwfull = NULL; /* ptr to first full dest word */ |
2191 | 0 | l_uint32 *psfwfull = NULL; /* ptr to first full src word */ |
2192 | 0 | l_int32 lwpartb; /* boolean (1, 0) if last word is partial */ |
2193 | 0 | l_uint32 lwmask; /* mask for last partial word */ |
2194 | 0 | l_int32 lwbits; /* last word bits in ovrhang */ |
2195 | 0 | l_uint32 *pdlwpart = NULL; /* ptr to last partial dest word */ |
2196 | 0 | l_uint32 *pslwpart = NULL; /* ptr to last partial src word */ |
2197 | 0 | l_int32 dirwpl; /* directed wpl (-wpl * sign(shift)) */ |
2198 | 0 | l_int32 absshift; /* absolute value of shift; for use in iterator */ |
2199 | 0 | l_int32 vlimit; /* vertical limit value for iterations */ |
2200 | 0 | l_int32 i, j; |
2201 | | |
2202 | | |
2203 | | /*--------------------------------------------------------* |
2204 | | * Scale horizontal dimensions by depth * |
2205 | | *--------------------------------------------------------*/ |
2206 | 0 | if (depth != 1) { |
2207 | 0 | pixw *= depth; |
2208 | 0 | x *= depth; |
2209 | 0 | w *= depth; |
2210 | 0 | } |
2211 | | |
2212 | | |
2213 | | /*--------------------------------------------------------* |
2214 | | * Clip horizontally * |
2215 | | *--------------------------------------------------------*/ |
2216 | 0 | if (x < 0) { |
2217 | 0 | w += x; /* reduce w */ |
2218 | 0 | x = 0; /* clip to x = 0 */ |
2219 | 0 | } |
2220 | 0 | if (x >= pixw || w <= 0) /* no part of vertical slice is in the image */ |
2221 | 0 | return; |
2222 | | |
2223 | 0 | if (x + w > pixw) |
2224 | 0 | w = pixw - x; /* clip to x + w = pixw */ |
2225 | | |
2226 | | /*--------------------------------------------------------* |
2227 | | * Preliminary calculations * |
2228 | | *--------------------------------------------------------*/ |
2229 | | /* is the first word partial? */ |
2230 | 0 | if ((x & 31) == 0) { /* if not */ |
2231 | 0 | fwpartb = 0; |
2232 | 0 | fwbits = 0; |
2233 | 0 | } else { /* if so */ |
2234 | 0 | fwpartb = 1; |
2235 | 0 | fwbits = 32 - (x & 31); |
2236 | 0 | fwmask = rmask32[fwbits]; |
2237 | 0 | if (shift >= 0) { /* go up from bottom */ |
2238 | 0 | pdfwpart = data + wpl * (pixh - 1) + (x >> 5); |
2239 | 0 | psfwpart = data + wpl * (pixh - 1 - shift) + (x >> 5); |
2240 | 0 | } else { /* go down from top */ |
2241 | 0 | pdfwpart = data + (x >> 5); |
2242 | 0 | psfwpart = data - wpl * shift + (x >> 5); |
2243 | 0 | } |
2244 | 0 | } |
2245 | | |
2246 | | /* is the first word doubly partial? */ |
2247 | 0 | if (w >= fwbits) { /* if not */ |
2248 | 0 | fwpart2b = 0; |
2249 | 0 | } else { /* if so */ |
2250 | 0 | fwpart2b = 1; |
2251 | 0 | fwmask &= lmask32[32 - fwbits + w]; |
2252 | 0 | } |
2253 | | |
2254 | | /* is there a full dest word? */ |
2255 | 0 | if (fwpart2b == 1) { /* not */ |
2256 | 0 | fwfullb = 0; |
2257 | 0 | nfullw = 0; |
2258 | 0 | } else { |
2259 | 0 | nfullw = (w - fwbits) >> 5; |
2260 | 0 | if (nfullw == 0) { /* if not */ |
2261 | 0 | fwfullb = 0; |
2262 | 0 | } else { /* if so */ |
2263 | 0 | fwfullb = 1; |
2264 | 0 | if (fwpartb) { |
2265 | 0 | pdfwfull = pdfwpart + 1; |
2266 | 0 | psfwfull = psfwpart + 1; |
2267 | 0 | } else if (shift >= 0) { /* go up from bottom */ |
2268 | 0 | pdfwfull = data + wpl * (pixh - 1) + (x >> 5); |
2269 | 0 | psfwfull = data + wpl * (pixh - 1 - shift) + (x >> 5); |
2270 | 0 | } else { /* go down from top */ |
2271 | 0 | pdfwfull = data + (x >> 5); |
2272 | 0 | psfwfull = data - wpl * shift + (x >> 5); |
2273 | 0 | } |
2274 | 0 | } |
2275 | 0 | } |
2276 | | |
2277 | | /* is the last word partial? */ |
2278 | 0 | lwbits = (x + w) & 31; |
2279 | 0 | if (fwpart2b == 1 || lwbits == 0) { /* if not */ |
2280 | 0 | lwpartb = 0; |
2281 | 0 | } else { |
2282 | 0 | lwpartb = 1; |
2283 | 0 | lwmask = lmask32[lwbits]; |
2284 | 0 | if (fwpartb) { |
2285 | 0 | pdlwpart = pdfwpart + 1 + nfullw; |
2286 | 0 | pslwpart = psfwpart + 1 + nfullw; |
2287 | 0 | } else if (shift >= 0) { /* go up from bottom */ |
2288 | 0 | pdlwpart = data + wpl * (pixh - 1) + (x >> 5) + nfullw; |
2289 | 0 | pslwpart = data + wpl * (pixh - 1 - shift) + (x >> 5) + nfullw; |
2290 | 0 | } else { /* go down from top */ |
2291 | 0 | pdlwpart = data + (x >> 5) + nfullw; |
2292 | 0 | pslwpart = data - wpl * shift + (x >> 5) + nfullw; |
2293 | 0 | } |
2294 | 0 | } |
2295 | | |
2296 | | /* determine the direction of flow from the shift |
2297 | | * If the shift >= 0, data flows downard from src |
2298 | | * to dest, starting at the bottom and working up. |
2299 | | * If shift < 0, data flows upward from src to |
2300 | | * dest, starting at the top and working down. */ |
2301 | 0 | dirwpl = (shift >= 0) ? -wpl : wpl; |
2302 | 0 | absshift = L_ABS(shift); |
2303 | 0 | vlimit = L_MAX(0, pixh - absshift); |
2304 | | |
2305 | | |
2306 | | /*--------------------------------------------------------* |
2307 | | * Now we're ready to do the ops * |
2308 | | *--------------------------------------------------------*/ |
2309 | | |
2310 | | /* Do the first partial word */ |
2311 | 0 | if (fwpartb) { |
2312 | 0 | for (i = 0; i < vlimit; i++) { |
2313 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, fwmask); |
2314 | 0 | pdfwpart += dirwpl; |
2315 | 0 | psfwpart += dirwpl; |
2316 | 0 | } |
2317 | | |
2318 | | /* Clear the incoming pixels */ |
2319 | 0 | for (i = vlimit; i < pixh; i++) { |
2320 | 0 | *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, fwmask); |
2321 | 0 | pdfwpart += dirwpl; |
2322 | 0 | } |
2323 | 0 | } |
2324 | | |
2325 | | /* Do the full words */ |
2326 | 0 | if (fwfullb) { |
2327 | 0 | for (i = 0; i < vlimit; i++) { |
2328 | 0 | for (j = 0; j < nfullw; j++) |
2329 | 0 | *(pdfwfull + j) = *(psfwfull + j); |
2330 | 0 | pdfwfull += dirwpl; |
2331 | 0 | psfwfull += dirwpl; |
2332 | 0 | } |
2333 | | |
2334 | | /* Clear the incoming pixels */ |
2335 | 0 | for (i = vlimit; i < pixh; i++) { |
2336 | 0 | for (j = 0; j < nfullw; j++) |
2337 | 0 | *(pdfwfull + j) = 0x0; |
2338 | 0 | pdfwfull += dirwpl; |
2339 | 0 | } |
2340 | 0 | } |
2341 | | |
2342 | | /* Do the last partial word */ |
2343 | 0 | if (lwpartb) { |
2344 | 0 | for (i = 0; i < vlimit; i++) { |
2345 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, lwmask); |
2346 | 0 | pdlwpart += dirwpl; |
2347 | 0 | pslwpart += dirwpl; |
2348 | 0 | } |
2349 | | |
2350 | | /* Clear the incoming pixels */ |
2351 | 0 | for (i = vlimit; i < pixh; i++) { |
2352 | 0 | *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, lwmask); |
2353 | 0 | pdlwpart += dirwpl; |
2354 | 0 | } |
2355 | 0 | } |
2356 | 0 | } |
2357 | | |
2358 | | |
2359 | | |
2360 | | /*--------------------------------------------------------------------* |
2361 | | * Low level in-place full width horizontal block transfer * |
2362 | | *--------------------------------------------------------------------*/ |
2363 | | /*! |
2364 | | * \brief rasteropHipLow() |
2365 | | * |
2366 | | * \param[in] data ptr to image data |
2367 | | * \param[in] pixh height |
2368 | | * \param[in] depth depth |
2369 | | * \param[in] wpl wpl |
2370 | | * \param[in] y y val of UL corner of rectangle |
2371 | | * \param[in] h height of rectangle |
2372 | | * \param[in] shift + shifts data to the left in a horizontal column |
2373 | | * \return 0 if OK; 1 on error. |
2374 | | * |
2375 | | * <pre> |
2376 | | * Notes: |
2377 | | * (1) This clears the pixels that are left exposed after the rasterop. |
2378 | | * Therefore, for Pix with depth > 1, these pixels become black, |
2379 | | * and must be subsequently SET if they are to be white. |
2380 | | * For example, see pixRasteropHip(). |
2381 | | * (2) This function performs clipping and calls shiftDataHorizontalLow() |
2382 | | * to do the in-place rasterop on each line. |
2383 | | * </pre> |
2384 | | */ |
2385 | | void |
2386 | | rasteropHipLow(l_uint32 *data, |
2387 | | l_int32 pixh, |
2388 | | l_int32 depth, |
2389 | | l_int32 wpl, |
2390 | | l_int32 y, |
2391 | | l_int32 h, |
2392 | | l_int32 shift) |
2393 | 4 | { |
2394 | 4 | l_int32 i; |
2395 | 4 | l_uint32 *line; |
2396 | | |
2397 | | /* clip band if necessary */ |
2398 | 4 | if (y < 0) { |
2399 | 0 | h += y; /* reduce h */ |
2400 | 0 | y = 0; /* clip to y = 0 */ |
2401 | 0 | } |
2402 | 4 | if (h <= 0 || y > pixh) /* no part of horizontal slice is in the image */ |
2403 | 0 | return; |
2404 | | |
2405 | 4 | if (y + h > pixh) |
2406 | 0 | h = pixh - y; /* clip to y + h = pixh */ |
2407 | | |
2408 | 220 | for (i = y; i < y + h; i++) { |
2409 | 216 | line = data + i * wpl; |
2410 | 216 | shiftDataHorizontalLow(line, wpl, line, wpl, shift * depth); |
2411 | 216 | } |
2412 | 4 | } |
2413 | | |
2414 | | |
2415 | | /*! |
2416 | | * \brief shiftDataHorizontalLow() |
2417 | | * |
2418 | | * \param[in] datad ptr to beginning of dest line |
2419 | | * \param[in] wpld wpl of dest |
2420 | | * \param[in] datas ptr to beginning of src line |
2421 | | * \param[in] wpls wpl of src |
2422 | | * \param[in] shift horizontal shift of block; >0 is to right |
2423 | | * \return void |
2424 | | * |
2425 | | * <pre> |
2426 | | * Notes: |
2427 | | * (1) This can also be used for in-place operation; see, e.g., |
2428 | | * rasteropHipLow(). |
2429 | | * (2) We are clearing the pixels that are shifted in from |
2430 | | * outside the image. This can be overridden by the |
2431 | | * incolor parameter in higher-level functions that call this. |
2432 | | * </pre> |
2433 | | */ |
2434 | | static void |
2435 | | shiftDataHorizontalLow(l_uint32 *datad, |
2436 | | l_int32 wpld, |
2437 | | l_uint32 *datas, |
2438 | | l_int32 wpls, |
2439 | | l_int32 shift) |
2440 | 216 | { |
2441 | 216 | l_int32 j, firstdw, wpl, rshift, lshift; |
2442 | 216 | l_uint32 *lined, *lines; |
2443 | | |
2444 | 216 | lined = datad; |
2445 | 216 | lines = datas; |
2446 | | |
2447 | 216 | if (shift >= 0) { /* src shift to right; data flows to |
2448 | | * right, starting at right edge and |
2449 | | * progressing leftward. */ |
2450 | 216 | firstdw = shift / 32; |
2451 | 216 | wpl = L_MIN(wpls, wpld - firstdw); |
2452 | 216 | lined += firstdw + wpl - 1; |
2453 | 216 | lines += wpl - 1; |
2454 | 216 | rshift = shift & 31; |
2455 | 216 | if (rshift == 0) { |
2456 | 0 | for (j = 0; j < wpl; j++) |
2457 | 0 | *lined-- = *lines--; |
2458 | | |
2459 | | /* clear out the rest to the left edge */ |
2460 | 0 | for (j = 0; j < firstdw; j++) |
2461 | 0 | *lined-- = 0; |
2462 | 216 | } else { |
2463 | 216 | lshift = 32 - rshift; |
2464 | 216 | for (j = 1; j < wpl; j++) { |
2465 | 0 | *lined-- = *(lines - 1) << lshift | *lines >> rshift; |
2466 | 0 | lines--; |
2467 | 0 | } |
2468 | 216 | *lined = *lines >> rshift; /* partial first */ |
2469 | | |
2470 | | /* clear out the rest to the left edge */ |
2471 | 216 | *lined &= ~lmask32[rshift]; |
2472 | 216 | lined--; |
2473 | 216 | for (j = 0; j < firstdw; j++) |
2474 | 0 | *lined-- = 0; |
2475 | 216 | } |
2476 | 216 | } else { /* src shift to left; data flows to left, starting |
2477 | | * at left edge and progressing rightward. */ |
2478 | 0 | firstdw = (-shift) / 32; |
2479 | 0 | wpl = L_MIN(wpls - firstdw, wpld); |
2480 | 0 | lines += firstdw; |
2481 | 0 | lshift = (-shift) & 31; |
2482 | 0 | if (lshift == 0) { |
2483 | 0 | for (j = 0; j < wpl; j++) |
2484 | 0 | *lined++ = *lines++; |
2485 | | |
2486 | | /* clear out the rest to the right edge */ |
2487 | 0 | for (j = 0; j < firstdw; j++) |
2488 | 0 | *lined++ = 0; |
2489 | 0 | } else { |
2490 | 0 | rshift = 32 - lshift; |
2491 | 0 | for (j = 1; j < wpl; j++) { |
2492 | 0 | *lined++ = *lines << lshift | *(lines + 1) >> rshift; |
2493 | 0 | lines++; |
2494 | 0 | } |
2495 | 0 | *lined = *lines << lshift; /* partial last */ |
2496 | | |
2497 | | /* clear out the rest to the right edge */ |
2498 | | /* first clear the lshift pixels of this partial word */ |
2499 | 0 | *lined &= ~rmask32[lshift]; |
2500 | 0 | lined++; |
2501 | | /* then the remaining words to the right edge */ |
2502 | 0 | for (j = 0; j < firstdw; j++) |
2503 | 0 | *lined++ = 0; |
2504 | 0 | } |
2505 | 0 | } |
2506 | 216 | } |