diff options
Diffstat (limited to 'Build/source/libs/poppler/poppler-0.12.4/splash/Splash.cc')
-rw-r--r-- | Build/source/libs/poppler/poppler-0.12.4/splash/Splash.cc | 3573 |
1 files changed, 0 insertions, 3573 deletions
diff --git a/Build/source/libs/poppler/poppler-0.12.4/splash/Splash.cc b/Build/source/libs/poppler/poppler-0.12.4/splash/Splash.cc deleted file mode 100644 index 834cb1097be..00000000000 --- a/Build/source/libs/poppler/poppler-0.12.4/splash/Splash.cc +++ /dev/null @@ -1,3573 +0,0 @@ -//======================================================================== -// -// Splash.cc -// -//======================================================================== - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2005-2009 Albert Astals Cid <aacid@kde.org> -// Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com> -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#include <config.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include "goo/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 "SplashFont.h" -#include "SplashGlyphBitmap.h" -#include "Splash.h" - -//------------------------------------------------------------------------ - -// distance of Bezier control point from center for circle approximation -// = (4 * (sqrt(2) - 1) / 3) * r -#define bezierCircle ((SplashCoord)0.55228475) -#define bezierCircle2 ((SplashCoord)(0.5 * 0.55228475)) - -// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result. -static inline Guchar div255(int x) { - return (Guchar)((x + (x >> 8) + 0x80) >> 8); -} - -//------------------------------------------------------------------------ -// SplashPipe -//------------------------------------------------------------------------ - -#define splashPipeMaxStages 9 - -struct SplashPipe { - // pixel coordinates - int x, y; - - // source pattern - SplashPattern *pattern; - - // source alpha and color - SplashCoord aInput; - GBool usesShape; - Guchar aSrc; - SplashColorPtr cSrc; - SplashColor cSrcVal; - - // non-isolated group alpha0 - Guchar *alpha0Ptr; - - // soft mask - SplashColorPtr softMaskPtr; - - // destination alpha and color - SplashColorPtr destColorPtr; - int destColorMask; - Guchar *destAlphaPtr; - - // shape - SplashCoord shape; - - // result alpha and color - GBool noTransparency; - SplashPipeResultColorCtrl resultColorCtrl; - - // non-isolated group correction - int nonIsolatedGroup; -}; - -SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = { - splashPipeResultColorNoAlphaBlendMono, - splashPipeResultColorNoAlphaBlendMono, - splashPipeResultColorNoAlphaBlendRGB, - splashPipeResultColorNoAlphaBlendRGB, - splashPipeResultColorNoAlphaBlendRGB -#if SPLASH_CMYK - , - splashPipeResultColorNoAlphaBlendCMYK -#endif -}; - -SplashPipeResultColorCtrl Splash::pipeResultColorAlphaNoBlend[] = { - splashPipeResultColorAlphaNoBlendMono, - splashPipeResultColorAlphaNoBlendMono, - splashPipeResultColorAlphaNoBlendRGB, - splashPipeResultColorNoAlphaBlendRGB, - splashPipeResultColorAlphaNoBlendRGB -#if SPLASH_CMYK - , - splashPipeResultColorAlphaNoBlendCMYK -#endif -}; - -SplashPipeResultColorCtrl Splash::pipeResultColorAlphaBlend[] = { - splashPipeResultColorAlphaBlendMono, - splashPipeResultColorAlphaBlendMono, - splashPipeResultColorAlphaBlendRGB, - splashPipeResultColorNoAlphaBlendRGB, - splashPipeResultColorAlphaBlendRGB -#if SPLASH_CMYK - , - splashPipeResultColorAlphaBlendCMYK -#endif -}; - -//------------------------------------------------------------------------ - -static void blendXor(SplashColorPtr src, SplashColorPtr dest, - SplashColorPtr blend, SplashColorMode cm) { - int i; - - for (i = 0; i < splashColorModeNComps[cm]; ++i) { - blend[i] = src[i] ^ dest[i]; - } -} - -//------------------------------------------------------------------------ -// modified region -//------------------------------------------------------------------------ - -void Splash::clearModRegion() { - modXMin = bitmap->getWidth(); - modYMin = bitmap->getHeight(); - modXMax = -1; - modYMax = -1; -} - -inline void Splash::updateModX(int x) { - if (x < modXMin) { - modXMin = x; - } - if (x > modXMax) { - modXMax = x; - } -} - -inline void Splash::updateModY(int y) { - if (y < modYMin) { - modYMin = y; - } - if (y > modYMax) { - modYMax = y; - } -} - -//------------------------------------------------------------------------ -// pipeline -//------------------------------------------------------------------------ - -inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, - SplashPattern *pattern, SplashColorPtr cSrc, - SplashCoord aInput, GBool usesShape, - GBool nonIsolatedGroup) { - pipeSetXY(pipe, x, y); - pipe->pattern = NULL; - - // source color - if (pattern) { - if (pattern->isStatic()) { - pattern->getColor(x, y, pipe->cSrcVal); - } else { - pipe->pattern = pattern; - } - pipe->cSrc = pipe->cSrcVal; - } else { - pipe->cSrc = cSrc; - } - - // source alpha - pipe->aInput = aInput; - if (!state->softMask) { - if (usesShape) { - pipe->aInput *= 255; - } else { - pipe->aSrc = (Guchar)splashRound(pipe->aInput * 255); - } - } - pipe->usesShape = usesShape; - - // result alpha - if (aInput == 1 && !state->softMask && !usesShape && - !state->inNonIsolatedGroup) { - pipe->noTransparency = gTrue; - } else { - pipe->noTransparency = gFalse; - } - - // result color - if (pipe->noTransparency) { - // the !state->blendFunc case is handled separately in pipeRun - pipe->resultColorCtrl = pipeResultColorNoAlphaBlend[bitmap->mode]; - } else if (!state->blendFunc) { - pipe->resultColorCtrl = pipeResultColorAlphaNoBlend[bitmap->mode]; - } else { - pipe->resultColorCtrl = pipeResultColorAlphaBlend[bitmap->mode]; - } - - // non-isolated group correction - if (nonIsolatedGroup) { - pipe->nonIsolatedGroup = splashColorModeNComps[bitmap->mode]; - } else { - pipe->nonIsolatedGroup = 0; - } -} - -inline void Splash::pipeRun(SplashPipe *pipe) { - Guchar aSrc, aDest, alpha2, alpha0, aResult; - SplashColor cDest, cBlend; - Guchar cResult0, cResult1, cResult2, cResult3; - - //----- source color - - // static pattern: handled in pipeInit - // fixed color: handled in pipeInit - - // dynamic pattern - if (pipe->pattern) { - pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal); - } - - if (pipe->noTransparency && !state->blendFunc) { - - //----- write destination pixel - - switch (bitmap->mode) { - case splashModeMono1: - cResult0 = pipe->cSrc[0]; - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; - } else { - *pipe->destColorPtr &= ~pipe->destColorMask; - } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; - } - break; - case splashModeMono8: - *pipe->destColorPtr++ = pipe->cSrc[0]; - break; - case splashModeRGB8: - *pipe->destColorPtr++ = pipe->cSrc[0]; - *pipe->destColorPtr++ = pipe->cSrc[1]; - *pipe->destColorPtr++ = pipe->cSrc[2]; - break; - case splashModeXBGR8: - *pipe->destColorPtr++ = pipe->cSrc[2]; - *pipe->destColorPtr++ = pipe->cSrc[1]; - *pipe->destColorPtr++ = pipe->cSrc[0]; - *pipe->destColorPtr++ = 255; - break; - case splashModeBGR8: - *pipe->destColorPtr++ = pipe->cSrc[2]; - *pipe->destColorPtr++ = pipe->cSrc[1]; - *pipe->destColorPtr++ = pipe->cSrc[0]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - *pipe->destColorPtr++ = pipe->cSrc[0]; - *pipe->destColorPtr++ = pipe->cSrc[1]; - *pipe->destColorPtr++ = pipe->cSrc[2]; - *pipe->destColorPtr++ = pipe->cSrc[3]; - break; -#endif - } - if (pipe->destAlphaPtr) { - *pipe->destAlphaPtr++ = 255; - } - - } else { - - //----- read destination pixel - - switch (bitmap->mode) { - case splashModeMono1: - cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00; - break; - case splashModeMono8: - cDest[0] = *pipe->destColorPtr; - break; - case splashModeRGB8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - break; - case splashModeXBGR8: - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; - cDest[3] = 255; - break; - case splashModeBGR8: - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - cDest[3] = pipe->destColorPtr[3]; - break; -#endif - } - if (pipe->destAlphaPtr) { - aDest = *pipe->destAlphaPtr; - } else { - aDest = 0xff; - } - - //----- blend function - - if (state->blendFunc) { - (*state->blendFunc)(pipe->cSrc, cDest, cBlend, bitmap->mode); - } - - //----- source alpha - - if (state->softMask) { - if (pipe->usesShape) { - aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++ - * pipe->shape); - } else { - aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++); - } - } else if (pipe->usesShape) { - // pipe->aInput is premultiplied by 255 in pipeInit - aSrc = (Guchar)splashRound(pipe->aInput * pipe->shape); - } else { - // precomputed in pipeInit - aSrc = pipe->aSrc; - } - - //----- result alpha and non-isolated group element correction - - if (pipe->noTransparency) { - alpha2 = aResult = 255; - } else { - aResult = aSrc + aDest - div255(aSrc * aDest); - - if (pipe->alpha0Ptr) { - alpha0 = *pipe->alpha0Ptr++; - alpha2 = aResult + alpha0 - div255(aResult * alpha0); - } else { - alpha2 = aResult; - } - } - - //----- result color - - cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy - - switch (pipe->resultColorCtrl) { - -#if SPLASH_CMYK - case splashPipeResultColorNoAlphaBlendCMYK: - cResult3 = div255((255 - aDest) * pipe->cSrc[3] + aDest * cBlend[3]); -#endif - case splashPipeResultColorNoAlphaBlendRGB: - cResult2 = div255((255 - aDest) * pipe->cSrc[2] + aDest * cBlend[2]); - cResult1 = div255((255 - aDest) * pipe->cSrc[1] + aDest * cBlend[1]); - case splashPipeResultColorNoAlphaBlendMono: - cResult0 = div255((255 - aDest) * pipe->cSrc[0] + aDest * cBlend[0]); - break; - - case splashPipeResultColorAlphaNoBlendMono: - if (alpha2 == 0) { - cResult0 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2); - } - break; - case splashPipeResultColorAlphaNoBlendRGB: - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2); - cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * pipe->cSrc[1]) / alpha2); - cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * pipe->cSrc[2]) / alpha2); - } - break; -#if SPLASH_CMYK - case splashPipeResultColorAlphaNoBlendCMYK: - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - cResult3 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2); - cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * pipe->cSrc[1]) / alpha2); - cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * pipe->cSrc[2]) / alpha2); - cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] + - aSrc * pipe->cSrc[3]) / alpha2); - } - break; -#endif - - case splashPipeResultColorAlphaBlendMono: - if (alpha2 == 0) { - cResult0 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * ((255 - aDest) * pipe->cSrc[0] + - aDest * cBlend[0]) / 255) / - alpha2); - } - break; - case splashPipeResultColorAlphaBlendRGB: - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * ((255 - aDest) * pipe->cSrc[0] + - aDest * cBlend[0]) / 255) / - alpha2); - cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * ((255 - aDest) * pipe->cSrc[1] + - aDest * cBlend[1]) / 255) / - alpha2); - cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * ((255 - aDest) * pipe->cSrc[2] + - aDest * cBlend[2]) / 255) / - alpha2); - } - break; -#if SPLASH_CMYK - case splashPipeResultColorAlphaBlendCMYK: - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - cResult3 = 0; - } else { - cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * ((255 - aDest) * pipe->cSrc[0] + - aDest * cBlend[0]) / 255) / - alpha2); - cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * ((255 - aDest) * pipe->cSrc[1] + - aDest * cBlend[1]) / 255) / - alpha2); - cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * ((255 - aDest) * pipe->cSrc[2] + - aDest * cBlend[2]) / 255) / - alpha2); - cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] + - aSrc * ((255 - aDest) * pipe->cSrc[3] + - aDest * cBlend[3]) / 255) / - alpha2); - } - break; -#endif - } - - //----- non-isolated group correction - - if (aResult != 0) { - switch (pipe->nonIsolatedGroup) { -#if SPLASH_CMYK - case 4: - cResult3 += (cResult3 - cDest[3]) * aDest * - (255 - aResult) / (255 * aResult); -#endif - case 3: - cResult2 += (cResult2 - cDest[2]) * aDest * - (255 - aResult) / (255 * aResult); - cResult1 += (cResult1 - cDest[1]) * aDest * - (255 - aResult) / (255 * aResult); - case 1: - cResult0 += (cResult0 - cDest[0]) * aDest * - (255 - aResult) / (255 * aResult); - case 0: - break; - } - } - - //----- write destination pixel - - switch (bitmap->mode) { - case splashModeMono1: - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; - } else { - *pipe->destColorPtr &= ~pipe->destColorMask; - } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; - } - break; - case splashModeMono8: - *pipe->destColorPtr++ = cResult0; - break; - case splashModeRGB8: - *pipe->destColorPtr++ = cResult0; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult2; - break; - case splashModeXBGR8: - *pipe->destColorPtr++ = cResult2; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult0; - *pipe->destColorPtr++ = 255; - break; - case splashModeBGR8: - *pipe->destColorPtr++ = cResult2; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult0; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - *pipe->destColorPtr++ = cResult0; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult2; - *pipe->destColorPtr++ = cResult3; - break; -#endif - } - if (pipe->destAlphaPtr) { - *pipe->destAlphaPtr++ = aResult; - } - - } - - ++pipe->x; -} - -inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) { - pipe->x = x; - pipe->y = y; - if (state->softMask) { - pipe->softMaskPtr = - &state->softMask->data[y * state->softMask->rowSize + x]; - } - switch (bitmap->mode) { - case splashModeMono1: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + (x >> 3)]; - pipe->destColorMask = 0x80 >> (x & 7); - break; - case splashModeMono8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + x]; - break; - case splashModeRGB8: - case splashModeBGR8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x]; - break; - case splashModeXBGR8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x]; - break; -#endif - } - if (bitmap->alpha) { - pipe->destAlphaPtr = &bitmap->alpha[y * bitmap->width + x]; - } else { - pipe->destAlphaPtr = NULL; - } - if (state->inNonIsolatedGroup && alpha0Bitmap->alpha) { - pipe->alpha0Ptr = - &alpha0Bitmap->alpha[(alpha0Y + y) * alpha0Bitmap->width + - (alpha0X + x)]; - } else { - pipe->alpha0Ptr = NULL; - } -} - -inline void Splash::pipeIncX(SplashPipe *pipe) { - ++pipe->x; - if (state->softMask) { - ++pipe->softMaskPtr; - } - switch (bitmap->mode) { - case splashModeMono1: - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; - } - break; - case splashModeMono8: - ++pipe->destColorPtr; - break; - case splashModeRGB8: - case splashModeBGR8: - pipe->destColorPtr += 3; - break; - case splashModeXBGR8: - pipe->destColorPtr += 4; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - pipe->destColorPtr += 4; - break; -#endif - } - if (pipe->destAlphaPtr) { - ++pipe->destAlphaPtr; - } - if (pipe->alpha0Ptr) { - ++pipe->alpha0Ptr; - } -} - -inline void Splash::drawPixel(SplashPipe *pipe, int x, int y, GBool noClip) { - if (noClip || state->clip->test(x, y)) { - pipeSetXY(pipe, x, y); - pipeRun(pipe); - updateModX(x); - updateModY(y); - } -} - -inline void Splash::drawAAPixelInit() { - aaBufY = -1; -} - -inline void Splash::drawAAPixel(SplashPipe *pipe, int x, int y) { -#if splashAASize == 4 - static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 }; - int w; -#else - int xx, yy; -#endif - SplashColorPtr p; - int x0, x1, t; - - if (x < 0 || x >= bitmap->width || - y < state->clip->getYMinI() || y > state->clip->getYMaxI()) { - return; - } - - // update aaBuf - if (y != aaBufY) { - memset(aaBuf->getDataPtr(), 0xff, - aaBuf->getRowSize() * aaBuf->getHeight()); - x0 = 0; - x1 = bitmap->width - 1; - state->clip->clipAALine(aaBuf, &x0, &x1, y); - aaBufY = y; - } - - // compute the shape value -#if splashAASize == 4 - p = aaBuf->getDataPtr() + (x >> 1); - w = aaBuf->getRowSize(); - if (x & 1) { - t = bitCount4[*p & 0x0f] + bitCount4[p[w] & 0x0f] + - bitCount4[p[2*w] & 0x0f] + bitCount4[p[3*w] & 0x0f]; - } else { - t = bitCount4[*p >> 4] + bitCount4[p[w] >> 4] + - bitCount4[p[2*w] >> 4] + bitCount4[p[3*w] >> 4]; - } -#else - t = 0; - for (yy = 0; yy < splashAASize; ++yy) { - for (xx = 0; xx < splashAASize; ++xx) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + - ((x * splashAASize + xx) >> 3); - t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; - } - } -#endif - - // draw the pixel - if (t != 0) { - pipeSetXY(pipe, x, y); - pipe->shape *= aaGamma[t]; - pipeRun(pipe); - updateModX(x); - updateModY(y); - } -} - -inline void Splash::drawSpan(SplashPipe *pipe, int x0, int x1, int y, - GBool noClip) { - int x; - - pipeSetXY(pipe, x0, y); - if (noClip) { - for (x = x0; x <= x1; ++x) { - pipeRun(pipe); - } - updateModX(x0); - updateModX(x1); - updateModY(y); - } else { - for (x = x0; x <= x1; ++x) { - if (state->clip->test(x, y)) { - pipeRun(pipe); - updateModX(x); - updateModY(y); - } else { - pipeIncX(pipe); - } - } - } -} - -inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y) { -#if splashAASize == 4 - static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 }; - SplashColorPtr p0, p1, p2, p3; - int t; -#else - SplashColorPtr p; - int xx, yy, t; -#endif - int x; - -#if splashAASize == 4 - p0 = aaBuf->getDataPtr() + (x0 >> 1); - p1 = p0 + aaBuf->getRowSize(); - p2 = p1 + aaBuf->getRowSize(); - p3 = p2 + aaBuf->getRowSize(); -#endif - pipeSetXY(pipe, x0, y); - for (x = x0; x <= x1; ++x) { - - // compute the shape value -#if splashAASize == 4 - if (x & 1) { - t = bitCount4[*p0 & 0x0f] + bitCount4[*p1 & 0x0f] + - bitCount4[*p2 & 0x0f] + bitCount4[*p3 & 0x0f]; - ++p0; ++p1; ++p2; ++p3; - } else { - t = bitCount4[*p0 >> 4] + bitCount4[*p1 >> 4] + - bitCount4[*p2 >> 4] + bitCount4[*p3 >> 4]; - } -#else - t = 0; - for (yy = 0; yy < splashAASize; ++yy) { - for (xx = 0; xx < splashAASize; ++xx) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + - ((x * splashAASize + xx) >> 3); - t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; - } - } -#endif - - if (t != 0) { - pipe->shape = aaGamma[t]; - pipeRun(pipe); - updateModX(x); - updateModY(y); - } else { - pipeIncX(pipe); - } - } -} - -//------------------------------------------------------------------------ - -// Transform a point from user space to device space. -inline void Splash::transform(SplashCoord *matrix, - SplashCoord xi, SplashCoord yi, - SplashCoord *xo, SplashCoord *yo) { - // [ m[0] m[1] 0 ] - // [xo yo 1] = [xi yi 1] * [ m[2] m[3] 0 ] - // [ m[4] m[5] 1 ] - *xo = xi * matrix[0] + yi * matrix[2] + matrix[4]; - *yo = xi * matrix[1] + yi * matrix[3] + matrix[5]; -} - -//------------------------------------------------------------------------ -// Splash -//------------------------------------------------------------------------ - -Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreenParams *screenParams) { - int i; - - bitmap = bitmapA; - vectorAntialias = vectorAntialiasA; - state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, - screenParams); - if (vectorAntialias) { - aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, - 1, splashModeMono1, gFalse); - for (i = 0; i <= splashAASize * splashAASize; ++i) { - aaGamma[i] = splashPow((SplashCoord)i / - (SplashCoord)(splashAASize * splashAASize), - 1.5); - } - } else { - aaBuf = NULL; - } - clearModRegion(); - debugMode = gFalse; -} - -Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreen *screenA) { - int i; - - bitmap = bitmapA; - vectorAntialias = vectorAntialiasA; - state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, - screenA); - if (vectorAntialias) { - aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, - 1, splashModeMono1, gFalse); - for (i = 0; i <= splashAASize * splashAASize; ++i) { - aaGamma[i] = splashPow((SplashCoord)i / - (SplashCoord)(splashAASize * splashAASize), - 1.5); - } - } else { - aaBuf = NULL; - } - clearModRegion(); - debugMode = gFalse; -} - -Splash::~Splash() { - while (state->next) { - restoreState(); - } - delete state; - if (vectorAntialias) { - delete aaBuf; - } -} - -//------------------------------------------------------------------------ -// state read -//------------------------------------------------------------------------ - -SplashCoord *Splash::getMatrix() { - return state->matrix; -} - -SplashPattern *Splash::getStrokePattern() { - return state->strokePattern; -} - -SplashPattern *Splash::getFillPattern() { - return state->fillPattern; -} - -SplashScreen *Splash::getScreen() { - return state->screen; -} - -SplashBlendFunc Splash::getBlendFunc() { - return state->blendFunc; -} - -SplashCoord Splash::getStrokeAlpha() { - return state->strokeAlpha; -} - -SplashCoord Splash::getFillAlpha() { - return state->fillAlpha; -} - -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; -} - -SplashBitmap *Splash::getSoftMask() { - return state->softMask; -} - -GBool Splash::getInNonIsolatedGroup() { - return state->inNonIsolatedGroup; -} - -//------------------------------------------------------------------------ -// state write -//------------------------------------------------------------------------ - -void Splash::setMatrix(SplashCoord *matrix) { - memcpy(state->matrix, matrix, 6 * sizeof(SplashCoord)); -} - -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::setBlendFunc(SplashBlendFunc func) { - state->blendFunc = func; -} - -void Splash::setStrokeAlpha(SplashCoord alpha) { - state->strokeAlpha = alpha; -} - -void Splash::setFillAlpha(SplashCoord alpha) { - state->fillAlpha = alpha; -} - -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::setStrokeAdjust(GBool strokeAdjust) { - state->strokeAdjust = strokeAdjust; -} - -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->matrix, state->flatness, eo); -} - -void Splash::setSoftMask(SplashBitmap *softMask) { - state->setSoftMask(softMask); -} - -void Splash::setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA, - int alpha0XA, int alpha0YA) { - alpha0Bitmap = alpha0BitmapA; - alpha0X = alpha0XA; - alpha0Y = alpha0YA; - state->inNonIsolatedGroup = gTrue; -} - -//------------------------------------------------------------------------ -// 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(SplashColorPtr color, Guchar alpha) { - SplashColorPtr row, p; - Guchar mono; - int x, y; - - switch (bitmap->mode) { - case splashModeMono1: - mono = (color[0] & 0x80) ? 0xff : 0x00; - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - mono, -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, mono, bitmap->rowSize * bitmap->height); - } - break; - case splashModeMono8: - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - color[0], -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); - } - break; - case splashModeRGB8: - if (color[0] == color[1] && color[1] == color[2]) { - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - color[0], -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); - } - } else { - row = bitmap->data; - for (y = 0; y < bitmap->height; ++y) { - p = row; - for (x = 0; x < bitmap->width; ++x) { - *p++ = color[2]; - *p++ = color[1]; - *p++ = color[0]; - } - row += bitmap->rowSize; - } - } - break; - case splashModeXBGR8: - if (color[0] == color[1] && color[1] == color[2]) { - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - color[0], -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); - } - } else { - row = bitmap->data; - for (y = 0; y < bitmap->height; ++y) { - p = row; - for (x = 0; x < bitmap->width; ++x) { - *p++ = color[0]; - *p++ = color[1]; - *p++ = color[2]; - *p++ = 255; - } - row += bitmap->rowSize; - } - } - break; - case splashModeBGR8: - if (color[0] == color[1] && color[1] == color[2]) { - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - color[0], -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); - } - } else { - row = bitmap->data; - for (y = 0; y < bitmap->height; ++y) { - p = row; - for (x = 0; x < bitmap->width; ++x) { - *p++ = color[0]; - *p++ = color[1]; - *p++ = color[2]; - } - row += bitmap->rowSize; - } - } - break; -#if SPLASH_CMYK - case splashModeCMYK8: - if (color[0] == color[1] && color[1] == color[2] && color[2] == color[3]) { - if (bitmap->rowSize < 0) { - memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), - color[0], -bitmap->rowSize * bitmap->height); - } else { - memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); - } - } else { - row = bitmap->data; - for (y = 0; y < bitmap->height; ++y) { - p = row; - for (x = 0; x < bitmap->width; ++x) { - *p++ = color[0]; - *p++ = color[1]; - *p++ = color[2]; - *p++ = color[3]; - } - row += bitmap->rowSize; - } - } - break; -#endif - } - - if (bitmap->alpha) { - memset(bitmap->alpha, alpha, bitmap->width * bitmap->height); - } - - updateModX(0); - updateModY(0); - updateModX(bitmap->width - 1); - updateModY(bitmap->height - 1); -} - -SplashError Splash::stroke(SplashPath *path) { - SplashPath *path2, *dPath; - - if (debugMode) { - printf("stroke [dash:%d] [width:%.2f]:\n", - state->lineDashLength, (double)state->lineWidth); - dumpPath(path); - } - opClipRes = splashClipAllOutside; - if (path->length == 0) { - return splashErrEmptyPath; - } - path2 = flattenPath(path, state->matrix, state->flatness); - if (state->lineDashLength > 0) { - dPath = makeDashedPath(path2); - delete path2; - path2 = dPath; - } - if (state->lineWidth == 0) { - strokeNarrow(path2); - } else { - strokeWide(path2); - } - delete path2; - return splashOk; -} - -void Splash::strokeNarrow(SplashPath *path) { - SplashPipe pipe; - SplashXPath *xPath; - SplashXPathSeg *seg; - int x0, x1, x2, x3, y0, y1, x, y, t; - SplashCoord dx, dy, dxdy; - SplashClipResult clipRes; - int nClipRes[3]; - int i; - - nClipRes[0] = nClipRes[1] = nClipRes[2] = 0; - - xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse); - - pipeInit(&pipe, 0, 0, state->strokePattern, NULL, state->strokeAlpha, - gFalse, gFalse); - - 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(&pipe, x0, x1, y0, 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; - x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy); - drawSpan(&pipe, x2, (x2 <= x3 - 1) ? x3 - 1 : x2, y0, - clipRes == splashClipAllInside); - x2 = x3; - for (y = y0 + 1; y <= y1 - 1; ++y) { - x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy); - drawSpan(&pipe, x2, x3 - 1, y, clipRes == splashClipAllInside); - x2 = x3; - } - drawSpan(&pipe, x2, x2 <= x1 ? x1 : x2, y1, - clipRes == splashClipAllInside); - } else { - x2 = x0; - x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy); - drawSpan(&pipe, (x3 + 1 <= x2) ? x3 + 1 : x2, x2, y0, - clipRes == splashClipAllInside); - x2 = x3; - for (y = y0 + 1; y <= y1 - 1; ++y) { - x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy); - drawSpan(&pipe, x3 + 1, x2, y, clipRes == splashClipAllInside); - x2 = x3; - } - drawSpan(&pipe, x1, (x1 <= x2) ? x2 : x1, y1, - clipRes == splashClipAllInside); - } - } - - // segment with |dy| > |dx| - } else { - dxdy = seg->dxdy; - if (y0 > y1) { - t = x0; x0 = x1; x1 = t; - t = y0; y0 = y1; y1 = t; - } - if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, - x0 <= x1 ? x1 : x0, y1)) - != splashClipAllOutside) { - drawPixel(&pipe, x0, y0, clipRes == splashClipAllInside); - for (y = y0 + 1; y <= y1 - 1; ++y) { - x = splashFloor(seg->x0 + ((SplashCoord)y - seg->y0) * dxdy); - drawPixel(&pipe, x, y, clipRes == splashClipAllInside); - } - drawPixel(&pipe, x1, y1, clipRes == splashClipAllInside); - } - } - ++nClipRes[clipRes]; - } - if (nClipRes[splashClipPartial] || - (nClipRes[splashClipAllInside] && nClipRes[splashClipAllOutside])) { - opClipRes = splashClipPartial; - } else if (nClipRes[splashClipAllInside]) { - opClipRes = splashClipAllInside; - } else { - opClipRes = splashClipAllOutside; - } - - delete xPath; -} - -void Splash::strokeWide(SplashPath *path) { - SplashPath *path2; - - path2 = makeStrokePath(path, gFalse); - fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha); - delete path2; -} - -SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix, - SplashCoord flatness) { - SplashPath *fPath; - SplashCoord flatness2; - Guchar flag; - int i; - - fPath = new SplashPath(); - flatness2 = flatness * flatness; - i = 0; - while (i < path->length) { - flag = path->flags[i]; - if (flag & splashPathFirst) { - fPath->moveTo(path->pts[i].x, path->pts[i].y); - ++i; - } else { - if (flag & splashPathCurve) { - flattenCurve(path->pts[i-1].x, path->pts[i-1].y, - path->pts[i ].x, path->pts[i ].y, - path->pts[i+1].x, path->pts[i+1].y, - path->pts[i+2].x, path->pts[i+2].y, - matrix, flatness2, fPath); - i += 3; - } else { - fPath->lineTo(path->pts[i].x, path->pts[i].y); - ++i; - } - if (path->flags[i-1] & splashPathClosed) { - fPath->close(); - } - } - } - return fPath; -} - -void Splash::flattenCurve(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - SplashCoord x2, SplashCoord y2, - SplashCoord x3, SplashCoord y3, - SplashCoord *matrix, SplashCoord flatness2, - SplashPath *fPath) { - SplashCoord cx[splashMaxCurveSplits + 1][3]; - SplashCoord cy[splashMaxCurveSplits + 1][3]; - int cNext[splashMaxCurveSplits + 1]; - SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh; - SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh; - SplashCoord dx, dy, mx, my, tx, ty, d1, d2; - int p1, p2, p3; - - // initial segment - p1 = 0; - p2 = splashMaxCurveSplits; - cx[p1][0] = x0; cy[p1][0] = y0; - cx[p1][1] = x1; cy[p1][1] = y1; - cx[p1][2] = x2; cy[p1][2] = y2; - cx[p2][0] = x3; cy[p2][0] = y3; - cNext[p1] = p2; - - while (p1 < splashMaxCurveSplits) { - - // get the next segment - xl0 = cx[p1][0]; yl0 = cy[p1][0]; - xx1 = cx[p1][1]; yy1 = cy[p1][1]; - xx2 = cx[p1][2]; yy2 = cy[p1][2]; - p2 = cNext[p1]; - xr3 = cx[p2][0]; yr3 = cy[p2][0]; - - // compute the distances (in device space) from the control points - // to the midpoint of the straight line (this is a bit of a hack, - // but it's much faster than computing the actual distances to the - // line) - transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my); - transform(matrix, xx1, yy1, &tx, &ty); - dx = tx - mx; - dy = ty - my; - d1 = dx*dx + dy*dy; - transform(matrix, xx2, yy2, &tx, &ty); - dx = tx - mx; - dy = ty - my; - d2 = dx*dx + dy*dy; - - // if the curve is flat enough, or no more subdivisions are - // allowed, add the straight line segment - if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) { - fPath->lineTo(xr3, yr3); - p1 = p2; - - // otherwise, subdivide the curve - } else { - xl1 = (xl0 + xx1) * 0.5; - yl1 = (yl0 + yy1) * 0.5; - xh = (xx1 + xx2) * 0.5; - yh = (yy1 + yy2) * 0.5; - xl2 = (xl1 + xh) * 0.5; - yl2 = (yl1 + yh) * 0.5; - xr2 = (xx2 + xr3) * 0.5; - yr2 = (yy2 + yr3) * 0.5; - xr1 = (xh + xr2) * 0.5; - yr1 = (yh + yr2) * 0.5; - xr0 = (xl2 + xr1) * 0.5; - yr0 = (yl2 + yr1) * 0.5; - // add the new subdivision points - p3 = (p1 + p2) / 2; - cx[p1][1] = xl1; cy[p1][1] = yl1; - cx[p1][2] = xl2; cy[p1][2] = yl2; - cNext[p1] = p3; - cx[p3][0] = xr0; cy[p3][0] = yr0; - cx[p3][1] = xr1; cy[p3][1] = yr1; - cx[p3][2] = xr2; cy[p3][2] = yr2; - cNext[p3] = p2; - } - } -} - -SplashPath *Splash::makeDashedPath(SplashPath *path) { - SplashPath *dPath; - SplashCoord lineDashTotal; - SplashCoord lineDashStartPhase, lineDashDist, segLen; - SplashCoord x0, y0, x1, y1, xa, ya; - GBool lineDashStartOn, lineDashOn, newPath; - int lineDashStartIdx, lineDashIdx; - int i, j, k; - - lineDashTotal = 0; - for (i = 0; i < state->lineDashLength; ++i) { - lineDashTotal += state->lineDash[i]; - } - lineDashStartPhase = state->lineDashPhase; - i = splashFloor(lineDashStartPhase / lineDashTotal); - lineDashStartPhase -= (SplashCoord)i * lineDashTotal; - lineDashStartOn = gTrue; - lineDashStartIdx = 0; - while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) { - lineDashStartOn = !lineDashStartOn; - lineDashStartPhase -= state->lineDash[lineDashStartIdx]; - ++lineDashStartIdx; - } - - dPath = new SplashPath(); - - // process each subpath - i = 0; - while (i < path->length) { - - // find the end of the subpath - for (j = i; - j < path->length - 1 && !(path->flags[j] & splashPathLast); - ++j) ; - - // initialize the dash parameters - lineDashOn = lineDashStartOn; - lineDashIdx = lineDashStartIdx; - lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase; - - // process each segment of the subpath - newPath = gTrue; - for (k = i; k < j; ++k) { - - // grab the segment - x0 = path->pts[k].x; - y0 = path->pts[k].y; - x1 = path->pts[k+1].x; - y1 = path->pts[k+1].y; - segLen = splashDist(x0, y0, x1, y1); - - // process the segment - while (segLen > 0) { - - if (lineDashDist >= segLen) { - if (lineDashOn) { - if (newPath) { - dPath->moveTo(x0, y0); - newPath = gFalse; - } - dPath->lineTo(x1, y1); - } - lineDashDist -= segLen; - segLen = 0; - - } else { - xa = x0 + (lineDashDist / segLen) * (x1 - x0); - ya = y0 + (lineDashDist / segLen) * (y1 - y0); - if (lineDashOn) { - if (newPath) { - dPath->moveTo(x0, y0); - newPath = gFalse; - } - dPath->lineTo(xa, ya); - } - x0 = xa; - y0 = ya; - segLen -= lineDashDist; - lineDashDist = 0; - } - - // get the next entry in the dash array - if (lineDashDist <= 0) { - lineDashOn = !lineDashOn; - if (++lineDashIdx == state->lineDashLength) { - lineDashIdx = 0; - } - lineDashDist = state->lineDash[lineDashIdx]; - newPath = gTrue; - } - } - } - i = j + 1; - } - - 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, state->fillAlpha); -} - -SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, - SplashPattern *pattern, - SplashCoord alpha) { - SplashPipe pipe; - 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->matrix, state->flatness, gTrue); - if (vectorAntialias) { - xPath->aaScale(); - } - xPath->sort(); - scanner = new SplashXPathScanner(xPath, eo); - - // get the min and max x and y values - if (vectorAntialias) { - scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI); - } else { - scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); - } - - // check clipping - if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) - != splashClipAllOutside) { - - // limit the y range - if (yMinI < state->clip->getYMinI()) { - yMinI = state->clip->getYMinI(); - } - if (yMaxI > state->clip->getYMaxI()) { - yMaxI = state->clip->getYMaxI(); - } - - pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse); - - // draw the spans - if (vectorAntialias) { - for (y = yMinI; y <= yMaxI; ++y) { - scanner->renderAALine(aaBuf, &x0, &x1, y); - if (clipRes != splashClipAllInside) { - state->clip->clipAALine(aaBuf, &x0, &x1, y); - } - drawAALine(&pipe, x0, x1, y); - } - } else { - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - drawSpan(&pipe, x0, x1, y, gTrue); - } else { - // limit the x range - if (x0 < state->clip->getXMinI()) { - x0 = state->clip->getXMinI(); - } - if (x1 > state->clip->getXMaxI()) { - x1 = state->clip->getXMaxI(); - } - clipRes2 = state->clip->testSpan(x0, x1, y); - drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); - } - } - } - } - } - opClipRes = clipRes; - - delete scanner; - delete xPath; - return splashOk; -} - -SplashError Splash::xorFill(SplashPath *path, GBool eo) { - SplashPipe pipe; - SplashXPath *xPath; - SplashXPathScanner *scanner; - int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; - SplashClipResult clipRes, clipRes2; - SplashBlendFunc origBlendFunc; - - if (path->length == 0) { - return splashErrEmptyPath; - } - xPath = new SplashXPath(path, state->matrix, 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) { - - // limit the y range - if (yMinI < state->clip->getYMinI()) { - yMinI = state->clip->getYMinI(); - } - if (yMaxI > state->clip->getYMaxI()) { - yMaxI = state->clip->getYMaxI(); - } - - origBlendFunc = state->blendFunc; - state->blendFunc = &blendXor; - pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse); - - // draw the spans - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - drawSpan(&pipe, x0, x1, y, gTrue); - } else { - // limit the x range - if (x0 < state->clip->getXMinI()) { - x0 = state->clip->getXMinI(); - } - if (x1 > state->clip->getXMaxI()) { - x1 = state->clip->getXMaxI(); - } - clipRes2 = state->clip->testSpan(x0, x1, y); - drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); - } - } - } - state->blendFunc = origBlendFunc; - } - opClipRes = clipRes; - - delete scanner; - delete xPath; - return splashOk; -} - -SplashError Splash::fillChar(SplashCoord x, SplashCoord y, - int c, SplashFont *font) { - SplashGlyphBitmap glyph; - SplashCoord xt, yt; - int x0, y0, xFrac, yFrac; - SplashClipResult clipRes; - - if (debugMode) { - printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", - (double)x, (double)y, c, c, c); - } - transform(state->matrix, x, y, &xt, &yt); - x0 = splashFloor(xt); - xFrac = splashFloor((xt - x0) * splashFontFraction); - y0 = splashFloor(yt); - yFrac = splashFloor((yt - y0) * splashFontFraction); - if (!font->getGlyph(c, xFrac, yFrac, &glyph, x0, y0, state->clip, &clipRes)) { - return splashErrNoGlyph; - } - if (clipRes != splashClipAllOutside) { - fillGlyph2(x0, y0, &glyph, clipRes == splashClipAllInside); - } - opClipRes = clipRes; - if (glyph.freeData) { - gfree(glyph.data); - } - return splashOk; -} - -void Splash::fillGlyph(SplashCoord x, SplashCoord y, - SplashGlyphBitmap *glyph) { - SplashCoord xt, yt; - int x0, y0; - - transform(state->matrix, x, y, &xt, &yt); - x0 = splashFloor(xt); - y0 = splashFloor(yt); - SplashClipResult clipRes = state->clip->testRect(x0 - glyph->x, - y0 - glyph->y, - x0 - glyph->x + glyph->w - 1, - y0 - glyph->y + glyph->h - 1); - if (clipRes != splashClipAllOutside) { - fillGlyph2(x0, y0, glyph, clipRes == splashClipAllInside); - } - opClipRes = clipRes; -} - -void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip) { - SplashPipe pipe; - int alpha0, alpha; - Guchar *p; - int x1, y1, xx, xx1, yy; - - p = glyph->data; - int xStart = x0 - glyph->x; - int yStart = y0 - glyph->y; - int xxLimit = glyph->w; - int yyLimit = glyph->h; - - if (yStart < 0) - { - p += glyph->w * -yStart; // move p to the beginning of the first painted row - yyLimit += yStart; - yStart = 0; - } - - if (xStart < 0) - { - p += -xStart; // move p to the first painted pixel - xxLimit += xStart; - xStart = 0; - } - - if (xxLimit + xStart >= bitmap->width) xxLimit = bitmap->width - xStart; - if (yyLimit + yStart >= bitmap->height) yyLimit = bitmap->height - yStart; - - if (noClip) { - if (glyph->aa) { - pipeInit(&pipe, xStart, yStart, - state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); - for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) { - pipeSetXY(&pipe, xStart, y1); - for (xx = 0, x1 = xStart; xx < xxLimit; ++xx, ++x1) { - alpha = p[xx]; - if (alpha != 0) { - pipe.shape = (SplashCoord)(alpha / 255.0); - pipeRun(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } - p += glyph->w; - } - } else { - const int widthEight = splashCeil(glyph->w / 8.0); - - pipeInit(&pipe, xStart, yStart, - state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); - for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) { - pipeSetXY(&pipe, xStart, y1); - for (xx = 0, x1 = xStart; xx < xxLimit; xx += 8) { - alpha0 = p[xx / 8]; - for (xx1 = 0; xx1 < 8 && xx + xx1 < xxLimit; ++xx1, ++x1) { - if (alpha0 & 0x80) { - pipeRun(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - alpha0 <<= 1; - } - } - p += widthEight; - } - } - } else { - if (glyph->aa) { - pipeInit(&pipe, xStart, yStart, - state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); - for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) { - pipeSetXY(&pipe, xStart, y1); - for (xx = 0, x1 = xStart; xx < xxLimit; ++xx, ++x1) { - if (state->clip->test(x1, y1)) { - alpha = p[xx]; - if (alpha != 0) { - pipe.shape = (SplashCoord)(alpha / 255.0); - pipeRun(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } else { - pipeIncX(&pipe); - } - } - p += glyph->w; - } - } else { - const int widthEight = splashCeil(glyph->w / 8.0); - - pipeInit(&pipe, xStart, yStart, - state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); - for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) { - pipeSetXY(&pipe, xStart, y1); - for (xx = 0, x1 = xStart; xx < xxLimit; xx += 8) { - alpha0 = p[xx / 8]; - for (xx1 = 0; xx1 < 8 && xx + xx1 < xxLimit; ++xx1, ++x1) { - if (state->clip->test(x1, y1)) { - if (alpha0 & 0x80) { - pipeRun(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } else { - pipeIncX(&pipe); - } - alpha0 <<= 1; - } - } - p += widthEight; - } - } - } -} - -SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, - int w, int h, SplashCoord *mat, - GBool glyphMode) { - SplashPipe pipe; - GBool rot; - SplashCoord xScale, yScale, xShear, yShear, yShear1; - int tx, tx2, ty, ty2, 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; - SplashColorPtr pixBuf, p; - int pixAcc; - int x, y, x1, x2, y2; - SplashCoord y1; - int n, m, i, j; - - if (debugMode) { - printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", - w, h, (double)mat[0], (double)mat[1], (double)mat[2], - (double)mat[3], (double)mat[4], (double)mat[5]); - } - - if (w == 0 && h == 0) return splashErrZeroImage; - - // 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]; - } - // Note 1: The PDF spec says that all pixels whose *centers* lie - // within the region get painted -- but that doesn't seem to match - // up with what Acrobat actually does: it ends up leaving gaps - // between image stripes. So we use the same rule here as for - // fills: any pixel that overlaps the region gets painted. - // Note 2: The "glyphMode" flag is a kludge: it switches back to - // "correct" behavior (matching the spec), for use in rendering Type - // 3 fonts. - // Note 3: The +/-0.01 in these computations is to avoid floating - // point precision problems which can lead to gaps between image - // stripes (it can cause image stripes to overlap, but that's a much - // less visible problem). - if (glyphMode) { - if (xScale >= 0) { - tx = splashRound(mat[4]); - tx2 = splashRound(mat[4] + xScale) - 1; - } else { - tx = splashRound(mat[4]) - 1; - tx2 = splashRound(mat[4] + xScale); - } - } else { - if (xScale >= 0) { - tx = splashFloor(mat[4] - 0.01); - tx2 = splashFloor(mat[4] + xScale + 0.01); - } else { - tx = splashFloor(mat[4] + 0.01); - tx2 = splashFloor(mat[4] + xScale - 0.01); - } - } - scaledWidth = abs(tx2 - tx) + 1; - if (glyphMode) { - if (yScale >= 0) { - ty = splashRound(mat[5]); - ty2 = splashRound(mat[5] + yScale) - 1; - } else { - ty = splashRound(mat[5]) - 1; - ty2 = splashRound(mat[5] + yScale); - } - } else { - if (yScale >= 0) { - ty = splashFloor(mat[5] - 0.01); - ty2 = splashFloor(mat[5] + yScale + 0.01); - } else { - ty = splashFloor(mat[5] + 0.01); - ty2 = splashFloor(mat[5] + yScale - 0.01); - } - } - scaledHeight = abs(ty2 - ty) + 1; - xSign = (xScale < 0) ? -1 : 1; - ySign = (yScale < 0) ? -1 : 1; - yShear1 = (SplashCoord)xSign * yShear; - - // clipping - ulx1 = 0; - uly1 = 0; - urx1 = xSign * (scaledWidth - 1); - ury1 = (int)(yShear * urx1); - llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); - lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1); - lrx1 = xSign * (scaledWidth - 1) + - splashRound(xShear * ySign * (scaledHeight - 1)); - lry1 = ySign * (scaledHeight - 1) + (int)(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); - opClipRes = clipRes; - - // compute Bresenham parameters for x and y scaling - yp = h / scaledHeight; - yq = h % scaledHeight; - xp = w / scaledWidth; - xq = w % scaledWidth; - - // allocate pixel buffer - if (yp < 0 || yp > INT_MAX - 1) { - return splashErrBadArg; - } - pixBuf = (SplashColorPtr)gmallocn((yp + 1), w); - - // initialize the pixel pipe - pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha, - gTrue, gFalse); - if (vectorAntialias) { - drawAAPixelInit(); - } - - // 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) { - (*src)(srcData, p); - p += w; - } - } - lastYStep = yStep; - - // loop-invariant constants - k1 = splashRound(xShear * ySign * y); - - // clipping test - if (clipRes != splashClipAllInside && - !rot && - (int)(yShear * k1) == - (int)(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 + (int)(yShear * k1); - clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); - if (clipRes2 == splashClipAllOutside) { - continue; - } - } else { - clipRes2 = clipRes; - } - - // init x scale Bresenham - xt = 0; - xSrc = 0; - - // x shear - x1 = k1; - - // y shear - y1 = (SplashCoord)ySign * y + yShear * x1; - // this is a kludge: if yShear1 is negative, then (int)y1 would - // change immediately after the first pixel, which is not what we - // want - if (yShear1 < 0) { - y1 += 0.999; - } - - // loop-invariant constants - n = yStep > 0 ? yStep : 1; - - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the alpha value for (x,y) after the x and y scaling - // operations - 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) { - pipe.shape = (pixAcc == n * m) - ? (SplashCoord)1 - : (SplashCoord)pixAcc / (SplashCoord)(n * m); - if (vectorAntialias && clipRes2 != splashClipAllInside) { - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, clipRes2 == splashClipAllInside); - } - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - } - - // free memory - gfree(pixBuf); - - return splashOk; -} - -SplashError Splash::drawImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, GBool srcAlpha, - int w, int h, SplashCoord *mat) { - SplashPipe pipe; - GBool ok, rot; - SplashCoord xScale, yScale, xShear, yShear, yShear1; - int tx, tx2, ty, ty2, 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; - SplashColorPtr colorBuf, p; - SplashColor pix; - Guchar *alphaBuf, *q; -#if SPLASH_CMYK - int pixAcc0, pixAcc1, pixAcc2, pixAcc3; -#else - int pixAcc0, pixAcc1, pixAcc2; -#endif - int alphaAcc; - SplashCoord pixMul, alphaMul, alpha; - int x, y, x1, x2, y2; - SplashCoord y1; - int nComps, n, m, i, j; - - if (debugMode) { - printf("drawImage: srcMode=%d srcAlpha=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", - srcMode, srcAlpha, w, h, (double)mat[0], (double)mat[1], (double)mat[2], - (double)mat[3], (double)mat[4], (double)mat[5]); - } - - // check color modes - ok = gFalse; // make gcc happy - nComps = 0; // make gcc happy - switch (bitmap->mode) { - case splashModeMono1: - case splashModeMono8: - ok = srcMode == splashModeMono8; - nComps = 1; - break; - case splashModeRGB8: - ok = srcMode == splashModeRGB8; - nComps = 3; - break; - case splashModeXBGR8: - ok = srcMode == splashModeXBGR8; - nComps = 4; - break; - case splashModeBGR8: - ok = srcMode == splashModeBGR8; - nComps = 3; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - ok = srcMode == splashModeCMYK8; - nComps = 4; - break; -#endif - } - if (!ok) { - return splashErrModeMismatch; - } - - // 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]; - } - // Note 1: The PDF spec says that all pixels whose *centers* lie - // within the region get painted -- but that doesn't seem to match - // up with what Acrobat actually does: it ends up leaving gaps - // between image stripes. So we use the same rule here as for - // fills: any pixel that overlaps the region gets painted. - // Note 2: The +/-0.01 in these computations is to avoid floating - // point precision problems which can lead to gaps between image - // stripes (it can cause image stripes to overlap, but that's a much - // less visible problem). - if (xScale >= 0) { - tx = splashFloor(mat[4] - 0.01); - tx2 = splashFloor(mat[4] + xScale + 0.01); - } else { - tx = splashFloor(mat[4] + 0.01); - tx2 = splashFloor(mat[4] + xScale - 0.01); - } - scaledWidth = abs(tx2 - tx) + 1; - if (yScale >= 0) { - ty = splashFloor(mat[5] - 0.01); - ty2 = splashFloor(mat[5] + yScale + 0.01); - } else { - ty = splashFloor(mat[5] + 0.01); - ty2 = splashFloor(mat[5] + yScale - 0.01); - } - scaledHeight = abs(ty2 - ty) + 1; - xSign = (xScale < 0) ? -1 : 1; - ySign = (yScale < 0) ? -1 : 1; - yShear1 = (SplashCoord)xSign * yShear; - - // clipping - ulx1 = 0; - uly1 = 0; - urx1 = xSign * (scaledWidth - 1); - ury1 = (int)(yShear * urx1); - llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); - lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1); - lrx1 = xSign * (scaledWidth - 1) + - splashRound(xShear * ySign * (scaledHeight - 1)); - lry1 = ySign * (scaledHeight - 1) + (int)(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); - opClipRes = clipRes; - if (clipRes == 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 buffers - if (yp < 0 || yp > INT_MAX - 1) { - return splashErrBadArg; - } - colorBuf = (SplashColorPtr)gmallocn3((yp + 1), w, nComps); - if (srcAlpha) { - alphaBuf = (Guchar *)gmallocn((yp + 1), w); - } else { - alphaBuf = NULL; - } - - pixAcc0 = pixAcc1 = pixAcc2 = 0; // make gcc happy -#if SPLASH_CMYK - pixAcc3 = 0; // make gcc happy -#endif - - // initialize the pixel pipe - pipeInit(&pipe, 0, 0, NULL, pix, state->fillAlpha, - srcAlpha || (vectorAntialias && clipRes != splashClipAllInside), - gFalse); - if (vectorAntialias) { - drawAAPixelInit(); - } - - if (srcAlpha) { - - // 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 = colorBuf; - q = alphaBuf; - for (i = 0; i < n; ++i) { - (*src)(srcData, p, q); - p += w * nComps; - q += w; - } - } - lastYStep = yStep; - - // loop-invariant constants - k1 = splashRound(xShear * ySign * y); - - // clipping test - if (clipRes != splashClipAllInside && - !rot && - (int)(yShear * k1) == - (int)(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 + (int)(yShear * k1); - clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); - if (clipRes2 == splashClipAllOutside) { - continue; - } - } else { - clipRes2 = clipRes; - } - - // init x scale Bresenham - xt = 0; - xSrc = 0; - - // x shear - x1 = k1; - - // y shear - y1 = (SplashCoord)ySign * y + yShear * x1; - // this is a kludge: if yShear1 is negative, then (int)y1 would - // change immediately after the first pixel, which is not what - // we want - if (yShear1 < 0) { - y1 += 0.999; - } - - // loop-invariant constants - n = yStep > 0 ? yStep : 1; - - switch (srcMode) { - - case splashModeMono1: - case splashModeMono8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - alphaAcc = 0; - p = colorBuf + xSrc; - q = alphaBuf + xSrc; - pixAcc0 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - alphaAcc += *q++; - } - p += w - m; - q += w - m; - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - alphaMul = pixMul * (1.0 / 255.0); - alpha = (SplashCoord)alphaAcc * alphaMul; - - if (alpha > 0) { - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - - // set pixel - pipe.shape = alpha; - if (vectorAntialias && clipRes != splashClipAllInside) { - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - - case splashModeRGB8: - case splashModeBGR8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - alphaAcc = 0; - p = colorBuf + xSrc * 3; - q = alphaBuf + xSrc; - pixAcc0 = pixAcc1 = pixAcc2 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - alphaAcc += *q++; - } - p += 3 * (w - m); - q += w - m; - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - alphaMul = pixMul * (1.0 / 255.0); - alpha = (SplashCoord)alphaAcc * alphaMul; - - if (alpha > 0) { - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - - // set pixel - pipe.shape = alpha; - if (vectorAntialias && clipRes != splashClipAllInside) { - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - - case splashModeXBGR8: - for (x = 0; x < scaledWidth; ++x) { - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - alphaAcc = 0; - p = colorBuf + xSrc * 4; - q = alphaBuf + xSrc; - pixAcc0 = pixAcc1 = pixAcc2 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - *p++; - alphaAcc += *q++; - } - p += 4 * (w - m); - q += w - m; - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - alphaMul = pixMul * (1.0 / 255.0); - alpha = (SplashCoord)alphaAcc * alphaMul; - - if (alpha > 0) { - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - pix[3] = 255; - - // set pixel - pipe.shape = alpha; - if (vectorAntialias && clipRes != splashClipAllInside) { - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - - -#if SPLASH_CMYK - case splashModeCMYK8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - alphaAcc = 0; - p = colorBuf + xSrc * 4; - q = alphaBuf + xSrc; - pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - pixAcc3 += *p++; - alphaAcc += *q++; - } - p += 4 * (w - m); - q += w - m; - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - alphaMul = pixMul * (1.0 / 255.0); - alpha = (SplashCoord)alphaAcc * alphaMul; - - if (alpha > 0) { - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - pix[3] = (int)((SplashCoord)pixAcc3 * pixMul); - - // set pixel - pipe.shape = alpha; - if (vectorAntialias && clipRes != splashClipAllInside) { - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; -#endif // SPLASH_CMYK - } - } - - } else { - - // 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 = colorBuf; - for (i = 0; i < n; ++i) { - (*src)(srcData, p, NULL); - p += w * nComps; - } - } - lastYStep = yStep; - - // loop-invariant constants - k1 = splashRound(xShear * ySign * y); - - // clipping test - if (clipRes != splashClipAllInside && - !rot && - (int)(yShear * k1) == - (int)(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 + (int)(yShear * k1); - clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); - if (clipRes2 == splashClipAllOutside) { - continue; - } - } else { - clipRes2 = clipRes; - } - - // init x scale Bresenham - xt = 0; - xSrc = 0; - - // x shear - x1 = k1; - - // y shear - y1 = (SplashCoord)ySign * y + yShear * x1; - // this is a kludge: if yShear1 is negative, then (int)y1 would - // change immediately after the first pixel, which is not what - // we want - if (yShear1 < 0) { - y1 += 0.999; - } - - // loop-invariant constants - n = yStep > 0 ? yStep : 1; - - switch (srcMode) { - - case splashModeMono1: - case splashModeMono8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - p = colorBuf + xSrc; - pixAcc0 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - } - p += w - m; - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - - // set pixel - if (vectorAntialias && clipRes != splashClipAllInside) { - pipe.shape = (SplashCoord)1; - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - - case splashModeRGB8: - case splashModeBGR8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - p = colorBuf + xSrc * 3; - pixAcc0 = pixAcc1 = pixAcc2 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - } - p += 3 * (w - m); - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - - // set pixel - if (vectorAntialias && clipRes != splashClipAllInside) { - pipe.shape = (SplashCoord)1; - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - - case splashModeXBGR8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - p = colorBuf + xSrc * 4; - pixAcc0 = pixAcc1 = pixAcc2 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - *p++; - } - p += 4 * (w - m); - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - pix[3] = 255; - - // set pixel - if (vectorAntialias && clipRes != splashClipAllInside) { - pipe.shape = (SplashCoord)1; - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; - -#if SPLASH_CMYK - case splashModeCMYK8: - for (x = 0; x < scaledWidth; ++x) { - - // x scale Bresenham - xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - - // rotation - if (rot) { - x2 = (int)y1; - y2 = -x1; - } else { - x2 = x1; - y2 = (int)y1; - } - - // compute the filtered pixel at (x,y) after the x and y scaling - // operations - m = xStep > 0 ? xStep : 1; - p = colorBuf + xSrc * 4; - pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - pixAcc0 += *p++; - pixAcc1 += *p++; - pixAcc2 += *p++; - pixAcc3 += *p++; - } - p += 4 * (w - m); - } - pixMul = (SplashCoord)1 / (SplashCoord)(n * m); - - pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); - pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); - pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); - pix[3] = (int)((SplashCoord)pixAcc3 * pixMul); - - // set pixel - if (vectorAntialias && clipRes != splashClipAllInside) { - pipe.shape = (SplashCoord)1; - drawAAPixel(&pipe, tx + x2, ty + y2); - } else { - drawPixel(&pipe, tx + x2, ty + y2, - clipRes2 == splashClipAllInside); - } - - // x scale Bresenham - xSrc += xStep; - - // x shear - x1 += xSign; - - // y shear - y1 += yShear1; - } - break; -#endif // SPLASH_CMYK - } - } - - } - - gfree(colorBuf); - gfree(alphaBuf); - - return splashOk; -} - -SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h, - GBool noClip, GBool nonIsolated) { - SplashPipe pipe; - SplashColor pixel; - Guchar alpha; - Guchar *ap; - int x, y; - - if (src->mode != bitmap->mode) { - return splashErrModeMismatch; - } - - if (src->alpha) { - pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha, - gTrue, nonIsolated); - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - alpha = *ap++; - if (noClip || state->clip->test(xDest + x, yDest + y)) { - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same - pipe.shape = (SplashCoord)(alpha / 255.0); - pipeRun(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - } - } - } - } else { - pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha, - gFalse, nonIsolated); - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - if (noClip || state->clip->test(xDest + x, yDest + y)) { - pipeRun(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - } - } - } - } - - return splashOk; -} - -void Splash::compositeBackground(SplashColorPtr color) { - SplashColorPtr p; - Guchar *q; - Guchar alpha, alpha1, c, color0, color1, color2; -#if SPLASH_CMYK - Guchar color3; -#endif - int x, y, mask; - - switch (bitmap->mode) { - case splashModeMono1: - color0 = color[0]; - for (y = 0; y < bitmap->height; ++y) { - p = &bitmap->data[y * bitmap->rowSize]; - q = &bitmap->alpha[y * bitmap->width]; - mask = 0x80; - for (x = 0; x < bitmap->width; ++x) { - alpha = *q++; - alpha1 = 255 - alpha; - c = (*p & mask) ? 0xff : 0x00; - c = div255(alpha1 * color0 + alpha * c); - if (c & 0x80) { - *p |= mask; - } else { - *p &= ~mask; - } - if (!(mask >>= 1)) { - mask = 0x80; - ++p; - } - } - } - break; - case splashModeMono8: - color0 = color[0]; - for (y = 0; y < bitmap->height; ++y) { - p = &bitmap->data[y * bitmap->rowSize]; - q = &bitmap->alpha[y * bitmap->width]; - for (x = 0; x < bitmap->width; ++x) { - alpha = *q++; - alpha1 = 255 - alpha; - p[0] = div255(alpha1 * color0 + alpha * p[0]); - ++p; - } - } - break; - case splashModeRGB8: - case splashModeBGR8: - color0 = color[0]; - color1 = color[1]; - color2 = color[2]; - for (y = 0; y < bitmap->height; ++y) { - p = &bitmap->data[y * bitmap->rowSize]; - q = &bitmap->alpha[y * bitmap->width]; - for (x = 0; x < bitmap->width; ++x) { - alpha = *q++; - alpha1 = 255 - alpha; - p[0] = div255(alpha1 * color0 + alpha * p[0]); - p[1] = div255(alpha1 * color1 + alpha * p[1]); - p[2] = div255(alpha1 * color2 + alpha * p[2]); - p += 3; - } - } - break; - case splashModeXBGR8: - color0 = color[0]; - color1 = color[1]; - color2 = color[2]; - for (y = 0; y < bitmap->height; ++y) { - p = &bitmap->data[y * bitmap->rowSize]; - q = &bitmap->alpha[y * bitmap->width]; - for (x = 0; x < bitmap->width; ++x) { - alpha = *q++; - alpha1 = 255 - alpha; - p[0] = div255(alpha1 * color0 + alpha * p[0]); - p[1] = div255(alpha1 * color1 + alpha * p[1]); - p[2] = div255(alpha1 * color2 + alpha * p[2]); - p[3] = 255; - p += 4; - } - } - break; -#if SPLASH_CMYK - case splashModeCMYK8: - color0 = color[0]; - color1 = color[1]; - color2 = color[2]; - color3 = color[3]; - for (y = 0; y < bitmap->height; ++y) { - p = &bitmap->data[y * bitmap->rowSize]; - q = &bitmap->alpha[y * bitmap->width]; - for (x = 0; x < bitmap->width; ++x) { - alpha = *q++; - alpha1 = 255 - alpha; - p[0] = div255(alpha1 * color0 + alpha * p[0]); - p[1] = div255(alpha1 * color1 + alpha * p[1]); - p[2] = div255(alpha1 * color2 + alpha * p[2]); - p[3] = div255(alpha1 * color3 + alpha * p[3]); - p += 4; - } - } - break; -#endif - } - memset(bitmap->alpha, 255, bitmap->width * bitmap->height); -} - -SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h) { - SplashColor pixel; - SplashColorPtr p; - Guchar *q; - int x, y, mask; - - if (src->mode != bitmap->mode) { - return splashErrModeMismatch; - } - - switch (bitmap->mode) { - case splashModeMono1: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + (xDest >> 3)]; - mask = 0x80 >> (xDest & 7); - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - if (pixel[0]) { - *p |= mask; - } else { - *p &= ~mask; - } - if (!(mask >>= 1)) { - mask = 0x80; - ++p; - } - } - } - break; - case splashModeMono8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest]; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - *p++ = pixel[0]; - } - } - break; - case splashModeRGB8: - case splashModeBGR8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest]; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - *p++ = pixel[0]; - *p++ = pixel[1]; - *p++ = pixel[2]; - } - } - break; - case splashModeXBGR8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest]; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - *p++ = pixel[0]; - *p++ = pixel[1]; - *p++ = pixel[2]; - *p++ = 255; - } - } - break; -#if SPLASH_CMYK - case splashModeCMYK8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest]; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - *p++ = pixel[0]; - *p++ = pixel[1]; - *p++ = pixel[2]; - *p++ = pixel[3]; - } - } - break; -#endif - } - - if (bitmap->alpha) { - for (y = 0; y < h; ++y) { - q = &bitmap->alpha[(yDest + y) * bitmap->width + xDest]; - for (x = 0; x < w; ++x) { - *q++ = 0x00; - } - } - } - - return splashOk; -} - -SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) { - SplashPath *pathIn, *pathOut; - SplashCoord w, d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext; - SplashCoord crossprod, dotprod, miter, m; - GBool first, last, closed; - int subpathStart, next, i; - int left0, left1, left2, right0, right1, right2, join0, join1, join2; - int leftFirst, rightFirst, firstPt; - - if (flatten) { - pathIn = flattenPath(path, state->matrix, state->flatness); - if (state->lineDashLength > 0) { - pathOut = makeDashedPath(pathIn); - delete pathIn; - pathIn = pathOut; - } - } else { - pathIn = path; - } - - subpathStart = 0; // make gcc happy - closed = gFalse; // make gcc happy - left0 = left1 = right0 = right1 = join0 = join1 = 0; // make gcc happy - leftFirst = rightFirst = firstPt = 0; // make gcc happy - - pathOut = new SplashPath(); - w = state->lineWidth; - - for (i = 0; i < pathIn->length - 1; ++i) { - if (pathIn->flags[i] & splashPathLast) { - continue; - } - if ((first = pathIn->flags[i] & splashPathFirst)) { - subpathStart = i; - closed = pathIn->flags[i] & splashPathClosed; - } - last = pathIn->flags[i+1] & splashPathLast; - - // compute the deltas for segment (i, i+1) - d = splashDist(pathIn->pts[i].x, pathIn->pts[i].y, - pathIn->pts[i+1].x, pathIn->pts[i+1].y); - 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 = (SplashCoord)1 / d; - dx = d * (pathIn->pts[i+1].x - pathIn->pts[i].x); - dy = d * (pathIn->pts[i+1].y - pathIn->pts[i].y); - } - wdx = (SplashCoord)0.5 * w * dx; - wdy = (SplashCoord)0.5 * w * dy; - - // compute the deltas for segment (i+1, next) - next = last ? subpathStart + 1 : i + 2; - d = splashDist(pathIn->pts[i+1].x, pathIn->pts[i+1].y, - pathIn->pts[next].x, pathIn->pts[next].y); - 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 - dxNext = 0; - dyNext = 1; - } else { - d = (SplashCoord)1 / d; - dxNext = d * (pathIn->pts[next].x - pathIn->pts[i+1].x); - dyNext = d * (pathIn->pts[next].y - pathIn->pts[i+1].y); - } - wdxNext = (SplashCoord)0.5 * w * dxNext; - wdyNext = (SplashCoord)0.5 * w * dyNext; - - // draw the start cap - pathOut->moveTo(pathIn->pts[i].x - wdy, pathIn->pts[i].y + wdx); - if (i == subpathStart) { - firstPt = pathOut->length - 1; - } - if (first && !closed) { - switch (state->lineCap) { - case splashLineCapButt: - pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx); - break; - case splashLineCapRound: - pathOut->curveTo(pathIn->pts[i].x - wdy - bezierCircle * wdx, - pathIn->pts[i].y + wdx - bezierCircle * wdy, - pathIn->pts[i].x - wdx - bezierCircle * wdy, - pathIn->pts[i].y - wdy + bezierCircle * wdx, - pathIn->pts[i].x - wdx, - pathIn->pts[i].y - wdy); - pathOut->curveTo(pathIn->pts[i].x - wdx + bezierCircle * wdy, - pathIn->pts[i].y - wdy - bezierCircle * wdx, - pathIn->pts[i].x + wdy - bezierCircle * wdx, - pathIn->pts[i].y - wdx - bezierCircle * wdy, - pathIn->pts[i].x + wdy, - pathIn->pts[i].y - wdx); - break; - case splashLineCapProjecting: - pathOut->lineTo(pathIn->pts[i].x - wdx - wdy, - pathIn->pts[i].y + wdx - wdy); - pathOut->lineTo(pathIn->pts[i].x - wdx + wdy, - pathIn->pts[i].y - wdx - wdy); - pathOut->lineTo(pathIn->pts[i].x + wdy, - pathIn->pts[i].y - wdx); - break; - } - } else { - pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx); - } - - // draw the left side of the segment rectangle - left2 = pathOut->length - 1; - pathOut->lineTo(pathIn->pts[i+1].x + wdy, pathIn->pts[i+1].y - wdx); - - // draw the end cap - if (last && !closed) { - switch (state->lineCap) { - case splashLineCapButt: - pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); - break; - case splashLineCapRound: - pathOut->curveTo(pathIn->pts[i+1].x + wdy + bezierCircle * wdx, - pathIn->pts[i+1].y - wdx + bezierCircle * wdy, - pathIn->pts[i+1].x + wdx + bezierCircle * wdy, - pathIn->pts[i+1].y + wdy - bezierCircle * wdx, - pathIn->pts[i+1].x + wdx, - pathIn->pts[i+1].y + wdy); - pathOut->curveTo(pathIn->pts[i+1].x + wdx - bezierCircle * wdy, - pathIn->pts[i+1].y + wdy + bezierCircle * wdx, - pathIn->pts[i+1].x - wdy + bezierCircle * wdx, - pathIn->pts[i+1].y + wdx + bezierCircle * wdy, - pathIn->pts[i+1].x - wdy, - pathIn->pts[i+1].y + wdx); - break; - case splashLineCapProjecting: - pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx, - pathIn->pts[i+1].y - wdx + wdy); - pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx, - pathIn->pts[i+1].y + wdx + wdy); - pathOut->lineTo(pathIn->pts[i+1].x - wdy, - pathIn->pts[i+1].y + wdx); - break; - } - } else { - pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); - } - - // draw the right side of the segment rectangle - right2 = pathOut->length - 1; - pathOut->close(); - - // draw the join - join2 = pathOut->length; - if (!last || closed) { - crossprod = dx * dyNext - dy * dxNext; - dotprod = -(dx * dxNext + dy * dyNext); - if (dotprod > 0.99999) { - // avoid a divide-by-zero -- set miter to something arbitrary - // such that sqrt(miter) will exceed miterLimit (and m is never - // used in that situation) - miter = (state->miterLimit + 1) * (state->miterLimit + 1); - m = 0; - } else { - miter = (SplashCoord)2 / ((SplashCoord)1 - dotprod); - if (miter < 1) { - // this can happen because of floating point inaccuracies - miter = 1; - } - m = splashSqrt(miter - 1); - } - - // round join - if (state->lineJoin == splashLineJoinRound) { - pathOut->moveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w, - pathIn->pts[i+1].y); - pathOut->curveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w, - pathIn->pts[i+1].y + bezierCircle2 * w, - pathIn->pts[i+1].x + bezierCircle2 * w, - pathIn->pts[i+1].y + (SplashCoord)0.5 * w, - pathIn->pts[i+1].x, - pathIn->pts[i+1].y + (SplashCoord)0.5 * w); - pathOut->curveTo(pathIn->pts[i+1].x - bezierCircle2 * w, - pathIn->pts[i+1].y + (SplashCoord)0.5 * w, - pathIn->pts[i+1].x - (SplashCoord)0.5 * w, - pathIn->pts[i+1].y + bezierCircle2 * w, - pathIn->pts[i+1].x - (SplashCoord)0.5 * w, - pathIn->pts[i+1].y); - pathOut->curveTo(pathIn->pts[i+1].x - (SplashCoord)0.5 * w, - pathIn->pts[i+1].y - bezierCircle2 * w, - pathIn->pts[i+1].x - bezierCircle2 * w, - pathIn->pts[i+1].y - (SplashCoord)0.5 * w, - pathIn->pts[i+1].x, - pathIn->pts[i+1].y - (SplashCoord)0.5 * w); - pathOut->curveTo(pathIn->pts[i+1].x + bezierCircle2 * w, - pathIn->pts[i+1].y - (SplashCoord)0.5 * w, - pathIn->pts[i+1].x + (SplashCoord)0.5 * w, - pathIn->pts[i+1].y - bezierCircle2 * w, - pathIn->pts[i+1].x + (SplashCoord)0.5 * w, - pathIn->pts[i+1].y); - - } else { - pathOut->moveTo(pathIn->pts[i+1].x, pathIn->pts[i+1].y); - - // angle < 180 - if (crossprod < 0) { - pathOut->lineTo(pathIn->pts[i+1].x - wdyNext, - pathIn->pts[i+1].y + wdxNext); - // miter join inside limit - if (state->lineJoin == splashLineJoinMiter && - splashSqrt(miter) <= state->miterLimit) { - pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx * m, - pathIn->pts[i+1].y + wdx + wdy * m); - pathOut->lineTo(pathIn->pts[i+1].x - wdy, - pathIn->pts[i+1].y + wdx); - // bevel join or miter join outside limit - } else { - pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); - } - - // angle >= 180 - } else { - pathOut->lineTo(pathIn->pts[i+1].x + wdy, - pathIn->pts[i+1].y - wdx); - // miter join inside limit - if (state->lineJoin == splashLineJoinMiter && - splashSqrt(miter) <= state->miterLimit) { - pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx * m, - pathIn->pts[i+1].y - wdx + wdy * m); - pathOut->lineTo(pathIn->pts[i+1].x + wdyNext, - pathIn->pts[i+1].y - wdxNext); - // bevel join or miter join outside limit - } else { - pathOut->lineTo(pathIn->pts[i+1].x + wdyNext, - pathIn->pts[i+1].y - wdxNext); - } - } - } - - pathOut->close(); - } - - // add stroke adjustment hints - if (state->strokeAdjust) { - if (i >= subpathStart + 1) { - if (i >= subpathStart + 2) { - pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0); - pathOut->addStrokeAdjustHint(left1, right1, join0, left2); - } else { - pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2); - } - pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1); - } - left0 = left1; - left1 = left2; - right0 = right1; - right1 = right2; - join0 = join1; - join1 = join2; - if (i == subpathStart) { - leftFirst = left2; - rightFirst = right2; - } - if (last) { - if (i >= subpathStart + 2) { - pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0); - pathOut->addStrokeAdjustHint(left1, right1, - join0, pathOut->length - 1); - } else { - pathOut->addStrokeAdjustHint(left1, right1, - firstPt, pathOut->length - 1); - } - if (closed) { - pathOut->addStrokeAdjustHint(left1, right1, firstPt, leftFirst); - pathOut->addStrokeAdjustHint(left1, right1, - rightFirst + 1, rightFirst + 1); - pathOut->addStrokeAdjustHint(leftFirst, rightFirst, - left1 + 1, right1); - pathOut->addStrokeAdjustHint(leftFirst, rightFirst, - join1, pathOut->length - 1); - } - } - } - } - - if (pathIn != path) { - delete pathIn; - } - - return pathOut; -} - -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\n", - i, (double)path->pts[i].x, (double)path->pts[i].y, - (path->flags[i] & splashPathFirst) ? " first" : "", - (path->flags[i] & splashPathLast) ? " last" : "", - (path->flags[i] & splashPathClosed) ? " closed" : "", - (path->flags[i] & splashPathCurve) ? " curve" : ""); - } -} - -void Splash::dumpXPath(SplashXPath *path) { - int i; - - for (i = 0; i < path->length; ++i) { - printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s%s%s%s%s\n", - i, (double)path->segs[i].x0, (double)path->segs[i].y0, - (double)path->segs[i].x1, (double)path->segs[i].y1, - (path->segs[i].flags & splashXPathFirst) ? "F" : " ", - (path->segs[i].flags & splashXPathLast) ? "L" : " ", - (path->segs[i].flags & splashXPathEnd0) ? "0" : " ", - (path->segs[i].flags & splashXPathEnd1) ? "1" : " ", - (path->segs[i].flags & splashXPathHoriz) ? "H" : " ", - (path->segs[i].flags & splashXPathVert) ? "V" : " ", - (path->segs[i].flags & splashXPathFlip) ? "P" : " "); - } -} |