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