blob: 83b1fbf157566f0f05d45423940c2541e930cba0 [file] [log] [blame]
//========================================================================
//
// 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;
}