1 //========================================================================
5 //========================================================================
10 #pragma implementation
16 #include "SplashErrorCodes.h"
17 #include "SplashMath.h"
18 #include "SplashBitmap.h"
19 #include "SplashState.h"
20 #include "SplashPath.h"
21 #include "SplashXPath.h"
22 #include "SplashXPathScanner.h"
23 #include "SplashPattern.h"
24 #include "SplashScreen.h"
25 #include "SplashFont.h"
26 #include "SplashGlyphBitmap.h"
29 //------------------------------------------------------------------------
31 static void blendNormal(SplashColorPtr src
, SplashColorPtr dest
,
32 SplashColorPtr blend
, SplashColorMode cm
) {
35 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
40 //------------------------------------------------------------------------
42 //------------------------------------------------------------------------
44 Splash::Splash(SplashBitmap
*bitmapA
) {
46 state
= new SplashState(bitmap
->width
, bitmap
->height
);
62 //------------------------------------------------------------------------
64 //------------------------------------------------------------------------
66 SplashPattern
*Splash::getStrokePattern() {
67 return state
->strokePattern
;
70 SplashPattern
*Splash::getFillPattern() {
71 return state
->fillPattern
;
74 SplashScreen
*Splash::getScreen() {
78 SplashBlendFunc
Splash::getBlendFunc() {
79 return state
->blendFunc
;
82 SplashCoord
Splash::getStrokeAlpha() {
83 return state
->strokeAlpha
;
86 SplashCoord
Splash::getFillAlpha() {
87 return state
->fillAlpha
;
90 SplashCoord
Splash::getLineWidth() {
91 return state
->lineWidth
;
94 int Splash::getLineCap() {
95 return state
->lineCap
;
98 int Splash::getLineJoin() {
99 return state
->lineJoin
;
102 SplashCoord
Splash::getMiterLimit() {
103 return state
->miterLimit
;
106 SplashCoord
Splash::getFlatness() {
107 return state
->flatness
;
110 SplashCoord
*Splash::getLineDash() {
111 return state
->lineDash
;
114 int Splash::getLineDashLength() {
115 return state
->lineDashLength
;
118 SplashCoord
Splash::getLineDashPhase() {
119 return state
->lineDashPhase
;
122 SplashClip
*Splash::getClip() {
126 //------------------------------------------------------------------------
128 //------------------------------------------------------------------------
130 void Splash::setStrokePattern(SplashPattern
*strokePattern
) {
131 state
->setStrokePattern(strokePattern
);
134 void Splash::setFillPattern(SplashPattern
*fillPattern
) {
135 state
->setFillPattern(fillPattern
);
138 void Splash::setScreen(SplashScreen
*screen
) {
139 state
->setScreen(screen
);
142 void Splash::setBlendFunc(SplashBlendFunc func
) {
143 state
->blendFunc
= func
;
146 void Splash::setStrokeAlpha(SplashCoord alpha
) {
147 state
->strokeAlpha
= alpha
;
150 void Splash::setFillAlpha(SplashCoord alpha
) {
151 state
->fillAlpha
= alpha
;
154 void Splash::setLineWidth(SplashCoord lineWidth
) {
155 state
->lineWidth
= lineWidth
;
158 void Splash::setLineCap(int lineCap
) {
159 state
->lineCap
= lineCap
;
162 void Splash::setLineJoin(int lineJoin
) {
163 state
->lineJoin
= lineJoin
;
166 void Splash::setMiterLimit(SplashCoord miterLimit
) {
167 state
->miterLimit
= miterLimit
;
170 void Splash::setFlatness(SplashCoord flatness
) {
174 state
->flatness
= flatness
;
178 void Splash::setLineDash(SplashCoord
*lineDash
, int lineDashLength
,
179 SplashCoord lineDashPhase
) {
180 state
->setLineDash(lineDash
, lineDashLength
, lineDashPhase
);
183 void Splash::clipResetToRect(SplashCoord x0
, SplashCoord y0
,
184 SplashCoord x1
, SplashCoord y1
) {
185 state
->clip
->resetToRect(x0
, y0
, x1
, y1
);
188 SplashError
Splash::clipToRect(SplashCoord x0
, SplashCoord y0
,
189 SplashCoord x1
, SplashCoord y1
) {
190 return state
->clip
->clipToRect(x0
, y0
, x1
, y1
);
193 SplashError
Splash::clipToPath(SplashPath
*path
, GBool eo
) {
194 return state
->clip
->clipToPath(path
, state
->flatness
, eo
);
197 //------------------------------------------------------------------------
198 // state save/restore
199 //------------------------------------------------------------------------
201 void Splash::saveState() {
202 SplashState
*newState
;
204 newState
= state
->copy();
205 newState
->next
= state
;
209 SplashError
Splash::restoreState() {
210 SplashState
*oldState
;
213 return splashErrNoSave
;
221 //------------------------------------------------------------------------
223 //------------------------------------------------------------------------
225 void Splash::setSoftMask(SplashBitmap
*softMaskA
) {
229 softMask
= softMaskA
;
232 //------------------------------------------------------------------------
234 //------------------------------------------------------------------------
236 void Splash::clearModRegion() {
237 modXMin
= bitmap
->getWidth();
238 modYMin
= bitmap
->getHeight();
243 inline void Splash::updateModX(int x
) {
252 inline void Splash::updateModY(int y
) {
261 //------------------------------------------------------------------------
262 // drawing operations
263 //------------------------------------------------------------------------
265 void Splash::clear(SplashColorPtr color
) {
266 SplashColorPtr row
, p
;
270 switch (bitmap
->mode
) {
271 case splashModeMono1
:
272 mono
= color
[0] ? 0xff : 0x00;
273 if (bitmap
->rowSize
< 0) {
274 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
275 mono
, -bitmap
->rowSize
* bitmap
->height
);
277 memset(bitmap
->data
, mono
, bitmap
->rowSize
* bitmap
->height
);
280 case splashModeMono8
:
281 if (bitmap
->rowSize
< 0) {
282 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
283 color
[0], -bitmap
->rowSize
* bitmap
->height
);
285 memset(bitmap
->data
, color
[0], bitmap
->rowSize
* bitmap
->height
);
288 case splashModeAMono8
:
289 if (color
[0] == color
[1]) {
290 if (bitmap
->rowSize
< 0) {
291 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
292 color
[0], -bitmap
->rowSize
* bitmap
->height
);
294 memset(bitmap
->data
, color
[0], bitmap
->rowSize
* bitmap
->height
);
298 for (y
= 0; y
< bitmap
->height
; ++y
) {
300 for (x
= 0; x
< bitmap
->width
; ++x
) {
304 row
+= bitmap
->rowSize
;
310 if (color
[0] == color
[1] && color
[1] == color
[2]) {
311 if (bitmap
->rowSize
< 0) {
312 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
313 color
[0], -bitmap
->rowSize
* bitmap
->height
);
315 memset(bitmap
->data
, color
[0], bitmap
->rowSize
* bitmap
->height
);
319 for (y
= 0; y
< bitmap
->height
; ++y
) {
321 for (x
= 0; x
< bitmap
->width
; ++x
) {
326 row
+= bitmap
->rowSize
;
330 case splashModeARGB8
:
331 case splashModeBGRA8
:
333 case splashModeCMYK8
:
335 if (color
[0] == color
[1] && color
[1] == color
[2] && color
[2] == color
[3]) {
336 if (bitmap
->rowSize
< 0) {
337 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
338 color
[0], -bitmap
->rowSize
* bitmap
->height
);
340 memset(bitmap
->data
, color
[0], bitmap
->rowSize
* bitmap
->height
);
344 for (y
= 0; y
< bitmap
->height
; ++y
) {
346 for (x
= 0; x
< bitmap
->width
; ++x
) {
352 row
+= bitmap
->rowSize
;
357 case splashModeACMYK8
:
358 if (color
[0] == color
[1] && color
[1] == color
[2] &&
359 color
[2] == color
[3] && color
[3] == color
[4]) {
360 if (bitmap
->rowSize
< 0) {
361 memset(bitmap
->data
+ bitmap
->rowSize
* (bitmap
->height
- 1),
362 color
[0], -bitmap
->rowSize
* bitmap
->height
);
364 memset(bitmap
->data
, color
[0], bitmap
->rowSize
* bitmap
->height
);
368 for (y
= 0; y
< bitmap
->height
; ++y
) {
370 for (x
= 0; x
< bitmap
->width
; ++x
) {
377 row
+= bitmap
->rowSize
;
386 updateModX(bitmap
->width
- 1);
387 updateModY(bitmap
->height
- 1);
390 SplashError
Splash::stroke(SplashPath
*path
) {
391 SplashXPath
*xPath
, *xPath2
;
394 printf("stroke [dash:%d] [width:%.2f]:\n",
395 state
->lineDashLength
, (double)state
->lineWidth
);
398 opClipRes
= splashClipAllOutside
;
399 if (path
->length
== 0) {
400 return splashErrEmptyPath
;
402 xPath
= new SplashXPath(path
, state
->flatness
, gFalse
);
403 if (xPath
->length
== 0) {
405 return splashErrEmptyPath
;
407 if (state
->lineDashLength
> 0) {
408 xPath2
= makeDashedPath(xPath
);
412 if (state
->lineWidth
<= 1) {
421 void Splash::strokeNarrow(SplashXPath
*xPath
) {
423 int x0
, x1
, x2
, x3
, y0
, y1
, x
, y
, t
;
424 SplashCoord dx
, dy
, dxdy
;
425 SplashClipResult clipRes
;
429 for (i
= 0, seg
= xPath
->segs
; i
< xPath
->length
; ++i
, ++seg
) {
431 x0
= splashFloor(seg
->x0
);
432 x1
= splashFloor(seg
->x1
);
433 y0
= splashFloor(seg
->y0
);
434 y1
= splashFloor(seg
->y1
);
436 // horizontal segment
439 t
= x0
; x0
= x1
; x1
= t
;
441 if ((clipRes
= state
->clip
->testSpan(x0
, x1
, y0
))
442 != splashClipAllOutside
) {
443 drawSpan(x0
, x1
, y0
, state
->strokePattern
, state
->strokeAlpha
,
444 clipRes
== splashClipAllInside
);
447 // segment with |dx| > |dy|
448 } else if (splashAbs(seg
->dxdy
) > 1) {
449 dx
= seg
->x1
- seg
->x0
;
450 dy
= seg
->y1
- seg
->y0
;
453 t
= y0
; y0
= y1
; y1
= t
;
454 t
= x0
; x0
= x1
; x1
= t
;
458 if ((clipRes
= state
->clip
->testRect(x0
<= x1
? x0
: x1
, y0
,
459 x0
<= x1
? x1
: x0
, y1
))
460 != splashClipAllOutside
) {
463 x3
= splashFloor(seg
->x0
+ ((SplashCoord
)y0
+ 1 - seg
->y0
) * dxdy
);
464 drawSpan(x2
, (x2
<= x3
- 1) ? x3
- 1 : x2
, y0
, state
->strokePattern
,
465 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
467 for (y
= y0
+ 1; y
<= y1
- 1; ++y
) {
468 x3
= splashFloor(seg
->x0
+ ((SplashCoord
)y
+ 1 - seg
->y0
) * dxdy
);
469 drawSpan(x2
, x3
- 1, y
, state
->strokePattern
,
470 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
473 drawSpan(x2
, x2
<= x1
? x1
: x2
, y1
, state
->strokePattern
,
474 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
477 x3
= splashFloor(seg
->x0
+ ((SplashCoord
)y0
+ 1 - seg
->y0
) * dxdy
);
478 drawSpan((x3
+ 1 <= x2
) ? x3
+ 1 : x2
, x2
, y0
, state
->strokePattern
,
479 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
481 for (y
= y0
+ 1; y
<= y1
- 1; ++y
) {
482 x3
= splashFloor(seg
->x0
+ ((SplashCoord
)y
+ 1 - seg
->y0
) * dxdy
);
483 drawSpan(x3
+ 1, x2
, y
, state
->strokePattern
,
484 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
487 drawSpan(x1
, (x1
<= x2
) ? x2
: x1
, y1
, state
->strokePattern
,
488 state
->strokeAlpha
, clipRes
== splashClipAllInside
);
492 // segment with |dy| > |dx|
496 t
= x0
; x0
= x1
; x1
= t
;
497 t
= y0
; y0
= y1
; y1
= t
;
499 if ((clipRes
= state
->clip
->testRect(x0
<= x1
? x0
: x1
, y0
,
500 x0
<= x1
? x1
: x0
, y1
))
501 != splashClipAllOutside
) {
502 drawPixel(x0
, y0
, state
->strokePattern
, state
->strokeAlpha
,
503 clipRes
== splashClipAllInside
);
504 for (y
= y0
+ 1; y
<= y1
- 1; ++y
) {
505 x
= splashFloor(seg
->x0
+ ((SplashCoord
)y
- seg
->y0
) * dxdy
);
506 drawPixel(x
, y
, state
->strokePattern
, state
->strokeAlpha
,
507 clipRes
== splashClipAllInside
);
509 drawPixel(x1
, y1
, state
->strokePattern
, state
->strokeAlpha
,
510 clipRes
== splashClipAllInside
);
515 if (nClipRes
[splashClipPartial
] ||
516 (nClipRes
[splashClipAllInside
] && nClipRes
[splashClipAllOutside
])) {
517 opClipRes
= splashClipPartial
;
518 } else if (nClipRes
[splashClipAllInside
]) {
519 opClipRes
= splashClipAllInside
;
521 opClipRes
= splashClipAllOutside
;
525 void Splash::strokeWide(SplashXPath
*xPath
) {
526 SplashXPathSeg
*seg
, *seg2
;
527 SplashPath
*widePath
;
528 SplashCoord d
, dx
, dy
, wdx
, wdy
, dxPrev
, dyPrev
, wdxPrev
, wdyPrev
;
529 SplashCoord dotprod
, miter
;
532 dx
= dy
= wdx
= wdy
= 0; // make gcc happy
533 dxPrev
= dyPrev
= wdxPrev
= wdyPrev
= 0; // make gcc happy
535 for (i
= 0, seg
= xPath
->segs
; i
< xPath
->length
; ++i
, ++seg
) {
537 // save the deltas for the previous segment; if this is the first
538 // segment on a subpath, compute the deltas for the last segment
539 // on the subpath (which may be used to draw a line join)
540 if (seg
->flags
& splashXPathFirst
) {
541 for (j
= i
+ 1, seg2
= &xPath
->segs
[j
]; j
< xPath
->length
; ++j
, ++seg2
) {
542 if (seg2
->flags
& splashXPathLast
) {
543 d
= splashDist(seg2
->x0
, seg2
->y0
, seg2
->x1
, seg2
->y1
);
545 //~ not clear what the behavior should be for joins with d==0
549 d
= (SplashCoord
)1 / d
;
550 dxPrev
= d
* (seg2
->x1
- seg2
->x0
);
551 dyPrev
= d
* (seg2
->y1
- seg2
->y0
);
553 wdxPrev
= (SplashCoord
)0.5 * state
->lineWidth
* dxPrev
;
554 wdyPrev
= (SplashCoord
)0.5 * state
->lineWidth
* dyPrev
;
565 // compute deltas for this line segment
566 d
= splashDist(seg
->x0
, seg
->y0
, seg
->x1
, seg
->y1
);
568 // we need to draw end caps on zero-length lines
569 //~ not clear what the behavior should be for splashLineCapButt with d==0
573 d
= (SplashCoord
)1 / d
;
574 dx
= d
* (seg
->x1
- seg
->x0
);
575 dy
= d
* (seg
->y1
- seg
->y0
);
577 wdx
= (SplashCoord
)0.5 * state
->lineWidth
* dx
;
578 wdy
= (SplashCoord
)0.5 * state
->lineWidth
* dy
;
580 // initialize the path (which will be filled)
581 widePath
= new SplashPath();
582 widePath
->moveTo(seg
->x0
- wdy
, seg
->y0
+ wdx
);
584 // draw the start cap
585 if (seg
->flags
& splashXPathEnd0
) {
586 switch (state
->lineCap
) {
587 case splashLineCapButt
:
588 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
590 case splashLineCapRound
:
591 widePath
->arcCWTo(seg
->x0
+ wdy
, seg
->y0
- wdx
, seg
->x0
, seg
->y0
);
593 case splashLineCapProjecting
:
594 widePath
->lineTo(seg
->x0
- wdx
- wdy
, seg
->y0
+ wdx
- wdy
);
595 widePath
->lineTo(seg
->x0
- wdx
+ wdy
, seg
->y0
- wdx
- wdy
);
596 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
600 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
603 // draw the left side of the segment
604 widePath
->lineTo(seg
->x1
+ wdy
, seg
->y1
- wdx
);
607 if (seg
->flags
& splashXPathEnd1
) {
608 switch (state
->lineCap
) {
609 case splashLineCapButt
:
610 widePath
->lineTo(seg
->x1
- wdy
, seg
->y1
+ wdx
);
612 case splashLineCapRound
:
613 widePath
->arcCWTo(seg
->x1
- wdy
, seg
->y1
+ wdx
, seg
->x1
, seg
->y1
);
615 case splashLineCapProjecting
:
616 widePath
->lineTo(seg
->x1
+ wdx
+ wdy
, seg
->y1
- wdx
+ wdy
);
617 widePath
->lineTo(seg
->x1
+ wdx
- wdy
, seg
->y1
+ wdx
+ wdy
);
618 widePath
->lineTo(seg
->x1
- wdy
, seg
->y1
+ wdx
);
622 widePath
->lineTo(seg
->x1
- wdy
, seg
->y1
+ wdx
);
625 // draw the right side of the segment
626 widePath
->lineTo(seg
->x0
- wdy
, seg
->y0
+ wdx
);
629 fillWithPattern(widePath
, gTrue
, state
->strokePattern
, state
->strokeAlpha
);
632 // draw the line join
633 if (!(seg
->flags
& splashXPathEnd0
)) {
635 switch (state
->lineJoin
) {
636 case splashLineJoinMiter
:
637 dotprod
= -(dx
* dxPrev
+ dy
* dyPrev
);
638 if (splashAbs(splashAbs(dotprod
) - 1) > 0.01) {
639 widePath
= new SplashPath();
640 widePath
->moveTo(seg
->x0
, seg
->y0
);
641 miter
= (SplashCoord
)2 / ((SplashCoord
)1 - dotprod
);
642 if (splashSqrt(miter
) <= state
->miterLimit
) {
643 miter
= splashSqrt(miter
- 1);
644 if (dy
* dxPrev
> dx
* dyPrev
) {
645 widePath
->lineTo(seg
->x0
+ wdyPrev
, seg
->y0
- wdxPrev
);
646 widePath
->lineTo(seg
->x0
+ wdy
- miter
* wdx
,
647 seg
->y0
- wdx
- miter
* wdy
);
648 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
650 widePath
->lineTo(seg
->x0
- wdyPrev
, seg
->y0
+ wdxPrev
);
651 widePath
->lineTo(seg
->x0
- wdy
- miter
* wdx
,
652 seg
->y0
+ wdx
- miter
* wdy
);
653 widePath
->lineTo(seg
->x0
- wdy
, seg
->y0
+ wdx
);
656 if (dy
* dxPrev
> dx
* dyPrev
) {
657 widePath
->lineTo(seg
->x0
+ wdyPrev
, seg
->y0
- wdxPrev
);
658 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
660 widePath
->lineTo(seg
->x0
- wdyPrev
, seg
->y0
+ wdxPrev
);
661 widePath
->lineTo(seg
->x0
- wdy
, seg
->y0
+ wdx
);
666 case splashLineJoinRound
:
667 widePath
= new SplashPath();
668 widePath
->moveTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
669 widePath
->arcCWTo(seg
->x0
+ wdy
, seg
->y0
- wdx
, seg
->x0
, seg
->y0
);
671 case splashLineJoinBevel
:
672 widePath
= new SplashPath();
673 widePath
->moveTo(seg
->x0
, seg
->y0
);
674 if (dy
* dxPrev
> dx
* dyPrev
) {
675 widePath
->lineTo(seg
->x0
+ wdyPrev
, seg
->y0
- wdxPrev
);
676 widePath
->lineTo(seg
->x0
+ wdy
, seg
->y0
- wdx
);
678 widePath
->lineTo(seg
->x0
- wdyPrev
, seg
->y0
+ wdxPrev
);
679 widePath
->lineTo(seg
->x0
- wdy
, seg
->y0
+ wdx
);
684 fillWithPattern(widePath
, gTrue
, state
->strokePattern
,
692 SplashXPath
*Splash::makeDashedPath(SplashXPath
*xPath
) {
694 GBool lineDashStartOn
, lineDashOn
;
695 GBool atSegStart
, atSegEnd
, atDashStart
, atDashEnd
;
696 int lineDashStartIdx
, lineDashIdx
, subpathStart
;
697 SplashCoord lineDashTotal
, lineDashStartPhase
, lineDashDist
;
700 SplashCoord sx0
, sy0
, sx1
, sy1
, ax0
, ay0
, ax1
, ay1
, dist
;
703 dPath
= new SplashXPath();
706 for (i
= 0; i
< state
->lineDashLength
; ++i
) {
707 lineDashTotal
+= state
->lineDash
[i
];
709 lineDashStartPhase
= state
->lineDashPhase
;
710 i
= splashFloor(lineDashStartPhase
/ lineDashTotal
);
711 lineDashStartPhase
-= (SplashCoord
)i
* lineDashTotal
;
712 lineDashStartOn
= gTrue
;
713 lineDashStartIdx
= 0;
714 while (lineDashStartPhase
>= state
->lineDash
[lineDashStartIdx
]) {
715 lineDashStartOn
= !lineDashStartOn
;
716 lineDashStartPhase
-= state
->lineDash
[lineDashStartIdx
];
726 dist
= splashDist(sx0
, sy0
, sx1
, sy1
);
727 lineDashOn
= lineDashStartOn
;
728 lineDashIdx
= lineDashStartIdx
;
729 lineDashDist
= state
->lineDash
[lineDashIdx
] - lineDashStartPhase
;
732 subpathStart
= dPath
->length
;
734 while (segIdx
< xPath
->length
) {
738 if (dist
<= lineDashDist
) {
741 lineDashDist
-= dist
;
744 atDashEnd
= lineDashDist
== 0 || (seg
->flags
& splashXPathLast
);
746 ax1
= sx0
+ (lineDashDist
/ dist
) * (sx1
- sx0
);
747 ay1
= sy0
+ (lineDashDist
/ dist
) * (sy1
- sy0
);
750 dist
-= lineDashDist
;
757 dPath
->addSegment(ax0
, ay0
, ax1
, ay1
,
758 atDashStart
, atDashEnd
,
759 atDashStart
, atDashEnd
);
760 // end of closed subpath
762 (seg
->flags
& splashXPathLast
) &&
763 !(seg
->flags
& splashXPathEnd1
)) {
764 dPath
->segs
[subpathStart
].flags
&= ~splashXPathEnd0
;
765 dPath
->segs
[dPath
->length
- 1].flags
&= ~splashXPathEnd1
;
770 lineDashOn
= !lineDashOn
;
771 if (++lineDashIdx
== state
->lineDashLength
) {
774 lineDashDist
= state
->lineDash
[lineDashIdx
];
777 atDashStart
= gFalse
;
780 if (++segIdx
< xPath
->length
) {
786 dist
= splashDist(sx0
, sy0
, sx1
, sy1
);
787 if (seg
->flags
& splashXPathFirst
) {
788 lineDashOn
= lineDashStartOn
;
789 lineDashIdx
= lineDashStartIdx
;
790 lineDashDist
= state
->lineDash
[lineDashIdx
] - lineDashStartPhase
;
792 subpathStart
= dPath
->length
;
804 SplashError
Splash::fill(SplashPath
*path
, GBool eo
) {
806 printf("fill [eo:%d]:\n", eo
);
809 return fillWithPattern(path
, eo
, state
->fillPattern
, state
->fillAlpha
);
812 SplashError
Splash::fillWithPattern(SplashPath
*path
, GBool eo
,
813 SplashPattern
*pattern
,
816 SplashXPathScanner
*scanner
;
817 int xMinI
, yMinI
, xMaxI
, yMaxI
, x0
, x1
, y
;
818 SplashClipResult clipRes
, clipRes2
;
820 if (path
->length
== 0) {
821 return splashErrEmptyPath
;
823 xPath
= new SplashXPath(path
, state
->flatness
, gTrue
);
825 scanner
= new SplashXPathScanner(xPath
, eo
);
827 // get the min and max x and y values
828 scanner
->getBBox(&xMinI
, &yMinI
, &xMaxI
, &yMaxI
);
831 if ((clipRes
= state
->clip
->testRect(xMinI
, yMinI
, xMaxI
, yMaxI
))
832 != splashClipAllOutside
) {
835 if (yMinI
< state
->clip
->getYMin()) {
836 yMinI
= state
->clip
->getYMin();
838 if (yMaxI
> state
->clip
->getYMax()) {
839 yMaxI
= state
->clip
->getYMax();
843 for (y
= yMinI
; y
<= yMaxI
; ++y
) {
844 while (scanner
->getNextSpan(y
, &x0
, &x1
)) {
845 if (clipRes
== splashClipAllInside
) {
846 drawSpan(x0
, x1
, y
, pattern
, alpha
, gTrue
);
849 if (x0
< state
->clip
->getXMin()) {
850 x0
= state
->clip
->getXMin();
852 if (x1
> state
->clip
->getXMax()) {
853 x1
= state
->clip
->getXMax();
855 clipRes2
= state
->clip
->testSpan(x0
, x1
, y
);
856 drawSpan(x0
, x1
, y
, pattern
, alpha
, clipRes2
== splashClipAllInside
);
868 SplashError
Splash::xorFill(SplashPath
*path
, GBool eo
) {
870 SplashXPathScanner
*scanner
;
871 int xMinI
, yMinI
, xMaxI
, yMaxI
, x0
, x1
, y
;
872 SplashClipResult clipRes
, clipRes2
;
874 if (path
->length
== 0) {
875 return splashErrEmptyPath
;
877 xPath
= new SplashXPath(path
, state
->flatness
, gTrue
);
879 scanner
= new SplashXPathScanner(xPath
, eo
);
881 // get the min and max x and y values
882 scanner
->getBBox(&xMinI
, &yMinI
, &xMaxI
, &yMaxI
);
885 if ((clipRes
= state
->clip
->testRect(xMinI
, yMinI
, xMaxI
, yMaxI
))
886 != splashClipAllOutside
) {
889 if (yMinI
< state
->clip
->getYMin()) {
890 yMinI
= state
->clip
->getYMin();
892 if (yMaxI
> state
->clip
->getYMax()) {
893 yMaxI
= state
->clip
->getYMax();
897 for (y
= yMinI
; y
<= yMaxI
; ++y
) {
898 while (scanner
->getNextSpan(y
, &x0
, &x1
)) {
899 if (clipRes
== splashClipAllInside
) {
900 xorSpan(x0
, x1
, y
, state
->fillPattern
, gTrue
);
903 if (x0
< state
->clip
->getXMin()) {
904 x0
= state
->clip
->getXMin();
906 if (x1
> state
->clip
->getXMax()) {
907 x1
= state
->clip
->getXMax();
909 clipRes2
= state
->clip
->testSpan(x0
, x1
, y
);
910 xorSpan(x0
, x1
, y
, state
->fillPattern
,
911 clipRes2
== splashClipAllInside
);
923 void Splash::drawPixel(int x
, int y
, SplashColorPtr color
,
924 SplashCoord alpha
, GBool noClip
) {
925 SplashBlendFunc blendFunc
;
927 SplashColor dest
, blend
;
931 if (noClip
|| state
->clip
->test(x
, y
)) {
932 if (alpha
!= 1 || softMask
|| state
->blendFunc
) {
933 blendFunc
= state
->blendFunc
? state
->blendFunc
: &blendNormal
;
935 alpha2
= (int)(alpha
* softMask
->data
[y
* softMask
->rowSize
+ x
]);
937 alpha2
= (int)(alpha
* 255);
939 ialpha2
= 255 - alpha2
;
940 switch (bitmap
->mode
) {
941 case splashModeMono1
:
942 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x
>> 3)];
943 dest
[0] = (*p
>> (7 - (x
& 7))) & 1;
944 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
945 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
947 *p
|= 0x80 >> (x
& 7);
949 *p
&= ~(0x80 >> (x
& 7));
952 case splashModeMono8
:
953 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x
];
954 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
955 // note: floor(x / 255) = x >> 8 (for 16-bit x)
956 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
958 case splashModeAMono8
:
959 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x
];
960 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
961 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
962 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
966 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x
];
967 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
968 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
969 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
970 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
972 case splashModeARGB8
:
973 case splashModeBGRA8
:
975 case splashModeCMYK8
:
977 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x
];
978 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
979 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
980 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
981 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
982 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
985 case splashModeACMYK8
:
986 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x
];
987 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
988 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
989 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
990 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
991 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
992 p
[4] = (alpha2
* blend
[4] + ialpha2
* p
[4]) >> 8;
997 switch (bitmap
->mode
) {
998 case splashModeMono1
:
999 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x
>> 3)];
1001 *p
|= 0x80 >> (x
& 7);
1003 *p
&= ~(0x80 >> (x
& 7));
1006 case splashModeMono8
:
1007 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x
];
1010 case splashModeAMono8
:
1011 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x
];
1015 case splashModeRGB8
:
1016 case splashModeBGR8
:
1017 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x
];
1022 case splashModeARGB8
:
1023 case splashModeBGRA8
:
1025 case splashModeCMYK8
:
1027 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x
];
1034 case splashModeACMYK8
:
1035 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x
];
1050 void Splash::drawPixel(int x
, int y
, SplashPattern
*pattern
,
1051 SplashCoord alpha
, GBool noClip
) {
1052 SplashBlendFunc blendFunc
;
1055 SplashColor dest
, blend
;
1056 int alpha2
, ialpha2
;
1059 if (noClip
|| state
->clip
->test(x
, y
)) {
1060 if (alpha
!= 1 || softMask
|| state
->blendFunc
) {
1061 blendFunc
= state
->blendFunc
? state
->blendFunc
: &blendNormal
;
1062 pattern
->getColor(x
, y
, color
);
1064 alpha2
= (int)(alpha
* softMask
->data
[y
* softMask
->rowSize
+ x
]);
1066 alpha2
= (int)(alpha
* 255);
1068 ialpha2
= 255 - alpha2
;
1069 switch (bitmap
->mode
) {
1070 case splashModeMono1
:
1071 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x
>> 3)];
1072 dest
[0] = (*p
>> (7 - (x
& 7))) & 1;
1073 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
1074 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
1076 *p
|= 0x80 >> (x
& 7);
1078 *p
&= ~(0x80 >> (x
& 7));
1081 case splashModeMono8
:
1082 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x
];
1083 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1084 // note: floor(x / 255) = x >> 8 (for 16-bit x)
1085 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1087 case splashModeAMono8
:
1088 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x
];
1089 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1090 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1091 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1093 case splashModeRGB8
:
1094 case splashModeBGR8
:
1095 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x
];
1096 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1097 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1098 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1099 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1101 case splashModeARGB8
:
1102 case splashModeBGRA8
:
1104 case splashModeCMYK8
:
1106 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x
];
1107 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1108 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1109 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1110 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1111 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1114 case splashModeACMYK8
:
1115 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x
];
1116 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1117 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1118 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1119 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1120 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1121 p
[4] = (alpha2
* blend
[4] + ialpha2
* p
[4]) >> 8;
1126 pattern
->getColor(x
, y
, color
);
1127 switch (bitmap
->mode
) {
1128 case splashModeMono1
:
1129 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x
>> 3)];
1131 *p
|= 0x80 >> (x
& 7);
1133 *p
&= ~(0x80 >> (x
& 7));
1136 case splashModeMono8
:
1137 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x
];
1140 case splashModeAMono8
:
1141 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x
];
1145 case splashModeRGB8
:
1146 case splashModeBGR8
:
1147 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x
];
1152 case splashModeARGB8
:
1153 case splashModeBGRA8
:
1155 case splashModeCMYK8
:
1157 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x
];
1164 case splashModeACMYK8
:
1165 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x
];
1180 void Splash::drawSpan(int x0
, int x1
, int y
, SplashPattern
*pattern
,
1181 SplashCoord alpha
, GBool noClip
) {
1182 SplashBlendFunc blendFunc
;
1185 SplashColor dest
, blend
;
1187 int alpha2
, ialpha2
;
1198 if (alpha
!= 1 || softMask
|| state
->blendFunc
) {
1199 blendFunc
= state
->blendFunc
? state
->blendFunc
: &blendNormal
;
1201 alpha2
= ialpha2
= 0; // make gcc happy
1203 alpha2
= (int)(alpha
* 255);
1204 ialpha2
= 255 - alpha2
;
1206 switch (bitmap
->mode
) {
1207 case splashModeMono1
:
1208 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x0
>> 3)];
1210 if (pattern
->isStatic()) {
1211 pattern
->getColor(0, 0, color
);
1214 for (; j
< 8 && i
< n
; ++i
, ++j
) {
1215 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1217 alpha2
= (int)(alpha
*
1218 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1219 ialpha2
= 255 - alpha2
;
1221 dest
[0] = (*p
>> (7 - j
)) & 1;
1222 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
1223 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
1240 for (j
= 0; j
< 8 && i
< n
; ++i
, ++j
) {
1241 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1243 alpha2
= (int)(alpha
*
1244 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1245 ialpha2
= 255 - alpha2
;
1247 dest
[0] = (*p
>> (7 - j
)) & 1;
1248 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
1249 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
1267 for (; j
< 8 && i
< n
; ++i
, ++j
) {
1268 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1269 pattern
->getColor(x0
+ i
, y
, color
);
1271 alpha2
= (int)(alpha
*
1272 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1273 ialpha2
= 255 - alpha2
;
1275 dest
[0] = (*p
>> (7 - j
)) & 1;
1276 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
1277 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
1294 for (j
= 0; j
< 8 && i
< n
; ++i
, ++j
) {
1295 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1296 pattern
->getColor(x0
+ i
, y
, color
);
1298 alpha2
= (int)(alpha
*
1299 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1300 ialpha2
= 255 - alpha2
;
1302 dest
[0] = (*p
>> (7 - j
)) & 1;
1303 (*blendFunc
)(color
, dest
, blend
, bitmap
->mode
);
1304 t
= (alpha2
* blend
[0] + ialpha2
* dest
[0]) >> 8;
1322 case splashModeMono8
:
1323 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x0
];
1324 if (pattern
->isStatic()) {
1325 pattern
->getColor(0, 0, color
);
1326 for (i
= 0; i
< n
; ++i
) {
1327 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1329 alpha2
= (int)(alpha
*
1330 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1331 ialpha2
= 255 - alpha2
;
1333 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1334 *p
= (alpha2
* blend
[0] + ialpha2
* *p
) >> 8;
1343 for (i
= 0; i
< n
; ++i
) {
1344 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1345 pattern
->getColor(x0
+ i
, y
, color
);
1347 alpha2
= (int)(alpha
*
1348 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1349 ialpha2
= 255 - alpha2
;
1351 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1352 *p
= (alpha2
* blend
[0] + ialpha2
* *p
) >> 8;
1363 case splashModeAMono8
:
1364 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x0
];
1365 if (pattern
->isStatic()) {
1366 pattern
->getColor(0, 0, color
);
1367 for (i
= 0; i
< n
; ++i
) {
1368 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1370 alpha2
= (int)(alpha
*
1371 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1372 ialpha2
= 255 - alpha2
;
1374 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1375 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1376 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1385 for (i
= 0; i
< n
; ++i
) {
1386 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1387 pattern
->getColor(x0
+ i
, y
, color
);
1389 alpha2
= (int)(alpha
*
1390 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1391 ialpha2
= 255 - alpha2
;
1393 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1394 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1395 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1406 case splashModeRGB8
:
1407 case splashModeBGR8
:
1408 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x0
];
1409 if (pattern
->isStatic()) {
1410 pattern
->getColor(0, 0, color
);
1411 for (i
= 0; i
< n
; ++i
) {
1412 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1414 alpha2
= (int)(alpha
*
1415 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1416 ialpha2
= 255 - alpha2
;
1418 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1419 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1420 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1421 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1430 for (i
= 0; i
< n
; ++i
) {
1431 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1432 pattern
->getColor(x0
+ i
, y
, color
);
1434 alpha2
= (int)(alpha
*
1435 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1436 ialpha2
= 255 - alpha2
;
1438 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1439 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1440 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1441 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1452 case splashModeARGB8
:
1453 case splashModeBGRA8
:
1455 case splashModeCMYK8
:
1457 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x0
];
1458 if (pattern
->isStatic()) {
1459 pattern
->getColor(0, 0, color
);
1460 for (i
= 0; i
< n
; ++i
) {
1461 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1463 alpha2
= (int)(alpha
*
1464 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1465 ialpha2
= 255 - alpha2
;
1467 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1468 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1469 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1470 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1471 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1480 for (i
= 0; i
< n
; ++i
) {
1481 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1482 pattern
->getColor(x0
+ i
, y
, color
);
1484 alpha2
= (int)(alpha
*
1485 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1486 ialpha2
= 255 - alpha2
;
1488 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1489 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1490 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1491 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1492 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1503 case splashModeACMYK8
:
1504 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x0
];
1505 if (pattern
->isStatic()) {
1506 pattern
->getColor(0, 0, color
);
1507 for (i
= 0; i
< n
; ++i
) {
1508 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1510 alpha2
= (int)(alpha
*
1511 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1512 ialpha2
= 255 - alpha2
;
1514 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1515 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1516 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1517 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1518 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1519 p
[4] = (alpha2
* blend
[4] + ialpha2
* p
[4]) >> 8;
1528 for (i
= 0; i
< n
; ++i
) {
1529 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1530 pattern
->getColor(x0
+ i
, y
, color
);
1532 alpha2
= (int)(alpha
*
1533 softMask
->data
[y
* softMask
->rowSize
+ x0
+ i
]);
1534 ialpha2
= 255 - alpha2
;
1536 (*blendFunc
)(color
, p
, blend
, bitmap
->mode
);
1537 p
[0] = (alpha2
* blend
[0] + ialpha2
* p
[0]) >> 8;
1538 p
[1] = (alpha2
* blend
[1] + ialpha2
* p
[1]) >> 8;
1539 p
[2] = (alpha2
* blend
[2] + ialpha2
* p
[2]) >> 8;
1540 p
[3] = (alpha2
* blend
[3] + ialpha2
* p
[3]) >> 8;
1541 p
[4] = (alpha2
* blend
[4] + ialpha2
* p
[4]) >> 8;
1555 switch (bitmap
->mode
) {
1556 case splashModeMono1
:
1557 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x0
>> 3)];
1559 if (pattern
->isStatic()) {
1560 pattern
->getColor(0, 0, color
);
1563 for (; j
< 8 && i
< n
; ++i
, ++j
) {
1564 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1581 for (j
= 0; j
< 8 && i
< n
; ++i
, ++j
) {
1582 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1600 for (; j
< 8 && i
< n
; ++i
, ++j
) {
1601 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1602 pattern
->getColor(x0
+ i
, y
, color
);
1619 for (j
= 0; j
< 8 && i
< n
; ++i
, ++j
) {
1620 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1621 pattern
->getColor(x0
+ i
, y
, color
);
1639 case splashModeMono8
:
1640 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x0
];
1641 if (pattern
->isStatic()) {
1642 pattern
->getColor(0, 0, color
);
1643 for (i
= 0; i
< n
; ++i
) {
1644 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1654 for (i
= 0; i
< n
; ++i
) {
1655 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1656 pattern
->getColor(x0
+ i
, y
, color
);
1668 case splashModeAMono8
:
1669 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x0
];
1670 if (pattern
->isStatic()) {
1671 pattern
->getColor(0, 0, color
);
1672 for (i
= 0; i
< n
; ++i
) {
1673 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1684 for (i
= 0; i
< n
; ++i
) {
1685 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1686 pattern
->getColor(x0
+ i
, y
, color
);
1699 case splashModeRGB8
:
1700 case splashModeBGR8
:
1701 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x0
];
1702 if (pattern
->isStatic()) {
1703 pattern
->getColor(0, 0, color
);
1704 for (i
= 0; i
< n
; ++i
) {
1705 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1717 for (i
= 0; i
< n
; ++i
) {
1718 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1719 pattern
->getColor(x0
+ i
, y
, color
);
1733 case splashModeARGB8
:
1734 case splashModeBGRA8
:
1736 case splashModeCMYK8
:
1738 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x0
];
1739 if (pattern
->isStatic()) {
1740 pattern
->getColor(0, 0, color
);
1741 for (i
= 0; i
< n
; ++i
) {
1742 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1755 for (i
= 0; i
< n
; ++i
) {
1756 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1757 pattern
->getColor(x0
+ i
, y
, color
);
1772 case splashModeACMYK8
:
1773 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x0
];
1774 if (pattern
->isStatic()) {
1775 pattern
->getColor(0, 0, color
);
1776 for (i
= 0; i
< n
; ++i
) {
1777 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1791 for (i
= 0; i
< n
; ++i
) {
1792 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1793 pattern
->getColor(x0
+ i
, y
, color
);
1813 void Splash::xorSpan(int x0
, int x1
, int y
, SplashPattern
*pattern
,
1828 switch (bitmap
->mode
) {
1829 case splashModeMono1
:
1830 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ (x0
>> 3)];
1834 for (; j
< 8 && i
< n
; ++i
, ++j
) {
1835 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1836 pattern
->getColor(x0
+ i
, y
, color
);
1851 for (j
= 0; j
< 8 && i
< n
; ++i
, ++j
) {
1852 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1853 pattern
->getColor(x0
+ i
, y
, color
);
1868 case splashModeMono8
:
1869 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ x0
];
1870 for (i
= 0; i
< n
; ++i
) {
1871 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1872 pattern
->getColor(x0
+ i
, y
, color
);
1883 case splashModeAMono8
:
1884 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 2 * x0
];
1885 for (i
= 0; i
< n
; ++i
) {
1886 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1887 pattern
->getColor(x0
+ i
, y
, color
);
1899 case splashModeRGB8
:
1900 case splashModeBGR8
:
1901 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 3 * x0
];
1902 for (i
= 0; i
< n
; ++i
) {
1903 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1904 pattern
->getColor(x0
+ i
, y
, color
);
1917 case splashModeARGB8
:
1918 case splashModeBGRA8
:
1920 case splashModeCMYK8
:
1922 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 4 * x0
];
1923 for (i
= 0; i
< n
; ++i
) {
1924 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1925 pattern
->getColor(x0
+ i
, y
, color
);
1939 case splashModeACMYK8
:
1940 p
= &bitmap
->data
[y
* bitmap
->rowSize
+ 5 * x0
];
1941 for (i
= 0; i
< n
; ++i
) {
1942 if (noClip
|| state
->clip
->test(x0
+ i
, y
)) {
1943 pattern
->getColor(x0
+ i
, y
, color
);
1961 SplashError
Splash::fillChar(SplashCoord x
, SplashCoord y
,
1962 int c
, SplashFont
*font
) {
1963 SplashGlyphBitmap glyph
;
1964 int x0
, y0
, xFrac
, yFrac
;
1968 printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n",
1969 (double)x
, (double)y
, c
, c
, c
);
1971 x0
= splashFloor(x
);
1972 xFrac
= splashFloor((x
- x0
) * splashFontFraction
);
1973 y0
= splashFloor(y
);
1974 yFrac
= splashFloor((y
- y0
) * splashFontFraction
);
1975 if (!font
->getGlyph(c
, xFrac
, yFrac
, &glyph
)) {
1976 return splashErrNoGlyph
;
1978 err
= fillGlyph(x
, y
, &glyph
);
1979 if (glyph
.freeData
) {
1985 SplashError
Splash::fillGlyph(SplashCoord x
, SplashCoord y
,
1986 SplashGlyphBitmap
*glyph
) {
1987 SplashBlendFunc blendFunc
;
1988 int alpha0
, alpha
, ialpha
;
1990 SplashColor fg
, dest
, blend
;
1992 SplashClipResult clipRes
;
1995 int x0
, y0
, x1
, y1
, xx
, xx1
, yy
;
1997 x0
= splashFloor(x
);
1998 y0
= splashFloor(y
);
2000 if ((clipRes
= state
->clip
->testRect(x0
- glyph
->x
,
2002 x0
- glyph
->x
+ glyph
->w
- 1,
2003 y0
- glyph
->y
+ glyph
->h
- 1))
2004 != splashClipAllOutside
) {
2005 noClip
= clipRes
== splashClipAllInside
;
2008 updateModX(x0
- glyph
->x
);
2009 updateModX(x0
- glyph
->x
+ glyph
->w
- 1);
2010 updateModY(y0
- glyph
->y
);
2011 updateModY(y0
- glyph
->y
+ glyph
->h
- 1);
2015 if (state
->fillAlpha
!= 1 || softMask
|| state
->blendFunc
) {
2016 blendFunc
= state
->blendFunc
? state
->blendFunc
: &blendNormal
;
2019 for (yy
= 0, y1
= y0
- glyph
->y
; yy
< glyph
->h
; ++yy
, ++y1
) {
2020 for (xx
= 0, x1
= x0
- glyph
->x
; xx
< glyph
->w
; ++xx
, ++x1
) {
2023 alpha
= (int)(alpha
* state
->fillAlpha
*
2024 softMask
->data
[y1
* softMask
->rowSize
+ x1
]);
2026 alpha
= (int)(alpha
* state
->fillAlpha
);
2029 if (noClip
|| state
->clip
->test(x1
, y1
)) {
2030 ialpha
= 255 - alpha
;
2031 state
->fillPattern
->getColor(x1
, y1
, fg
);
2032 switch (bitmap
->mode
) {
2033 case splashModeMono1
:
2034 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ (x1
>> 3)];
2035 dest
[0] = (*pix
>> (7 - (x1
& 7))) & 1;
2036 (*blendFunc
)(fg
, dest
, blend
, bitmap
->mode
);
2037 t
= (alpha
* blend
[0] + ialpha
* dest
[0]) >> 8;
2039 *pix
|= 0x80 >> (x1
& 7);
2041 *pix
&= ~(0x80 >> (x1
& 7));
2044 case splashModeMono8
:
2045 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ x1
];
2046 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2047 // note: floor(x / 255) = x >> 8 (for 16-bit x)
2048 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2050 case splashModeAMono8
:
2051 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 2 * x1
];
2052 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2053 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2054 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2056 case splashModeRGB8
:
2057 case splashModeBGR8
:
2058 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 3 * x1
];
2059 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2060 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2061 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2062 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2064 case splashModeARGB8
:
2065 case splashModeBGRA8
:
2067 case splashModeCMYK8
:
2069 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 4 * x1
];
2070 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2071 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2072 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2073 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2074 pix
[3] = (alpha
* blend
[3] + ialpha
* pix
[3]) >> 8;
2077 case splashModeACMYK8
:
2078 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 5 * x1
];
2079 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2080 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2081 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2082 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2083 pix
[3] = (alpha
* blend
[3] + ialpha
* pix
[3]) >> 8;
2084 pix
[4] = (alpha
* blend
[4] + ialpha
* pix
[4]) >> 8;
2099 for (yy
= 0, y1
= y0
- glyph
->y
; yy
< glyph
->h
; ++yy
, ++y1
) {
2100 for (xx
= 0, x1
= x0
- glyph
->x
; xx
< glyph
->w
; xx
+= 8) {
2102 for (xx1
= 0; xx1
< 8 && xx
+ xx1
< glyph
->w
; ++xx1
, ++x1
) {
2103 if (alpha0
& 0x80) {
2104 if (noClip
|| state
->clip
->test(x1
, y1
)) {
2106 alpha
= (int)(state
->fillAlpha
*
2107 softMask
->data
[y1
* softMask
->rowSize
+ x1
]);
2109 alpha
= (int)(state
->fillAlpha
* 255);
2111 ialpha
= 255 - alpha
;
2112 state
->fillPattern
->getColor(x1
, y1
, fg
);
2113 switch (bitmap
->mode
) {
2114 case splashModeMono1
:
2115 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ (x1
>> 3)];
2116 dest
[0] = (*pix
>> (7 - (x1
& 7))) & 1;
2117 (*blendFunc
)(fg
, dest
, blend
, bitmap
->mode
);
2118 t
= (alpha
* blend
[0] + ialpha
* dest
[0]) >> 8;
2120 *pix
|= 0x80 >> (x1
& 7);
2122 *pix
&= ~(0x80 >> (x1
& 7));
2125 case splashModeMono8
:
2126 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ x1
];
2127 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2128 // note: floor(x / 255) = x >> 8 (for 16-bit x)
2129 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2131 case splashModeAMono8
:
2132 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 2 * x1
];
2133 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2134 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2135 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2137 case splashModeRGB8
:
2138 case splashModeBGR8
:
2139 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 3 * x1
];
2140 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2141 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2142 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2143 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2145 case splashModeARGB8
:
2146 case splashModeBGRA8
:
2148 case splashModeCMYK8
:
2150 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 4 * x1
];
2151 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2152 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2153 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2154 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2155 pix
[3] = (alpha
* blend
[3] + ialpha
* pix
[3]) >> 8;
2158 case splashModeACMYK8
:
2159 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 5 * x1
];
2160 (*blendFunc
)(fg
, pix
, blend
, bitmap
->mode
);
2161 pix
[0] = (alpha
* blend
[0] + ialpha
* pix
[0]) >> 8;
2162 pix
[1] = (alpha
* blend
[1] + ialpha
* pix
[1]) >> 8;
2163 pix
[2] = (alpha
* blend
[2] + ialpha
* pix
[2]) >> 8;
2164 pix
[3] = (alpha
* blend
[3] + ialpha
* pix
[3]) >> 8;
2165 pix
[4] = (alpha
* blend
[4] + ialpha
* pix
[4]) >> 8;
2184 for (yy
= 0, y1
= y0
- glyph
->y
; yy
< glyph
->h
; ++yy
, ++y1
) {
2185 for (xx
= 0, x1
= x0
- glyph
->x
; xx
< glyph
->w
; ++xx
, ++x1
) {
2188 if (noClip
|| state
->clip
->test(x1
, y1
)) {
2189 ialpha
= 255 - alpha
;
2190 state
->fillPattern
->getColor(x1
, y1
, fg
);
2191 switch (bitmap
->mode
) {
2192 case splashModeMono1
:
2193 if (alpha
>= 0x80) {
2194 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ (x1
>> 3)];
2196 *pix
|= 0x80 >> (x1
& 7);
2198 *pix
&= ~(0x80 >> (x1
& 7));
2202 case splashModeMono8
:
2203 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ x1
];
2204 // note: floor(x / 255) = x >> 8 (for 16-bit x)
2205 pix
[0] = (alpha
* fg
[0] + ialpha
* pix
[0]) >> 8;
2207 case splashModeAMono8
:
2208 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 2 * x1
];
2209 pix
[0] = (alpha
* fg
[0] + ialpha
* pix
[0]) >> 8;
2210 pix
[1] = (alpha
* fg
[1] + ialpha
* pix
[1]) >> 8;
2212 case splashModeRGB8
:
2213 case splashModeBGR8
:
2214 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 3 * x1
];
2215 pix
[0] = (alpha
* fg
[0] + ialpha
* pix
[0]) >> 8;
2216 pix
[1] = (alpha
* fg
[1] + ialpha
* pix
[1]) >> 8;
2217 pix
[2] = (alpha
* fg
[2] + ialpha
* pix
[2]) >> 8;
2219 case splashModeARGB8
:
2220 case splashModeBGRA8
:
2222 case splashModeCMYK8
:
2224 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 4 * x1
];
2225 pix
[0] = (alpha
* fg
[0] + ialpha
* pix
[0]) >> 8;
2226 pix
[1] = (alpha
* fg
[1] + ialpha
* pix
[1]) >> 8;
2227 pix
[2] = (alpha
* fg
[2] + ialpha
* pix
[2]) >> 8;
2228 pix
[3] = (alpha
* fg
[3] + ialpha
* pix
[3]) >> 8;
2231 case splashModeACMYK8
:
2232 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 5 * x1
];
2233 pix
[0] = (alpha
* fg
[0] + ialpha
* pix
[0]) >> 8;
2234 pix
[1] = (alpha
* fg
[1] + ialpha
* pix
[1]) >> 8;
2235 pix
[2] = (alpha
* fg
[2] + ialpha
* pix
[2]) >> 8;
2236 pix
[3] = (alpha
* fg
[3] + ialpha
* pix
[3]) >> 8;
2237 pix
[4] = (alpha
* fg
[4] + ialpha
* pix
[4]) >> 8;
2252 for (yy
= 0, y1
= y0
- glyph
->y
; yy
< glyph
->h
; ++yy
, ++y1
) {
2253 for (xx
= 0, x1
= x0
- glyph
->x
; xx
< glyph
->w
; xx
+= 8) {
2255 for (xx1
= 0; xx1
< 8 && xx
+ xx1
< glyph
->w
; ++xx1
, ++x1
) {
2256 if (alpha0
& 0x80) {
2257 if (noClip
|| state
->clip
->test(x1
, y1
)) {
2258 state
->fillPattern
->getColor(x1
, y1
, fg
);
2259 switch (bitmap
->mode
) {
2260 case splashModeMono1
:
2261 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ (x1
>> 3)];
2263 *pix
|= 0x80 >> (x1
& 7);
2265 *pix
&= ~(0x80 >> (x1
& 7));
2268 case splashModeMono8
:
2269 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ x1
];
2272 case splashModeAMono8
:
2273 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 2 * x1
];
2277 case splashModeRGB8
:
2278 case splashModeBGR8
:
2279 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 3 * x1
];
2284 case splashModeARGB8
:
2285 case splashModeBGRA8
:
2287 case splashModeCMYK8
:
2289 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 4 * x1
];
2296 case splashModeACMYK8
:
2297 pix
= &bitmap
->data
[y1
* bitmap
->rowSize
+ 5 * x1
];
2319 opClipRes
= clipRes
;
2324 SplashError
Splash::fillImageMask(SplashImageMaskSource src
, void *srcData
,
2325 int w
, int h
, SplashCoord
*mat
) {
2327 SplashCoord xScale
, yScale
, xShear
, yShear
, yShear1
;
2328 int tx
, tx2
, ty
, ty2
, scaledWidth
, scaledHeight
, xSign
, ySign
;
2329 int ulx
, uly
, llx
, lly
, urx
, ury
, lrx
, lry
;
2330 int ulx1
, uly1
, llx1
, lly1
, urx1
, ury1
, lrx1
, lry1
;
2331 int xMin
, xMax
, yMin
, yMax
;
2332 SplashClipResult clipRes
, clipRes2
;
2333 int yp
, yq
, yt
, yStep
, lastYStep
;
2334 int xp
, xq
, xt
, xStep
, xSrc
;
2335 int k1
, spanXMin
, spanXMax
, spanY
;
2336 SplashColorPtr pixBuf
, p
;
2339 int x
, y
, x1
, x2
, y2
;
2344 printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
2345 w
, h
, (double)mat
[0], (double)mat
[1], (double)mat
[2],
2346 (double)mat
[3], (double)mat
[4], (double)mat
[5]);
2349 // check for singular matrix
2350 if (splashAbs(mat
[0] * mat
[3] - mat
[1] * mat
[2]) < 0.000001) {
2351 return splashErrSingularMatrix
;
2354 // compute scale, shear, rotation, translation parameters
2355 rot
= splashAbs(mat
[1]) > splashAbs(mat
[0]);
2358 yScale
= mat
[2] - (mat
[0] * mat
[3]) / mat
[1];
2359 xShear
= -mat
[3] / yScale
;
2360 yShear
= -mat
[0] / mat
[1];
2363 yScale
= mat
[3] - (mat
[1] * mat
[2]) / mat
[0];
2364 xShear
= mat
[2] / yScale
;
2365 yShear
= mat
[1] / mat
[0];
2367 // the +/-0.01 in these computations is to avoid floating point
2368 // precision problems which can lead to gaps between image stripes
2369 // (it can cause image stripes to overlap, but that's a much less
2372 tx
= splashRound(mat
[4] - 0.01);
2373 tx2
= splashRound(mat
[4] + xScale
+ 0.01) - 1;
2375 tx
= splashRound(mat
[4] + 0.01) - 1;
2376 tx2
= splashRound(mat
[4] + xScale
- 0.01);
2378 scaledWidth
= abs(tx2
- tx
) + 1;
2379 if (scaledWidth
== 0) {
2380 // technically, this should draw nothing, but it generally seems
2381 // better to draw a one-pixel-wide stripe rather than throwing it
2386 ty
= splashRound(mat
[5] - 0.01);
2387 ty2
= splashRound(mat
[5] + yScale
+ 0.01) - 1;
2389 ty
= splashRound(mat
[5] + 0.01) - 1;
2390 ty2
= splashRound(mat
[5] + yScale
- 0.01);
2392 scaledHeight
= abs(ty2
- ty
) + 1;
2393 if (scaledHeight
== 0) {
2394 // technically, this should draw nothing, but it generally seems
2395 // better to draw a one-pixel-wide stripe rather than throwing it
2399 xSign
= (xScale
< 0) ? -1 : 1;
2400 ySign
= (yScale
< 0) ? -1 : 1;
2401 yShear1
= (SplashCoord
)xSign
* yShear
;
2406 urx1
= xSign
* (scaledWidth
- 1);
2407 ury1
= (int)(yShear
* urx1
);
2408 llx1
= splashRound(xShear
* ySign
* (scaledHeight
- 1));
2409 lly1
= ySign
* (scaledHeight
- 1) + (int)(yShear
* llx1
);
2410 lrx1
= xSign
* (scaledWidth
- 1) +
2411 splashRound(xShear
* ySign
* (scaledHeight
- 1));
2412 lry1
= ySign
* (scaledHeight
- 1) + (int)(yShear
* lrx1
);
2414 ulx
= tx
+ uly1
; uly
= ty
- ulx1
;
2415 urx
= tx
+ ury1
; ury
= ty
- urx1
;
2416 llx
= tx
+ lly1
; lly
= ty
- llx1
;
2417 lrx
= tx
+ lry1
; lry
= ty
- lrx1
;
2419 ulx
= tx
+ ulx1
; uly
= ty
+ uly1
;
2420 urx
= tx
+ urx1
; ury
= ty
+ ury1
;
2421 llx
= tx
+ llx1
; lly
= ty
+ lly1
;
2422 lrx
= tx
+ lrx1
; lry
= ty
+ lry1
;
2424 xMin
= (ulx
< urx
) ? (ulx
< llx
) ? (ulx
< lrx
) ? ulx
: lrx
2425 : (llx
< lrx
) ? llx
: lrx
2426 : (urx
< llx
) ? (urx
< lrx
) ? urx
: lrx
2427 : (llx
< lrx
) ? llx
: lrx
;
2428 xMax
= (ulx
> urx
) ? (ulx
> llx
) ? (ulx
> lrx
) ? ulx
: lrx
2429 : (llx
> lrx
) ? llx
: lrx
2430 : (urx
> llx
) ? (urx
> lrx
) ? urx
: lrx
2431 : (llx
> lrx
) ? llx
: lrx
;
2432 yMin
= (uly
< ury
) ? (uly
< lly
) ? (uly
< lry
) ? uly
: lry
2433 : (lly
< lry
) ? lly
: lry
2434 : (ury
< lly
) ? (ury
< lry
) ? ury
: lry
2435 : (lly
< lry
) ? lly
: lry
;
2436 yMax
= (uly
> ury
) ? (uly
> lly
) ? (uly
> lry
) ? uly
: lry
2437 : (lly
> lry
) ? lly
: lry
2438 : (ury
> lly
) ? (ury
> lry
) ? ury
: lry
2439 : (lly
> lry
) ? lly
: lry
;
2440 clipRes
= state
->clip
->testRect(xMin
, yMin
, xMax
, yMax
);
2441 opClipRes
= clipRes
;
2443 // compute Bresenham parameters for x and y scaling
2444 yp
= h
/ scaledHeight
;
2445 yq
= h
% scaledHeight
;
2446 xp
= w
/ scaledWidth
;
2447 xq
= w
% scaledWidth
;
2449 // allocate pixel buffer
2450 pixBuf
= (SplashColorPtr
)gmalloc((yp
+ 1) * w
);
2452 // init y scale Bresenham
2456 for (y
= 0; y
< scaledHeight
; ++y
) {
2458 // y scale Bresenham
2461 if (yt
>= scaledHeight
) {
2466 // read row(s) from image
2467 n
= (yp
> 0) ? yStep
: lastYStep
;
2470 for (i
= 0; i
< n
; ++i
) {
2477 // loop-invariant constants
2478 k1
= splashRound(xShear
* ySign
* y
);
2481 if (clipRes
!= splashClipAllInside
&&
2483 (int)(yShear
* k1
) ==
2484 (int)(yShear
* (xSign
* (scaledWidth
- 1) + k1
))) {
2487 spanXMax
= spanXMin
+ (scaledWidth
- 1);
2490 spanXMin
= spanXMax
- (scaledWidth
- 1);
2492 spanY
= ty
+ ySign
* y
+ (int)(yShear
* k1
);
2493 clipRes2
= state
->clip
->testSpan(spanXMin
, spanXMax
, spanY
);
2494 if (clipRes2
== splashClipAllOutside
) {
2501 // init x scale Bresenham
2509 y1
= (SplashCoord
)ySign
* y
+ yShear
* x1
;
2510 // this is a kludge: if yShear1 is negative, then (int)y1 would
2511 // change immediately after the first pixel, which is not what we
2517 // loop-invariant constants
2518 n
= yStep
> 0 ? yStep
: 1;
2520 for (x
= 0; x
< scaledWidth
; ++x
) {
2522 // x scale Bresenham
2525 if (xt
>= scaledWidth
) {
2539 // compute the alpha value for (x,y) after the x and y scaling
2541 m
= xStep
> 0 ? xStep
: 1;
2544 for (i
= 0; i
< n
; ++i
) {
2545 for (j
= 0; j
< m
; ++j
) {
2551 // blend fill color with background
2553 if (pixAcc
== n
* m
) {
2554 drawPixel(tx
+ x2
, ty
+ y2
, state
->fillPattern
, state
->fillAlpha
,
2555 clipRes2
== splashClipAllInside
);
2557 alpha
= (SplashCoord
)pixAcc
/ (SplashCoord
)(n
* m
);
2558 drawPixel(tx
+ x2
, ty
+ y2
, state
->fillPattern
,
2559 state
->fillAlpha
* alpha
,
2560 clipRes2
== splashClipAllInside
);
2564 // x scale Bresenham
2581 SplashError
Splash::drawImage(SplashImageSource src
, void *srcData
,
2582 SplashColorMode srcMode
,
2583 int w
, int h
, SplashCoord
*mat
) {
2584 GBool ok
, rot
, halftone
, srcAlpha
;
2585 SplashCoord xScale
, yScale
, xShear
, yShear
, yShear1
;
2586 int tx
, tx2
, ty
, ty2
, scaledWidth
, scaledHeight
, xSign
, ySign
;
2587 int ulx
, uly
, llx
, lly
, urx
, ury
, lrx
, lry
;
2588 int ulx1
, uly1
, llx1
, lly1
, urx1
, ury1
, lrx1
, lry1
;
2589 int xMin
, xMax
, yMin
, yMax
;
2590 SplashClipResult clipRes
, clipRes2
;
2591 int yp
, yq
, yt
, yStep
, lastYStep
;
2592 int xp
, xq
, xt
, xStep
, xSrc
;
2593 int k1
, spanXMin
, spanXMax
, spanY
;
2594 SplashColorPtr pixBuf
, p
;
2597 int pixAcc0
, pixAcc1
, pixAcc2
, pixAcc3
;
2599 int pixAcc0
, pixAcc1
, pixAcc2
;
2602 SplashCoord pixMul
, alphaMul
, alpha
;
2603 int x
, y
, x1
, x2
, y2
;
2605 int nComps
, n
, m
, i
, j
;
2608 printf("drawImage: srcMode=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
2609 srcMode
, w
, h
, (double)mat
[0], (double)mat
[1], (double)mat
[2],
2610 (double)mat
[3], (double)mat
[4], (double)mat
[5]);
2613 // check color modes
2614 ok
= gFalse
; // make gcc happy
2615 nComps
= 0; // make gcc happy
2618 switch (bitmap
->mode
) {
2619 case splashModeMono1
:
2620 ok
= srcMode
== splashModeMono1
|| srcMode
== splashModeMono8
||
2621 srcMode
== splashModeAMono8
;
2622 halftone
= srcMode
== splashModeMono8
|| srcMode
== splashModeAMono8
;
2623 srcAlpha
= srcMode
== splashModeAMono8
;
2624 nComps
= srcAlpha
? 2 : 1;
2626 case splashModeMono8
:
2627 ok
= srcMode
== splashModeMono8
|| srcMode
== splashModeAMono8
;
2628 srcAlpha
= srcMode
== splashModeAMono8
;
2629 nComps
= srcAlpha
? 2 : 1;
2631 case splashModeAMono8
:
2632 //~ not implemented yet
2636 case splashModeRGB8
:
2637 ok
= srcMode
== splashModeRGB8
|| srcMode
== splashModeARGB8
;
2638 srcAlpha
= srcMode
== splashModeARGB8
;
2639 nComps
= srcAlpha
? 4 : 3;
2641 case splashModeBGR8
:
2642 ok
= srcMode
== splashModeBGR8
|| srcMode
== splashModeBGRA8
;
2643 srcAlpha
= srcMode
== splashModeBGRA8
;
2644 nComps
= srcAlpha
? 4 : 3;
2647 case splashModeCMYK8
:
2648 ok
= srcMode
== splashModeCMYK8
|| srcMode
== splashModeACMYK8
;
2649 srcAlpha
= srcMode
== splashModeACMYK8
;
2650 nComps
= srcAlpha
? 5 : 4;
2653 case splashModeARGB8
:
2654 case splashModeBGRA8
:
2656 case splashModeACMYK8
:
2658 //~ not implemented yet
2664 return splashErrModeMismatch
;
2667 // check for singular matrix
2668 if (splashAbs(mat
[0] * mat
[3] - mat
[1] * mat
[2]) < 0.000001) {
2669 return splashErrSingularMatrix
;
2672 // compute scale, shear, rotation, translation parameters
2673 rot
= splashAbs(mat
[1]) > splashAbs(mat
[0]);
2676 yScale
= mat
[2] - (mat
[0] * mat
[3]) / mat
[1];
2677 xShear
= -mat
[3] / yScale
;
2678 yShear
= -mat
[0] / mat
[1];
2681 yScale
= mat
[3] - (mat
[1] * mat
[2]) / mat
[0];
2682 xShear
= mat
[2] / yScale
;
2683 yShear
= mat
[1] / mat
[0];
2685 // the +/-0.01 in these computations is to avoid floating point
2686 // precision problems which can lead to gaps between image stripes
2687 // (it can cause image stripes to overlap, but that's a much less
2690 tx
= splashRound(mat
[4] - 0.01);
2691 tx2
= splashRound(mat
[4] + xScale
+ 0.01) - 1;
2693 tx
= splashRound(mat
[4] + 0.01) - 1;
2694 tx2
= splashRound(mat
[4] + xScale
- 0.01);
2696 scaledWidth
= abs(tx2
- tx
) + 1;
2697 if (scaledWidth
== 0) {
2698 // technically, this should draw nothing, but it generally seems
2699 // better to draw a one-pixel-wide stripe rather than throwing it
2704 ty
= splashRound(mat
[5] - 0.01);
2705 ty2
= splashRound(mat
[5] + yScale
+ 0.01) - 1;
2707 ty
= splashRound(mat
[5] + 0.01) - 1;
2708 ty2
= splashRound(mat
[5] + yScale
- 0.01);
2710 scaledHeight
= abs(ty2
- ty
) + 1;
2711 if (scaledHeight
== 0) {
2712 // technically, this should draw nothing, but it generally seems
2713 // better to draw a one-pixel-wide stripe rather than throwing it
2717 xSign
= (xScale
< 0) ? -1 : 1;
2718 ySign
= (yScale
< 0) ? -1 : 1;
2719 yShear1
= (SplashCoord
)xSign
* yShear
;
2724 urx1
= xSign
* (scaledWidth
- 1);
2725 ury1
= (int)(yShear
* urx1
);
2726 llx1
= splashRound(xShear
* ySign
* (scaledHeight
- 1));
2727 lly1
= ySign
* (scaledHeight
- 1) + (int)(yShear
* llx1
);
2728 lrx1
= xSign
* (scaledWidth
- 1) +
2729 splashRound(xShear
* ySign
* (scaledHeight
- 1));
2730 lry1
= ySign
* (scaledHeight
- 1) + (int)(yShear
* lrx1
);
2732 ulx
= tx
+ uly1
; uly
= ty
- ulx1
;
2733 urx
= tx
+ ury1
; ury
= ty
- urx1
;
2734 llx
= tx
+ lly1
; lly
= ty
- llx1
;
2735 lrx
= tx
+ lry1
; lry
= ty
- lrx1
;
2737 ulx
= tx
+ ulx1
; uly
= ty
+ uly1
;
2738 urx
= tx
+ urx1
; ury
= ty
+ ury1
;
2739 llx
= tx
+ llx1
; lly
= ty
+ lly1
;
2740 lrx
= tx
+ lrx1
; lry
= ty
+ lry1
;
2742 xMin
= (ulx
< urx
) ? (ulx
< llx
) ? (ulx
< lrx
) ? ulx
: lrx
2743 : (llx
< lrx
) ? llx
: lrx
2744 : (urx
< llx
) ? (urx
< lrx
) ? urx
: lrx
2745 : (llx
< lrx
) ? llx
: lrx
;
2746 xMax
= (ulx
> urx
) ? (ulx
> llx
) ? (ulx
> lrx
) ? ulx
: lrx
2747 : (llx
> lrx
) ? llx
: lrx
2748 : (urx
> llx
) ? (urx
> lrx
) ? urx
: lrx
2749 : (llx
> lrx
) ? llx
: lrx
;
2750 yMin
= (uly
< ury
) ? (uly
< lly
) ? (uly
< lry
) ? uly
: lry
2751 : (lly
< lry
) ? lly
: lry
2752 : (ury
< lly
) ? (ury
< lry
) ? ury
: lry
2753 : (lly
< lry
) ? lly
: lry
;
2754 yMax
= (uly
> ury
) ? (uly
> lly
) ? (uly
> lry
) ? uly
: lry
2755 : (lly
> lry
) ? lly
: lry
2756 : (ury
> lly
) ? (ury
> lry
) ? ury
: lry
2757 : (lly
> lry
) ? lly
: lry
;
2758 clipRes
= state
->clip
->testRect(xMin
, yMin
, xMax
, yMax
);
2759 opClipRes
= clipRes
;
2760 if (clipRes
== splashClipAllOutside
) {
2764 // compute Bresenham parameters for x and y scaling
2765 yp
= h
/ scaledHeight
;
2766 yq
= h
% scaledHeight
;
2767 xp
= w
/ scaledWidth
;
2768 xq
= w
% scaledWidth
;
2770 // allocate pixel buffer
2771 pixBuf
= (SplashColorPtr
)gmalloc((yp
+ 1) * w
* nComps
);
2773 pixAcc0
= pixAcc1
= pixAcc2
= 0; // make gcc happy
2775 pixAcc3
= 0; // make gcc happy
2780 // init y scale Bresenham
2784 for (y
= 0; y
< scaledHeight
; ++y
) {
2786 // y scale Bresenham
2789 if (yt
>= scaledHeight
) {
2794 // read row(s) from image
2795 n
= (yp
> 0) ? yStep
: lastYStep
;
2798 for (i
= 0; i
< n
; ++i
) {
2805 // loop-invariant constants
2806 k1
= splashRound(xShear
* ySign
* y
);
2809 if (clipRes
!= splashClipAllInside
&&
2811 (int)(yShear
* k1
) ==
2812 (int)(yShear
* (xSign
* (scaledWidth
- 1) + k1
))) {
2815 spanXMax
= spanXMin
+ (scaledWidth
- 1);
2818 spanXMin
= spanXMax
- (scaledWidth
- 1);
2820 spanY
= ty
+ ySign
* y
+ (int)(yShear
* k1
);
2821 clipRes2
= state
->clip
->testSpan(spanXMin
, spanXMax
, spanY
);
2822 if (clipRes2
== splashClipAllOutside
) {
2829 // init x scale Bresenham
2837 y1
= (SplashCoord
)ySign
* y
+ yShear
* x1
;
2838 // this is a kludge: if yShear1 is negative, then (int)y1 would
2839 // change immediately after the first pixel, which is not what
2845 // loop-invariant constants
2846 n
= yStep
> 0 ? yStep
: 1;
2848 for (x
= 0; x
< scaledWidth
; ++x
) {
2850 // x scale Bresenham
2853 if (xt
>= scaledWidth
) {
2867 // compute the filtered pixel at (x,y) after the x and y scaling
2869 m
= xStep
> 0 ? xStep
: 1;
2872 case splashModeAMono8
:
2873 p
= pixBuf
+ xSrc
* 2;
2875 for (i
= 0; i
< n
; ++i
) {
2876 for (j
= 0; j
< m
; ++j
) {
2883 case splashModeARGB8
:
2884 p
= pixBuf
+ xSrc
* 4;
2885 pixAcc0
= pixAcc1
= pixAcc2
= 0;
2886 for (i
= 0; i
< n
; ++i
) {
2887 for (j
= 0; j
< m
; ++j
) {
2896 case splashModeBGRA8
:
2897 p
= pixBuf
+ xSrc
* 4;
2898 pixAcc0
= pixAcc1
= pixAcc2
= 0;
2899 for (i
= 0; i
< n
; ++i
) {
2900 for (j
= 0; j
< m
; ++j
) {
2910 case splashModeACMYK8
:
2911 p
= pixBuf
+ xSrc
* 5;
2912 pixAcc0
= pixAcc1
= pixAcc2
= pixAcc3
= 0;
2913 for (i
= 0; i
< n
; ++i
) {
2914 for (j
= 0; j
< m
; ++j
) {
2925 default: // make gcc happy
2928 pixMul
= (SplashCoord
)1 / (SplashCoord
)(n
* m
);
2929 alphaMul
= pixMul
* (1.0 / 256.0);
2930 alpha
= (SplashCoord
)alphaAcc
* alphaMul
;
2933 // mono8 -> mono1 conversion, with halftoning
2935 pix
[0] = state
->screen
->test(tx
+ x2
, ty
+ y2
,
2936 (SplashCoord
)pixAcc0
* pixMul
* (1.0 / 256.0));
2938 // no conversion, no halftoning
2940 switch (bitmap
->mode
) {
2942 case splashModeCMYK8
:
2943 pix
[3] = (int)((SplashCoord
)pixAcc3
* pixMul
);
2946 case splashModeRGB8
:
2947 case splashModeBGR8
:
2948 pix
[2] = (int)((SplashCoord
)pixAcc2
* pixMul
);
2949 pix
[1] = (int)((SplashCoord
)pixAcc1
* pixMul
);
2951 case splashModeMono1
:
2952 case splashModeMono8
:
2953 pix
[0] = (int)((SplashCoord
)pixAcc0
* pixMul
);
2955 default: // make gcc happy
2961 drawPixel(tx
+ x2
, ty
+ y2
, pix
, alpha
* state
->fillAlpha
,
2962 clipRes2
== splashClipAllInside
);
2965 // x scale Bresenham
2978 // init y scale Bresenham
2982 for (y
= 0; y
< scaledHeight
; ++y
) {
2984 // y scale Bresenham
2987 if (yt
>= scaledHeight
) {
2992 // read row(s) from image
2993 n
= (yp
> 0) ? yStep
: lastYStep
;
2996 for (i
= 0; i
< n
; ++i
) {
3003 // loop-invariant constants
3004 k1
= splashRound(xShear
* ySign
* y
);
3007 if (clipRes
!= splashClipAllInside
&&
3009 (int)(yShear
* k1
) ==
3010 (int)(yShear
* (xSign
* (scaledWidth
- 1) + k1
))) {
3013 spanXMax
= spanXMin
+ (scaledWidth
- 1);
3016 spanXMin
= spanXMax
- (scaledWidth
- 1);
3018 spanY
= ty
+ ySign
* y
+ (int)(yShear
* k1
);
3019 clipRes2
= state
->clip
->testSpan(spanXMin
, spanXMax
, spanY
);
3020 if (clipRes2
== splashClipAllOutside
) {
3027 // init x scale Bresenham
3035 y1
= (SplashCoord
)ySign
* y
+ yShear
* x1
;
3036 // this is a kludge: if yShear1 is negative, then (int)y1 would
3037 // change immediately after the first pixel, which is not what
3043 // loop-invariant constants
3044 n
= yStep
> 0 ? yStep
: 1;
3046 for (x
= 0; x
< scaledWidth
; ++x
) {
3048 // x scale Bresenham
3051 if (xt
>= scaledWidth
) {
3065 // compute the filtered pixel at (x,y) after the x and y scaling
3067 m
= xStep
> 0 ? xStep
: 1;
3069 case splashModeMono1
:
3070 case splashModeMono8
:
3073 for (i
= 0; i
< n
; ++i
) {
3074 for (j
= 0; j
< m
; ++j
) {
3080 case splashModeRGB8
:
3081 case splashModeBGR8
:
3082 p
= pixBuf
+ xSrc
* 3;
3083 pixAcc0
= pixAcc1
= pixAcc2
= 0;
3084 for (i
= 0; i
< n
; ++i
) {
3085 for (j
= 0; j
< m
; ++j
) {
3094 case splashModeCMYK8
:
3095 p
= pixBuf
+ xSrc
* 4;
3096 pixAcc0
= pixAcc1
= pixAcc2
= pixAcc3
= 0;
3097 for (i
= 0; i
< n
; ++i
) {
3098 for (j
= 0; j
< m
; ++j
) {
3108 default: // make gcc happy
3111 pixMul
= (SplashCoord
)1 / (SplashCoord
)(n
* m
);
3113 // mono8 -> mono1 conversion, with halftoning
3115 pix
[0] = state
->screen
->test(tx
+ x2
, ty
+ y2
,
3116 (SplashCoord
)pixAcc0
* pixMul
* (1.0 / 256.0));
3118 // no conversion, no halftoning
3120 switch (bitmap
->mode
) {
3122 case splashModeCMYK8
:
3123 pix
[3] = (int)((SplashCoord
)pixAcc3
* pixMul
);
3126 case splashModeRGB8
:
3127 case splashModeBGR8
:
3128 pix
[2] = (int)((SplashCoord
)pixAcc2
* pixMul
);
3129 pix
[1] = (int)((SplashCoord
)pixAcc1
* pixMul
);
3131 case splashModeMono1
:
3132 case splashModeMono8
:
3133 pix
[0] = (int)((SplashCoord
)pixAcc0
* pixMul
);
3135 default: // make gcc happy
3141 drawPixel(tx
+ x2
, ty
+ y2
, pix
, state
->fillAlpha
,
3142 clipRes2
== splashClipAllInside
);
3144 // x scale Bresenham
3162 void Splash::dumpPath(SplashPath
*path
) {
3165 for (i
= 0; i
< path
->length
; ++i
) {
3166 printf(" %3d: x=%8.2f y=%8.2f%s%s%s%s%s\n",
3167 i
, (double)path
->pts
[i
].x
, (double)path
->pts
[i
].y
,
3168 (path
->flags
[i
] & splashPathFirst
) ? " first" : "",
3169 (path
->flags
[i
] & splashPathLast
) ? " last" : "",
3170 (path
->flags
[i
] & splashPathClosed
) ? " closed" : "",
3171 (path
->flags
[i
] & splashPathCurve
) ? " curve" : "",
3172 (path
->flags
[i
] & splashPathArcCW
) ? " arcCW" : "");
3176 void Splash::dumpXPath(SplashXPath
*path
) {
3179 for (i
= 0; i
< path
->length
; ++i
) {
3180 printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s%s%s%s%s\n",
3181 i
, (double)path
->segs
[i
].x0
, (double)path
->segs
[i
].y0
,
3182 (double)path
->segs
[i
].x1
, (double)path
->segs
[i
].y1
,
3183 (path
->segs
[i
].flags
& splashXPathFirst
) ? "F" : " ",
3184 (path
->segs
[i
].flags
& splashXPathLast
) ? "L" : " ",
3185 (path
->segs
[i
].flags
& splashXPathEnd0
) ? "0" : " ",
3186 (path
->segs
[i
].flags
& splashXPathEnd1
) ? "1" : " ",
3187 (path
->segs
[i
].flags
& splashXPathHoriz
) ? "H" : " ",
3188 (path
->segs
[i
].flags
& splashXPathVert
) ? "V" : " ",
3189 (path
->segs
[i
].flags
& splashXPathFlip
) ? "P" : " ");