1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16 /*
17 * roplow.c
18 *
19 * Low level dest-only
20 * void rasteropUniLow()
21 * static void rasteropUniWordAlignedlLow()
22 * static void rasteropUniGeneralLow()
23 *
24 * Low level src and dest
25 * void rasteropLow()
26 * static void rasteropWordAlignedLow()
27 * static void rasteropVAlignedLow()
28 * static void rasteropGeneralLow()
29 *
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "allheaders.h"
36
37 #define COMBINE_PARTIAL(d, s, m) ( ((d) & ~(m)) | ((s) & (m)) )
38
39 static const l_int32 SHIFT_LEFT = 0;
40 static const l_int32 SHIFT_RIGHT = 1;
41
42 static void rasteropUniWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
43 l_int32 dy, l_int32 dw, l_int32 dh,
44 l_int32 op);
45
46 static void rasteropUniGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
47 l_int32 dy, l_int32 dw, l_int32 dh,
48 l_int32 op);
49
50 static void rasteropWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
51 l_int32 dy, l_int32 dw, l_int32 dh,
52 l_int32 op, l_uint32 *datas, l_int32 swpl,
53 l_int32 sx, l_int32 sy);
54
55 static void rasteropVAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
56 l_int32 dy, l_int32 dw, l_int32 dh,
57 l_int32 op, l_uint32 *datas, l_int32 swpl,
58 l_int32 sx, l_int32 sy);
59
60 static void rasteropGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
61 l_int32 dy, l_int32 dw, l_int32 dh,
62 l_int32 op, l_uint32 *datas, l_int32 swpl,
63 l_int32 sx, l_int32 sy);
64
65
66 static const l_uint32 lmask32[] = {0x0,
67 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
68 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
69 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
70 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
71 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
72 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
73 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
74 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff};
75
76 static const l_uint32 rmask32[] = {0x0,
77 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
78 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
79 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
80 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
81 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
82 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
83 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
84 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
85
86
87 /*--------------------------------------------------------------------*
88 * Low-level dest-only rasterops *
89 *--------------------------------------------------------------------*/
90 /*!
91 * rasteropUniLow()
92 *
93 * Input: datad (ptr to dest image data)
94 * dpixw (width of dest)
95 * dpixh (height of dest)
96 * depth (depth of src and dest)
97 * dwpl (wpl of dest)
98 * dx (x val of UL corner of dest rectangle)
99 * dy (y val of UL corner of dest rectangle)
100 * dw (width of dest rectangle)
101 * dh (height of dest rectangle)
102 * op (op code)
103 * Return: void
104 *
105 * Action: scales width, performs clipping, checks alignment, and
106 * dispatches for the rasterop.
107 */
108 void
rasteropUniLow(l_uint32 * datad,l_int32 dpixw,l_int32 dpixh,l_int32 depth,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op)109 rasteropUniLow(l_uint32 *datad,
110 l_int32 dpixw,
111 l_int32 dpixh,
112 l_int32 depth,
113 l_int32 dwpl,
114 l_int32 dx,
115 l_int32 dy,
116 l_int32 dw,
117 l_int32 dh,
118 l_int32 op)
119 {
120 l_int32 dhangw, dhangh;
121
122 /* -------------------------------------------------------*
123 * scale horizontal dimensions by depth
124 * -------------------------------------------------------*/
125 if (depth != 1) {
126 dpixw *= depth;
127 dx *= depth;
128 dw *= depth;
129 }
130
131 /* -------------------------------------------------------*
132 * clip rectangle to dest image
133 * -------------------------------------------------------*/
134 /* first, clip horizontally (dx, dw) */
135 if (dx < 0) {
136 dw += dx; /* reduce dw */
137 dx = 0;
138 }
139 dhangw = dx + dw - dpixw; /* rect ovhang dest to right */
140 if (dhangw > 0)
141 dw -= dhangw; /* reduce dw */
142
143 /* then, clip vertically (dy, dh) */
144 if (dy < 0) {
145 dh += dy; /* reduce dh */
146 dy = 0;
147 }
148 dhangh = dy + dh - dpixh; /* rect ovhang dest below */
149 if (dhangh > 0)
150 dh -= dhangh; /* reduce dh */
151
152 /* if clipped entirely, quit */
153 if ((dw <= 0) || (dh <= 0))
154 return;
155
156 /* -------------------------------------------------------*
157 * dispatch to aligned or non-aligned blitters
158 * -------------------------------------------------------*/
159 if ((dx & 31) == 0)
160 rasteropUniWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op);
161 else
162 rasteropUniGeneralLow(datad, dwpl, dx, dy, dw, dh, op);
163 return;
164 }
165
166
167
168 /*--------------------------------------------------------------------*
169 * Static low-level uni rasterop with word alignment *
170 *--------------------------------------------------------------------*/
171 /*!
172 * rasteropUniWordAlignedLow()
173 *
174 * Input: datad (ptr to dest image data)
175 * dwpl (wpl of dest)
176 * dx (x val of UL corner of dest rectangle)
177 * dy (y val of UL corner of dest rectangle)
178 * dw (width of dest rectangle)
179 * dh (height of dest rectangle)
180 * op (op code)
181 * Return: void
182 *
183 * This is called when the dest rect is left aligned
184 * on (32-bit) word boundaries. That is: dx & 31 == 0.
185 *
186 * We make an optimized implementation of this because
187 * it is a common case: e.g., operating on a full dest image.
188 */
189 static void
rasteropUniWordAlignedLow(l_uint32 * datad,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op)190 rasteropUniWordAlignedLow(l_uint32 *datad,
191 l_int32 dwpl,
192 l_int32 dx,
193 l_int32 dy,
194 l_int32 dw,
195 l_int32 dh,
196 l_int32 op)
197 {
198 l_int32 nfullw; /* number of full words */
199 l_uint32 *pfword; /* ptr to first word */
200 l_int32 lwbits; /* number of ovrhang bits in last partial word */
201 l_uint32 lwmask; /* mask for last partial word */
202 l_uint32 *lined;
203 l_int32 i, j;
204
205 /*--------------------------------------------------------*
206 * Preliminary calculations *
207 *--------------------------------------------------------*/
208 nfullw = dw >> 5;
209 lwbits = dw & 31;
210 if (lwbits)
211 lwmask = lmask32[lwbits];
212 pfword = datad + dwpl * dy + (dx >> 5);
213
214
215 /*--------------------------------------------------------*
216 * Now we're ready to do the ops *
217 *--------------------------------------------------------*/
218 switch (op)
219 {
220 case PIX_CLR:
221 for (i = 0; i < dh; i++) {
222 lined = pfword + i * dwpl;
223 for (j = 0; j < nfullw; j++)
224 *lined++ = 0x0;
225 if (lwbits)
226 *lined = COMBINE_PARTIAL(*lined, 0x0, lwmask);
227 }
228 break;
229 case PIX_SET:
230 for (i = 0; i < dh; i++) {
231 lined = pfword + i * dwpl;
232 for (j = 0; j < nfullw; j++)
233 *lined++ = 0xffffffff;
234 if (lwbits)
235 *lined = COMBINE_PARTIAL(*lined, 0xffffffff, lwmask);
236 }
237 break;
238 case PIX_NOT(PIX_DST):
239 for (i = 0; i < dh; i++) {
240 lined = pfword + i * dwpl;
241 for (j = 0; j < nfullw; j++) {
242 *lined = ~(*lined);
243 lined++;
244 }
245 if (lwbits)
246 *lined = COMBINE_PARTIAL(*lined, ~(*lined), lwmask);
247 }
248 break;
249 default:
250 fprintf(stderr, "Operation %d not permitted here!\n", op);
251 }
252
253 return;
254 }
255
256
257 /*--------------------------------------------------------------------*
258 * Static low-level uni rasterop without word alignment *
259 *--------------------------------------------------------------------*/
260 /*!
261 * rasteropUniGeneralLow()
262 *
263 * Input: datad (ptr to dest image data)
264 * dwpl (wpl of dest)
265 * dx (x val of UL corner of dest rectangle)
266 * dy (y val of UL corner of dest rectangle)
267 * dw (width of dest rectangle)
268 * dh (height of dest rectangle)
269 * op (op code)
270 * Return: void
271 */
272 static void
rasteropUniGeneralLow(l_uint32 * datad,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op)273 rasteropUniGeneralLow(l_uint32 *datad,
274 l_int32 dwpl,
275 l_int32 dx,
276 l_int32 dy,
277 l_int32 dw,
278 l_int32 dh,
279 l_int32 op)
280 {
281 l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
282 l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */
283 l_uint32 dfwmask; /* mask for first partial dest word */
284 l_int32 dfwbits; /* first word dest bits in ovrhang */
285 l_uint32 *pdfwpart; /* ptr to first partial dest word */
286 l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
287 l_int32 dnfullw; /* number of full words in dest */
288 l_uint32 *pdfwfull; /* ptr to first full dest word */
289 l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
290 l_uint32 dlwmask; /* mask for last partial dest word */
291 l_int32 dlwbits; /* last word dest bits in ovrhang */
292 l_uint32 *pdlwpart; /* ptr to last partial dest word */
293 l_int32 i, j;
294
295
296 /*--------------------------------------------------------*
297 * Preliminary calculations *
298 *--------------------------------------------------------*/
299 /* is the first word partial? */
300 if ((dx & 31) == 0) { /* if not */
301 dfwpartb = 0;
302 dfwbits = 0;
303 }
304 else { /* if so */
305 dfwpartb = 1;
306 dfwbits = 32 - (dx & 31);
307 dfwmask = rmask32[dfwbits];
308 pdfwpart = datad + dwpl * dy + (dx >> 5);
309 }
310
311 /* is the first word doubly partial? */
312 if (dw >= dfwbits) /* if not */
313 dfwpart2b = 0;
314 else { /* if so */
315 dfwpart2b = 1;
316 dfwmask &= lmask32[32 - dfwbits + dw];
317 }
318
319 /* is there a full dest word? */
320 if (dfwpart2b == 1) { /* not */
321 dfwfullb = 0;
322 dnfullw = 0;
323 }
324 else {
325 dnfullw = (dw - dfwbits) >> 5;
326 if (dnfullw == 0) /* if not */
327 dfwfullb = 0;
328 else { /* if so */
329 dfwfullb = 1;
330 if (dfwpartb)
331 pdfwfull = pdfwpart + 1;
332 else
333 pdfwfull = datad + dwpl * dy + (dx >> 5);
334 }
335 }
336
337 /* is the last word partial? */
338 dlwbits = (dx + dw) & 31;
339 if (dfwpart2b == 1 || dlwbits == 0) /* if not */
340 dlwpartb = 0;
341 else {
342 dlwpartb = 1;
343 dlwmask = lmask32[dlwbits];
344 if (dfwpartb)
345 pdlwpart = pdfwpart + 1 + dnfullw;
346 else
347 pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw;
348 }
349
350
351 /*--------------------------------------------------------*
352 * Now we're ready to do the ops *
353 *--------------------------------------------------------*/
354 switch (op)
355 {
356 case PIX_CLR:
357 /* do the first partial word */
358 if (dfwpartb) {
359 for (i = 0; i < dh; i++) {
360 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, dfwmask);
361 pdfwpart += dwpl;
362 }
363 }
364
365 /* do the full words */
366 if (dfwfullb) {
367 for (i = 0; i < dh; i++) {
368 for (j = 0; j < dnfullw; j++)
369 *(pdfwfull + j) = 0x0;
370 pdfwfull += dwpl;
371 }
372 }
373
374 /* do the last partial word */
375 if (dlwpartb) {
376 for (i = 0; i < dh; i++) {
377 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, dlwmask);
378 pdlwpart += dwpl;
379 }
380 }
381 break;
382 case PIX_SET:
383 /* do the first partial word */
384 if (dfwpartb) {
385 for (i = 0; i < dh; i++) {
386 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0xffffffff, dfwmask);
387 pdfwpart += dwpl;
388 }
389 }
390
391 /* do the full words */
392 if (dfwfullb) {
393 for (i = 0; i < dh; i++) {
394 for (j = 0; j < dnfullw; j++)
395 *(pdfwfull + j) = 0xffffffff;
396 pdfwfull += dwpl;
397 }
398 }
399
400 /* do the last partial word */
401 if (dlwpartb) {
402 for (i = 0; i < dh; i++) {
403 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0xffffffff, dlwmask);
404 pdlwpart += dwpl;
405 }
406 }
407 break;
408 case PIX_NOT(PIX_DST):
409 /* do the first partial word */
410 if (dfwpartb) {
411 for (i = 0; i < dh; i++) {
412 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*pdfwpart), dfwmask);
413 pdfwpart += dwpl;
414 }
415 }
416
417 /* do the full words */
418 if (dfwfullb) {
419 for (i = 0; i < dh; i++) {
420 for (j = 0; j < dnfullw; j++)
421 *(pdfwfull + j) = ~(*(pdfwfull + j));
422 pdfwfull += dwpl;
423 }
424 }
425
426 /* do the last partial word */
427 if (dlwpartb) {
428 for (i = 0; i < dh; i++) {
429 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pdlwpart), dlwmask);
430 pdlwpart += dwpl;
431 }
432 }
433 break;
434 default:
435 fprintf(stderr, "Operation %d not permitted here!\n", op);
436 }
437
438 return;
439 }
440
441
442
443 /*--------------------------------------------------------------------*
444 * Low-level src and dest rasterops *
445 *--------------------------------------------------------------------*/
446 /*!
447 * rasteropLow()
448 *
449 * Input: datad (ptr to dest image data)
450 * dpixw (width of dest)
451 * dpixh (height of dest)
452 * depth (depth of src and dest)
453 * dwpl (wpl of dest)
454 * dx (x val of UL corner of dest rectangle)
455 * dy (y val of UL corner of dest rectangle)
456 * dw (width of dest rectangle)
457 * dh (height of dest rectangle)
458 * op (op code)
459 * datas (ptr to src image data)
460 * spixw (width of src)
461 * spixh (height of src)
462 * swpl (wpl of src)
463 * sx (x val of UL corner of src rectangle)
464 * sy (y val of UL corner of src rectangle)
465 * Return: void
466 *
467 * Action: Scales width, performs clipping, checks alignment, and
468 * dispatches for the rasterop.
469 *
470 * Warning: the two images must have equal depth. This is not checked.
471 */
472 void
rasteropLow(l_uint32 * datad,l_int32 dpixw,l_int32 dpixh,l_int32 depth,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op,l_uint32 * datas,l_int32 spixw,l_int32 spixh,l_int32 swpl,l_int32 sx,l_int32 sy)473 rasteropLow(l_uint32 *datad,
474 l_int32 dpixw,
475 l_int32 dpixh,
476 l_int32 depth,
477 l_int32 dwpl,
478 l_int32 dx,
479 l_int32 dy,
480 l_int32 dw,
481 l_int32 dh,
482 l_int32 op,
483 l_uint32 *datas,
484 l_int32 spixw,
485 l_int32 spixh,
486 l_int32 swpl,
487 l_int32 sx,
488 l_int32 sy)
489 {
490 l_int32 dhangw, shangw, dhangh, shangh;
491
492 /* -------------------------------------------------------*
493 * scale horizontal dimensions by depth
494 * -------------------------------------------------------*/
495 if (depth != 1) {
496 dpixw *= depth;
497 dx *= depth;
498 dw *= depth;
499 spixw *= depth;
500 sx *= depth;
501 }
502
503
504 /* -------------------------------------------------------*
505 * clip to max rectangle within both src and dest
506 * -------------------------------------------------------*/
507 /* first, clip horizontally (sx, dx, dw) */
508 if (dx < 0) {
509 sx -= dx; /* increase sx */
510 dw += dx; /* reduce dw */
511 dx = 0;
512 }
513 if (sx < 0) {
514 dx -= sx; /* increase dx */
515 dw += sx; /* reduce dw */
516 sx = 0;
517 }
518 dhangw = dx + dw - dpixw; /* rect ovhang dest to right */
519 if (dhangw > 0)
520 dw -= dhangw; /* reduce dw */
521 shangw = sx + dw - spixw; /* rect ovhang src to right */
522 if (shangw > 0)
523 dw -= shangw; /* reduce dw */
524
525 /* then, clip vertically (sy, dy, dh) */
526 if (dy < 0) {
527 sy -= dy; /* increase sy */
528 dh += dy; /* reduce dh */
529 dy = 0;
530 }
531 if (sy < 0) {
532 dy -= sy; /* increase dy */
533 dh += sy; /* reduce dh */
534 sy = 0;
535 }
536 dhangh = dy + dh - dpixh; /* rect ovhang dest below */
537 if (dhangh > 0)
538 dh -= dhangh; /* reduce dh */
539 shangh = sy + dh - spixh; /* rect ovhang src below */
540 if (shangh > 0)
541 dh -= shangh; /* reduce dh */
542
543 /* if clipped entirely, quit */
544 if ((dw <= 0) || (dh <= 0))
545 return;
546
547 /* -------------------------------------------------------*
548 * dispatch to aligned or non-aligned blitters
549 * -------------------------------------------------------*/
550 if (((dx & 31) == 0) && ((sx & 31) == 0))
551 rasteropWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op,
552 datas, swpl, sx, sy);
553 else if ((dx & 31) == (sx & 31))
554 rasteropVAlignedLow(datad, dwpl, dx, dy, dw, dh, op,
555 datas, swpl, sx, sy);
556 else
557 rasteropGeneralLow(datad, dwpl, dx, dy, dw, dh, op,
558 datas, swpl, sx, sy);
559
560 return;
561 }
562
563
564 /*--------------------------------------------------------------------*
565 * Static low-level rasterop with vertical word alignment *
566 *--------------------------------------------------------------------*/
567 /*!
568 * rasteropWordAlignedLow()
569 *
570 * Input: datad (ptr to dest image data)
571 * dwpl (wpl of dest)
572 * dx (x val of UL corner of dest rectangle)
573 * dy (y val of UL corner of dest rectangle)
574 * dw (width of dest rectangle)
575 * dh (height of dest rectangle)
576 * op (op code)
577 * datas (ptr to src image data)
578 * swpl (wpl of src)
579 * sx (x val of UL corner of src rectangle)
580 * sy (y val of UL corner of src rectangle)
581 * Return: void
582 *
583 * This is called when both the src and dest rects
584 * are left aligned on (32-bit) word boundaries.
585 * That is: dx & 31 == 0 and sx & 31 == 0
586 *
587 * We make an optimized implementation of this because
588 * it is a common case: e.g., two images are rasterop'd
589 * starting from their UL corners (0,0).
590 */
591 static void
rasteropWordAlignedLow(l_uint32 * datad,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op,l_uint32 * datas,l_int32 swpl,l_int32 sx,l_int32 sy)592 rasteropWordAlignedLow(l_uint32 *datad,
593 l_int32 dwpl,
594 l_int32 dx,
595 l_int32 dy,
596 l_int32 dw,
597 l_int32 dh,
598 l_int32 op,
599 l_uint32 *datas,
600 l_int32 swpl,
601 l_int32 sx,
602 l_int32 sy)
603 {
604 l_int32 nfullw; /* number of full words */
605 l_uint32 *psfword; /* ptr to first src word */
606 l_uint32 *pdfword; /* ptr to first dest word */
607 l_int32 lwbits; /* number of ovrhang bits in last partial word */
608 l_uint32 lwmask; /* mask for last partial word */
609 l_uint32 *lines, *lined;
610 l_int32 i, j;
611
612
613 /*--------------------------------------------------------*
614 * Preliminary calculations *
615 *--------------------------------------------------------*/
616 nfullw = dw >> 5;
617 lwbits = dw & 31;
618 if (lwbits)
619 lwmask = lmask32[lwbits];
620 psfword = datas + swpl * sy + (sx >> 5);
621 pdfword = datad + dwpl * dy + (dx >> 5);
622
623 /*--------------------------------------------------------*
624 * Now we're ready to do the ops *
625 *--------------------------------------------------------*/
626 switch (op)
627 {
628 case PIX_SRC:
629 for (i = 0; i < dh; i++) {
630 lines = psfword + i * swpl;
631 lined = pdfword + i * dwpl;
632 for (j = 0; j < nfullw; j++) {
633 *lined = *lines;
634 lined++;
635 lines++;
636 }
637 if (lwbits)
638 *lined = COMBINE_PARTIAL(*lined, *lines, lwmask);
639 }
640 break;
641 case PIX_NOT(PIX_SRC):
642 for (i = 0; i < dh; i++) {
643 lines = psfword + i * swpl;
644 lined = pdfword + i * dwpl;
645 for (j = 0; j < nfullw; j++) {
646 *lined = ~(*lines);
647 lined++;
648 lines++;
649 }
650 if (lwbits)
651 *lined = COMBINE_PARTIAL(*lined, ~(*lines), lwmask);
652 }
653 break;
654 case (PIX_SRC | PIX_DST):
655 for (i = 0; i < dh; i++) {
656 lines = psfword + i * swpl;
657 lined = pdfword + i * dwpl;
658 for (j = 0; j < nfullw; j++) {
659 *lined = (*lines | *lined);
660 lined++;
661 lines++;
662 }
663 if (lwbits)
664 *lined = COMBINE_PARTIAL(*lined, (*lines | *lined), lwmask);
665 }
666 break;
667 case (PIX_SRC & PIX_DST):
668 for (i = 0; i < dh; i++) {
669 lines = psfword + i * swpl;
670 lined = pdfword + i * dwpl;
671 for (j = 0; j < nfullw; j++) {
672 *lined = (*lines & *lined);
673 lined++;
674 lines++;
675 }
676 if (lwbits)
677 *lined = COMBINE_PARTIAL(*lined, (*lines & *lined), lwmask);
678 }
679 break;
680 case (PIX_SRC ^ PIX_DST):
681 for (i = 0; i < dh; i++) {
682 lines = psfword + i * swpl;
683 lined = pdfword + i * dwpl;
684 for (j = 0; j < nfullw; j++) {
685 *lined = (*lines ^ *lined);
686 lined++;
687 lines++;
688 }
689 if (lwbits)
690 *lined = COMBINE_PARTIAL(*lined, (*lines ^ *lined), lwmask);
691 }
692 break;
693 case (PIX_NOT(PIX_SRC) | PIX_DST):
694 for (i = 0; i < dh; i++) {
695 lines = psfword + i * swpl;
696 lined = pdfword + i * dwpl;
697 for (j = 0; j < nfullw; j++) {
698 *lined = (~(*lines) | *lined);
699 lined++;
700 lines++;
701 }
702 if (lwbits)
703 *lined = COMBINE_PARTIAL(*lined, (~(*lines) | *lined), lwmask);
704 }
705 break;
706 case (PIX_NOT(PIX_SRC) & PIX_DST):
707 for (i = 0; i < dh; i++) {
708 lines = psfword + i * swpl;
709 lined = pdfword + i * dwpl;
710 for (j = 0; j < nfullw; j++) {
711 *lined = (~(*lines) & *lined);
712 lined++;
713 lines++;
714 }
715 if (lwbits)
716 *lined = COMBINE_PARTIAL(*lined, (~(*lines) & *lined), lwmask);
717 }
718 break;
719 case (PIX_SRC | PIX_NOT(PIX_DST)):
720 for (i = 0; i < dh; i++) {
721 lines = psfword + i * swpl;
722 lined = pdfword + i * dwpl;
723 for (j = 0; j < nfullw; j++) {
724 *lined = (*lines | ~(*lined));
725 lined++;
726 lines++;
727 }
728 if (lwbits)
729 *lined = COMBINE_PARTIAL(*lined, (*lines | ~(*lined)), lwmask);
730 }
731 break;
732 case (PIX_SRC & PIX_NOT(PIX_DST)):
733 for (i = 0; i < dh; i++) {
734 lines = psfword + i * swpl;
735 lined = pdfword + i * dwpl;
736 for (j = 0; j < nfullw; j++) {
737 *lined = (*lines & ~(*lined));
738 lined++;
739 lines++;
740 }
741 if (lwbits)
742 *lined = COMBINE_PARTIAL(*lined, (*lines & ~(*lined)), lwmask);
743 }
744 break;
745 case (PIX_NOT(PIX_SRC | PIX_DST)):
746 for (i = 0; i < dh; i++) {
747 lines = psfword + i * swpl;
748 lined = pdfword + i * dwpl;
749 for (j = 0; j < nfullw; j++) {
750 *lined = ~(*lines | *lined);
751 lined++;
752 lines++;
753 }
754 if (lwbits)
755 *lined = COMBINE_PARTIAL(*lined, ~(*lines | *lined), lwmask);
756 }
757 break;
758 case (PIX_NOT(PIX_SRC & PIX_DST)):
759 for (i = 0; i < dh; i++) {
760 lines = psfword + i * swpl;
761 lined = pdfword + i * dwpl;
762 for (j = 0; j < nfullw; j++) {
763 *lined = ~(*lines & *lined);
764 lined++;
765 lines++;
766 }
767 if (lwbits)
768 *lined = COMBINE_PARTIAL(*lined, ~(*lines & *lined), lwmask);
769 }
770 break;
771 /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
772 case (PIX_NOT(PIX_SRC ^ PIX_DST)):
773 for (i = 0; i < dh; i++) {
774 lines = psfword + i * swpl;
775 lined = pdfword + i * dwpl;
776 for (j = 0; j < nfullw; j++) {
777 *lined = ~(*lines ^ *lined);
778 lined++;
779 lines++;
780 }
781 if (lwbits)
782 *lined = COMBINE_PARTIAL(*lined, ~(*lines ^ *lined), lwmask);
783 }
784 break;
785 default:
786 fprintf(stderr, "Operation %d invalid\n", op);
787 }
788
789 return;
790 }
791
792
793
794 /*--------------------------------------------------------------------*
795 * Static low-level rasterop with vertical word alignment *
796 *--------------------------------------------------------------------*/
797 /*!
798 * rasteropVAlignedLow()
799 *
800 * Input: datad (ptr to dest image data)
801 * dwpl (wpl of dest)
802 * dx (x val of UL corner of dest rectangle)
803 * dy (y val of UL corner of dest rectangle)
804 * dw (width of dest rectangle)
805 * dh (height of dest rectangle)
806 * op (op code)
807 * datas (ptr to src image data)
808 * swpl (wpl of src)
809 * sx (x val of UL corner of src rectangle)
810 * sy (y val of UL corner of src rectangle)
811 * Return: void
812 *
813 * This is called when the left side of the src and dest
814 * rects have the same alignment relative to (32-bit) word
815 * boundaries; i.e., (dx & 31) == (sx & 31)
816 */
817 static void
rasteropVAlignedLow(l_uint32 * datad,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op,l_uint32 * datas,l_int32 swpl,l_int32 sx,l_int32 sy)818 rasteropVAlignedLow(l_uint32 *datad,
819 l_int32 dwpl,
820 l_int32 dx,
821 l_int32 dy,
822 l_int32 dw,
823 l_int32 dh,
824 l_int32 op,
825 l_uint32 *datas,
826 l_int32 swpl,
827 l_int32 sx,
828 l_int32 sy)
829 {
830 l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
831 l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */
832 l_uint32 dfwmask; /* mask for first partial dest word */
833 l_int32 dfwbits; /* first word dest bits in ovrhang */
834 l_uint32 *pdfwpart; /* ptr to first partial dest word */
835 l_uint32 *psfwpart; /* ptr to first partial src word */
836 l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
837 l_int32 dnfullw; /* number of full words in dest */
838 l_uint32 *pdfwfull; /* ptr to first full dest word */
839 l_uint32 *psfwfull; /* ptr to first full src word */
840 l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
841 l_uint32 dlwmask; /* mask for last partial dest word */
842 l_int32 dlwbits; /* last word dest bits in ovrhang */
843 l_uint32 *pdlwpart; /* ptr to last partial dest word */
844 l_uint32 *pslwpart; /* ptr to last partial src word */
845 l_int32 i, j;
846
847
848 /*--------------------------------------------------------*
849 * Preliminary calculations *
850 *--------------------------------------------------------*/
851 /* is the first word partial? */
852 if ((dx & 31) == 0) { /* if not */
853 dfwpartb = 0;
854 dfwbits = 0;
855 }
856 else { /* if so */
857 dfwpartb = 1;
858 dfwbits = 32 - (dx & 31);
859 dfwmask = rmask32[dfwbits];
860 pdfwpart = datad + dwpl * dy + (dx >> 5);
861 psfwpart = datas + swpl * sy + (sx >> 5);
862 }
863
864 /* is the first word doubly partial? */
865 if (dw >= dfwbits) /* if not */
866 dfwpart2b = 0;
867 else { /* if so */
868 dfwpart2b = 1;
869 dfwmask &= lmask32[32 - dfwbits + dw];
870 }
871
872 /* is there a full dest word? */
873 if (dfwpart2b == 1) { /* not */
874 dfwfullb = 0;
875 dnfullw = 0;
876 }
877 else {
878 dnfullw = (dw - dfwbits) >> 5;
879 if (dnfullw == 0) /* if not */
880 dfwfullb = 0;
881 else { /* if so */
882 dfwfullb = 1;
883 if (dfwpartb) {
884 pdfwfull = pdfwpart + 1;
885 psfwfull = psfwpart + 1;
886 }
887 else {
888 pdfwfull = datad + dwpl * dy + (dx >> 5);
889 psfwfull = datas + swpl * sy + (sx >> 5);
890 }
891 }
892 }
893
894 /* is the last word partial? */
895 dlwbits = (dx + dw) & 31;
896 if (dfwpart2b == 1 || dlwbits == 0) /* if not */
897 dlwpartb = 0;
898 else {
899 dlwpartb = 1;
900 dlwmask = lmask32[dlwbits];
901 if (dfwpartb) {
902 pdlwpart = pdfwpart + 1 + dnfullw;
903 pslwpart = psfwpart + 1 + dnfullw;
904 }
905 else {
906 pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw;
907 pslwpart = datas + swpl * sy + (sx >> 5) + dnfullw;
908 }
909 }
910
911
912 /*--------------------------------------------------------*
913 * Now we're ready to do the ops *
914 *--------------------------------------------------------*/
915 switch (op)
916 {
917 case PIX_SRC:
918 /* do the first partial word */
919 if (dfwpartb) {
920 for (i = 0; i < dh; i++) {
921 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, dfwmask);
922 pdfwpart += dwpl;
923 psfwpart += swpl;
924 }
925 }
926
927 /* do the full words */
928 if (dfwfullb) {
929 for (i = 0; i < dh; i++) {
930 for (j = 0; j < dnfullw; j++)
931 *(pdfwfull + j) = *(psfwfull + j);
932 pdfwfull += dwpl;
933 psfwfull += swpl;
934 }
935 }
936
937 /* do the last partial word */
938 if (dlwpartb) {
939 for (i = 0; i < dh; i++) {
940 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, dlwmask);
941 pdlwpart += dwpl;
942 pslwpart += swpl;
943 }
944 }
945 break;
946 case PIX_NOT(PIX_SRC):
947 /* do the first partial word */
948 if (dfwpartb) {
949 for (i = 0; i < dh; i++) {
950 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*psfwpart), dfwmask);
951 pdfwpart += dwpl;
952 psfwpart += swpl;
953 }
954 }
955
956 /* do the full words */
957 if (dfwfullb) {
958 for (i = 0; i < dh; i++) {
959 for (j = 0; j < dnfullw; j++)
960 *(pdfwfull + j) = ~(*(psfwfull + j));
961 pdfwfull += dwpl;
962 psfwfull += swpl;
963 }
964 }
965
966 /* do the last partial word */
967 if (dlwpartb) {
968 for (i = 0; i < dh; i++) {
969 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pslwpart), dlwmask);
970 pdlwpart += dwpl;
971 pslwpart += swpl;
972 }
973 }
974 break;
975 case (PIX_SRC | PIX_DST):
976 /* do the first partial word */
977 if (dfwpartb) {
978 for (i = 0; i < dh; i++) {
979 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
980 (*psfwpart | *pdfwpart), dfwmask);
981 pdfwpart += dwpl;
982 psfwpart += swpl;
983 }
984 }
985
986 /* do the full words */
987 if (dfwfullb) {
988 for (i = 0; i < dh; i++) {
989 for (j = 0; j < dnfullw; j++)
990 *(pdfwfull + j) |= *(psfwfull + j);
991 pdfwfull += dwpl;
992 psfwfull += swpl;
993 }
994 }
995
996 /* do the last partial word */
997 if (dlwpartb) {
998 for (i = 0; i < dh; i++) {
999 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1000 (*pslwpart | *pdlwpart), dlwmask);
1001 pdlwpart += dwpl;
1002 pslwpart += swpl;
1003 }
1004 }
1005 break;
1006 case (PIX_SRC & PIX_DST):
1007 /* do the first partial word */
1008 if (dfwpartb) {
1009 for (i = 0; i < dh; i++) {
1010 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1011 (*psfwpart & *pdfwpart), dfwmask);
1012 pdfwpart += dwpl;
1013 psfwpart += swpl;
1014 }
1015 }
1016
1017 /* do the full words */
1018 if (dfwfullb) {
1019 for (i = 0; i < dh; i++) {
1020 for (j = 0; j < dnfullw; j++)
1021 *(pdfwfull + j) &= *(psfwfull + j);
1022 pdfwfull += dwpl;
1023 psfwfull += swpl;
1024 }
1025 }
1026
1027 /* do the last partial word */
1028 if (dlwpartb) {
1029 for (i = 0; i < dh; i++) {
1030 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1031 (*pslwpart & *pdlwpart), dlwmask);
1032 pdlwpart += dwpl;
1033 pslwpart += swpl;
1034 }
1035 }
1036 break;
1037 case (PIX_SRC ^ PIX_DST):
1038 /* do the first partial word */
1039 if (dfwpartb) {
1040 for (i = 0; i < dh; i++) {
1041 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1042 (*psfwpart ^ *pdfwpart), dfwmask);
1043 pdfwpart += dwpl;
1044 psfwpart += swpl;
1045 }
1046 }
1047
1048 /* do the full words */
1049 if (dfwfullb) {
1050 for (i = 0; i < dh; i++) {
1051 for (j = 0; j < dnfullw; j++)
1052 *(pdfwfull + j) ^= *(psfwfull + j);
1053 pdfwfull += dwpl;
1054 psfwfull += swpl;
1055 }
1056 }
1057
1058 /* do the last partial word */
1059 if (dlwpartb) {
1060 for (i = 0; i < dh; i++) {
1061 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1062 (*pslwpart ^ *pdlwpart), dlwmask);
1063 pdlwpart += dwpl;
1064 pslwpart += swpl;
1065 }
1066 }
1067 break;
1068 case (PIX_NOT(PIX_SRC) | PIX_DST):
1069 /* do the first partial word */
1070 if (dfwpartb) {
1071 for (i = 0; i < dh; i++) {
1072 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1073 (~(*psfwpart) | *pdfwpart), dfwmask);
1074 pdfwpart += dwpl;
1075 psfwpart += swpl;
1076 }
1077 }
1078
1079 /* do the full words */
1080 if (dfwfullb) {
1081 for (i = 0; i < dh; i++) {
1082 for (j = 0; j < dnfullw; j++)
1083 *(pdfwfull + j) |= ~(*(psfwfull + j));
1084 pdfwfull += dwpl;
1085 psfwfull += swpl;
1086 }
1087 }
1088
1089 /* do the last partial word */
1090 if (dlwpartb) {
1091 for (i = 0; i < dh; i++) {
1092 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1093 (~(*pslwpart) | *pdlwpart), dlwmask);
1094 pdlwpart += dwpl;
1095 pslwpart += swpl;
1096 }
1097 }
1098 break;
1099 case (PIX_NOT(PIX_SRC) & PIX_DST):
1100 /* do the first partial word */
1101 if (dfwpartb) {
1102 for (i = 0; i < dh; i++) {
1103 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1104 (~(*psfwpart) & *pdfwpart), dfwmask);
1105 pdfwpart += dwpl;
1106 psfwpart += swpl;
1107 }
1108 }
1109
1110 /* do the full words */
1111 if (dfwfullb) {
1112 for (i = 0; i < dh; i++) {
1113 for (j = 0; j < dnfullw; j++)
1114 *(pdfwfull + j) &= ~(*(psfwfull + j));
1115 pdfwfull += dwpl;
1116 psfwfull += swpl;
1117 }
1118 }
1119
1120 /* do the last partial word */
1121 if (dlwpartb) {
1122 for (i = 0; i < dh; i++) {
1123 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1124 (~(*pslwpart) & *pdlwpart), dlwmask);
1125 pdlwpart += dwpl;
1126 pslwpart += swpl;
1127 }
1128 }
1129 break;
1130 case (PIX_SRC | PIX_NOT(PIX_DST)):
1131 /* do the first partial word */
1132 if (dfwpartb) {
1133 for (i = 0; i < dh; i++) {
1134 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1135 (*psfwpart | ~(*pdfwpart)), dfwmask);
1136 pdfwpart += dwpl;
1137 psfwpart += swpl;
1138 }
1139 }
1140
1141 /* do the full words */
1142 if (dfwfullb) {
1143 for (i = 0; i < dh; i++) {
1144 for (j = 0; j < dnfullw; j++)
1145 *(pdfwfull + j) = *(psfwfull + j) | ~(*(pdfwfull + j));
1146 pdfwfull += dwpl;
1147 psfwfull += swpl;
1148 }
1149 }
1150
1151 /* do the last partial word */
1152 if (dlwpartb) {
1153 for (i = 0; i < dh; i++) {
1154 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1155 (*pslwpart | ~(*pdlwpart)), dlwmask);
1156 pdlwpart += dwpl;
1157 pslwpart += swpl;
1158 }
1159 }
1160 break;
1161 case (PIX_SRC & PIX_NOT(PIX_DST)):
1162 /* do the first partial word */
1163 if (dfwpartb) {
1164 for (i = 0; i < dh; i++) {
1165 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1166 (*psfwpart & ~(*pdfwpart)), dfwmask);
1167 pdfwpart += dwpl;
1168 psfwpart += swpl;
1169 }
1170 }
1171
1172 /* do the full words */
1173 if (dfwfullb) {
1174 for (i = 0; i < dh; i++) {
1175 for (j = 0; j < dnfullw; j++)
1176 *(pdfwfull + j) = *(psfwfull + j) & ~(*(pdfwfull + j));
1177 pdfwfull += dwpl;
1178 psfwfull += swpl;
1179 }
1180 }
1181
1182 /* do the last partial word */
1183 if (dlwpartb) {
1184 for (i = 0; i < dh; i++) {
1185 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1186 (*pslwpart & ~(*pdlwpart)), dlwmask);
1187 pdlwpart += dwpl;
1188 pslwpart += swpl;
1189 }
1190 }
1191 break;
1192 case (PIX_NOT(PIX_SRC | PIX_DST)):
1193 /* do the first partial word */
1194 if (dfwpartb) {
1195 for (i = 0; i < dh; i++) {
1196 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1197 ~(*psfwpart | *pdfwpart), dfwmask);
1198 pdfwpart += dwpl;
1199 psfwpart += swpl;
1200 }
1201 }
1202
1203 /* do the full words */
1204 if (dfwfullb) {
1205 for (i = 0; i < dh; i++) {
1206 for (j = 0; j < dnfullw; j++)
1207 *(pdfwfull + j) = ~(*(psfwfull + j) | *(pdfwfull + j));
1208 pdfwfull += dwpl;
1209 psfwfull += swpl;
1210 }
1211 }
1212
1213 /* do the last partial word */
1214 if (dlwpartb) {
1215 for (i = 0; i < dh; i++) {
1216 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1217 ~(*pslwpart | *pdlwpart), dlwmask);
1218 pdlwpart += dwpl;
1219 pslwpart += swpl;
1220 }
1221 }
1222 break;
1223 case (PIX_NOT(PIX_SRC & PIX_DST)):
1224 /* do the first partial word */
1225 if (dfwpartb) {
1226 for (i = 0; i < dh; i++) {
1227 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1228 ~(*psfwpart & *pdfwpart), dfwmask);
1229 pdfwpart += dwpl;
1230 psfwpart += swpl;
1231 }
1232 }
1233
1234 /* do the full words */
1235 if (dfwfullb) {
1236 for (i = 0; i < dh; i++) {
1237 for (j = 0; j < dnfullw; j++)
1238 *(pdfwfull + j) = ~(*(psfwfull + j) & *(pdfwfull + j));
1239 pdfwfull += dwpl;
1240 psfwfull += swpl;
1241 }
1242 }
1243
1244 /* do the last partial word */
1245 if (dlwpartb) {
1246 for (i = 0; i < dh; i++) {
1247 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1248 ~(*pslwpart & *pdlwpart), dlwmask);
1249 pdlwpart += dwpl;
1250 pslwpart += swpl;
1251 }
1252 }
1253 break;
1254 /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
1255 case (PIX_NOT(PIX_SRC ^ PIX_DST)):
1256 /* do the first partial word */
1257 if (dfwpartb) {
1258 for (i = 0; i < dh; i++) {
1259 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1260 ~(*psfwpart ^ *pdfwpart), dfwmask);
1261 pdfwpart += dwpl;
1262 psfwpart += swpl;
1263 }
1264 }
1265
1266 /* do the full words */
1267 if (dfwfullb) {
1268 for (i = 0; i < dh; i++) {
1269 for (j = 0; j < dnfullw; j++)
1270 *(pdfwfull + j) = ~(*(psfwfull + j) ^ *(pdfwfull + j));
1271 pdfwfull += dwpl;
1272 psfwfull += swpl;
1273 }
1274 }
1275
1276 /* do the last partial word */
1277 if (dlwpartb) {
1278 for (i = 0; i < dh; i++) {
1279 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1280 ~(*pslwpart ^ *pdlwpart), dlwmask);
1281 pdlwpart += dwpl;
1282 pslwpart += swpl;
1283 }
1284 }
1285 break;
1286 default:
1287 fprintf(stderr, "Operation %x invalid\n", op);
1288 }
1289
1290 return;
1291 }
1292
1293
1294 /*--------------------------------------------------------------------*
1295 * Static low-level rasterop without vertical word alignment *
1296 *--------------------------------------------------------------------*/
1297 /*!
1298 * rasteropGeneralLow()
1299 *
1300 * Input: datad (ptr to dest image data)
1301 * dwpl (wpl of dest)
1302 * dx (x val of UL corner of dest rectangle)
1303 * dy (y val of UL corner of dest rectangle)
1304 * dw (width of dest rectangle)
1305 * dh (height of dest rectangle)
1306 * op (op code)
1307 * datas (ptr to src image data)
1308 * swpl (wpl of src)
1309 * sx (x val of UL corner of src rectangle)
1310 * sy (y val of UL corner of src rectangle)
1311 * Return: void
1312 *
1313 * This is called when the src and dest rects are
1314 * do not have the same (32-bit) word alignment.
1315 *
1316 * The method is a generalization of rasteropVAlignLow().
1317 * There, the src image pieces were directly merged
1318 * with the dest. Here, we shift the source bits
1319 * to fill words that are aligned with the dest, and
1320 * then use those "source words" exactly in place
1321 * of the source words that were used in rasteropVAlignLow().
1322 *
1323 * The critical parameter is thus the shift required
1324 * for the src. Consider the left edge of the rectangle.
1325 * The overhang into the src and dest words are found,
1326 * and the difference is exactly this shift. There are
1327 * two separate cases, depending on whether the src pixels
1328 * are shifted left or right. If the src overhang is
1329 * larger than the dest overhang, the src is shifted to
1330 * the right, a number of pixels equal to the shift are
1331 * left over for filling the next dest word, if necessary.
1332 * But if the dest overhang is larger than the src,
1333 * the src is shifted to the left, and it may also be
1334 * necessary to shift an equal number of pixels in from
1335 * the next src word. However, in both cases, after
1336 * the first partial (or complete) dest word has been
1337 * filled, the next src pixels will come from a left
1338 * shift that exhausts the pixels in the src word.
1339 */
1340 static void
rasteropGeneralLow(l_uint32 * datad,l_int32 dwpl,l_int32 dx,l_int32 dy,l_int32 dw,l_int32 dh,l_int32 op,l_uint32 * datas,l_int32 swpl,l_int32 sx,l_int32 sy)1341 rasteropGeneralLow(l_uint32 *datad,
1342 l_int32 dwpl,
1343 l_int32 dx,
1344 l_int32 dy,
1345 l_int32 dw,
1346 l_int32 dh,
1347 l_int32 op,
1348 l_uint32 *datas,
1349 l_int32 swpl,
1350 l_int32 sx,
1351 l_int32 sy)
1352 {
1353 l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
1354 l_int32 dfwpart2b; /* boolean (1, 0) if 1st dest word is doubly partial */
1355 l_uint32 dfwmask; /* mask for first partial dest word */
1356 l_int32 dfwbits; /* first word dest bits in overhang; 0-31 */
1357 l_int32 dhang; /* dest overhang in first partial word, */
1358 /* or 0 if dest is word aligned (same as dfwbits) */
1359 l_uint32 *pdfwpart; /* ptr to first partial dest word */
1360 l_uint32 *psfwpart; /* ptr to first partial src word */
1361 l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
1362 l_int32 dnfullw; /* number of full words in dest */
1363 l_uint32 *pdfwfull; /* ptr to first full dest word */
1364 l_uint32 *psfwfull; /* ptr to first full src word */
1365 l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
1366 l_uint32 dlwmask; /* mask for last partial dest word */
1367 l_int32 dlwbits; /* last word dest bits in ovrhang */
1368 l_uint32 *pdlwpart; /* ptr to last partial dest word */
1369 l_uint32 *pslwpart; /* ptr to last partial src word */
1370 l_uint32 sword; /* compose src word aligned with the dest words */
1371 l_int32 sfwbits; /* first word src bits in overhang (1-32), */
1372 /* or 32 if src is word aligned */
1373 l_int32 shang; /* source overhang in the first partial word, */
1374 /* or 0 if src is word aligned (not same as sfwbits) */
1375 l_int32 sleftshift; /* bits to shift left for source word to align */
1376 /* with the dest. Also the number of bits that */
1377 /* get shifted to the right to align with the dest. */
1378 l_int32 srightshift; /* bits to shift right for source word to align */
1379 /* with dest. Also, the number of bits that get */
1380 /* shifted left to align with the dest. */
1381 l_int32 srightmask; /* mask for selecting sleftshift bits that have */
1382 /* been shifted right by srightshift bits */
1383 l_int32 sfwshiftdir; /* either SHIFT_LEFT or SHIFT_RIGHT */
1384 l_int32 sfwaddb; /* boolean: do we need an additional sfw right shift? */
1385 l_int32 slwaddb; /* boolean: do we need an additional slw right shift? */
1386 l_int32 i, j;
1387
1388
1389 /*--------------------------------------------------------*
1390 * Preliminary calculations *
1391 *--------------------------------------------------------*/
1392 /* To get alignment of src with dst (e.g., in the
1393 * full words) the src must do a left shift of its
1394 * relative overhang in the current src word,
1395 * and OR that with a right shift of
1396 * (31 - relative overhang) from the next src word.
1397 * We find the absolute overhangs, the relative overhangs,
1398 * the required shifts and the src mask */
1399 if ((sx & 31) == 0)
1400 shang = 0;
1401 else
1402 shang = 32 - (sx & 31);
1403 if ((dx & 31) == 0)
1404 dhang = 0;
1405 else
1406 dhang = 32 - (dx & 31);
1407
1408 if (shang == 0 && dhang == 0) { /* this should be treated by an
1409 aligned operation, not by
1410 this general rasterop! */
1411 sleftshift = 0;
1412 srightshift = 0;
1413 srightmask = rmask32[0];
1414 }
1415 else {
1416 if (dhang > shang)
1417 sleftshift = dhang - shang;
1418 else
1419 sleftshift = 32 - (shang - dhang);
1420 srightshift = 32 - sleftshift;
1421 srightmask = rmask32[sleftshift];
1422 }
1423
1424 /* is the first dest word partial? */
1425 if ((dx & 31) == 0) { /* if not */
1426 dfwpartb = 0;
1427 dfwbits = 0;
1428 }
1429 else { /* if so */
1430 dfwpartb = 1;
1431 dfwbits = 32 - (dx & 31);
1432 dfwmask = rmask32[dfwbits];
1433 pdfwpart = datad + dwpl * dy + (dx >> 5);
1434 psfwpart = datas + swpl * sy + (sx >> 5);
1435 sfwbits = 32 - (sx & 31);
1436 if (dfwbits > sfwbits) {
1437 sfwshiftdir = SHIFT_LEFT; /* and shift by sleftshift */
1438 if (dw < shang)
1439 sfwaddb = 0;
1440 else
1441 sfwaddb = 1; /* and rshift in next src word by srightshift */
1442 }
1443 else
1444 sfwshiftdir = SHIFT_RIGHT; /* and shift by srightshift */
1445 }
1446
1447 /* is the first dest word doubly partial? */
1448 if (dw >= dfwbits) /* if not */
1449 dfwpart2b = 0;
1450 else { /* if so */
1451 dfwpart2b = 1;
1452 dfwmask &= lmask32[32 - dfwbits + dw];
1453 }
1454
1455 /* is there a full dest word? */
1456 if (dfwpart2b == 1) { /* not */
1457 dfwfullb = 0;
1458 dnfullw = 0;
1459 }
1460 else {
1461 dnfullw = (dw - dfwbits) >> 5;
1462 if (dnfullw == 0) /* if not */
1463 dfwfullb = 0;
1464 else { /* if so */
1465 dfwfullb = 1;
1466 pdfwfull = datad + dwpl * dy + ((dx + dhang) >> 5);
1467 psfwfull = datas + swpl * sy + ((sx + dhang) >> 5); /* yes, dhang */
1468 }
1469 }
1470
1471 /* is the last dest word partial? */
1472 dlwbits = (dx + dw) & 31;
1473 if (dfwpart2b == 1 || dlwbits == 0) /* if not */
1474 dlwpartb = 0;
1475 else {
1476 dlwpartb = 1;
1477 dlwmask = lmask32[dlwbits];
1478 pdlwpart = datad + dwpl * dy + ((dx + dhang) >> 5) + dnfullw;
1479 pslwpart = datas + swpl * sy + ((sx + dhang) >> 5) + dnfullw;
1480 if (dlwbits <= srightshift) /* must be <= here !!! */
1481 slwaddb = 0; /* we got enough bits from current src word */
1482 else
1483 slwaddb = 1; /* must rshift in next src word by srightshift */
1484 }
1485
1486
1487 /*--------------------------------------------------------*
1488 * Now we're ready to do the ops *
1489 *--------------------------------------------------------*/
1490 switch (op)
1491 {
1492 case PIX_SRC:
1493 /* do the first partial word */
1494 if (dfwpartb) {
1495 for (i = 0; i < dh; i++)
1496 {
1497 if (sfwshiftdir == SHIFT_LEFT) {
1498 sword = *psfwpart << sleftshift;
1499 if (sfwaddb)
1500 sword = COMBINE_PARTIAL(sword,
1501 *(psfwpart + 1) >> srightshift,
1502 srightmask);
1503 }
1504 else /* shift right */
1505 sword = *psfwpart >> srightshift;
1506
1507 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, sword, dfwmask);
1508 pdfwpart += dwpl;
1509 psfwpart += swpl;
1510 }
1511 }
1512
1513 /* do the full words */
1514 if (dfwfullb) {
1515 for (i = 0; i < dh; i++) {
1516 for (j = 0; j < dnfullw; j++) {
1517 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1518 *(psfwfull + j + 1) >> srightshift,
1519 srightmask);
1520 *(pdfwfull + j) = sword;
1521 }
1522 pdfwfull += dwpl;
1523 psfwfull += swpl;
1524 }
1525 }
1526
1527 /* do the last partial word */
1528 if (dlwpartb) {
1529 for (i = 0; i < dh; i++) {
1530 sword = *pslwpart << sleftshift;
1531 if (slwaddb)
1532 sword = COMBINE_PARTIAL(sword,
1533 *(pslwpart + 1) >> srightshift,
1534 srightmask);
1535
1536 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, sword, dlwmask);
1537 pdlwpart += dwpl;
1538 pslwpart += swpl;
1539 }
1540 }
1541 break;
1542 case PIX_NOT(PIX_SRC):
1543 /* do the first partial word */
1544 if (dfwpartb) {
1545 for (i = 0; i < dh; i++)
1546 {
1547 if (sfwshiftdir == SHIFT_LEFT) {
1548 sword = *psfwpart << sleftshift;
1549 if (sfwaddb)
1550 sword = COMBINE_PARTIAL(sword,
1551 *(psfwpart + 1) >> srightshift,
1552 srightmask);
1553 }
1554 else /* shift right */
1555 sword = *psfwpart >> srightshift;
1556
1557 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~sword, dfwmask);
1558 pdfwpart += dwpl;
1559 psfwpart += swpl;
1560 }
1561 }
1562
1563 /* do the full words */
1564 if (dfwfullb) {
1565 for (i = 0; i < dh; i++) {
1566 for (j = 0; j < dnfullw; j++) {
1567 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1568 *(psfwfull + j + 1) >> srightshift,
1569 srightmask);
1570 *(pdfwfull + j) = ~sword;
1571 }
1572 pdfwfull += dwpl;
1573 psfwfull += swpl;
1574 }
1575 }
1576
1577 /* do the last partial word */
1578 if (dlwpartb) {
1579 for (i = 0; i < dh; i++) {
1580 sword = *pslwpart << sleftshift;
1581 if (slwaddb)
1582 sword = COMBINE_PARTIAL(sword,
1583 *(pslwpart + 1) >> srightshift,
1584 srightmask);
1585
1586 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~sword, dlwmask);
1587 pdlwpart += dwpl;
1588 pslwpart += swpl;
1589 }
1590 }
1591 break;
1592 case (PIX_SRC | PIX_DST):
1593 /* do the first partial word */
1594 if (dfwpartb) {
1595 for (i = 0; i < dh; i++)
1596 {
1597 if (sfwshiftdir == SHIFT_LEFT) {
1598 sword = *psfwpart << sleftshift;
1599 if (sfwaddb)
1600 sword = COMBINE_PARTIAL(sword,
1601 *(psfwpart + 1) >> srightshift,
1602 srightmask);
1603 }
1604 else /* shift right */
1605 sword = *psfwpart >> srightshift;
1606
1607 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1608 (sword | *pdfwpart), dfwmask);
1609 pdfwpart += dwpl;
1610 psfwpart += swpl;
1611 }
1612 }
1613
1614 /* do the full words */
1615 if (dfwfullb) {
1616 for (i = 0; i < dh; i++) {
1617 for (j = 0; j < dnfullw; j++) {
1618 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1619 *(psfwfull + j + 1) >> srightshift,
1620 srightmask);
1621 *(pdfwfull + j) |= sword;
1622 }
1623 pdfwfull += dwpl;
1624 psfwfull += swpl;
1625 }
1626 }
1627
1628 /* do the last partial word */
1629 if (dlwpartb) {
1630 for (i = 0; i < dh; i++) {
1631 sword = *pslwpart << sleftshift;
1632 if (slwaddb)
1633 sword = COMBINE_PARTIAL(sword,
1634 *(pslwpart + 1) >> srightshift,
1635 srightmask);
1636
1637 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1638 (sword | *pdlwpart), dlwmask);
1639 pdlwpart += dwpl;
1640 pslwpart += swpl;
1641 }
1642 }
1643 break;
1644 case (PIX_SRC & PIX_DST):
1645 /* do the first partial word */
1646 if (dfwpartb) {
1647 for (i = 0; i < dh; i++)
1648 {
1649 if (sfwshiftdir == SHIFT_LEFT) {
1650 sword = *psfwpart << sleftshift;
1651 if (sfwaddb)
1652 sword = COMBINE_PARTIAL(sword,
1653 *(psfwpart + 1) >> srightshift,
1654 srightmask);
1655 }
1656 else /* shift right */
1657 sword = *psfwpart >> srightshift;
1658
1659 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1660 (sword & *pdfwpart), dfwmask);
1661 pdfwpart += dwpl;
1662 psfwpart += swpl;
1663 }
1664 }
1665
1666 /* do the full words */
1667 if (dfwfullb) {
1668 for (i = 0; i < dh; i++) {
1669 for (j = 0; j < dnfullw; j++) {
1670 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1671 *(psfwfull + j + 1) >> srightshift,
1672 srightmask);
1673 *(pdfwfull + j) &= sword;
1674 }
1675 pdfwfull += dwpl;
1676 psfwfull += swpl;
1677 }
1678 }
1679
1680 /* do the last partial word */
1681 if (dlwpartb) {
1682 for (i = 0; i < dh; i++) {
1683 sword = *pslwpart << sleftshift;
1684 if (slwaddb)
1685 sword = COMBINE_PARTIAL(sword,
1686 *(pslwpart + 1) >> srightshift,
1687 srightmask);
1688
1689 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1690 (sword & *pdlwpart), dlwmask);
1691 pdlwpart += dwpl;
1692 pslwpart += swpl;
1693 }
1694 }
1695 break;
1696 case (PIX_SRC ^ PIX_DST):
1697 /* do the first partial word */
1698 if (dfwpartb) {
1699 for (i = 0; i < dh; i++)
1700 {
1701 if (sfwshiftdir == SHIFT_LEFT) {
1702 sword = *psfwpart << sleftshift;
1703 if (sfwaddb)
1704 sword = COMBINE_PARTIAL(sword,
1705 *(psfwpart + 1) >> srightshift,
1706 srightmask);
1707 }
1708 else /* shift right */
1709 sword = *psfwpart >> srightshift;
1710
1711 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1712 (sword ^ *pdfwpart), dfwmask);
1713 pdfwpart += dwpl;
1714 psfwpart += swpl;
1715 }
1716 }
1717
1718 /* do the full words */
1719 if (dfwfullb) {
1720 for (i = 0; i < dh; i++) {
1721 for (j = 0; j < dnfullw; j++) {
1722 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1723 *(psfwfull + j + 1) >> srightshift,
1724 srightmask);
1725 *(pdfwfull + j) ^= sword;
1726 }
1727 pdfwfull += dwpl;
1728 psfwfull += swpl;
1729 }
1730 }
1731
1732 /* do the last partial word */
1733 if (dlwpartb) {
1734 for (i = 0; i < dh; i++) {
1735 sword = *pslwpart << sleftshift;
1736 if (slwaddb)
1737 sword = COMBINE_PARTIAL(sword,
1738 *(pslwpart + 1) >> srightshift,
1739 srightmask);
1740
1741 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1742 (sword ^ *pdlwpart), dlwmask);
1743 pdlwpart += dwpl;
1744 pslwpart += swpl;
1745 }
1746 }
1747 break;
1748 case (PIX_NOT(PIX_SRC) | PIX_DST):
1749 /* do the first partial word */
1750 if (dfwpartb) {
1751 for (i = 0; i < dh; i++)
1752 {
1753 if (sfwshiftdir == SHIFT_LEFT) {
1754 sword = *psfwpart << sleftshift;
1755 if (sfwaddb)
1756 sword = COMBINE_PARTIAL(sword,
1757 *(psfwpart + 1) >> srightshift,
1758 srightmask);
1759 }
1760 else /* shift right */
1761 sword = *psfwpart >> srightshift;
1762
1763 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1764 (~sword | *pdfwpart), dfwmask);
1765 pdfwpart += dwpl;
1766 psfwpart += swpl;
1767 }
1768 }
1769
1770 /* do the full words */
1771 if (dfwfullb) {
1772 for (i = 0; i < dh; i++) {
1773 for (j = 0; j < dnfullw; j++) {
1774 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1775 *(psfwfull + j + 1) >> srightshift,
1776 srightmask);
1777 *(pdfwfull + j) |= ~sword;
1778 }
1779 pdfwfull += dwpl;
1780 psfwfull += swpl;
1781 }
1782 }
1783
1784 /* do the last partial word */
1785 if (dlwpartb) {
1786 for (i = 0; i < dh; i++) {
1787 sword = *pslwpart << sleftshift;
1788 if (slwaddb)
1789 sword = COMBINE_PARTIAL(sword,
1790 *(pslwpart + 1) >> srightshift,
1791 srightmask);
1792
1793 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1794 (~sword | *pdlwpart), dlwmask);
1795 pdlwpart += dwpl;
1796 pslwpart += swpl;
1797 }
1798 }
1799 break;
1800 case (PIX_NOT(PIX_SRC) & PIX_DST):
1801 /* do the first partial word */
1802 if (dfwpartb) {
1803 for (i = 0; i < dh; i++)
1804 {
1805 if (sfwshiftdir == SHIFT_LEFT) {
1806 sword = *psfwpart << sleftshift;
1807 if (sfwaddb)
1808 sword = COMBINE_PARTIAL(sword,
1809 *(psfwpart + 1) >> srightshift,
1810 srightmask);
1811 }
1812 else /* shift right */
1813 sword = *psfwpart >> srightshift;
1814
1815 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1816 (~sword & *pdfwpart), dfwmask);
1817 pdfwpart += dwpl;
1818 psfwpart += swpl;
1819 }
1820 }
1821
1822 /* do the full words */
1823 if (dfwfullb) {
1824 for (i = 0; i < dh; i++) {
1825 for (j = 0; j < dnfullw; j++) {
1826 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1827 *(psfwfull + j + 1) >> srightshift,
1828 srightmask);
1829 *(pdfwfull + j) &= ~sword;
1830 }
1831 pdfwfull += dwpl;
1832 psfwfull += swpl;
1833 }
1834 }
1835
1836 /* do the last partial word */
1837 if (dlwpartb) {
1838 for (i = 0; i < dh; i++) {
1839 sword = *pslwpart << sleftshift;
1840 if (slwaddb)
1841 sword = COMBINE_PARTIAL(sword,
1842 *(pslwpart + 1) >> srightshift,
1843 srightmask);
1844
1845 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1846 (~sword & *pdlwpart), dlwmask);
1847 pdlwpart += dwpl;
1848 pslwpart += swpl;
1849 }
1850 }
1851 break;
1852 case (PIX_SRC | PIX_NOT(PIX_DST)):
1853 /* do the first partial word */
1854 if (dfwpartb) {
1855 for (i = 0; i < dh; i++)
1856 {
1857 if (sfwshiftdir == SHIFT_LEFT) {
1858 sword = *psfwpart << sleftshift;
1859 if (sfwaddb)
1860 sword = COMBINE_PARTIAL(sword,
1861 *(psfwpart + 1) >> srightshift,
1862 srightmask);
1863 }
1864 else /* shift right */
1865 sword = *psfwpart >> srightshift;
1866
1867 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1868 (sword | ~(*pdfwpart)), dfwmask);
1869 pdfwpart += dwpl;
1870 psfwpart += swpl;
1871 }
1872 }
1873
1874 /* do the full words */
1875 if (dfwfullb) {
1876 for (i = 0; i < dh; i++) {
1877 for (j = 0; j < dnfullw; j++) {
1878 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1879 *(psfwfull + j + 1) >> srightshift,
1880 srightmask);
1881 *(pdfwfull + j) = sword | ~(*(pdfwfull + j));
1882 }
1883 pdfwfull += dwpl;
1884 psfwfull += swpl;
1885 }
1886 }
1887
1888 /* do the last partial word */
1889 if (dlwpartb) {
1890 for (i = 0; i < dh; i++) {
1891 sword = *pslwpart << sleftshift;
1892 if (slwaddb)
1893 sword = COMBINE_PARTIAL(sword,
1894 *(pslwpart + 1) >> srightshift,
1895 srightmask);
1896
1897 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1898 (sword | ~(*pdlwpart)), dlwmask);
1899 pdlwpart += dwpl;
1900 pslwpart += swpl;
1901 }
1902 }
1903 break;
1904 case (PIX_SRC & PIX_NOT(PIX_DST)):
1905 /* do the first partial word */
1906 if (dfwpartb) {
1907 for (i = 0; i < dh; i++)
1908 {
1909 if (sfwshiftdir == SHIFT_LEFT) {
1910 sword = *psfwpart << sleftshift;
1911 if (sfwaddb)
1912 sword = COMBINE_PARTIAL(sword,
1913 *(psfwpart + 1) >> srightshift,
1914 srightmask);
1915 }
1916 else /* shift right */
1917 sword = *psfwpart >> srightshift;
1918
1919 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1920 (sword & ~(*pdfwpart)), dfwmask);
1921 pdfwpart += dwpl;
1922 psfwpart += swpl;
1923 }
1924 }
1925
1926 /* do the full words */
1927 if (dfwfullb) {
1928 for (i = 0; i < dh; i++) {
1929 for (j = 0; j < dnfullw; j++) {
1930 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1931 *(psfwfull + j + 1) >> srightshift,
1932 srightmask);
1933 *(pdfwfull + j) = sword & ~(*(pdfwfull + j));
1934 }
1935 pdfwfull += dwpl;
1936 psfwfull += swpl;
1937 }
1938 }
1939
1940 /* do the last partial word */
1941 if (dlwpartb) {
1942 for (i = 0; i < dh; i++) {
1943 sword = *pslwpart << sleftshift;
1944 if (slwaddb)
1945 sword = COMBINE_PARTIAL(sword,
1946 *(pslwpart + 1) >> srightshift,
1947 srightmask);
1948
1949 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
1950 (sword & ~(*pdlwpart)), dlwmask);
1951 pdlwpart += dwpl;
1952 pslwpart += swpl;
1953 }
1954 }
1955 break;
1956 case (PIX_NOT(PIX_SRC | PIX_DST)):
1957 /* do the first partial word */
1958 if (dfwpartb) {
1959 for (i = 0; i < dh; i++)
1960 {
1961 if (sfwshiftdir == SHIFT_LEFT) {
1962 sword = *psfwpart << sleftshift;
1963 if (sfwaddb)
1964 sword = COMBINE_PARTIAL(sword,
1965 *(psfwpart + 1) >> srightshift,
1966 srightmask);
1967 }
1968 else /* shift right */
1969 sword = *psfwpart >> srightshift;
1970
1971 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
1972 ~(sword | *pdfwpart), dfwmask);
1973 pdfwpart += dwpl;
1974 psfwpart += swpl;
1975 }
1976 }
1977
1978 /* do the full words */
1979 if (dfwfullb) {
1980 for (i = 0; i < dh; i++) {
1981 for (j = 0; j < dnfullw; j++) {
1982 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
1983 *(psfwfull + j + 1) >> srightshift,
1984 srightmask);
1985 *(pdfwfull + j) = ~(sword | *(pdfwfull + j));
1986 }
1987 pdfwfull += dwpl;
1988 psfwfull += swpl;
1989 }
1990 }
1991
1992 /* do the last partial word */
1993 if (dlwpartb) {
1994 for (i = 0; i < dh; i++) {
1995 sword = *pslwpart << sleftshift;
1996 if (slwaddb)
1997 sword = COMBINE_PARTIAL(sword,
1998 *(pslwpart + 1) >> srightshift,
1999 srightmask);
2000
2001 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
2002 ~(sword | *pdlwpart), dlwmask);
2003 pdlwpart += dwpl;
2004 pslwpart += swpl;
2005 }
2006 }
2007 break;
2008 case (PIX_NOT(PIX_SRC & PIX_DST)):
2009 /* do the first partial word */
2010 if (dfwpartb) {
2011 for (i = 0; i < dh; i++)
2012 {
2013 if (sfwshiftdir == SHIFT_LEFT) {
2014 sword = *psfwpart << sleftshift;
2015 if (sfwaddb)
2016 sword = COMBINE_PARTIAL(sword,
2017 *(psfwpart + 1) >> srightshift,
2018 srightmask);
2019 }
2020 else /* shift right */
2021 sword = *psfwpart >> srightshift;
2022
2023 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
2024 ~(sword & *pdfwpart), dfwmask);
2025 pdfwpart += dwpl;
2026 psfwpart += swpl;
2027 }
2028 }
2029
2030 /* do the full words */
2031 if (dfwfullb) {
2032 for (i = 0; i < dh; i++) {
2033 for (j = 0; j < dnfullw; j++) {
2034 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
2035 *(psfwfull + j + 1) >> srightshift,
2036 srightmask);
2037 *(pdfwfull + j) = ~(sword & *(pdfwfull + j));
2038 }
2039 pdfwfull += dwpl;
2040 psfwfull += swpl;
2041 }
2042 }
2043
2044 /* do the last partial word */
2045 if (dlwpartb) {
2046 for (i = 0; i < dh; i++) {
2047 sword = *pslwpart << sleftshift;
2048 if (slwaddb)
2049 sword = COMBINE_PARTIAL(sword,
2050 *(pslwpart + 1) >> srightshift,
2051 srightmask);
2052
2053 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
2054 ~(sword & *pdlwpart), dlwmask);
2055 pdlwpart += dwpl;
2056 pslwpart += swpl;
2057 }
2058 }
2059 break;
2060 /* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
2061 case (PIX_NOT(PIX_SRC ^ PIX_DST)):
2062 /* do the first partial word */
2063 if (dfwpartb) {
2064 for (i = 0; i < dh; i++)
2065 {
2066 if (sfwshiftdir == SHIFT_LEFT) {
2067 sword = *psfwpart << sleftshift;
2068 if (sfwaddb)
2069 sword = COMBINE_PARTIAL(sword,
2070 *(psfwpart + 1) >> srightshift,
2071 srightmask);
2072 }
2073 else /* shift right */
2074 sword = *psfwpart >> srightshift;
2075
2076 *pdfwpart = COMBINE_PARTIAL(*pdfwpart,
2077 ~(sword ^ *pdfwpart), dfwmask);
2078 pdfwpart += dwpl;
2079 psfwpart += swpl;
2080 }
2081 }
2082
2083 /* do the full words */
2084 if (dfwfullb) {
2085 for (i = 0; i < dh; i++) {
2086 for (j = 0; j < dnfullw; j++) {
2087 sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
2088 *(psfwfull + j + 1) >> srightshift,
2089 srightmask);
2090 *(pdfwfull + j) = ~(sword ^ *(pdfwfull + j));
2091 }
2092 pdfwfull += dwpl;
2093 psfwfull += swpl;
2094 }
2095 }
2096
2097 /* do the last partial word */
2098 if (dlwpartb) {
2099 for (i = 0; i < dh; i++) {
2100 sword = *pslwpart << sleftshift;
2101 if (slwaddb)
2102 sword = COMBINE_PARTIAL(sword,
2103 *(pslwpart + 1) >> srightshift,
2104 srightmask);
2105
2106 *pdlwpart = COMBINE_PARTIAL(*pdlwpart,
2107 ~(sword ^ *pdlwpart), dlwmask);
2108 pdlwpart += dwpl;
2109 pslwpart += swpl;
2110 }
2111 }
2112 break;
2113 default:
2114 fprintf(stderr, "Operation %x invalid\n", op);
2115 }
2116
2117 return;
2118 }
2119
2120