summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc447
1 files changed, 447 insertions, 0 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
new file mode 100644
index 00000000000..d0f5f1ea401
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
@@ -0,0 +1,447 @@
+//========================================================================
+//
+// TileCompositor.cc
+//
+// Copyright 2014 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <math.h>
+#include "gmempp.h"
+#include "GString.h"
+#include "GList.h"
+#include "SplashBitmap.h"
+#include "GlobalParams.h"
+#include "DisplayState.h"
+#include "TileMap.h"
+#include "TileCache.h"
+#include "TileCompositor.h"
+
+//------------------------------------------------------------------------
+
+// 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);
+}
+
+//------------------------------------------------------------------------
+
+TileCompositor::TileCompositor(DisplayState *stateA,
+ TileMap *tileMapA,
+ TileCache *tileCacheA) {
+ state = stateA;
+ state->setTileCompositor(this);
+ tileMap = tileMapA;
+ tileCache = tileCacheA;
+ bitmap = NULL;
+ bitmapValid = gFalse;
+}
+
+TileCompositor::~TileCompositor() {
+ delete bitmap;
+}
+
+SplashBitmap *TileCompositor::getBitmap(GBool *finished) {
+ GList *tiles;
+ PlacedTileDesc *tile;
+ SplashBitmap *tileBitmap;
+ GBool allTilesFinished, tileFinished;
+ int xSrc, ySrc, xDest, yDest, w, h, i;
+
+ if (bitmapValid) {
+ *finished = gTrue;
+ return bitmap;
+ }
+ if (!bitmap ||
+ bitmap->getWidth() != state->getWinW() ||
+ bitmap->getHeight() != state->getWinH()) {
+ if (bitmap) {
+ delete bitmap;
+ }
+ bitmap = new SplashBitmap(state->getWinW(), state->getWinH(),
+ state->getBitmapRowPad(), state->getColorMode(),
+ gFalse);
+ }
+ clearBitmap();
+
+ //--- PDF content
+ allTilesFinished = gTrue;
+ tiles = tileMap->getTileList();
+ tileCache->setActiveTileList(tiles);
+ for (i = 0; i < tiles->getLength(); ++i) {
+ tile = (PlacedTileDesc *)tiles->get(i);
+ if (tile->px >= 0) {
+ xSrc = 0;
+ xDest = tile->px;
+ w = tile->tw;
+ } else {
+ xSrc = -tile->px;
+ xDest = 0;
+ w = tile->tw + tile->px;
+ }
+ if (xDest + w > state->getWinW()) {
+ w = state->getWinW() - xDest;
+ }
+ if (tile->py >= 0) {
+ ySrc = 0;
+ yDest = tile->py;
+ h = tile->th;
+ } else {
+ ySrc = -tile->py;
+ yDest = 0;
+ h = tile->th + tile->py;
+ }
+ if (yDest + h > state->getWinH()) {
+ h = state->getWinH() - yDest;
+ }
+ if (w > 0 && h > 0) {
+ if ((tileBitmap = tileCache->getTileBitmap(tile, &tileFinished))) {
+ blit(tileBitmap, xSrc, ySrc,
+ bitmap, xDest, yDest, w, h, !tileFinished);
+ } else {
+ fill(xDest, yDest, w, h, state->getPaperColor());
+ }
+ allTilesFinished &= tileFinished;
+ }
+ }
+
+
+ //--- selection
+ if (state->hasSelection()) {
+ drawSelection();
+ }
+
+ if (finished) {
+ *finished = allTilesFinished;
+ }
+ bitmapValid = allTilesFinished;
+
+ return bitmap;
+}
+
+void TileCompositor::drawSelection() {
+ SelectRect *rect;
+ int x0, y0, x1, y1, t, i;
+
+ for (i = 0; i < state->getNumSelectRects(); ++i) {
+ rect = state->getSelectRect(i);
+ tileMap->cvtUserToWindow(rect->page, rect->x0, rect->y0, &x0, &y0);
+ tileMap->cvtUserToWindow(rect->page, rect->x1, rect->y1, &x1, &y1);
+ if (x0 > x1) {
+ t = x0; x0 = x1; x1 = t;
+ }
+ if (y0 > y1) {
+ t = y0; y0 = y1; y1 = t;
+ }
+ if (x0 < 0) {
+ x0 = 0;
+ } else if (x0 > state->getWinW()) {
+ x0 = state->getWinW();
+ }
+ if (y0 < 0) {
+ y0 = 0;
+ } else if (y0 > state->getWinH()) {
+ y0 = state->getWinH();
+ }
+ if (x1 < 0) {
+ x1 = 0;
+ } else if (x1 > state->getWinW()) {
+ x1 = state->getWinW();
+ }
+ if (y1 < 0) {
+ y1 = 0;
+ } else if (y1 > state->getWinH()) {
+ y1 = state->getWinH();
+ }
+ // NB: in any of the non-continuous modes, if selectPage isn't
+ // displayed, cvtUserToWindow will return 0,0 -- so we need to
+ // check for x0 < x1 and y0 < y1 here
+ if (x0 < x1 && y0 < y1) {
+ applySelection(x0, y0, x1 - x0, y1 - y0, state->getSelectColor());
+ }
+ }
+}
+
+
+void TileCompositor::paperColorChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::matteColorChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::selectColorChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::reverseVideoChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::docChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::windowSizeChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::displayModeChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::zoomChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::rotateChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::scrollPositionChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::selectionChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::regionsChanged() {
+ bitmapValid = gFalse;
+}
+
+void TileCompositor::optionalContentChanged() {
+ bitmapValid = gFalse;
+}
+
+
+void TileCompositor::forceRedraw() {
+ bitmapValid = gFalse;
+}
+
+// Clear the bitmap to matteColor. This only supports the RGB8 and
+// BGR8 color modes.
+void TileCompositor::clearBitmap() {
+ SplashColorPtr data, row, p;
+ int rowSize, w, h, x, y;
+
+ w = bitmap->getWidth();
+ h = bitmap->getHeight();
+ rowSize = bitmap->getRowSize();
+ data = bitmap->getDataPtr();
+
+ switch (state->getColorMode()) {
+ case splashModeRGB8:
+ if (state->getMatteColor()[0] == state->getMatteColor()[1] &&
+ state->getMatteColor()[1] == state->getMatteColor()[2]) {
+ if (rowSize < 0) {
+ memset(data + rowSize * (h - 1), state->getMatteColor()[0],
+ -rowSize * h);
+ } else {
+ memset(data, state->getMatteColor()[0], rowSize * h);
+ }
+ } else {
+ row = data;
+ for (y = 0; y < h; ++y) {
+ p = row;
+ for (x = 0; x < w; ++x) {
+ *p++ = state->getMatteColor()[0];
+ *p++ = state->getMatteColor()[1];
+ *p++ = state->getMatteColor()[2];
+ }
+ row += rowSize;
+ }
+ }
+ break;
+ case splashModeBGR8:
+ if (state->getMatteColor()[0] == state->getMatteColor()[1] &&
+ state->getMatteColor()[1] == state->getMatteColor()[2]) {
+ if (rowSize < 0) {
+ memset(data + rowSize * (h - 1), state->getMatteColor()[0],
+ -rowSize * h);
+ } else {
+ memset(data, state->getMatteColor()[0], rowSize * h);
+ }
+ } else {
+ row = data;
+ for (y = 0; y < h; ++y) {
+ p = row;
+ for (x = 0; x < w; ++x) {
+ *p++ = state->getMatteColor()[2];
+ *p++ = state->getMatteColor()[1];
+ *p++ = state->getMatteColor()[0];
+ }
+ row += rowSize;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Copy [xSrc, ySrc, w, h] from srcBitmap to [xDest, yDest] in
+// destBitmap. This only supports the RGB8 and BGR8 color modes.
+// If [compositeWithPaper] is true, composites the source bitmap
+// with the paper color (used for incremental updates).
+void TileCompositor::blit(SplashBitmap *srcBitmap, int xSrc, int ySrc,
+ SplashBitmap *destBitmap, int xDest, int yDest,
+ int w, int h, GBool compositeWithPaper) {
+ SplashColorPtr srcData, destData, srcP, destP;
+ SplashColorPtr paperColor;
+ Guchar *alphaData, *alphaP;
+ Guchar alpha, alpha1;
+ int srcRowSize, destRowSize, alphaRowSize, x, y;
+
+ srcData = srcBitmap->getDataPtr();
+ srcRowSize = srcBitmap->getRowSize();
+ destData = destBitmap->getDataPtr();
+ destRowSize = destBitmap->getRowSize();
+
+ if (compositeWithPaper && (alphaData = srcBitmap->getAlphaPtr())) {
+ alphaRowSize = srcBitmap->getWidth();
+ paperColor = state->getPaperColor();
+ for (y = 0; y < h; ++y) {
+ destP = &destData[(yDest + y) * destRowSize + 3 * xDest];
+ srcP = &srcData[(ySrc + y) * srcRowSize + 3 * xSrc];
+ alphaP = &alphaData[(ySrc + y) * alphaRowSize + xSrc];
+ for (x = 0; x < w; ++x) {
+ alpha = *alphaP++;
+ //~ this needs to swap paperColor 0/1/2 in BGR8 mode (?)
+ if (alpha == 255) {
+ destP[0] = srcP[0];
+ destP[1] = srcP[1];
+ destP[2] = srcP[2];
+ } else if (alpha == 0) {
+ destP[0] = paperColor[0];
+ destP[1] = paperColor[1];
+ destP[2] = paperColor[2];
+ } else {
+ alpha1 = 255 - alpha;
+ destP[0] = div255(alpha1 * paperColor[0] + alpha * srcP[0]);
+ destP[1] = div255(alpha1 * paperColor[1] + alpha * srcP[1]);
+ destP[2] = div255(alpha1 * paperColor[2] + alpha * srcP[2]);
+ }
+ srcP += 3;
+ destP += 3;
+ }
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ destP = &destData[(yDest + y) * destRowSize + 3 * xDest];
+ srcP = &srcData[(ySrc + y) * srcRowSize + 3 * xSrc];
+ memcpy(destP, srcP, 3 * w);
+ }
+ }
+}
+
+// Fill [xDest, yDest, w, h] with color. This only supports the RGB8
+// and BGR8 color modes.
+void TileCompositor::fill(int xDest, int yDest, int w, int h,
+ SplashColorPtr color) {
+ SplashColorPtr data, p;
+ Guchar c0, c1, c2;
+ int rowSize, x, y;
+
+ if (xDest < 0) {
+ w += xDest;
+ xDest = 0;
+ }
+ if (xDest + w > state->getWinW()) {
+ w = state->getWinW() - xDest;
+ }
+ if (w <= 0) {
+ return;
+ }
+ if (yDest < 0) {
+ h += yDest;
+ yDest = 0;
+ }
+ if (yDest + h > state->getWinH()) {
+ h = state->getWinH() - yDest;
+ }
+ if (h <= 0) {
+ return;
+ }
+ data = bitmap->getDataPtr();
+ rowSize = bitmap->getRowSize();
+ if (bitmap->getMode() == splashModeRGB8) {
+ c0 = color[0];
+ c1 = color[1];
+ c2 = color[2];
+ } else {
+ c0 = color[2];
+ c1 = color[1];
+ c2 = color[0];
+ }
+ for (y = 0; y < h; ++y) {
+ p = &data[(yDest + y) * rowSize + 3 * xDest];
+ for (x = 0; x < w; ++x) {
+ p[0] = c0;
+ p[1] = c1;
+ p[2] = c2;
+ p += 3;
+ }
+ }
+}
+
+// Apply a selection of <color> to the specified rectangle. This only
+// supports the RGB8 and BGR8 color modes.
+void TileCompositor::applySelection(int xDest, int yDest, int w, int h,
+ SplashColorPtr color) {
+ SplashColorPtr data, p;
+ Guchar c0, c1, c2;
+ int rowSize, x, y;
+
+ if (xDest < 0) {
+ w += xDest;
+ xDest = 0;
+ }
+ if (xDest + w > state->getWinW()) {
+ w = state->getWinW() - xDest;
+ }
+ if (w <= 0) {
+ return;
+ }
+ if (yDest < 0) {
+ h += yDest;
+ yDest = 0;
+ }
+ if (yDest + h > state->getWinH()) {
+ h = state->getWinH() - yDest;
+ }
+ if (h <= 0) {
+ return;
+ }
+ data = bitmap->getDataPtr();
+ rowSize = bitmap->getRowSize();
+ if (bitmap->getMode() == splashModeRGB8) {
+ c0 = color[0];
+ c1 = color[1];
+ c2 = color[2];
+ } else {
+ c0 = color[2];
+ c1 = color[1];
+ c2 = color[0];
+ }
+ for (y = 0; y < h; ++y) {
+ p = &data[(yDest + y) * rowSize + 3 * xDest];
+ for (x = 0; x < w; ++x) {
+ p[0] = (3 * p[0] + c0) / 4;
+ p[1] = (3 * p[1] + c1) / 4;
+ p[2] = (3 * p[2] + c2) / 4;
+ p += 3;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+