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