1 //========================================================================
5 // Copyright 2000-2001 Emmanuel Lesueur
7 //========================================================================
10 #include "AOutputDev.h"
16 #define CHECKBM(bm) check_start = bm.data(); \
17 check_stop = check_start + bm.modulo * bm.height * bm.bpp;
18 #define CHECK(p) if ((Guchar*)(p) < check_start || (Guchar*)(p) >= check_stop) { \
19 dprintf("#### Error: overflow line %d\n", __LINE__); \
25 extern "C" void dprintf(const char *,...);
31 inline double length(double x
, double y
) { return sqrt(x
* x
+ y
* y
); }
32 template<class T
> inline T
abs(T x
) { return x
< 0 ? -x
: x
; }
33 template<class T
> inline T
max(T x
, T y
) { return x
< y
? y
: x
; }
34 template<class T
> inline T
min(T x
, T y
) { return x
< y
? x
: y
; }
35 template<class T
> inline void swap(T
& x
, T
& y
) { T t
= x
; x
= y
; y
= t
; }
37 template<class colorT
> inline
38 void _rectfill(ABitmap
& bm
, int x0
, int y0
, int w
, int h
, colorT color
) {
41 int modulo
= bm
.modulo
;
42 colorT
*dest
= (colorT
*) bm
.data();
51 if (x0
+ w
>= bm
.width
)
57 if (y0
+ h
>= bm
.height
)
60 dest
+= y0
* modulo
+ x0
;
74 template<class colorT
> inline
75 void _fill(ABitmap
& bm
, int x0
, int y0
, region
* area
, colorT color
) {
78 int modulo
= bm
.modulo
;
79 colorT
*dest
= (colorT
*) bm
.data();
81 x0
+= NEARESTPEL(area
->origin
.x
) - bm
.xoffset
;
82 y0
+= NEARESTPEL(area
->origin
.y
) - bm
.yoffset
;
87 //printf("fill (%d,%d,%d,%d)\n",area->xmin,area->ymin,w,h);
88 for (edgelist
*edge
= area
->anchor
; VALIDEDGE(edge
); edge
= edge
->link
->link
) {
89 pel
*leftP
= edge
->xvalues
;
90 pel
*rightP
= edge
->link
->xvalues
;
91 int y1
= edge
->ymin
+ y0
;
92 int y2
= min(edge
->ymax
+ y0
, h
);
93 //printf("edge: %d -> %d\n",y1,y2);
99 colorT
* p
= dest
+ y1
* modulo
;
101 int x1
= max(*leftP
++ + x0
, 0);
102 int x2
= min(*rightP
++ + x0
, w
);
103 //printf("\t %d -> %d\n",x1,x2);
117 template<class colorT
>
118 void AAfillrun(colorT
* q
, int x1
, int x2
, colorT c1
, colorT c2
) {
140 template<class colorT
> inline
141 void _AAfill(ABitmap
& bm
, int x0
, int y0
, region
* area
,
142 colorT c1
, colorT c2
, colorT c3
, colorT c4
) {
144 edgelist
*prev
= area
->anchor
;
147 int modulo
= bm
.modulo
;
148 colorT
*dest
= (colorT
*) bm
.data();
149 int bw
= bm
.width
<< 1;
150 int bh
= bm
.height
<< 1;
151 int bx
= bm
.xoffset
- x0
- NEARESTPEL(area
->origin
.x
) << 1;
152 int by
= bm
.yoffset
- y0
- NEARESTPEL(area
->origin
.y
) << 1;
153 /*DB(printf("--------------AAFill--------------\n");
154 for(edgelist* e=area->anchor;VALIDEDGE(e);e=e->link->link) {
155 printf("swath : y1=%d, y2=%d, top: %d -> %d, bottom : %d -> %d\n",
156 e->ymin-by,e->ymax-by,
157 *e->xvalues-bx,*e->link->xvalues-by,
158 e->xvalues[e->ymax-e->ymin-1]-bx,
159 e->link->xvalues[e->ymax-e->ymin-1]-by);
161 edgelist
*prevprev
= NULL
;
162 int prev_ymin
= prev
->ymin
;
163 for (edgelist
*edge
= area
->anchor
; VALIDEDGE(edge
); edge
= edge
->link
->link
) {
164 pel
*leftP
= edge
->xvalues
;
165 pel
*rightP
= edge
->link
->xvalues
;
166 int y1
= edge
->ymin
- by
;
167 int y2
= min(edge
->ymax
- by
, bh
);
168 if (y1
!= prev_ymin
) {
173 //printf("edge: %d -> %d\n",y1,y2);
181 colorT
* p
= dest
+ (y1
>> 1) * modulo
;
183 int x1
= max(*leftP
++ - bx
, 0);
184 int x2
= min(*rightP
++ - bx
, bw
);
185 if (prevprev
== NULL
|| prevprev
->ymax
- by
!= y1
)
186 AAfillrun(p
, x1
, x2
, c1
, c2
);
188 colorT
* q
= p
+ (x1
>> 1);
189 for (edgelist
*e
= prevprev
; x1
< x2
&& e
!= prev
; e
= e
->link
->link
) {
190 int z1
= max(e
->xvalues
[e
->ymax
- e
->ymin
- 1] - bx
, 0);
191 int z2
= min(e
->link
->xvalues
[e
->ymax
- e
->ymin
- 1] - bx
, bw
);
192 if (z1
>= x2
|| z2
<= x1
|| z1
>= z2
)
212 } else if (x1
== z1
&& (x1
& 1)) {
238 AAfillrun(p
, x1
, x2
, c1
, c2
);
246 int x1
= max(*leftP
++ - bx
, 0);
247 int x2
= min(*rightP
++ - bx
, bw
);
248 int z1
= max(*leftP
++ - bx
, 0);
249 int z2
= min(*rightP
++ - bx
, bw
);
250 //printf("\t %d -> %d\n",x1,x2);
251 if (z1
>= x2
|| z1
>= z2
|| x1
>= x2
) {
254 AAfillrun(p
, x1
, x2
, c1
, c2
);
255 AAfillrun(p
, z1
, z2
, c1
, c2
);
259 // ****************************
261 // -> (1) 2 (3) 4 (3) 2 (1)
263 if (x1
> z1
) { // We are only interested in the
264 int t
= x1
; // average number of filled pixels
265 x1
= z1
; // in a 2x2 square, so we can
266 z1
= t
; // replace a situation like:
268 if (z2
> x2
) { // ***** by *******
273 // Here, we have x1 <= z1 < z2 <= x2
274 colorT
* q
= p
+ (x1
>> 1);
278 *q
++ = c1
; // | *|******
281 *q
++ = c2
; // | *|****
336 int x1
= max(*leftP
++ - bx
, 0);
337 int x2
= min(*rightP
++ - bx
, bw
);
338 AAfillrun(p
, x1
, x2
, c1
, c2
);
341 //DB(printf("-----------------------------------\n");)
345 template<class colorT
> inline
346 void _clippedHLine(ABitmap
& bm
, int y
, int x1
, int x2
, colorT color
, DashState
& ds
) {
348 colorT
*p
= (colorT
*)bm
.data() + y
* bm
.modulo
+ x1
;
362 ds
.advance(1 << DashState::fractBits
);
365 if (x1
== x2
&& ds
.isOn()) {
372 template<class colorT
> inline
373 void _clippedVLine(ABitmap
& bm
, int x
, int y1
, int y2
, colorT color
, DashState
& ds
) {
376 colorT
*p
= (colorT
*)bm
.data() + y1
* m
+ x
;
391 ds
.advance(1 << DashState::fractBits
);
394 if (y1
== y2
&& ds
.isOn()) {
401 inline int RoundFP(int xy
, int b
) { return xy
+ (1 << b
- 1) >> b
; }
402 inline int TruncFP(int xy
, int b
) { return xy
>> b
; }
404 // called with y1 < y2
405 // use the exact algorithm of the type1 rasterizer, so that shapes filled
406 // and stroked have a boundary that matches the interior.
407 template<class colorT
> inline
408 void _clippedLine(ABitmap
& bm
, fractpel x1
, fractpel y1
, fractpel x2
, fractpel y2
, colorT color
, DashState
& ds
) {
412 x1
= TruncFP(x1
, FRACTBITS
- PREC
);
413 y1
= TruncFP(y1
, FRACTBITS
- PREC
);
414 x2
= TruncFP(x2
, FRACTBITS
- PREC
);
415 y2
= TruncFP(y2
, FRACTBITS
- PREC
);
416 //dprintf("line x=%d..%d, y=%d..%d, bm %dx%d\n",x1,x2,y1,y2,bm.width,bm.height);
421 int x
= RoundFP(x1
, PREC
);
422 int y
= RoundFP(y1
, PREC
);
424 colorT
*p
= (colorT
*)bm
.data() + y
* m
+ x
;
425 //dprintf("x=%d..%d, y=%d..%d\n",x,RoundFP(x2,PREC),y,RoundFP(y2,PREC));
427 CHECK((colorT
*)bm
.data() + RoundFP(y2
, PREC
) * m
+ RoundFP(x2
, PREC
))
428 int county
= RoundFP(y2
, PREC
) - y
;
429 int countx
= RoundFP(x2
, PREC
) - x
;
435 d
= (dy
* (x1
- (x
<< PREC
) + (1 << (PREC
- 1))) -
436 dx
* ((y
<< PREC
) - y1
+ (1 << (PREC
- 1)))) >> PREC
;
439 d
= (dy
* ((x
<< PREC
) - x1
+ (1 << (PREC
- 1))) -
440 dx
* ((y
<< PREC
) - y1
+ (1 << (PREC
- 1)))) >> PREC
;
443 //dprintf("d=%d dx=%d dy=%d pstep=%d count %d countx %d\n", d,dx,dy,pstep,count,countx);
449 while (--county
>= 0) {
471 while (countx
-- >= 0) {
478 double l
= length(dx
<< DashState::fractBits
, dy
<< DashState::fractBits
);
492 while (--county
>= 0) {
520 while (countx
-- >= 0) {
531 template<class colorT
>
532 inline void clippedLine(ABitmap
& bm
, int x1
, int y1
, int x2
, int y2
, colorT color
) {
534 int adx
= dx
< 0 ? -dx
: dx
;
536 int ady
= dy
< 0 ? -dy
: dy
;
540 int sx
= dx
< 0 ? -1 : 1;
541 colorT
*p
= (colorT
*)bm
.data() + /*y1 * m +*/ x1
;
542 int sy
= (ady
<< 16) / adx
;
543 int ry
= ((ady
<< 16) % adx
) >> 1;
549 y1
+= ry
+ (1 << 15);
551 p
[(y1
>> 16) * m
] = color
;
554 } while (--adx
>= 0);
557 colorT
*p
= (colorT
*)bm
.data() + y1
* m
;
560 int sx
= (adx
<< 16) / ady
;
561 int rx
= ((adx
<< 16) % ady
) >> 1;
567 x1
+= rx
+ (1 << 15);
572 } while (--ady
>= 0);
577 // copy bm2 to bm1 through area. 'area' and 'bm2' *must* be clipped to
578 // the boundary of bm1.
579 template<int BPP
> inline
580 void _clippedCopy(ABitmap
& bm1
, ABitmap
& bm2
, region
* area
) {
582 int modulo1
= bm1
.modulo
* BPP
;
583 int modulo2
= bm2
.modulo
* BPP
;
584 int xoffs1
= bm1
.xoffset
- NEARESTPEL(area
->origin
.x
);
585 int yoffs1
= bm1
.yoffset
- NEARESTPEL(area
->origin
.y
);
586 int xoffs2
= bm2
.xoffset
- bm1
.xoffset
;
587 int yoffs2
= bm2
.yoffset
- bm1
.yoffset
;
588 Guchar
*dest
= (Guchar
*) bm1
.data();
589 const Guchar
*src
= (const Guchar
*) bm2
.data();
590 int width
= bm1
.width
;
591 int height
= bm1
.height
;
593 for (edgelist
*edge
= area
->anchor
; VALIDEDGE(edge
); edge
= edge
->link
->link
) {
594 pel
*leftP
= edge
->xvalues
;
595 pel
*rightP
= edge
->link
->xvalues
;
596 int y1
= edge
->ymin
- yoffs1
;
597 int y2
= edge
->ymax
- yoffs1
;
609 p
= dest
+ y1
* modulo1
;
610 q
= src
+ (y1
- yoffs2
) * modulo2
;
613 int x1
= *leftP
++ - xoffs1
;
614 int x2
= *rightP
++ - xoffs1
;
623 CHECK(p
+ (x2
- 1) * BPP
)
625 q
+ (x1
- xoffs2
) * BPP
, (x2
- x1
) * BPP
);
635 template<class colorT
> inline
636 void _drawPicLine(AOutputDev::DrawPicParams
& params
,
637 int y
, int x1
, int x2
,
638 int xp1
, int yp1
, int xp2
, int yp2
) {
641 IDB(printf("drawPicLine(y=%d, %d -> %d, (%d,%d)->(%d,%d)\n", y
, x1
, x2
, xp1
, yp1
, xp2
, yp2
));
646 dxp
= ((xp2
- xp1
) << 16) / (x2
- x1
);
647 dyp
= ((yp2
- yp1
) << 16) / (x2
- x1
);
658 if (x2
>= params
.bm
->width
)
659 x2
= params
.bm
->width
- 1;
661 int w
= params
.srcWidth
;
662 colorT
*q
= (colorT
*)params
.bm
->data() + y
* params
.bm
->modulo
+ x1
;
664 if (params
.maskSrc
) {
665 const Guchar
*p
= params
.maskSrc
;
666 colorT
c(params
.color
);
668 for (int x
= x1
; x
<= x2
; ++x
) {
669 if (p
[(yp
>> 16) * w
+ (xp
>> 16)])
677 const colorT
*p
= (const colorT
*)params
.src
;
679 for (int x
= x1
; x
<= x2
; ++x
) {
680 *q
++ = p
[(yp
>> 16) * w
+ (xp
>> 16)];