| //======================================================================== |
| // |
| // CairoOutputDevX.cc |
| // |
| // Copyright 2003 Glyph & Cog, LLC |
| // Copyright 2004 Red Hat, Inc |
| // |
| //======================================================================== |
| |
| #include <config.h> |
| |
| #ifdef USE_GCC_PRAGMAS |
| #pragma implementation |
| #endif |
| |
| #include <string.h> |
| #include <math.h> |
| #include <cairo.h> |
| #include <cairo/cairo-xlib.h> |
| #include <X11/Xutil.h> |
| |
| #include "goo/gfile.h" |
| #include "GlobalParams.h" |
| #include "Error.h" |
| #include "Object.h" |
| #include <fofi/FoFiTrueType.h> |
| #include <splash/SplashBitmap.h> |
| #include "TextOutputDev.h" |
| #include "CairoOutputDevX.h" |
| |
| //------------------------------------------------------------------------ |
| // CairoOutputDevX |
| //------------------------------------------------------------------------ |
| |
| CairoOutputDevX::CairoOutputDevX(Display *displayA, int screenNumA, |
| Visual *visualA, Colormap colormapA, |
| GBool reverseVideoA, SplashColor paperColorA, |
| GBool installCmapA, int rgbCubeSizeA, |
| GBool incrementalUpdateA, |
| void (*redrawCbkA)(void *data), |
| void *redrawCbkDataA) { |
| XVisualInfo visualTempl; |
| XVisualInfo *visualList; |
| int nVisuals; |
| |
| pixmap = 0; |
| pixmap_w = 1; |
| pixmap_h = 1; |
| |
| incrementalUpdate = incrementalUpdateA; |
| redrawCbk = redrawCbkA; |
| redrawCbkData = redrawCbkDataA; |
| |
| //----- set up the X color stuff |
| |
| display = displayA; |
| screenNum = screenNumA; |
| visual = visualA; |
| |
| // check for TrueColor visual |
| //~ this should scan the list, not just look at the first one |
| visualTempl.visualid = XVisualIDFromVisual(visual); |
| visualList = XGetVisualInfo(display, VisualIDMask, |
| &visualTempl, &nVisuals); |
| if (nVisuals < 1) { |
| // this shouldn't happen |
| XFree((XPointer)visualList); |
| visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl, |
| &nVisuals); |
| } |
| depth = visualList->depth; |
| XFree((XPointer)visualList); |
| |
| text = new TextPage(gFalse); |
| |
| createCairo (NULL); |
| } |
| |
| CairoOutputDevX::~CairoOutputDevX() { |
| delete text; |
| } |
| |
| void |
| CairoOutputDevX::createCairo(GfxState *state) { |
| int w, h; |
| XGCValues gcv; |
| GC gc; |
| cairo_surface_t *surface; |
| |
| w = state ? (int)(state->getPageWidth() + 0.5) : 1; |
| h = state ? (int)(state->getPageHeight() + 0.5) : 1; |
| |
| if (!pixmap || w != pixmap_w || h != pixmap_h) { |
| if (pixmap) { |
| XFreePixmap(display, pixmap); |
| } |
| pixmap_w = w; |
| pixmap_h = h; |
| Window window = |
| XCreateSimpleWindow(display, RootWindow (display, screenNum), 0, 0, 1, 1, 0, |
| WhitePixel(display, screenNum), WhitePixel(display, screenNum)); |
| |
| pixmap = XCreatePixmap(display, window, w, h, |
| depth); |
| XDestroyWindow (display, window); |
| } |
| |
| gcv.foreground = WhitePixel(display, screenNum); |
| gc = XCreateGC(display, pixmap, GCForeground, &gcv); |
| XFillRectangle(display, pixmap, gc, 0, 0, w, h); |
| |
| surface = cairo_xlib_surface_create(display, pixmap, |
| DefaultVisual(display, DefaultScreen(display)), |
| w, h); |
| cairo = cairo_create (surface); |
| cairo_surface_destroy (surface); |
| |
| XFreeGC(display, gc); |
| } |
| |
| void CairoOutputDevX::drawChar(GfxState *state, double x, double y, |
| double dx, double dy, |
| double originX, double originY, |
| CharCode code, Unicode *u, int uLen) { |
| text->addChar(state, x, y, dx, dy, code, u, uLen); |
| CairoOutputDev::drawChar(state, x, y, dx, dy, originX, originY, |
| code, u, uLen); |
| } |
| |
| GBool CairoOutputDevX::beginType3Char(GfxState *state, double x, double y, |
| double dx, double dy, |
| CharCode code, Unicode *u, int uLen) { |
| text->addChar(state, x, y, dx, dy, code, u, uLen); |
| return CairoOutputDev::beginType3Char(state, x, y, dx, dy, code, u, uLen); |
| } |
| |
| int CairoOutputDevX::getBitmapWidth() { |
| return pixmap_w; |
| }; |
| int CairoOutputDevX::getBitmapHeight() { |
| return pixmap_h; |
| }; |
| |
| void CairoOutputDevX::clear() { |
| startDoc(NULL); |
| startPage(0, NULL); |
| } |
| |
| void CairoOutputDevX::startPage(int pageNum, GfxState *state) { |
| CairoOutputDev::startPage(pageNum, state); |
| text->startPage(state); |
| } |
| |
| void CairoOutputDevX::updateFont(GfxState *state) { |
| CairoOutputDev::updateFont(state); |
| text->updateFont(state); |
| } |
| |
| void CairoOutputDevX::endPage() { |
| CairoOutputDev::endPage(); |
| if (!incrementalUpdate) { |
| (*redrawCbk)(redrawCbkData); |
| } |
| text->coalesce(gTrue); |
| } |
| |
| void CairoOutputDevX::dump() { |
| if (incrementalUpdate) { |
| (*redrawCbk)(redrawCbkData); |
| } |
| } |
| |
| void CairoOutputDevX::redraw(int srcX, int srcY, |
| Drawable destDrawable, GC destGC, |
| int destX, int destY, |
| int width, int height) { |
| XCopyArea(display, pixmap, destDrawable, destGC, |
| srcX, srcY, width, height, |
| destX, destY); |
| } |
| |
| #define xoutRound(x) ((int)((x) + 0.5)) |
| |
| GBool CairoOutputDevX::findText(Unicode *s, int len, |
| GBool startAtTop, GBool stopAtBottom, |
| GBool startAtLast, GBool stopAtLast, |
| int *xMin, int *yMin, |
| int *xMax, int *yMax) { |
| double xMin1, yMin1, xMax1, yMax1; |
| |
| xMin1 = (double)*xMin; |
| yMin1 = (double)*yMin; |
| xMax1 = (double)*xMax; |
| yMax1 = (double)*yMax; |
| if (text->findText(s, len, startAtTop, stopAtBottom, |
| startAtLast, stopAtLast, |
| &xMin1, &yMin1, &xMax1, &yMax1)) { |
| *xMin = xoutRound(xMin1); |
| *xMax = xoutRound(xMax1); |
| *yMin = xoutRound(yMin1); |
| *yMax = xoutRound(yMax1); |
| return gTrue; |
| } |
| return gFalse; |
| } |
| |
| GooString *CairoOutputDevX::getText(int xMin, int yMin, int xMax, int yMax) { |
| return text->getText((double)xMin, (double)yMin, |
| (double)xMax, (double)yMax); |
| } |
| |
| void CairoOutputDevX::xorRectangle(int x0, int y0, int x1, int y1, |
| SplashPattern *pattern) { |
| return; |
| } |
| |