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 "SplashClip.h"
26 #include "SplashFont.h"
27 #include "SplashGlyphBitmap.h"
30 //------------------------------------------------------------------------
32 //------------------------------------------------------------------------
34 Splash::Splash(SplashBitmap *bitmapA) {
36 state = new SplashState(bitmap->width, bitmap->height);
47 //------------------------------------------------------------------------
49 //------------------------------------------------------------------------
52 SplashPattern *Splash::getStrokePattern() {
53 return state->strokePattern;
56 SplashPattern *Splash::getFillPattern() {
57 return state->fillPattern;
60 SplashScreen *Splash::getScreen() {
64 SplashCoord Splash::getLineWidth() {
65 return state->lineWidth;
68 int Splash::getLineCap() {
69 return state->lineCap;
72 int Splash::getLineJoin() {
73 return state->lineJoin;
76 SplashCoord Splash::getMiterLimit() {
77 return state->miterLimit;
80 SplashCoord Splash::getFlatness() {
81 return state->flatness;
84 SplashCoord *Splash::getLineDash() {
85 return state->lineDash;
88 int Splash::getLineDashLength() {
89 return state->lineDashLength;
92 SplashCoord Splash::getLineDashPhase() {
93 return state->lineDashPhase;
96 SplashClip *Splash::getClip() {
100 //------------------------------------------------------------------------
102 //------------------------------------------------------------------------
104 void Splash::setStrokePattern(SplashPattern *strokePattern) {
105 state->setStrokePattern(strokePattern);
108 void Splash::setFillPattern(SplashPattern *fillPattern) {
109 state->setFillPattern(fillPattern);
112 void Splash::setScreen(SplashScreen *screen) {
113 state->setScreen(screen);
116 void Splash::setLineWidth(SplashCoord lineWidth) {
117 state->lineWidth = lineWidth;
120 void Splash::setLineCap(int lineCap) {
121 state->lineCap = lineCap;
124 void Splash::setLineJoin(int lineJoin) {
125 state->lineJoin = lineJoin;
128 void Splash::setMiterLimit(SplashCoord miterLimit) {
129 state->miterLimit = miterLimit;
132 void Splash::setFlatness(SplashCoord flatness) {
136 state->flatness = flatness;
140 void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength,
141 SplashCoord lineDashPhase) {
142 state->setLineDash(lineDash, lineDashLength, lineDashPhase);
145 void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0,
146 SplashCoord x1, SplashCoord y1) {
147 state->clip->resetToRect(x0, y0, x1, y1);
150 SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0,
151 SplashCoord x1, SplashCoord y1) {
152 return state->clip->clipToRect(x0, y0, x1, y1);
155 SplashError Splash::clipToPath(SplashPath *path, GBool eo) {
156 return state->clip->clipToPath(path, state->flatness, eo);
159 //------------------------------------------------------------------------
160 // state save/restore
161 //------------------------------------------------------------------------
163 void Splash::saveState() {
164 SplashState *newState;
166 newState = state->copy();
167 newState->next = state;
171 SplashError Splash::restoreState() {
172 SplashState *oldState;
175 return splashErrNoSave;
183 //------------------------------------------------------------------------
184 // drawing operations
185 //------------------------------------------------------------------------
187 void Splash::clear(SplashColor color) {
191 SplashRGB8P *rgb8pline, *rgb8p;
192 SplashBGR8P *bgr8line, *bgr8;
196 switch (bitmap->mode) {
197 case splashModeMono1:
198 n = ((bitmap->width + 7) >> 3) * bitmap->height;
199 data = color.mono1 ? 0xff : 0x00;
200 for (i = 0, mono1 = bitmap->data.mono1; i < n; ++i, ++mono1) {
204 case splashModeMono8:
205 n = bitmap->width * bitmap->height;
206 for (i = 0, mono8 = bitmap->data.mono8; i < n; ++i, ++mono8) {
207 *mono8 = color.mono8;
211 n = bitmap->width * bitmap->height;
212 for (i = 0, rgb8 = bitmap->data.rgb8; i < n; ++i, ++rgb8) {
216 case splashModeRGB8Packed:
217 rgb8pline = bitmap->data.rgb8p;
218 for (y = 0; y < bitmap->height; ++y) {
220 for (x = 0; x < bitmap->width; ++x) {
221 rgb8p[0] = splashRGB8R(color.rgb8);
222 rgb8p[1] = splashRGB8G(color.rgb8);
223 rgb8p[2] = splashRGB8B(color.rgb8);
226 rgb8pline += bitmap->rowSize;
229 case splashModeBGR8Packed:
230 bgr8line = bitmap->data.bgr8;
231 for (y = 0; y < bitmap->height; ++y) {
233 for (x = 0; x < bitmap->width; ++x) {
234 bgr8[2] = splashBGR8R(color.bgr8);
235 bgr8[1] = splashBGR8G(color.bgr8);
236 bgr8[0] = splashBGR8B(color.bgr8);
239 bgr8line += bitmap->rowSize;
245 SplashError Splash::stroke(SplashPath *path) {
246 SplashXPath *xPath, *xPath2;
249 printf("stroke [dash:%d] [width:%.2f]:\n",
250 state->lineDashLength, state->lineWidth);
253 if (path->length == 0) {
254 return splashErrEmptyPath;
256 xPath = new SplashXPath(path, state->flatness, gFalse);
257 if (state->lineDashLength > 0) {
258 xPath2 = makeDashedPath(xPath);
262 if (state->lineWidth <= 1) {
271 void Splash::strokeNarrow(SplashXPath *xPath) {
273 int x0, x1, x2, x3, y0, y1, x, y, t;
274 SplashCoord dx, dy, dxdy;
275 SplashClipResult clipRes;
278 for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
280 x0 = splashFloor(seg->x0);
281 x1 = splashFloor(seg->x1);
282 y0 = splashFloor(seg->y0);
283 y1 = splashFloor(seg->y1);
285 // horizontal segment
288 t = x0; x0 = x1; x1 = t;
290 if ((clipRes = state->clip->testSpan(x0, x1, y0))
291 != splashClipAllOutside) {
292 drawSpan(x0, x1, y0, state->strokePattern,
293 clipRes == splashClipAllInside);
296 // segment with |dx| > |dy|
297 } else if (splashAbs(seg->dxdy) > 1) {
298 dx = seg->x1 - seg->x0;
299 dy = seg->y1 - seg->y0;
302 t = y0; y0 = y1; y1 = t;
303 t = x0; x0 = x1; x1 = t;
307 if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
308 x0 <= x1 ? x1 : x0, y1))
309 != splashClipAllOutside) {
312 for (y = y0; y < y1; ++y) {
313 x3 = splashFloor(seg->x0 + (y + 1 - seg->y0) * dxdy);
314 drawSpan(x2, x3 - 1, y, state->strokePattern,
315 clipRes == splashClipAllInside);
318 drawSpan(x2, x1, y, state->strokePattern,
319 clipRes == splashClipAllInside);
322 for (y = y0; y < y1; ++y) {
323 x3 = splashFloor(seg->x0 + (y + 1 - seg->y0) * dxdy);
324 drawSpan(x3 + 1, x2, y, state->strokePattern,
325 clipRes == splashClipAllInside);
328 drawSpan(x1, x2, y, state->strokePattern,
329 clipRes == splashClipAllInside);
333 // segment with |dy| > |dx|
337 t = y0; y0 = y1; y1 = t;
339 if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
340 x0 <= x1 ? x1 : x0, y1))
341 != splashClipAllOutside) {
342 for (y = y0; y <= y1; ++y) {
343 x = splashFloor(seg->x0 + (y - seg->y0) * dxdy);
344 drawPixel(x, y, state->strokePattern,
345 clipRes == splashClipAllInside);
352 void Splash::strokeWide(SplashXPath *xPath) {
353 SplashXPathSeg *seg, *seg2;
354 SplashPath *widePath;
355 SplashCoord d, dx, dy, wdx, wdy, dxPrev, dyPrev, wdxPrev, wdyPrev;
356 SplashCoord dotprod, miter;
359 dx = dy = wdx = wdy = 0; // make gcc happy
360 dxPrev = dyPrev = wdxPrev = wdyPrev = 0; // make gcc happy
362 for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
364 // save the deltas for the previous segment; if this is the first
365 // segment on a subpath, compute the deltas for the last segment
366 // on the subpath (which may be used to draw a line join)
367 if (seg->flags & splashXPathFirst) {
368 for (j = i + 1, seg2 = &xPath->segs[j]; j < xPath->length; ++j, ++seg2) {
369 if (seg2->flags & splashXPathLast) {
370 d = splashDist(seg2->x0, seg2->y0, seg2->x1, seg2->y1);
372 //~ not clear what the behavior should be for joins with d==0
377 dxPrev = d * (seg2->x1 - seg2->x0);
378 dyPrev = d * (seg2->y1 - seg2->y0);
380 wdxPrev = 0.5 * state->lineWidth * dxPrev;
381 wdyPrev = 0.5 * state->lineWidth * dyPrev;
392 // compute deltas for this line segment
393 d = splashDist(seg->x0, seg->y0, seg->x1, seg->y1);
395 // we need to draw end caps on zero-length lines
396 //~ not clear what the behavior should be for splashLineCapButt with d==0
401 dx = d * (seg->x1 - seg->x0);
402 dy = d * (seg->y1 - seg->y0);
404 wdx = 0.5 * state->lineWidth * dx;
405 wdy = 0.5 * state->lineWidth * dy;
407 // initialize the path (which will be filled)
408 widePath = new SplashPath();
409 widePath->moveTo(seg->x0 - wdy, seg->y0 + wdx);
411 // draw the start cap
412 if (seg->flags & splashXPathEnd0) {
413 switch (state->lineCap) {
414 case splashLineCapButt:
415 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
417 case splashLineCapRound:
418 widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0);
420 case splashLineCapProjecting:
421 widePath->lineTo(seg->x0 - wdx - wdy, seg->y0 + wdx - wdy);
422 widePath->lineTo(seg->x0 - wdx + wdy, seg->y0 - wdx - wdy);
423 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
427 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
430 // draw the left side of the segment
431 widePath->lineTo(seg->x1 + wdy, seg->y1 - wdx);
434 if (seg->flags & splashXPathEnd1) {
435 switch (state->lineCap) {
436 case splashLineCapButt:
437 widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);
439 case splashLineCapRound:
440 widePath->arcCWTo(seg->x1 - wdy, seg->y1 + wdx, seg->x1, seg->y1);
442 case splashLineCapProjecting:
443 widePath->lineTo(seg->x1 + wdx + wdy, seg->y1 - wdx + wdy);
444 widePath->lineTo(seg->x1 + wdx - wdy, seg->y1 + wdx + wdy);
445 widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);
449 widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);
452 // draw the right side of the segment
453 widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);
456 fillWithPattern(widePath, gTrue, state->strokePattern);
459 // draw the line join
460 if (!(seg->flags & splashXPathEnd0)) {
462 switch (state->lineJoin) {
463 case splashLineJoinMiter:
464 dotprod = -(dx * dxPrev + dy * dyPrev);
466 widePath = new SplashPath();
467 widePath->moveTo(seg->x0, seg->y0);
468 miter = 2 / (1 - dotprod);
469 if (splashSqrt(miter) <= state->miterLimit) {
470 miter = splashSqrt(miter - 1);
471 if (dy * dxPrev > dx * dyPrev) {
472 widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);
473 widePath->lineTo(seg->x0 + wdy - miter * wdx,
474 seg->y0 - wdx - miter * wdy);
475 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
477 widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);
478 widePath->lineTo(seg->x0 - wdy - miter * wdx,
479 seg->y0 + wdx - miter * wdy);
480 widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);
483 if (dy * dxPrev > dx * dyPrev) {
484 widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);
485 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
487 widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);
488 widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);
493 case splashLineJoinRound:
494 widePath = new SplashPath();
495 widePath->moveTo(seg->x0 + wdy, seg->y0 - wdx);
496 widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0);
498 case splashLineJoinBevel:
499 widePath = new SplashPath();
500 widePath->moveTo(seg->x0, seg->y0);
501 if (dy * dxPrev > dx * dyPrev) {
502 widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);
503 widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);
505 widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);
506 widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);
511 fillWithPattern(widePath, gTrue, state->strokePattern);
518 SplashXPath *Splash::makeDashedPath(SplashXPath *xPath) {
520 GBool lineDashStartOn, lineDashOn;
521 GBool atSegStart, atSegEnd, atDashStart, atDashEnd;
522 int lineDashStartIdx, lineDashIdx, subpathStart;
523 SplashCoord lineDashTotal, lineDashStartPhase, lineDashDist;
526 SplashCoord sx0, sy0, sx1, sy1, ax0, ay0, ax1, ay1, dist;
529 dPath = new SplashXPath();
532 for (i = 0; i < state->lineDashLength; ++i) {
533 lineDashTotal += state->lineDash[i];
535 lineDashStartPhase = state->lineDashPhase;
536 i = splashFloor(lineDashStartPhase / lineDashTotal);
537 lineDashStartPhase -= i * lineDashTotal;
538 lineDashStartOn = gTrue;
539 lineDashStartIdx = 0;
540 while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
541 lineDashStartOn = !lineDashStartOn;
542 lineDashStartPhase -= state->lineDash[lineDashStartIdx];
552 dist = splashDist(sx0, sy0, sx1, sy1);
553 lineDashOn = lineDashStartOn;
554 lineDashIdx = lineDashStartIdx;
555 lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;
558 subpathStart = dPath->length;
560 while (segIdx < xPath->length) {
564 if (dist <= lineDashDist) {
567 lineDashDist -= dist;
570 atDashEnd = lineDashDist == 0 || (seg->flags & splashXPathLast);
572 ax1 = sx0 + (lineDashDist / dist) * (sx1 - sx0);
573 ay1 = sy0 + (lineDashDist / dist) * (sy1 - sy0);
576 dist -= lineDashDist;
583 dPath->addSegment(ax0, ay0, ax1, ay1,
584 atDashStart, atDashEnd,
585 atDashStart, atDashEnd);
586 // end of closed subpath
588 (seg->flags & splashXPathLast) &&
589 !(seg->flags & splashXPathEnd1)) {
590 dPath->segs[subpathStart].flags &= ~splashXPathEnd0;
591 dPath->segs[dPath->length - 1].flags &= ~splashXPathEnd1;
596 lineDashOn = !lineDashOn;
597 if (++lineDashIdx == state->lineDashLength) {
600 lineDashDist = state->lineDash[lineDashIdx];
603 atDashStart = gFalse;
606 if (++segIdx < xPath->length) {
612 dist = splashDist(sx0, sy0, sx1, sy1);
613 if (seg->flags & splashXPathFirst) {
614 lineDashOn = lineDashStartOn;
615 lineDashIdx = lineDashStartIdx;
616 lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;
618 subpathStart = dPath->length;
630 SplashError Splash::fill(SplashPath *path, GBool eo) {
632 printf("fill [eo:%d]:\n", eo);
635 return fillWithPattern(path, eo, state->fillPattern);
638 SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
639 SplashPattern *pattern) {
641 SplashXPathScanner *scanner;
642 int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
643 SplashClipResult clipRes, clipRes2;
645 if (path->length == 0) {
646 return splashErrEmptyPath;
648 xPath = new SplashXPath(path, state->flatness, gTrue);
650 scanner = new SplashXPathScanner(xPath, eo);
652 // get the min and max x and y values
653 scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
656 if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
657 != splashClipAllOutside) {
660 for (y = yMinI; y <= yMaxI; ++y) {
661 while (scanner->getNextSpan(y, &x0, &x1)) {
662 if (clipRes == splashClipAllInside) {
663 drawSpan(x0, x1, y, pattern, gTrue);
665 clipRes2 = state->clip->testSpan(x0, x1, y);
666 drawSpan(x0, x1, y, pattern, clipRes2 == splashClipAllInside);
677 SplashError Splash::xorFill(SplashPath *path, GBool eo) {
679 SplashXPathScanner *scanner;
680 int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
681 SplashClipResult clipRes, clipRes2;
683 if (path->length == 0) {
684 return splashErrEmptyPath;
686 xPath = new SplashXPath(path, state->flatness, gTrue);
688 scanner = new SplashXPathScanner(xPath, eo);
690 // get the min and max x and y values
691 scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
694 if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
695 != splashClipAllOutside) {
698 for (y = yMinI; y <= yMaxI; ++y) {
699 while (scanner->getNextSpan(y, &x0, &x1)) {
700 if (clipRes == splashClipAllInside) {
701 xorSpan(x0, x1, y, state->fillPattern, gTrue);
703 clipRes2 = state->clip->testSpan(x0, x1, y);
704 xorSpan(x0, x1, y, state->fillPattern,
705 clipRes2 == splashClipAllInside);
716 void Splash::drawPixel(int x, int y, SplashColor *color, GBool noClip) {
721 if (noClip || state->clip->test(x, y)) {
722 switch (bitmap->mode) {
723 case splashModeMono1:
724 mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x >> 3)];
726 *mono1 |= 0x80 >> (x & 7);
728 *mono1 &= ~(0x80 >> (x & 7));
731 case splashModeMono8:
732 bitmap->data.mono8[y * bitmap->width + x] = color->mono8;
735 bitmap->data.rgb8[y * bitmap->width + x] = color->rgb8;
737 case splashModeRGB8Packed:
738 rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x];
739 rgb8p[0] = splashRGB8R(color->rgb8);
740 rgb8p[1] = splashRGB8G(color->rgb8);
741 rgb8p[2] = splashRGB8B(color->rgb8);
743 case splashModeBGR8Packed:
744 bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x];
745 bgr8[2] = splashBGR8R(color->bgr8);
746 bgr8[1] = splashBGR8G(color->bgr8);
747 bgr8[0] = splashBGR8B(color->bgr8);
753 void Splash::drawPixel(int x, int y, SplashPattern *pattern, GBool noClip) {
759 if (noClip || state->clip->test(x, y)) {
760 color = pattern->getColor(x, y);
761 switch (bitmap->mode) {
762 case splashModeMono1:
763 mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x >> 3)];
765 *mono1 |= 0x80 >> (x & 7);
767 *mono1 &= ~(0x80 >> (x & 7));
770 case splashModeMono8:
771 bitmap->data.mono8[y * bitmap->width + x] = color.mono8;
774 bitmap->data.rgb8[y * bitmap->width + x] = color.rgb8;
776 case splashModeRGB8Packed:
777 rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x];
778 rgb8p[0] = splashRGB8R(color.rgb8);
779 rgb8p[1] = splashRGB8G(color.rgb8);
780 rgb8p[2] = splashRGB8B(color.rgb8);
782 case splashModeBGR8Packed:
783 bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x];
784 bgr8[2] = splashBGR8R(color.bgr8);
785 bgr8[1] = splashBGR8G(color.bgr8);
786 bgr8[0] = splashBGR8B(color.bgr8);
792 void Splash::drawSpan(int x0, int x1, int y, SplashPattern *pattern,
805 switch (bitmap->mode) {
806 case splashModeMono1:
807 mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x0 >> 3)];
811 for (j = x0 & 7; j < 8 && i < n; ++i, ++j) {
812 if (noClip || state->clip->test(x0 + i, y)) {
813 color = pattern->getColor(x0 + i, y);
826 for (j = 0; j < 8 && i < n; ++i, ++j) {
827 if (noClip || state->clip->test(x0 + i, y)) {
828 color = pattern->getColor(x0 + i, y);
841 case splashModeMono8:
842 mono8 = &bitmap->data.mono8[y * bitmap->width + x0];
843 for (i = 0; i < n; ++i) {
844 if (noClip || state->clip->test(x0 + i, y)) {
845 color = pattern->getColor(x0 + i, y);
846 *mono8 = color.mono8;
853 rgb8 = &bitmap->data.rgb8[y * bitmap->width + x0];
854 for (i = 0; i < n; ++i) {
855 if (noClip || state->clip->test(x0 + i, y)) {
856 color = pattern->getColor(x0 + i, y);
863 case splashModeRGB8Packed:
864 rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x0];
865 for (i = 0; i < n; ++i) {
866 if (noClip || state->clip->test(x0 + i, y)) {
867 color = pattern->getColor(x0 + i, y);
868 rgb8p[0] = splashRGB8R(color.rgb8);
869 rgb8p[1] = splashRGB8G(color.rgb8);
870 rgb8p[2] = splashRGB8B(color.rgb8);
876 case splashModeBGR8Packed:
877 bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x0];
878 for (i = 0; i < n; ++i) {
879 if (noClip || state->clip->test(x0 + i, y)) {
880 color = pattern->getColor(x0 + i, y);
881 bgr8[2] = splashBGR8R(color.bgr8);
882 bgr8[1] = splashBGR8G(color.bgr8);
883 bgr8[0] = splashBGR8B(color.bgr8);
891 void Splash::xorSpan(int x0, int x1, int y, SplashPattern *pattern,
904 switch (bitmap->mode) {
905 case splashModeMono1:
906 mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x0 >> 3)];
910 for (j = x0 & 7; j < 8 && i < n; ++i, ++j) {
911 if (noClip || state->clip->test(x0 + i, y)) {
912 color = pattern->getColor(x0 + i, y);
923 for (j = 0; j < 8 && i < n; ++i, ++j) {
924 if (noClip || state->clip->test(x0 + i, y)) {
925 color = pattern->getColor(x0 + i, y);
936 case splashModeMono8:
937 mono8 = &bitmap->data.mono8[y * bitmap->width + x0];
938 for (i = 0; i < n; ++i) {
939 if (noClip || state->clip->test(x0 + i, y)) {
940 color = pattern->getColor(x0 + i, y);
941 *mono8 ^= color.mono8;
948 rgb8 = &bitmap->data.rgb8[y * bitmap->width + x0];
949 for (i = 0; i < n; ++i) {
950 if (noClip || state->clip->test(x0 + i, y)) {
951 color = pattern->getColor(x0 + i, y);
958 case splashModeRGB8Packed:
959 rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x0];
960 for (i = 0; i < n; ++i) {
961 if (noClip || state->clip->test(x0 + i, y)) {
962 color = pattern->getColor(x0 + i, y);
963 rgb8p[0] ^= splashRGB8R(color.rgb8);
964 rgb8p[1] ^= splashRGB8G(color.rgb8);
965 rgb8p[2] ^= splashRGB8B(color.rgb8);
971 case splashModeBGR8Packed:
972 bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x0];
973 for (i = 0; i < n; ++i) {
974 if (noClip || state->clip->test(x0 + i, y)) {
975 color = pattern->getColor(x0 + i, y);
976 bgr8[2] ^= splashBGR8R(color.bgr8);
977 bgr8[1] ^= splashBGR8G(color.bgr8);
978 bgr8[0] ^= splashBGR8B(color.bgr8);
986 void Splash::getPixel(int x, int y, SplashColor *pixel) {
990 if (y < 0 || y >= bitmap->height || x < 0 || x >= bitmap->width) {
993 switch (bitmap->mode) {
994 case splashModeMono1:
995 pixel->mono1 = (bitmap->data.mono1[y * bitmap->rowSize + (x >> 3)]
996 >> (7 - (x & 7))) & 1;
998 case splashModeMono8:
999 pixel->mono8 = bitmap->data.mono8[y * bitmap->width + x];
1001 case splashModeRGB8:
1002 pixel->rgb8 = bitmap->data.rgb8[y * bitmap->width + x];
1004 case splashModeRGB8Packed:
1005 rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x];
1006 pixel->rgb8 = splashMakeRGB8(rgb8p[0], rgb8p[1], rgb8p[2]);
1008 case splashModeBGR8Packed:
1009 bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x];
1010 pixel->bgr8 = splashMakeBGR8(bgr8[2], bgr8[1], bgr8[0]);
1015 SplashError Splash::fillChar(SplashCoord x, SplashCoord y,
1016 int c, SplashFont *font) {
1017 SplashGlyphBitmap glyph;
1018 int x0, y0, xFrac, yFrac;
1022 printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n",
1025 x0 = splashFloor(x);
1026 xFrac = splashFloor((x - x0) * splashFontFraction);
1027 y0 = splashFloor(y);
1028 yFrac = splashFloor((y - y0) * splashFontFraction);
1029 if (!font->getGlyph(c, xFrac, yFrac, &glyph)) {
1030 return splashErrNoGlyph;
1032 err = fillGlyph(x, y, &glyph);
1033 if (glyph.freeData) {
1039 SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y,
1040 SplashGlyphBitmap *glyph) {
1044 SplashMono1P *mono1Ptr;
1045 SplashMono8 *mono8Ptr;
1046 SplashRGB8 *rgb8Ptr;
1047 SplashRGB8P *rgb8pPtr;
1048 SplashBGR8P *bgr8Ptr;
1049 SplashMono8 bgMono8;
1051 SplashClipResult clipRes;
1053 int x0, y0, x1, y1, xx, xx1, yy;
1055 x0 = splashFloor(x);
1056 y0 = splashFloor(y);
1058 if ((clipRes = state->clip->testRect(x0 - glyph->x,
1060 x0 - glyph->x + glyph->w - 1,
1061 y0 - glyph->y + glyph->h - 1))
1062 != splashClipAllOutside) {
1063 noClip = clipRes == splashClipAllInside;
1068 for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
1069 for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
1072 if (noClip || state->clip->test(x1, y1)) {
1073 ialpha = 255 - alpha;
1074 fg = state->fillPattern->getColor(x1, y1);
1075 switch (bitmap->mode) {
1076 case splashModeMono1:
1077 if (alpha >= 0x80) {
1078 mono1Ptr = &bitmap->data.mono1[y1 * bitmap->rowSize +
1081 *mono1Ptr |= 0x80 >> (x1 & 7);
1083 *mono1Ptr &= ~(0x80 >> (x1 & 7));
1087 case splashModeMono8:
1088 mono8Ptr = &bitmap->data.mono8[y1 * bitmap->width + x1];
1089 bgMono8 = *mono8Ptr;
1090 // note: floor(x / 255) = x >> 8 (for 16-bit x)
1091 *mono8Ptr = (alpha * fg.mono8 + ialpha * bgMono8) >> 8;
1093 case splashModeRGB8:
1094 rgb8Ptr = &bitmap->data.rgb8[y1 * bitmap->width + x1];
1095 bgR = splashRGB8R(*rgb8Ptr);
1096 bgG = splashRGB8G(*rgb8Ptr);
1097 bgB = splashRGB8B(*rgb8Ptr);
1098 *rgb8Ptr = splashMakeRGB8((alpha * splashRGB8R(fg.rgb8) +
1100 (alpha * splashRGB8G(fg.rgb8) +
1102 (alpha * splashRGB8B(fg.rgb8) +
1103 ialpha * bgB) >> 8);
1105 case splashModeRGB8Packed:
1106 rgb8pPtr = &bitmap->data.rgb8p[y1 * bitmap->rowSize + 3 * x1];
1108 (alpha * splashRGB8R(fg.rgb8) + ialpha * rgb8pPtr[0]) >> 8;
1110 (alpha * splashRGB8G(fg.rgb8) + ialpha * rgb8pPtr[1]) >> 8;
1112 (alpha * splashRGB8B(fg.rgb8) + ialpha * rgb8pPtr[2]) >> 8;
1114 case splashModeBGR8Packed:
1115 bgr8Ptr = &bitmap->data.bgr8[y1 * bitmap->rowSize + 3 * x1];
1117 (alpha * splashBGR8R(fg.bgr8) + ialpha * bgr8Ptr[2]) >> 8;
1119 (alpha * splashBGR8G(fg.bgr8) + ialpha * bgr8Ptr[1]) >> 8;
1121 (alpha * splashBGR8B(fg.bgr8) + ialpha * bgr8Ptr[0]) >> 8;
1131 for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
1132 for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) {
1134 for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
1136 if (noClip || state->clip->test(x1, y1)) {
1137 fg = state->fillPattern->getColor(x1, y1);
1138 switch (bitmap->mode) {
1139 case splashModeMono1:
1140 mono1Ptr = &bitmap->data.mono1[y1 * bitmap->rowSize +
1143 *mono1Ptr |= 0x80 >> (x1 & 7);
1145 *mono1Ptr &= ~(0x80 >> (x1 & 7));
1148 case splashModeMono8:
1149 bitmap->data.mono8[y1 * bitmap->width + x1] = fg.mono8;
1151 case splashModeRGB8:
1152 bitmap->data.rgb8[y1 * bitmap->width + x1] = fg.rgb8;
1154 case splashModeRGB8Packed:
1155 rgb8pPtr = &bitmap->data.rgb8p[y1 * bitmap->rowSize + 3 * x1];
1156 rgb8pPtr[0] = splashRGB8R(fg.rgb8);
1157 rgb8pPtr[1] = splashRGB8G(fg.rgb8);
1158 rgb8pPtr[2] = splashRGB8B(fg.rgb8);
1160 case splashModeBGR8Packed:
1161 bgr8Ptr = &bitmap->data.bgr8[y1 * bitmap->rowSize + 3 * x1];
1162 bgr8Ptr[2] = splashBGR8R(fg.bgr8);
1163 bgr8Ptr[1] = splashBGR8G(fg.bgr8);
1164 bgr8Ptr[0] = splashBGR8B(fg.bgr8);
1179 SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
1180 int w, int h, SplashCoord *mat) {
1182 SplashCoord xScale, yScale, xShear, yShear;
1183 int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
1184 int ulx, uly, llx, lly, urx, ury, lrx, lry;
1185 int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
1186 int xMin, xMax, yMin, yMax;
1187 SplashClipResult clipRes, clipRes2;
1188 int yp, yq, yt, yStep, lastYStep;
1189 int xp, xq, xt, xStep, xSrc;
1190 int k1, spanXMin, spanXMax, spanY;
1191 SplashMono1 *pixBuf;
1195 SplashColor fg, bg, pix;
1196 int x, y, x1, y1, x2, y2;
1200 printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
1201 w, h, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
1204 // check for singular matrix
1205 if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) {
1206 return splashErrSingularMatrix;
1209 // compute scale, shear, rotation, translation parameters
1210 rot = splashAbs(mat[1]) > splashAbs(mat[0]);
1213 yScale = mat[2] - (mat[0] * mat[3]) / mat[1];
1214 xShear = -mat[3] / yScale;
1215 yShear = -mat[0] / mat[1];
1218 yScale = mat[3] - (mat[1] * mat[2]) / mat[0];
1219 xShear = mat[2] / yScale;
1220 yShear = mat[1] / mat[0];
1222 tx = splashRound(mat[4]);
1223 ty = splashRound(mat[5]);
1224 scaledWidth = abs(splashRound(mat[4] + xScale) - tx) + 1;
1225 scaledHeight = abs(splashRound(mat[5] + yScale) - ty) + 1;
1226 xSign = (xScale < 0) ? -1 : 1;
1227 ySign = (yScale < 0) ? -1 : 1;
1232 urx1 = xSign * (scaledWidth - 1);
1233 ury1 = splashRound(yShear * urx1);
1234 llx1 = splashRound(xShear * ySign * (scaledHeight - 1));
1235 lly1 = ySign * (scaledHeight - 1) + splashRound(yShear * llx1);
1236 lrx1 = xSign * (scaledWidth - 1) +
1237 splashRound(xShear * ySign * (scaledHeight - 1));
1238 lry1 = ySign * (scaledHeight - 1) + splashRound(yShear * lrx1);
1240 ulx = tx + uly1; uly = ty - ulx1;
1241 urx = tx + ury1; ury = ty - urx1;
1242 llx = tx + lly1; lly = ty - llx1;
1243 lrx = tx + lry1; lry = ty - lrx1;
1245 ulx = tx + ulx1; uly = ty + uly1;
1246 urx = tx + urx1; ury = ty + ury1;
1247 llx = tx + llx1; lly = ty + lly1;
1248 lrx = tx + lrx1; lry = ty + lry1;
1250 xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
1251 : (llx < lrx) ? llx : lrx
1252 : (urx < llx) ? (urx < lrx) ? urx : lrx
1253 : (llx < lrx) ? llx : lrx;
1254 xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
1255 : (llx > lrx) ? llx : lrx
1256 : (urx > llx) ? (urx > lrx) ? urx : lrx
1257 : (llx > lrx) ? llx : lrx;
1258 yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
1259 : (lly < lry) ? lly : lry
1260 : (ury < lly) ? (ury < lry) ? ury : lry
1261 : (lly < lry) ? lly : lry;
1262 yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
1263 : (lly > lry) ? lly : lry
1264 : (ury > lly) ? (ury > lry) ? ury : lry
1265 : (lly > lry) ? lly : lry;
1266 clipRes = state->clip->testRect(xMin, yMin, xMax, yMax);
1268 // compute Bresenham parameters for x and y scaling
1269 yp = h / scaledHeight;
1270 yq = h % scaledHeight;
1271 xp = w / scaledWidth;
1272 xq = w % scaledWidth;
1274 // allocate pixel buffer
1275 pixBuf = (SplashMono1 *)gmalloc((yp + 1) * w * sizeof(SplashMono1));
1277 // init y scale Bresenham
1281 for (y = 0; y < scaledHeight; ++y) {
1283 // y scale Bresenham
1286 if (yt >= scaledHeight) {
1291 // read row(s) from image
1292 n = (yp > 0) ? yStep : lastYStep;
1295 for (i = 0; i < n; ++i) {
1296 for (j = 0; j < w; ++j) {
1297 (*src)(srcData, p++);
1303 // loop-invariant constants
1304 k1 = splashRound(xShear * ySign * y);
1307 if (clipRes != splashClipAllInside &&
1309 splashRound(yShear * k1) ==
1310 splashRound(yShear * (xSign * (scaledWidth - 1) + k1))) {
1313 spanXMax = spanXMin + (scaledWidth - 1);
1316 spanXMin = spanXMax - (scaledWidth - 1);
1318 spanY = ty + ySign * y + splashRound(xShear * ySign * y);
1319 clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY);
1320 if (clipRes2 == splashClipAllOutside) {
1327 // init x scale Bresenham
1331 for (x = 0; x < scaledWidth; ++x) {
1333 // x scale Bresenham
1336 if (xt >= scaledWidth) {
1342 x1 = xSign * x + k1;
1345 y1 = ySign * y + splashRound(yShear * x1);
1356 // compute the alpha value for (x,y) after the x and y scaling
1358 n = yStep > 0 ? yStep : 1;
1359 m = xStep > 0 ? xStep : 1;
1362 for (i = 0; i < n; ++i) {
1363 for (j = 0; j < m; ++j) {
1369 // blend fill color with background
1371 fg = state->fillPattern->getColor(tx + x2, ty + y2);
1372 if (pixAcc == n * m) {
1375 getPixel(tx + x2, ty + y2, &bg);
1376 alpha = (SplashCoord)pixAcc / (SplashCoord)(n * m);
1377 switch (bitmap->mode) {
1378 case splashModeMono1:
1379 pix.mono1 = splashRound(alpha * fg.mono1 +
1380 (1 - alpha) * bg.mono1);
1382 case splashModeMono8:
1383 pix.mono8 = splashRound(alpha * fg.mono8 +
1384 (1 - alpha) * bg.mono8);
1386 case splashModeRGB8:
1387 case splashModeRGB8Packed:
1388 pix.rgb8 = splashMakeRGB8(
1389 splashRound(alpha * splashRGB8R(fg.rgb8) +
1390 (1 - alpha) * splashRGB8R(bg.rgb8)),
1391 splashRound(alpha * splashRGB8G(fg.rgb8) +
1392 (1 - alpha) * splashRGB8G(bg.rgb8)),
1393 splashRound(alpha * splashRGB8B(fg.rgb8) +
1394 (1 - alpha) * splashRGB8B(bg.rgb8)));
1396 case splashModeBGR8Packed:
1397 pix.bgr8 = splashMakeBGR8(
1398 splashRound(alpha * splashBGR8R(fg.bgr8) +
1399 (1 - alpha) * splashBGR8R(bg.bgr8)),
1400 splashRound(alpha * splashBGR8G(fg.bgr8) +
1401 (1 - alpha) * splashBGR8G(bg.bgr8)),
1402 splashRound(alpha * splashBGR8B(fg.bgr8) +
1403 (1 - alpha) * splashBGR8B(bg.bgr8)));
1407 drawPixel(tx + x2, ty + y2, &pix, clipRes2 == splashClipAllInside);
1410 // x scale Bresenham
1421 SplashError Splash::drawImage(SplashImageSource src, void *srcData,
1422 SplashColorMode srcMode,
1423 int w, int h, SplashCoord *mat) {
1424 GBool ok, rot, halftone;
1425 SplashCoord xScale, yScale, xShear, yShear;
1426 int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
1427 int ulx, uly, llx, lly, urx, ury, lrx, lry;
1428 int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
1429 int xMin, xMax, yMin, yMax;
1430 SplashClipResult clipRes, clipRes2;
1431 int yp, yq, yt, yStep, lastYStep;
1432 int xp, xq, xt, xStep, xSrc;
1433 int k1, spanXMin, spanXMax, spanY;
1434 SplashColor *pixBuf, *p;
1435 Guchar *alphaBuf, *q;
1437 SplashCoord pixAcc[splashMaxColorComps];
1439 SplashCoord pixMul, alphaMul, alpha;
1440 int x, y, x1, y1, x2, y2;
1444 printf("drawImage: srcMode=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n",
1445 srcMode, w, h, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
1448 // check color modes
1449 ok = gFalse; // make gcc happy
1450 switch (bitmap->mode) {
1451 case splashModeMono1:
1452 ok = srcMode == splashModeMono1 || srcMode == splashModeMono8;
1454 case splashModeMono8:
1455 ok = srcMode == splashModeMono8;
1457 case splashModeRGB8:
1458 ok = srcMode == splashModeRGB8;
1460 case splashModeRGB8Packed:
1461 ok = srcMode == splashModeRGB8Packed;
1463 case splashModeBGR8Packed:
1464 ok = srcMode == splashModeBGR8Packed;
1468 return splashErrModeMismatch;
1470 halftone = bitmap->mode == splashModeMono1 && srcMode == splashModeMono8;
1472 // check for singular matrix
1473 if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) {
1474 return splashErrSingularMatrix;
1477 // compute scale, shear, rotation, translation parameters
1478 rot = splashAbs(mat[1]) > splashAbs(mat[0]);
1481 yScale = mat[2] - (mat[0] * mat[3]) / mat[1];
1482 xShear = -mat[3] / yScale;
1483 yShear = -mat[0] / mat[1];
1486 yScale = mat[3] - (mat[1] * mat[2]) / mat[0];
1487 xShear = mat[2] / yScale;
1488 yShear = mat[1] / mat[0];
1490 tx = splashRound(mat[4]);
1491 ty = splashRound(mat[5]);
1492 scaledWidth = abs(splashRound(mat[4] + xScale) - tx) + 1;
1493 scaledHeight = abs(splashRound(mat[5] + yScale) - ty) + 1;
1494 xSign = (xScale < 0) ? -1 : 1;
1495 ySign = (yScale < 0) ? -1 : 1;
1500 urx1 = xSign * (scaledWidth - 1);
1501 ury1 = splashRound(yShear * urx1);
1502 llx1 = splashRound(xShear * ySign * (scaledHeight - 1));
1503 lly1 = ySign * (scaledHeight - 1) + splashRound(yShear * llx1);
1504 lrx1 = xSign * (scaledWidth - 1) +
1505 splashRound(xShear * ySign * (scaledHeight - 1));
1506 lry1 = ySign * (scaledHeight - 1) + splashRound(yShear * lrx1);
1508 ulx = tx + uly1; uly = ty - ulx1;
1509 urx = tx + ury1; ury = ty - urx1;
1510 llx = tx + lly1; lly = ty - llx1;
1511 lrx = tx + lry1; lry = ty - lrx1;
1513 ulx = tx + ulx1; uly = ty + uly1;
1514 urx = tx + urx1; ury = ty + ury1;
1515 llx = tx + llx1; lly = ty + lly1;
1516 lrx = tx + lrx1; lry = ty + lry1;
1518 xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
1519 : (llx < lrx) ? llx : lrx
1520 : (urx < llx) ? (urx < lrx) ? urx : lrx
1521 : (llx < lrx) ? llx : lrx;
1522 xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
1523 : (llx > lrx) ? llx : lrx
1524 : (urx > llx) ? (urx > lrx) ? urx : lrx
1525 : (llx > lrx) ? llx : lrx;
1526 yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
1527 : (lly < lry) ? lly : lry
1528 : (ury < lly) ? (ury < lry) ? ury : lry
1529 : (lly < lry) ? lly : lry;
1530 yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
1531 : (lly > lry) ? lly : lry
1532 : (ury > lly) ? (ury > lry) ? ury : lry
1533 : (lly > lry) ? lly : lry;
1534 if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax))
1535 == splashClipAllOutside) {
1539 // compute Bresenham parameters for x and y scaling
1540 yp = h / scaledHeight;
1541 yq = h % scaledHeight;
1542 xp = w / scaledWidth;
1543 xq = w % scaledWidth;
1545 // allocate pixel buffer
1546 pixBuf = (SplashColor *)gmalloc((yp + 1) * w * sizeof(SplashColor));
1547 alphaBuf = (Guchar *)gmalloc((yp + 1) * w * sizeof(Guchar));
1549 // init y scale Bresenham
1553 for (y = 0; y < scaledHeight; ++y) {
1555 // y scale Bresenham
1558 if (yt >= scaledHeight) {
1563 // read row(s) from image
1564 n = (yp > 0) ? yStep : lastYStep;
1568 for (i = 0; i < n; ++i) {
1569 for (j = 0; j < w; ++j) {
1570 (*src)(srcData, p++, q++);
1576 // loop-invariant constants
1577 k1 = splashRound(xShear * ySign * y);
1580 if (clipRes != splashClipAllInside &&
1582 splashRound(yShear * k1) ==
1583 splashRound(yShear * (xSign * (scaledWidth - 1) + k1))) {
1586 spanXMax = spanXMin + (scaledWidth - 1);
1589 spanXMin = spanXMax - (scaledWidth - 1);
1591 spanY = ty + ySign * y + splashRound(xShear * ySign * y);
1592 clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY);
1593 if (clipRes2 == splashClipAllOutside) {
1600 // init x scale Bresenham
1604 for (x = 0; x < scaledWidth; ++x) {
1606 // x scale Bresenham
1609 if (xt >= scaledWidth) {
1615 x1 = xSign * x + k1;
1618 y1 = ySign * y + splashRound(yShear * x1);
1629 // compute the filtered pixel at (x,y) after the x and y scaling
1631 n = yStep > 0 ? yStep : 1;
1632 m = xStep > 0 ? xStep : 1;
1634 q = alphaBuf + xSrc;
1635 for (i = 0; i < splashMaxColorComps; ++i) {
1639 for (i = 0; i < n; ++i) {
1640 for (j = 0; j < m; ++j) {
1642 case splashModeMono1:
1643 pixAcc[0] += p->mono1;
1645 case splashModeMono8:
1646 pixAcc[0] += p->mono8;
1648 case splashModeRGB8:
1649 case splashModeRGB8Packed:
1650 pixAcc[0] += splashRGB8R(p->rgb8);
1651 pixAcc[1] += splashRGB8G(p->rgb8);
1652 pixAcc[2] += splashRGB8B(p->rgb8);
1654 case splashModeBGR8Packed:
1655 pixAcc[0] += splashBGR8R(p->bgr8);
1656 pixAcc[1] += splashBGR8G(p->bgr8);
1657 pixAcc[2] += splashBGR8B(p->bgr8);
1666 alphaMul = 1 / (SplashCoord)(n * m);
1668 pixMul = (SplashCoord)alphaMul / 256.0;
1672 alpha = (SplashCoord)alphaAcc * alphaMul;
1674 //~ this should blend if 0 < alpha < 1
1677 // mono8 -> mono1 conversion, with halftoning
1679 pix.mono1 = state->screen->test(tx + x2, ty + y2,
1680 pixAcc[0] * pixMul);
1682 // no conversion, no halftoning
1684 switch (bitmap->mode) {
1685 case splashModeMono1:
1686 pix.mono1 = splashRound(pixAcc[0] * pixMul);
1688 case splashModeMono8:
1689 pix.mono8 = splashRound(pixAcc[0] * pixMul);
1691 case splashModeRGB8:
1692 case splashModeRGB8Packed:
1693 pix.rgb8 = splashMakeRGB8(splashRound(pixAcc[0] * pixMul),
1694 splashRound(pixAcc[1] * pixMul),
1695 splashRound(pixAcc[2] * pixMul));
1697 case splashModeBGR8Packed:
1698 pix.bgr8 = splashMakeBGR8(splashRound(pixAcc[0] * pixMul),
1699 splashRound(pixAcc[1] * pixMul),
1700 splashRound(pixAcc[2] * pixMul));
1706 drawPixel(tx + x2, ty + y2, &pix, clipRes2 == splashClipAllInside);
1709 // x scale Bresenham
1720 void Splash::dumpPath(SplashPath *path) {
1723 for (i = 0; i < path->length; ++i) {
1724 printf(" %3d: x=%8.2f y=%8.2f%s%s%s%s%s\n",
1725 i, path->pts[i].x, path->pts[i].y,
1726 (path->flags[i] & splashPathFirst) ? " first" : "",
1727 (path->flags[i] & splashPathLast) ? " last" : "",
1728 (path->flags[i] & splashPathClosed) ? " closed" : "",
1729 (path->flags[i] & splashPathCurve) ? " curve" : "",
1730 (path->flags[i] & splashPathArcCW) ? " arcCW" : "");