diff options
Diffstat (limited to 'pdf/splash/Splash.cc')
-rw-r--r-- | pdf/splash/Splash.cc | 1732 |
1 files changed, 0 insertions, 1732 deletions
diff --git a/pdf/splash/Splash.cc b/pdf/splash/Splash.cc deleted file mode 100644 index 6202dd1..0000000 --- a/pdf/splash/Splash.cc +++ /dev/null @@ -1,1732 +0,0 @@ -//======================================================================== -// -// Splash.cc -// -//======================================================================== - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gmem.h" -#include "SplashErrorCodes.h" -#include "SplashMath.h" -#include "SplashBitmap.h" -#include "SplashState.h" -#include "SplashPath.h" -#include "SplashXPath.h" -#include "SplashXPathScanner.h" -#include "SplashPattern.h" -#include "SplashScreen.h" -#include "SplashClip.h" -#include "SplashFont.h" -#include "SplashGlyphBitmap.h" -#include "Splash.h" - -//------------------------------------------------------------------------ -// Splash -//------------------------------------------------------------------------ - -Splash::Splash(SplashBitmap *bitmapA) { - bitmap = bitmapA; - state = new SplashState(bitmap->width, bitmap->height); - debugMode = gFalse; -} - -Splash::~Splash() { - while (state->next) { - restoreState(); - } - delete state; -} - -//------------------------------------------------------------------------ -// state read -//------------------------------------------------------------------------ - - -SplashPattern *Splash::getStrokePattern() { - return state->strokePattern; -} - -SplashPattern *Splash::getFillPattern() { - return state->fillPattern; -} - -SplashScreen *Splash::getScreen() { - return state->screen; -} - -SplashCoord Splash::getLineWidth() { - return state->lineWidth; -} - -int Splash::getLineCap() { - return state->lineCap; -} - -int Splash::getLineJoin() { - return state->lineJoin; -} - -SplashCoord Splash::getMiterLimit() { - return state->miterLimit; -} - -SplashCoord Splash::getFlatness() { - return state->flatness; -} - -SplashCoord *Splash::getLineDash() { - return state->lineDash; -} - -int Splash::getLineDashLength() { - return state->lineDashLength; -} - -SplashCoord Splash::getLineDashPhase() { - return state->lineDashPhase; -} - -SplashClip *Splash::getClip() { - return state->clip; -} - -//------------------------------------------------------------------------ -// state write -//------------------------------------------------------------------------ - -void Splash::setStrokePattern(SplashPattern *strokePattern) { - state->setStrokePattern(strokePattern); -} - -void Splash::setFillPattern(SplashPattern *fillPattern) { - state->setFillPattern(fillPattern); -} - -void Splash::setScreen(SplashScreen *screen) { - state->setScreen(screen); -} - -void Splash::setLineWidth(SplashCoord lineWidth) { - state->lineWidth = lineWidth; -} - -void Splash::setLineCap(int lineCap) { - state->lineCap = lineCap; -} - -void Splash::setLineJoin(int lineJoin) { - state->lineJoin = lineJoin; -} - -void Splash::setMiterLimit(SplashCoord miterLimit) { - state->miterLimit = miterLimit; -} - -void Splash::setFlatness(SplashCoord flatness) { - if (flatness < 1) { - state->flatness = 1; - } else { - state->flatness = flatness; - } -} - -void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength, - SplashCoord lineDashPhase) { - state->setLineDash(lineDash, lineDashLength, lineDashPhase); -} - -void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1) { - state->clip->resetToRect(x0, y0, x1, y1); -} - -SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1) { - return state->clip->clipToRect(x0, y0, x1, y1); -} - -SplashError Splash::clipToPath(SplashPath *path, GBool eo) { - return state->clip->clipToPath(path, state->flatness, eo); -} - -//------------------------------------------------------------------------ -// state save/restore -//------------------------------------------------------------------------ - -void Splash::saveState() { - SplashState *newState; - - newState = state->copy(); - newState->next = state; - state = newState; -} - -SplashError Splash::restoreState() { - SplashState *oldState; - - if (!state->next) { - return splashErrNoSave; - } - oldState = state; - state = state->next; - delete oldState; - return splashOk; -} - -//------------------------------------------------------------------------ -// drawing operations -//------------------------------------------------------------------------ - -void Splash::clear(SplashColor color) { - SplashMono1P *mono1; - SplashMono8 *mono8; - SplashRGB8 *rgb8; - SplashRGB8P *rgb8pline, *rgb8p; - SplashBGR8P *bgr8line, *bgr8; - SplashMono1 data; - int n, i, x, y; - - switch (bitmap->mode) { - case splashModeMono1: - n = ((bitmap->width + 7) >> 3) * bitmap->height; - data = color.mono1 ? 0xff : 0x00; - for (i = 0, mono1 = bitmap->data.mono1; i < n; ++i, ++mono1) { - *mono1 = data; - } - break; - case splashModeMono8: - n = bitmap->width * bitmap->height; - for (i = 0, mono8 = bitmap->data.mono8; i < n; ++i, ++mono8) { - *mono8 = color.mono8; - } - break; - case splashModeRGB8: - n = bitmap->width * bitmap->height; - for (i = 0, rgb8 = bitmap->data.rgb8; i < n; ++i, ++rgb8) { - *rgb8 = color.rgb8; - } - break; - case splashModeRGB8Packed: - rgb8pline = bitmap->data.rgb8p; - for (y = 0; y < bitmap->height; ++y) { - rgb8p = rgb8pline; - for (x = 0; x < bitmap->width; ++x) { - rgb8p[0] = splashRGB8R(color.rgb8); - rgb8p[1] = splashRGB8G(color.rgb8); - rgb8p[2] = splashRGB8B(color.rgb8); - rgb8p += 3; - } - rgb8pline += bitmap->rowSize; - } - break; - case splashModeBGR8Packed: - bgr8line = bitmap->data.bgr8; - for (y = 0; y < bitmap->height; ++y) { - bgr8 = bgr8line; - for (x = 0; x < bitmap->width; ++x) { - bgr8[2] = splashBGR8R(color.bgr8); - bgr8[1] = splashBGR8G(color.bgr8); - bgr8[0] = splashBGR8B(color.bgr8); - bgr8 += 3; - } - bgr8line += bitmap->rowSize; - } - break; - } -} - -SplashError Splash::stroke(SplashPath *path) { - SplashXPath *xPath, *xPath2; - - if (debugMode) { - printf("stroke [dash:%d] [width:%.2f]:\n", - state->lineDashLength, state->lineWidth); - dumpPath(path); - } - if (path->length == 0) { - return splashErrEmptyPath; - } - xPath = new SplashXPath(path, state->flatness, gFalse); - if (state->lineDashLength > 0) { - xPath2 = makeDashedPath(xPath); - delete xPath; - xPath = xPath2; - } - if (state->lineWidth <= 1) { - strokeNarrow(xPath); - } else { - strokeWide(xPath); - } - delete xPath; - return splashOk; -} - -void Splash::strokeNarrow(SplashXPath *xPath) { - SplashXPathSeg *seg; - int x0, x1, x2, x3, y0, y1, x, y, t; - SplashCoord dx, dy, dxdy; - SplashClipResult clipRes; - int i; - - for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) { - - x0 = splashFloor(seg->x0); - x1 = splashFloor(seg->x1); - y0 = splashFloor(seg->y0); - y1 = splashFloor(seg->y1); - - // horizontal segment - if (y0 == y1) { - if (x0 > x1) { - t = x0; x0 = x1; x1 = t; - } - if ((clipRes = state->clip->testSpan(x0, x1, y0)) - != splashClipAllOutside) { - drawSpan(x0, x1, y0, state->strokePattern, - clipRes == splashClipAllInside); - } - - // segment with |dx| > |dy| - } else if (splashAbs(seg->dxdy) > 1) { - dx = seg->x1 - seg->x0; - dy = seg->y1 - seg->y0; - dxdy = seg->dxdy; - if (y0 > y1) { - t = y0; y0 = y1; y1 = t; - t = x0; x0 = x1; x1 = t; - dx = -dx; - dy = -dy; - } - if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, - x0 <= x1 ? x1 : x0, y1)) - != splashClipAllOutside) { - if (dx > 0) { - x2 = x0; - for (y = y0; y < y1; ++y) { - x3 = splashFloor(seg->x0 + (y + 1 - seg->y0) * dxdy); - drawSpan(x2, x3 - 1, y, state->strokePattern, - clipRes == splashClipAllInside); - x2 = x3; - } - drawSpan(x2, x1, y, state->strokePattern, - clipRes == splashClipAllInside); - } else { - x2 = x0; - for (y = y0; y < y1; ++y) { - x3 = splashFloor(seg->x0 + (y + 1 - seg->y0) * dxdy); - drawSpan(x3 + 1, x2, y, state->strokePattern, - clipRes == splashClipAllInside); - x2 = x3; - } - drawSpan(x1, x2, y, state->strokePattern, - clipRes == splashClipAllInside); - } - } - - // segment with |dy| > |dx| - } else { - dxdy = seg->dxdy; - if (y0 > y1) { - t = y0; y0 = y1; y1 = t; - } - if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, - x0 <= x1 ? x1 : x0, y1)) - != splashClipAllOutside) { - for (y = y0; y <= y1; ++y) { - x = splashFloor(seg->x0 + (y - seg->y0) * dxdy); - drawPixel(x, y, state->strokePattern, - clipRes == splashClipAllInside); - } - } - } - } -} - -void Splash::strokeWide(SplashXPath *xPath) { - SplashXPathSeg *seg, *seg2; - SplashPath *widePath; - SplashCoord d, dx, dy, wdx, wdy, dxPrev, dyPrev, wdxPrev, wdyPrev; - SplashCoord dotprod, miter; - int i, j; - - dx = dy = wdx = wdy = 0; // make gcc happy - dxPrev = dyPrev = wdxPrev = wdyPrev = 0; // make gcc happy - - for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) { - - // save the deltas for the previous segment; if this is the first - // segment on a subpath, compute the deltas for the last segment - // on the subpath (which may be used to draw a line join) - if (seg->flags & splashXPathFirst) { - for (j = i + 1, seg2 = &xPath->segs[j]; j < xPath->length; ++j, ++seg2) { - if (seg2->flags & splashXPathLast) { - d = splashDist(seg2->x0, seg2->y0, seg2->x1, seg2->y1); - if (d == 0) { - //~ not clear what the behavior should be for joins with d==0 - dxPrev = 0; - dyPrev = 1; - } else { - d = 1 / d; - dxPrev = d * (seg2->x1 - seg2->x0); - dyPrev = d * (seg2->y1 - seg2->y0); - } - wdxPrev = 0.5 * state->lineWidth * dxPrev; - wdyPrev = 0.5 * state->lineWidth * dyPrev; - break; - } - } - } else { - dxPrev = dx; - dyPrev = dy; - wdxPrev = wdx; - wdyPrev = wdy; - } - - // compute deltas for this line segment - d = splashDist(seg->x0, seg->y0, seg->x1, seg->y1); - if (d == 0) { - // we need to draw end caps on zero-length lines - //~ not clear what the behavior should be for splashLineCapButt with d==0 - dx = 0; - dy = 1; - } else { - d = 1 / d; - dx = d * (seg->x1 - seg->x0); - dy = d * (seg->y1 - seg->y0); - } - wdx = 0.5 * state->lineWidth * dx; - wdy = 0.5 * state->lineWidth * dy; - - // initialize the path (which will be filled) - widePath = new SplashPath(); - widePath->moveTo(seg->x0 - wdy, seg->y0 + wdx); - - // draw the start cap - if (seg->flags & splashXPathEnd0) { - switch (state->lineCap) { - case splashLineCapButt: - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - break; - case splashLineCapRound: - widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0); - break; - case splashLineCapProjecting: - widePath->lineTo(seg->x0 - wdx - wdy, seg->y0 + wdx - wdy); - widePath->lineTo(seg->x0 - wdx + wdy, seg->y0 - wdx - wdy); - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - break; - } - } else { - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - } - - // draw the left side of the segment - widePath->lineTo(seg->x1 + wdy, seg->y1 - wdx); - - // draw the end cap - if (seg->flags & splashXPathEnd1) { - switch (state->lineCap) { - case splashLineCapButt: - widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx); - break; - case splashLineCapRound: - widePath->arcCWTo(seg->x1 - wdy, seg->y1 + wdx, seg->x1, seg->y1); - break; - case splashLineCapProjecting: - widePath->lineTo(seg->x1 + wdx + wdy, seg->y1 - wdx + wdy); - widePath->lineTo(seg->x1 + wdx - wdy, seg->y1 + wdx + wdy); - widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx); - break; - } - } else { - widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx); - } - - // draw the right side of the segment - widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx); - - // fill the segment - fillWithPattern(widePath, gTrue, state->strokePattern); - delete widePath; - - // draw the line join - if (!(seg->flags & splashXPathEnd0)) { - widePath = NULL; - switch (state->lineJoin) { - case splashLineJoinMiter: - dotprod = -(dx * dxPrev + dy * dyPrev); - if (dotprod != 1) { - widePath = new SplashPath(); - widePath->moveTo(seg->x0, seg->y0); - miter = 2 / (1 - dotprod); - if (splashSqrt(miter) <= state->miterLimit) { - miter = splashSqrt(miter - 1); - if (dy * dxPrev > dx * dyPrev) { - widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev); - widePath->lineTo(seg->x0 + wdy - miter * wdx, - seg->y0 - wdx - miter * wdy); - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - } else { - widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev); - widePath->lineTo(seg->x0 - wdy - miter * wdx, - seg->y0 + wdx - miter * wdy); - widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx); - } - } else { - if (dy * dxPrev > dx * dyPrev) { - widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev); - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - } else { - widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev); - widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx); - } - } - } - break; - case splashLineJoinRound: - widePath = new SplashPath(); - widePath->moveTo(seg->x0 + wdy, seg->y0 - wdx); - widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0); - break; - case splashLineJoinBevel: - widePath = new SplashPath(); - widePath->moveTo(seg->x0, seg->y0); - if (dy * dxPrev > dx * dyPrev) { - widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev); - widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx); - } else { - widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev); - widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx); - } - break; - } - if (widePath) { - fillWithPattern(widePath, gTrue, state->strokePattern); - delete widePath; - } - } - } -} - -SplashXPath *Splash::makeDashedPath(SplashXPath *xPath) { - SplashXPath *dPath; - GBool lineDashStartOn, lineDashOn; - GBool atSegStart, atSegEnd, atDashStart, atDashEnd; - int lineDashStartIdx, lineDashIdx, subpathStart; - SplashCoord lineDashTotal, lineDashStartPhase, lineDashDist; - int segIdx; - SplashXPathSeg *seg; - SplashCoord sx0, sy0, sx1, sy1, ax0, ay0, ax1, ay1, dist; - int i; - - dPath = new SplashXPath(); - - lineDashTotal = 0; - for (i = 0; i < state->lineDashLength; ++i) { - lineDashTotal += state->lineDash[i]; - } - lineDashStartPhase = state->lineDashPhase; - i = splashFloor(lineDashStartPhase / lineDashTotal); - lineDashStartPhase -= i * lineDashTotal; - lineDashStartOn = gTrue; - lineDashStartIdx = 0; - while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) { - lineDashStartOn = !lineDashStartOn; - lineDashStartPhase -= state->lineDash[lineDashStartIdx]; - ++lineDashStartIdx; - } - - segIdx = 0; - seg = xPath->segs; - sx0 = seg->x0; - sy0 = seg->y0; - sx1 = seg->x1; - sy1 = seg->y1; - dist = splashDist(sx0, sy0, sx1, sy1); - lineDashOn = lineDashStartOn; - lineDashIdx = lineDashStartIdx; - lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase; - atSegStart = gTrue; - atDashStart = gTrue; - subpathStart = dPath->length; - - while (segIdx < xPath->length) { - - ax0 = sx0; - ay0 = sy0; - if (dist <= lineDashDist) { - ax1 = sx1; - ay1 = sy1; - lineDashDist -= dist; - dist = 0; - atSegEnd = gTrue; - atDashEnd = lineDashDist == 0 || (seg->flags & splashXPathLast); - } else { - ax1 = sx0 + (lineDashDist / dist) * (sx1 - sx0); - ay1 = sy0 + (lineDashDist / dist) * (sy1 - sy0); - sx0 = ax1; - sy0 = ay1; - dist -= lineDashDist; - lineDashDist = 0; - atSegEnd = gFalse; - atDashEnd = gTrue; - } - - if (lineDashOn) { - dPath->addSegment(ax0, ay0, ax1, ay1, - atDashStart, atDashEnd, - atDashStart, atDashEnd); - // end of closed subpath - if (atSegEnd && - (seg->flags & splashXPathLast) && - !(seg->flags & splashXPathEnd1)) { - dPath->segs[subpathStart].flags &= ~splashXPathEnd0; - dPath->segs[dPath->length - 1].flags &= ~splashXPathEnd1; - } - } - - if (atDashEnd) { - lineDashOn = !lineDashOn; - if (++lineDashIdx == state->lineDashLength) { - lineDashIdx = 0; - } - lineDashDist = state->lineDash[lineDashIdx]; - atDashStart = gTrue; - } else { - atDashStart = gFalse; - } - if (atSegEnd) { - if (++segIdx < xPath->length) { - ++seg; - sx0 = seg->x0; - sy0 = seg->y0; - sx1 = seg->x1; - sy1 = seg->y1; - dist = splashDist(sx0, sy0, sx1, sy1); - if (seg->flags & splashXPathFirst) { - lineDashOn = lineDashStartOn; - lineDashIdx = lineDashStartIdx; - lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase; - atDashStart = gTrue; - subpathStart = dPath->length; - } - } - atSegStart = gTrue; - } else { - atSegStart = gFalse; - } - } - - return dPath; -} - -SplashError Splash::fill(SplashPath *path, GBool eo) { - if (debugMode) { - printf("fill [eo:%d]:\n", eo); - dumpPath(path); - } - return fillWithPattern(path, eo, state->fillPattern); -} - -SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, - SplashPattern *pattern) { - SplashXPath *xPath; - SplashXPathScanner *scanner; - int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; - SplashClipResult clipRes, clipRes2; - - if (path->length == 0 || path->length == 1) { - return splashErrEmptyPath; - } - xPath = new SplashXPath(path, state->flatness, gTrue); - xPath->sort(); - scanner = new SplashXPathScanner(xPath, eo); - - // get the min and max x and y values - scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); - - // check clipping - if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) - != splashClipAllOutside) { - - // draw the spans - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - drawSpan(x0, x1, y, pattern, gTrue); - } else { - clipRes2 = state->clip->testSpan(x0, x1, y); - drawSpan(x0, x1, y, pattern, clipRes2 == splashClipAllInside); - } - } - } - } - - delete scanner; - delete xPath; - return splashOk; -} - -SplashError Splash::xorFill(SplashPath *path, GBool eo) { - SplashXPath *xPath; - SplashXPathScanner *scanner; - int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; - SplashClipResult clipRes, clipRes2; - - if (path->length == 0) { - return splashErrEmptyPath; - } - xPath = new SplashXPath(path, state->flatness, gTrue); - xPath->sort(); - scanner = new SplashXPathScanner(xPath, eo); - - // get the min and max x and y values - scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); - - // check clipping - if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) - != splashClipAllOutside) { - - // draw the spans - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - xorSpan(x0, x1, y, state->fillPattern, gTrue); - } else { - clipRes2 = state->clip->testSpan(x0, x1, y); - xorSpan(x0, x1, y, state->fillPattern, - clipRes2 == splashClipAllInside); - } - } - } - } - - delete scanner; - delete xPath; - return splashOk; -} - -void Splash::drawPixel(int x, int y, SplashColor *color, GBool noClip) { - SplashMono1P *mono1; - SplashRGB8P *rgb8p; - SplashBGR8P *bgr8; - - if (noClip || state->clip->test(x, y)) { - switch (bitmap->mode) { - case splashModeMono1: - mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x >> 3)]; - if (color->mono1) { - *mono1 |= 0x80 >> (x & 7); - } else { - *mono1 &= ~(0x80 >> (x & 7)); - } - break; - case splashModeMono8: - bitmap->data.mono8[y * bitmap->width + x] = color->mono8; - break; - case splashModeRGB8: - bitmap->data.rgb8[y * bitmap->width + x] = color->rgb8; - break; - case splashModeRGB8Packed: - rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x]; - rgb8p[0] = splashRGB8R(color->rgb8); - rgb8p[1] = splashRGB8G(color->rgb8); - rgb8p[2] = splashRGB8B(color->rgb8); - break; - case splashModeBGR8Packed: - bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x]; - bgr8[2] = splashBGR8R(color->bgr8); - bgr8[1] = splashBGR8G(color->bgr8); - bgr8[0] = splashBGR8B(color->bgr8); - break; - } - } -} - -void Splash::drawPixel(int x, int y, SplashPattern *pattern, GBool noClip) { - SplashColor color; - SplashMono1P *mono1; - SplashRGB8P *rgb8p; - SplashBGR8P *bgr8; - - if (noClip || state->clip->test(x, y)) { - color = pattern->getColor(x, y); - switch (bitmap->mode) { - case splashModeMono1: - mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x >> 3)]; - if (color.mono1) { - *mono1 |= 0x80 >> (x & 7); - } else { - *mono1 &= ~(0x80 >> (x & 7)); - } - break; - case splashModeMono8: - bitmap->data.mono8[y * bitmap->width + x] = color.mono8; - break; - case splashModeRGB8: - bitmap->data.rgb8[y * bitmap->width + x] = color.rgb8; - break; - case splashModeRGB8Packed: - rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x]; - rgb8p[0] = splashRGB8R(color.rgb8); - rgb8p[1] = splashRGB8G(color.rgb8); - rgb8p[2] = splashRGB8B(color.rgb8); - break; - case splashModeBGR8Packed: - bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x]; - bgr8[2] = splashBGR8R(color.bgr8); - bgr8[1] = splashBGR8G(color.bgr8); - bgr8[0] = splashBGR8B(color.bgr8); - break; - } - } -} - -void Splash::drawSpan(int x0, int x1, int y, SplashPattern *pattern, - GBool noClip) { - SplashColor color; - SplashMono1P *mono1; - SplashMono8 *mono8; - SplashRGB8 *rgb8; - SplashRGB8P *rgb8p; - SplashBGR8P *bgr8; - SplashMono1 mask1; - int i, j, n; - - n = x1 - x0 + 1; - - switch (bitmap->mode) { - case splashModeMono1: - mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x0 >> 3)]; - i = 0; - if ((j = x0 & 7)) { - mask1 = 0x80 >> j; - for (j = x0 & 7; j < 8 && i < n; ++i, ++j) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - if (color.mono1) { - *mono1 |= mask1; - } else { - *mono1 &= ~mask1; - } - } - mask1 >>= 1; - } - ++mono1; - } - while (i < n) { - mask1 = 0x80; - for (j = 0; j < 8 && i < n; ++i, ++j) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - if (color.mono1) { - *mono1 |= mask1; - } else { - *mono1 &= ~mask1; - } - } - mask1 >>= 1; - } - ++mono1; - } - break; - - case splashModeMono8: - mono8 = &bitmap->data.mono8[y * bitmap->width + x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - *mono8 = color.mono8; - } - ++mono8; - } - break; - - case splashModeRGB8: - rgb8 = &bitmap->data.rgb8[y * bitmap->width + x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - *rgb8 = color.rgb8; - } - ++rgb8; - } - break; - - case splashModeRGB8Packed: - rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - rgb8p[0] = splashRGB8R(color.rgb8); - rgb8p[1] = splashRGB8G(color.rgb8); - rgb8p[2] = splashRGB8B(color.rgb8); - } - rgb8p += 3; - } - break; - - case splashModeBGR8Packed: - bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - bgr8[2] = splashBGR8R(color.bgr8); - bgr8[1] = splashBGR8G(color.bgr8); - bgr8[0] = splashBGR8B(color.bgr8); - } - bgr8 += 3; - } - break; - } -} - -void Splash::xorSpan(int x0, int x1, int y, SplashPattern *pattern, - GBool noClip) { - SplashColor color; - SplashMono1P *mono1; - SplashMono8 *mono8; - SplashRGB8 *rgb8; - SplashRGB8P *rgb8p; - SplashBGR8P *bgr8; - SplashMono1 mask1; - int i, j, n; - - n = x1 - x0 + 1; - - switch (bitmap->mode) { - case splashModeMono1: - mono1 = &bitmap->data.mono8[y * bitmap->rowSize + (x0 >> 3)]; - i = 0; - if ((j = x0 & 7)) { - mask1 = 0x80 >> j; - for (j = x0 & 7; j < 8 && i < n; ++i, ++j) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - if (color.mono1) { - *mono1 ^= mask1; - } - } - mask1 >>= 1; - } - ++mono1; - } - while (i < n) { - mask1 = 0x80; - for (j = 0; j < 8 && i < n; ++i, ++j) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - if (color.mono1) { - *mono1 ^= mask1; - } - } - mask1 >>= 1; - } - ++mono1; - } - break; - - case splashModeMono8: - mono8 = &bitmap->data.mono8[y * bitmap->width + x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - *mono8 ^= color.mono8; - } - ++mono8; - } - break; - - case splashModeRGB8: - rgb8 = &bitmap->data.rgb8[y * bitmap->width + x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - *rgb8 ^= color.rgb8; - } - ++rgb8; - } - break; - - case splashModeRGB8Packed: - rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - rgb8p[0] ^= splashRGB8R(color.rgb8); - rgb8p[1] ^= splashRGB8G(color.rgb8); - rgb8p[2] ^= splashRGB8B(color.rgb8); - } - rgb8p += 3; - } - break; - - case splashModeBGR8Packed: - bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x0]; - for (i = 0; i < n; ++i) { - if (noClip || state->clip->test(x0 + i, y)) { - color = pattern->getColor(x0 + i, y); - bgr8[2] ^= splashBGR8R(color.bgr8); - bgr8[1] ^= splashBGR8G(color.bgr8); - bgr8[0] ^= splashBGR8B(color.bgr8); - } - bgr8 += 3; - } - break; - } -} - -void Splash::getPixel(int x, int y, SplashColor *pixel) { - SplashRGB8P *rgb8p; - SplashBGR8P *bgr8; - - if (y < 0 || y >= bitmap->height || x < 0 || x >= bitmap->width) { - return; - } - switch (bitmap->mode) { - case splashModeMono1: - pixel->mono1 = (bitmap->data.mono1[y * bitmap->rowSize + (x >> 3)] - >> (7 - (x & 7))) & 1; - break; - case splashModeMono8: - pixel->mono8 = bitmap->data.mono8[y * bitmap->width + x]; - break; - case splashModeRGB8: - pixel->rgb8 = bitmap->data.rgb8[y * bitmap->width + x]; - break; - case splashModeRGB8Packed: - rgb8p = &bitmap->data.rgb8p[y * bitmap->rowSize + 3 * x]; - pixel->rgb8 = splashMakeRGB8(rgb8p[0], rgb8p[1], rgb8p[2]); - break; - case splashModeBGR8Packed: - bgr8 = &bitmap->data.bgr8[y * bitmap->rowSize + 3 * x]; - pixel->bgr8 = splashMakeBGR8(bgr8[2], bgr8[1], bgr8[0]); - break; - } -} - -SplashError Splash::fillChar(SplashCoord x, SplashCoord y, - int c, SplashFont *font) { - SplashGlyphBitmap glyph; - int x0, y0, xFrac, yFrac; - SplashError err; - - if (debugMode) { - printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", - x, y, c, c, c); - } - x0 = splashFloor(x); - xFrac = splashFloor((x - x0) * splashFontFraction); - y0 = splashFloor(y); - yFrac = splashFloor((y - y0) * splashFontFraction); - if (!font->getGlyph(c, xFrac, yFrac, &glyph)) { - return splashErrNoGlyph; - } - err = fillGlyph(x, y, &glyph); - if (glyph.freeData) { - gfree(glyph.data); - } - return err; -} - -SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, - SplashGlyphBitmap *glyph) { - int alpha, ialpha; - Guchar *p; - SplashColor fg; - SplashMono1P *mono1Ptr; - SplashMono8 *mono8Ptr; - SplashRGB8 *rgb8Ptr; - SplashRGB8P *rgb8pPtr; - SplashBGR8P *bgr8Ptr; - SplashMono8 bgMono8; - int bgR, bgG, bgB; - SplashClipResult clipRes; - GBool noClip; - int x0, y0, x1, y1, xx, xx1, yy; - - x0 = splashFloor(x); - y0 = splashFloor(y); - - if ((clipRes = state->clip->testRect(x0 - glyph->x, - y0 - glyph->y, - x0 - glyph->x + glyph->w - 1, - y0 - glyph->y + glyph->h - 1)) - != splashClipAllOutside) { - noClip = clipRes == splashClipAllInside; - - //~ optimize this - if (glyph->aa) { - p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { - alpha = *p++; - if (alpha > 0) { - if (noClip || state->clip->test(x1, y1)) { - ialpha = 255 - alpha; - fg = state->fillPattern->getColor(x1, y1); - switch (bitmap->mode) { - case splashModeMono1: - if (alpha >= 0x80) { - mono1Ptr = &bitmap->data.mono1[y1 * bitmap->rowSize + - (x1 >> 3)]; - if (fg.mono1) { - *mono1Ptr |= 0x80 >> (x1 & 7); - } else { - *mono1Ptr &= ~(0x80 >> (x1 & 7)); - } - } - break; - case splashModeMono8: - mono8Ptr = &bitmap->data.mono8[y1 * bitmap->width + x1]; - bgMono8 = *mono8Ptr; - // note: floor(x / 255) = x >> 8 (for 16-bit x) - *mono8Ptr = (alpha * fg.mono8 + ialpha * bgMono8) >> 8; - break; - case splashModeRGB8: - rgb8Ptr = &bitmap->data.rgb8[y1 * bitmap->width + x1]; - bgR = splashRGB8R(*rgb8Ptr); - bgG = splashRGB8G(*rgb8Ptr); - bgB = splashRGB8B(*rgb8Ptr); - *rgb8Ptr = splashMakeRGB8((alpha * splashRGB8R(fg.rgb8) + - ialpha * bgR) >> 8, - (alpha * splashRGB8G(fg.rgb8) + - ialpha * bgG) >> 8, - (alpha * splashRGB8B(fg.rgb8) + - ialpha * bgB) >> 8); - break; - case splashModeRGB8Packed: - rgb8pPtr = &bitmap->data.rgb8p[y1 * bitmap->rowSize + 3 * x1]; - rgb8pPtr[0] = - (alpha * splashRGB8R(fg.rgb8) + ialpha * rgb8pPtr[0]) >> 8; - rgb8pPtr[1] = - (alpha * splashRGB8G(fg.rgb8) + ialpha * rgb8pPtr[1]) >> 8; - rgb8pPtr[2] = - (alpha * splashRGB8B(fg.rgb8) + ialpha * rgb8pPtr[2]) >> 8; - break; - case splashModeBGR8Packed: - bgr8Ptr = &bitmap->data.bgr8[y1 * bitmap->rowSize + 3 * x1]; - bgr8Ptr[2] = - (alpha * splashBGR8R(fg.bgr8) + ialpha * bgr8Ptr[2]) >> 8; - bgr8Ptr[1] = - (alpha * splashBGR8G(fg.bgr8) + ialpha * bgr8Ptr[1]) >> 8; - bgr8Ptr[0] = - (alpha * splashBGR8B(fg.bgr8) + ialpha * bgr8Ptr[0]) >> 8; - break; - } - } - } - } - } - - } else { - p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { - alpha = *p++; - for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { - if (alpha & 0x80) { - if (noClip || state->clip->test(x1, y1)) { - fg = state->fillPattern->getColor(x1, y1); - switch (bitmap->mode) { - case splashModeMono1: - mono1Ptr = &bitmap->data.mono1[y1 * bitmap->rowSize + - (x1 >> 3)]; - if (fg.mono1) { - *mono1Ptr |= 0x80 >> (x1 & 7); - } else { - *mono1Ptr &= ~(0x80 >> (x1 & 7)); - } - break; - case splashModeMono8: - bitmap->data.mono8[y1 * bitmap->width + x1] = fg.mono8; - break; - case splashModeRGB8: - bitmap->data.rgb8[y1 * bitmap->width + x1] = fg.rgb8; - break; - case splashModeRGB8Packed: - rgb8pPtr = &bitmap->data.rgb8p[y1 * bitmap->rowSize + 3 * x1]; - rgb8pPtr[0] = splashRGB8R(fg.rgb8); - rgb8pPtr[1] = splashRGB8G(fg.rgb8); - rgb8pPtr[2] = splashRGB8B(fg.rgb8); - break; - case splashModeBGR8Packed: - bgr8Ptr = &bitmap->data.bgr8[y1 * bitmap->rowSize + 3 * x1]; - bgr8Ptr[2] = splashBGR8R(fg.bgr8); - bgr8Ptr[1] = splashBGR8G(fg.bgr8); - bgr8Ptr[0] = splashBGR8B(fg.bgr8); - break; - } - } - } - alpha <<= 1; - } - } - } - } - } - - return splashOk; -} - -SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, - int w, int h, SplashCoord *mat) { - GBool rot; - SplashCoord xScale, yScale, xShear, yShear; - int tx, ty, scaledWidth, scaledHeight, xSign, ySign; - int ulx, uly, llx, lly, urx, ury, lrx, lry; - int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1; - int xMin, xMax, yMin, yMax; - SplashClipResult clipRes, clipRes2; - int yp, yq, yt, yStep, lastYStep; - int xp, xq, xt, xStep, xSrc; - int k1, spanXMin, spanXMax, spanY; - SplashMono1 *pixBuf; - SplashMono1 *p; - int pixAcc; - SplashCoord alpha; - SplashColor fg, bg, pix; - int x, y, x1, y1, x2, y2; - int n, m, i, j; - - if (debugMode) { - printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", - w, h, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); - } - - // check for singular matrix - if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) { - return splashErrSingularMatrix; - } - - // compute scale, shear, rotation, translation parameters - rot = splashAbs(mat[1]) > splashAbs(mat[0]); - if (rot) { - xScale = -mat[1]; - yScale = mat[2] - (mat[0] * mat[3]) / mat[1]; - xShear = -mat[3] / yScale; - yShear = -mat[0] / mat[1]; - } else { - xScale = mat[0]; - yScale = mat[3] - (mat[1] * mat[2]) / mat[0]; - xShear = mat[2] / yScale; - yShear = mat[1] / mat[0]; - } - tx = splashRound(mat[4]); - ty = splashRound(mat[5]); - scaledWidth = abs(splashRound(mat[4] + xScale) - tx) + 1; - scaledHeight = abs(splashRound(mat[5] + yScale) - ty) + 1; - xSign = (xScale < 0) ? -1 : 1; - ySign = (yScale < 0) ? -1 : 1; - - // clipping - ulx1 = 0; - uly1 = 0; - urx1 = xSign * (scaledWidth - 1); - ury1 = splashRound(yShear * urx1); - llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); - lly1 = ySign * (scaledHeight - 1) + splashRound(yShear * llx1); - lrx1 = xSign * (scaledWidth - 1) + - splashRound(xShear * ySign * (scaledHeight - 1)); - lry1 = ySign * (scaledHeight - 1) + splashRound(yShear * lrx1); - if (rot) { - ulx = tx + uly1; uly = ty - ulx1; - urx = tx + ury1; ury = ty - urx1; - llx = tx + lly1; lly = ty - llx1; - lrx = tx + lry1; lry = ty - lrx1; - } else { - ulx = tx + ulx1; uly = ty + uly1; - urx = tx + urx1; ury = ty + ury1; - llx = tx + llx1; lly = ty + lly1; - lrx = tx + lrx1; lry = ty + lry1; - } - xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx - : (llx < lrx) ? llx : lrx - : (urx < llx) ? (urx < lrx) ? urx : lrx - : (llx < lrx) ? llx : lrx; - xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx - : (llx > lrx) ? llx : lrx - : (urx > llx) ? (urx > lrx) ? urx : lrx - : (llx > lrx) ? llx : lrx; - yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry - : (lly < lry) ? lly : lry - : (ury < lly) ? (ury < lry) ? ury : lry - : (lly < lry) ? lly : lry; - yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry - : (lly > lry) ? lly : lry - : (ury > lly) ? (ury > lry) ? ury : lry - : (lly > lry) ? lly : lry; - clipRes = state->clip->testRect(xMin, yMin, xMax, yMax); - - // compute Bresenham parameters for x and y scaling - yp = h / scaledHeight; - yq = h % scaledHeight; - xp = w / scaledWidth; - xq = w % scaledWidth; - - // allocate pixel buffer - pixBuf = (SplashMono1 *)gmalloc((yp + 1) * w * sizeof(SplashMono1)); - - // init y scale Bresenham - yt = 0; - lastYStep = 1; - - for (y = 0; y < scaledHeight; ++y) { - - // y scale Bresenham - yStep = yp; - yt += yq; - if (yt >= scaledHeight) { - yt -= scaledHeight; - ++yStep; - } - - // read row(s) from image - n = (yp > 0) ? yStep : lastYStep; - if (n > 0) { - p = pixBuf; - for (i = 0; i < n; ++i) { - for (j = 0; j < w; ++j) { - (*src)(srcData, p++); - } - } - } - lastYStep = yStep; - - // loop-invariant constants - k1 = splashRound(xShear * ySign * y); - - // clipping test - if (clipRes != splashClipAllInside && - !rot && - splashRound(yShear * k1) == - splashRound(yShear * (xSign * (scaledWidth - 1) + k1))) { - if (xSign > 0) { - spanXMin = tx + k1; - spanXMax = spanXMin + (scaledWidth - 1); - } else { - spanXMax = tx + k1; - spanXMin = spanXMax - (scaledWidth - 1); - } - spanY = ty + ySign * y + splashRound(xShear * ySign * y); - clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); - if (clipRes2 == splashClipAllOutside) { - continue; - } - } else { - clipRes2 = clipRes; - } - - // init x scale Bresenham - xt = 0; - xSrc = 0; - - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // x shear - x1 = xSign * x + k1; - - // y shear - y1 = ySign * y + splashRound(yShear * x1); - - // rotation - if (rot) { - x2 = y1; - y2 = -x1; - } else { - x2 = x1; - y2 = y1; - } - - // compute the alpha value for (x,y) after the x and y scaling - // operations - n = yStep > 0 ? yStep : 1; - m = xStep > 0 ? xStep : 1; - p = pixBuf + xSrc; - pixAcc = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc += *p++; - } - p += w - m; - } - - // blend fill color with background - if (pixAcc != 0) { - fg = state->fillPattern->getColor(tx + x2, ty + y2); - if (pixAcc == n * m) { - pix = fg; - } else { - getPixel(tx + x2, ty + y2, &bg); - alpha = (SplashCoord)pixAcc / (SplashCoord)(n * m); - switch (bitmap->mode) { - case splashModeMono1: - pix.mono1 = splashRound(alpha * fg.mono1 + - (1 - alpha) * bg.mono1); - break; - case splashModeMono8: - pix.mono8 = splashRound(alpha * fg.mono8 + - (1 - alpha) * bg.mono8); - break; - case splashModeRGB8: - case splashModeRGB8Packed: - pix.rgb8 = splashMakeRGB8( - splashRound(alpha * splashRGB8R(fg.rgb8) + - (1 - alpha) * splashRGB8R(bg.rgb8)), - splashRound(alpha * splashRGB8G(fg.rgb8) + - (1 - alpha) * splashRGB8G(bg.rgb8)), - splashRound(alpha * splashRGB8B(fg.rgb8) + - (1 - alpha) * splashRGB8B(bg.rgb8))); - break; - case splashModeBGR8Packed: - pix.bgr8 = splashMakeBGR8( - splashRound(alpha * splashBGR8R(fg.bgr8) + - (1 - alpha) * splashBGR8R(bg.bgr8)), - splashRound(alpha * splashBGR8G(fg.bgr8) + - (1 - alpha) * splashBGR8G(bg.bgr8)), - splashRound(alpha * splashBGR8B(fg.bgr8) + - (1 - alpha) * splashBGR8B(bg.bgr8))); - break; - } - } - drawPixel(tx + x2, ty + y2, &pix, clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - } - } - - // free memory - gfree(pixBuf); - - return splashOk; -} - -SplashError Splash::drawImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, - int w, int h, SplashCoord *mat) { - GBool ok, rot, halftone; - SplashCoord xScale, yScale, xShear, yShear; - int tx, ty, scaledWidth, scaledHeight, xSign, ySign; - int ulx, uly, llx, lly, urx, ury, lrx, lry; - int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1; - int xMin, xMax, yMin, yMax; - SplashClipResult clipRes, clipRes2; - int yp, yq, yt, yStep, lastYStep; - int xp, xq, xt, xStep, xSrc; - int k1, spanXMin, spanXMax, spanY; - SplashColor *pixBuf, *p; - Guchar *alphaBuf, *q; - SplashColor pix; - SplashCoord pixAcc[splashMaxColorComps]; - int alphaAcc; - SplashCoord pixMul, alphaMul, alpha; - int x, y, x1, y1, x2, y2; - int n, m, i, j; - - if (debugMode) { - printf("drawImage: srcMode=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", - srcMode, w, h, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); - } - - // check color modes - ok = gFalse; // make gcc happy - switch (bitmap->mode) { - case splashModeMono1: - ok = srcMode == splashModeMono1 || srcMode == splashModeMono8; - break; - case splashModeMono8: - ok = srcMode == splashModeMono8; - break; - case splashModeRGB8: - ok = srcMode == splashModeRGB8; - break; - case splashModeRGB8Packed: - ok = srcMode == splashModeRGB8Packed; - break; - case splashModeBGR8Packed: - ok = srcMode == splashModeBGR8Packed; - break; - } - if (!ok) { - return splashErrModeMismatch; - } - halftone = bitmap->mode == splashModeMono1 && srcMode == splashModeMono8; - - // check for singular matrix - if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) { - return splashErrSingularMatrix; - } - - // compute scale, shear, rotation, translation parameters - rot = splashAbs(mat[1]) > splashAbs(mat[0]); - if (rot) { - xScale = -mat[1]; - yScale = mat[2] - (mat[0] * mat[3]) / mat[1]; - xShear = -mat[3] / yScale; - yShear = -mat[0] / mat[1]; - } else { - xScale = mat[0]; - yScale = mat[3] - (mat[1] * mat[2]) / mat[0]; - xShear = mat[2] / yScale; - yShear = mat[1] / mat[0]; - } - tx = splashRound(mat[4]); - ty = splashRound(mat[5]); - scaledWidth = abs(splashRound(mat[4] + xScale) - tx) + 1; - scaledHeight = abs(splashRound(mat[5] + yScale) - ty) + 1; - xSign = (xScale < 0) ? -1 : 1; - ySign = (yScale < 0) ? -1 : 1; - - // clipping - ulx1 = 0; - uly1 = 0; - urx1 = xSign * (scaledWidth - 1); - ury1 = splashRound(yShear * urx1); - llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); - lly1 = ySign * (scaledHeight - 1) + splashRound(yShear * llx1); - lrx1 = xSign * (scaledWidth - 1) + - splashRound(xShear * ySign * (scaledHeight - 1)); - lry1 = ySign * (scaledHeight - 1) + splashRound(yShear * lrx1); - if (rot) { - ulx = tx + uly1; uly = ty - ulx1; - urx = tx + ury1; ury = ty - urx1; - llx = tx + lly1; lly = ty - llx1; - lrx = tx + lry1; lry = ty - lrx1; - } else { - ulx = tx + ulx1; uly = ty + uly1; - urx = tx + urx1; ury = ty + ury1; - llx = tx + llx1; lly = ty + lly1; - lrx = tx + lrx1; lry = ty + lry1; - } - xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx - : (llx < lrx) ? llx : lrx - : (urx < llx) ? (urx < lrx) ? urx : lrx - : (llx < lrx) ? llx : lrx; - xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx - : (llx > lrx) ? llx : lrx - : (urx > llx) ? (urx > lrx) ? urx : lrx - : (llx > lrx) ? llx : lrx; - yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry - : (lly < lry) ? lly : lry - : (ury < lly) ? (ury < lry) ? ury : lry - : (lly < lry) ? lly : lry; - yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry - : (lly > lry) ? lly : lry - : (ury > lly) ? (ury > lry) ? ury : lry - : (lly > lry) ? lly : lry; - if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax)) - == splashClipAllOutside) { - return splashOk; - } - - // compute Bresenham parameters for x and y scaling - yp = h / scaledHeight; - yq = h % scaledHeight; - xp = w / scaledWidth; - xq = w % scaledWidth; - - // allocate pixel buffer - pixBuf = (SplashColor *)gmalloc((yp + 1) * w * sizeof(SplashColor)); - alphaBuf = (Guchar *)gmalloc((yp + 1) * w * sizeof(Guchar)); - - // init y scale Bresenham - yt = 0; - lastYStep = 1; - - for (y = 0; y < scaledHeight; ++y) { - - // y scale Bresenham - yStep = yp; - yt += yq; - if (yt >= scaledHeight) { - yt -= scaledHeight; - ++yStep; - } - - // read row(s) from image - n = (yp > 0) ? yStep : lastYStep; - if (n > 0) { - p = pixBuf; - q = alphaBuf; - for (i = 0; i < n; ++i) { - for (j = 0; j < w; ++j) { - (*src)(srcData, p++, q++); - } - } - } - lastYStep = yStep; - - // loop-invariant constants - k1 = splashRound(xShear * ySign * y); - - // clipping test - if (clipRes != splashClipAllInside && - !rot && - splashRound(yShear * k1) == - splashRound(yShear * (xSign * (scaledWidth - 1) + k1))) { - if (xSign > 0) { - spanXMin = tx + k1; - spanXMax = spanXMin + (scaledWidth - 1); - } else { - spanXMax = tx + k1; - spanXMin = spanXMax - (scaledWidth - 1); - } - spanY = ty + ySign * y + splashRound(xShear * ySign * y); - clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); - if (clipRes2 == splashClipAllOutside) { - continue; - } - } else { - clipRes2 = clipRes; - } - - // init x scale Bresenham - xt = 0; - xSrc = 0; - - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // x shear - x1 = xSign * x + k1; - - // y shear - y1 = ySign * y + splashRound(yShear * x1); - - // rotation - if (rot) { - x2 = y1; - y2 = -x1; - } else { - x2 = x1; - y2 = y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - n = yStep > 0 ? yStep : 1; - m = xStep > 0 ? xStep : 1; - p = pixBuf + xSrc; - q = alphaBuf + xSrc; - for (i = 0; i < splashMaxColorComps; ++i) { - pixAcc[i] = 0; - } - alphaAcc = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - switch (srcMode) { - case splashModeMono1: - pixAcc[0] += p->mono1; - break; - case splashModeMono8: - pixAcc[0] += p->mono8; - break; - case splashModeRGB8: - case splashModeRGB8Packed: - pixAcc[0] += splashRGB8R(p->rgb8); - pixAcc[1] += splashRGB8G(p->rgb8); - pixAcc[2] += splashRGB8B(p->rgb8); - break; - case splashModeBGR8Packed: - pixAcc[0] += splashBGR8R(p->bgr8); - pixAcc[1] += splashBGR8G(p->bgr8); - pixAcc[2] += splashBGR8B(p->bgr8); - break; - } - ++p; - alphaAcc += *q++; - } - p += w - m; - q += w - m; - } - alphaMul = 1 / (SplashCoord)(n * m); - if (halftone) { - pixMul = (SplashCoord)alphaMul / 256.0; - } else { - pixMul = alphaMul; - } - alpha = (SplashCoord)alphaAcc * alphaMul; - - //~ this should blend if 0 < alpha < 1 - if (alpha > 0.75) { - - // mono8 -> mono1 conversion, with halftoning - if (halftone) { - pix.mono1 = state->screen->test(tx + x2, ty + y2, - pixAcc[0] * pixMul); - - // no conversion, no halftoning - } else { - switch (bitmap->mode) { - case splashModeMono1: - pix.mono1 = splashRound(pixAcc[0] * pixMul); - break; - case splashModeMono8: - pix.mono8 = splashRound(pixAcc[0] * pixMul); - break; - case splashModeRGB8: - case splashModeRGB8Packed: - pix.rgb8 = splashMakeRGB8(splashRound(pixAcc[0] * pixMul), - splashRound(pixAcc[1] * pixMul), - splashRound(pixAcc[2] * pixMul)); - break; - case splashModeBGR8Packed: - pix.bgr8 = splashMakeBGR8(splashRound(pixAcc[0] * pixMul), - splashRound(pixAcc[1] * pixMul), - splashRound(pixAcc[2] * pixMul)); - break; - } - } - - // set pixel - drawPixel(tx + x2, ty + y2, &pix, clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - } - } - - gfree(pixBuf); - gfree(alphaBuf); - - return splashOk; -} - -void Splash::dumpPath(SplashPath *path) { - int i; - - for (i = 0; i < path->length; ++i) { - printf(" %3d: x=%8.2f y=%8.2f%s%s%s%s%s\n", - i, path->pts[i].x, path->pts[i].y, - (path->flags[i] & splashPathFirst) ? " first" : "", - (path->flags[i] & splashPathLast) ? " last" : "", - (path->flags[i] & splashPathClosed) ? " closed" : "", - (path->flags[i] & splashPathCurve) ? " curve" : "", - (path->flags[i] & splashPathArcCW) ? " arcCW" : ""); - } -} |