home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
xpdf
/
gfxstate.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1999-04-05
|
22KB
|
953 lines
//========================================================================
//
// GfxState.cc
//
// Copyright 1996 Derek B. Noonburg
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <stddef.h>
#include <math.h>
#include <string.h> // for memcpy()
#include "gmem.h"
#include "Error.h"
#include "Object.h"
#include "GfxState.h"
//------------------------------------------------------------------------
// GfxColor
//------------------------------------------------------------------------
void GfxColor::setCMYK(double c, double m, double y, double k) {
if ((r = 1 - (c + k)) < 0)
r = 0;
if ((g = 1 - (m + k)) < 0)
g = 0;
if ((b = 1 - (y + k)) < 0)
b = 0;
}
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
GfxColorSpace::GfxColorSpace(Object *colorSpace) {
Object csObj;
Object obj, obj2;
char *s;
int x;
int i, j;
ok = gTrue;
lookup = NULL;
// check for Separation colorspace
colorSpace->copy(&csObj);
sepFunc = NULL;
if (colorSpace->isArray()) {
colorSpace->arrayGet(0, &obj);
if (obj.isName("Separation")) {
csObj.free();
colorSpace->arrayGet(2, &csObj);
sepFunc = new Function(colorSpace->arrayGet(3, &obj2));
obj2.free();
if (!sepFunc->isOk()) {
delete sepFunc;
sepFunc = NULL;
}
}
obj.free();
}
// get mode
indexed = gFalse;
if (csObj.isName()) {
setMode(&csObj);
} else if (csObj.isArray()) {
csObj.arrayGet(0, &obj);
if (obj.isName("Indexed") || obj.isName("I")) {
indexed = gTrue;
setMode(csObj.arrayGet(1, &obj2));
obj2.free();
} else {
setMode(&csObj);
}
obj.free();
} else {
goto err1;
}
if (!ok)
return;
// get lookup table for indexed colorspace
if (indexed) {
csObj.arrayGet(2, &obj);
if (!obj.isInt())
goto err2;
indexHigh = obj.getInt();
obj.free();
lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar));
csObj.arrayGet(3, &obj);
if (obj.isStream()) {
obj.streamReset();
for (i = 0; i <= indexHigh; ++i) {
for (j = 0; j < numComps; ++j) {
if ((x = obj.streamGetChar()) == EOF)
goto err2;
lookup[i][j] = (Guchar)x;
}
}
} else if (obj.isString()) {
s = obj.getString()->getCString();
for (i = 0; i <= indexHigh; ++i)
for (j = 0; j < numComps; ++j)
lookup[i][j] = (Guchar)*s++;
} else {
goto err2;
}
obj.free();
}
csObj.free();
return;
err2:
obj.free();
err1:
csObj.free();
ok = gFalse;
}
GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
sepFunc = NULL;
mode = mode1;
indexed = gFalse;
switch (mode) {
case colorGray: numComps = 1; break;
case colorCMYK: numComps = 4; break;
case colorRGB: numComps = 3; break;
}
lookup = NULL;
ok = gTrue;
}
GfxColorSpace::~GfxColorSpace() {
if (sepFunc)
delete sepFunc;
gfree(lookup);
}
GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) {
int size;
if (colorSpace->sepFunc)
sepFunc = colorSpace->sepFunc->copy();
else
sepFunc = NULL;
mode = colorSpace->mode;
indexed = colorSpace->indexed;
numComps = colorSpace->numComps;
indexHigh = colorSpace->indexHigh;
if (indexed) {
size = (indexHigh + 1) * 4 * sizeof(Guchar);
lookup = (Guchar (*)[4])gmalloc(size);
memcpy(lookup, colorSpace->lookup, size);
} else {
lookup = NULL;
}
ok = gTrue;
}
void GfxColorSpace::setMode(Object *colorSpace) {
Object obj;
if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
mode = colorGray;
numComps = 1;
} else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
mode = colorRGB;
numComps = 3;
} else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
mode = colorCMYK;
numComps = 4;
} else if (colorSpace->isArray()) {
colorSpace->arrayGet(0, &obj);
if (obj.isName("CalGray")) {
mode = colorGray;
numComps = 1;
} else if (obj.isName("CalRGB")) {
mode = colorRGB;
numComps = 3;
} else if (obj.isName("CalCMYK")) {
mode = colorCMYK;
numComps = 4;
} else {
ok = gFalse;
}
obj.free();
} else {
ok = gFalse;
}
}
void GfxColorSpace::getColor(double x[4], GfxColor *color) {
double y[4];
Guchar *p;
if (sepFunc) {
sepFunc->transform(x, y);
} else {
y[0] = x[0];
y[1] = x[1];
y[2] = x[2];
y[3] = x[3];
}
if (indexed) {
p = lookup[(int)(y[0] + 0.5)];
switch (mode) {
case colorGray:
color->setGray(p[0] / 255.0);
break;
case colorCMYK:
color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
break;
case colorRGB:
color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
break;
}
} else {
switch (mode) {
case colorGray:
color->setGray(y[0]);
break;
case colorCMYK:
color->setCMYK(y[0], y[1], y[2], y[3]);
break;
case colorRGB:
color->setRGB(y[0], y[1], y[2]);
break;
}
}
}
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
Function::Function(Object *funcObj) {
Stream *str;
Dict *dict;
int nSamples, sampleBits;
double sampleMul;
Object obj1, obj2;
Guint buf, bitMask;
int bits;
int s;
int i;
ok = gFalse;
samples = NULL;
if (!funcObj->isStream()) {
error(-1, "Expected function dictionary");
goto err3;
}
str = funcObj->getStream();
dict = str->getDict();
//----- FunctionType
if (!dict->lookup("FunctionType", &obj1)->isInt() ||
obj1.getInt() != 0) {
error(-1, "Unknown function type");
goto err2;
}
obj1.free();
//----- Domain
if (!dict->lookup("Domain", &obj1)->isArray()) {
error(-1, "Function is missing domain");
goto err2;
}
m = obj1.arrayGetLength() / 2;
if (m > 4) {
error(-1, "Functions with more than 1 input are unsupported");
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function domain array");
goto err1;
}
domain[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function domain array");
goto err1;
}
domain[i][1] = obj2.getNum();
obj2.free();
}
obj1.free();
//----- Range
if (!dict->lookup("Range", &obj1)->isArray()) {
error(-1, "Function is missing range");
goto err2;
}
n = obj1.arrayGetLength() / 2;
if (n > 4) {
error(-1, "Functions with more than 4 outputs are unsupported");
goto err2;
}
for (i = 0; i < n; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function range array");
goto err1;
}
range[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function range array");
goto err1;
}
range[i][1] = obj2.getNum();
obj2.free();
}
obj1.free();
//----- Size
if (!dict->lookup("Size", &obj1)->isArray() ||
obj1.arrayGetLength() != m) {
error(-1, "Function has missing or invalid size array");
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isInt()) {
error(-1, "Illegal value in function size array");
goto err1;
}
sampleSize[i] = obj2.getInt();
obj2.free();
}
obj1.free();
//----- BitsPerSample
if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
error(-1, "Function has missing or invalid BitsPerSample");
goto err2;
}
sampleBits = obj1.getInt();
sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
obj1.free();
//----- Encode
if (dict->lookup("Encode", &obj1)->isArray() &&
obj1.arrayGetLength() == 2*m) {
for (i = 0; i < m; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function encode array");
goto err1;
}
encode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function encode array");
goto err1;
}
encode[i][1] = obj2.getNum();
obj2.free();
}
} else {
for (i = 0; i < m; ++i) {
encode[i][0] = 0;
encode[i][1] = sampleSize[i] - 1;
}
}
obj1.free();
//----- Decode
if (dict->lookup("Decode", &obj1)->isArray() &&
obj1.arrayGetLength() == 2*n) {
for (i = 0; i < n; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function decode array");
goto err1;
}
decode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function decode array");
goto err1;
}
decode[i][1] = obj2.getNum();
obj2.free();
}
} else {
for (i = 0; i < n; ++i) {
decode[i][0] = range[i][0];
decode[i][1] = range[i][1];
}
}
obj1.free();
//----- samples
nSamples = n;
for (i = 0; i < m; ++i)
nSamples *= sampleSize[i];
samples = (double *)gmalloc(nSamples * sizeof(double));
buf = 0;
bits = 0;
bitMask = (1 << sampleBits) - 1;
str->reset();
for (i = 0; i < nSamples; ++i) {
if (sampleBits == 8) {
s = str->getChar();
} else if (sampleBits == 16) {
s = str->getChar();
s = (s << 8) + str->getChar();
} else if (sampleBits == 32) {
s = str->getChar();
s = (s << 8) + str->getChar();
s = (s << 8) + str->getChar();
s = (s << 8) + str->getChar();
} else {
while (bits < sampleBits) {
buf = (buf << 8) | (str->getChar() & 0xff);
bits += 8;
}
s = (buf >> (bits - sampleBits)) & bitMask;
bits -= sampleBits;
}
samples[i] = (double)s * sampleMul;
}
ok = gTrue;
return;
err1:
obj2.free();
err2:
obj1.free();
err3:
return;
}
Function::Function(Function *func) {
int nSamples, i;
m = func->m;
n = func->n;
memcpy(domain, func->domain, sizeof(domain));
memcpy(range, func->range, sizeof(range));
memcpy(sampleSize, func->sampleSize, sizeof(sampleSize));
memcpy(encode, func->encode, sizeof(encode));
memcpy(decode, func->decode, sizeof(decode));
nSamples = n;
for (i = 0; i < m; ++i)
nSamples *= sampleSize[i];
samples = (double *)gmalloc(nSamples * sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
ok = gTrue;
}
Function::~Function() {
if (samples)
gfree(samples);
}
void Function::transform(double *in, double *out) {
double e[4];
double s;
double x0, x1;
int e0, e1;
double efrac;
int i;
// map input values into sample array
for (i = 0; i < m; ++i) {
e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
(encode[i][1] - encode[i][0]) + encode[i][0];
if (e[i] < 0)
e[i] = 0;
else if (e[i] > sampleSize[i] - 1)
e[i] = sampleSize[i] - 1;
}
for (i = 0; i < n; ++i) {
// m-linear interpolation
// (only m=1 is currently supported)
e0 = (int)floor(e[0]);
e1 = (int)ceil(e[0]);
efrac = e[0] - e0;
x0 = samples[e0 * n + i];
x1 = samples[e1 * n + i];
s = (1 - efrac) * x0 + efrac * x1;
// map output values to range
out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
if (out[i] < range[i][0])
out[i] = range[i][0];
else if (out[i] > range[i][1])
out[i] = range[i][1];
}
}
//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
GfxColorSpace *colorSpace1) {
GfxColor color;
double x[4];
int maxPixel;
Object obj;
int i, j;
ok = gTrue;
// bits per component and colorspace
bits = bits1;
maxPixel = (1 << bits) - 1;
colorSpace = colorSpace1;
mode = colorSpace->getMode();
// get decode map
if (decode->isNull()) {
if (colorSpace->isIndexed()) {
indexed = gTrue;
numComps = 1;
decodeLow[0] = 0;
decodeRange[0] = maxPixel;
} else {
indexed = gFalse;
numComps = colorSpace->getNumPixelComps();
for (i = 0; i < numComps; ++i) {
decodeLow[i] = 0;
decodeRange[i] = 1;
}
}
} else if (decode->isArray()) {
numComps = decode->arrayGetLength() / 2;
if (numComps != colorSpace->getNumPixelComps())
goto err1;
indexed = colorSpace->isIndexed();
for (i = 0; i < numComps; ++i) {
decode->arrayGet(2*i, &obj);
if (!obj.isNum())
goto err2;
decodeLow[i] = obj.getNum();
obj.free();
decode->arrayGet(2*i+1, &obj);
if (!obj.isNum())
goto err2;
decodeRange[i] = obj.getNum() - decodeLow[i];
obj.free();
}
} else {
goto err1;
}
// construct lookup table
lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double));
if (indexed) {
for (i = 0; i <= maxPixel; ++i) {
x[0] = (double)i;
colorSpace->getColor(x, &color);
lookup[i][0] = color.getR();
lookup[i][1] = color.getG();
lookup[i][2] = color.getB();
}
} else {
for (i = 0; i <= maxPixel; ++i)
for (j = 0; j < numComps; ++j)
lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
}
return;
err2:
obj.free();
err1:
ok = gFalse;
}
GfxImageColorMap::~GfxImageColorMap() {
delete colorSpace;
gfree(lookup);
}
void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
double *p;
if (indexed) {
p = lookup[x[0]];
color->setRGB(p[0], p[1], p[2]);
} else {
switch (mode) {
case colorGray:
color->setGray(lookup[x[0]][0]);
break;
case colorCMYK:
color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
lookup[x[2]][2], lookup[x[3]][3]);
break;
case colorRGB:
color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
break;
}
}
}
//------------------------------------------------------------------------
// GfxSubpath and GfxPath
//------------------------------------------------------------------------
GfxSubpath::GfxSubpath(double x1, double y1) {
size = 16;
x = (double *)gmalloc(size * sizeof(double));
y = (double *)gmalloc(size * sizeof(double));
curve = (GBool *)gmalloc(size * sizeof(GBool));
n = 1;
x[0] = x1;
y[0] = y1;
curve[0] = gFalse;
}
GfxSubpath::~GfxSubpath() {
gfree(x);
gfree(y);
gfree(curve);
}
// Used for copy().
GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
size = subpath->size;
n = subpath->n;
x = (double *)gmalloc(size * sizeof(double));
y = (double *)gmalloc(size * sizeof(double));
curve = (GBool *)gmalloc(size * sizeof(GBool));
memcpy(x, subpath->x, n * sizeof(double));
memcpy(y, subpath->y, n * sizeof(double));
memcpy(curve, subpath->curve, n * sizeof(GBool));
}
void GfxSubpath::lineTo(double x1, double y1) {
if (n >= size) {
size += 16;
x = (double *)grealloc(x, size * sizeof(double));
y = (double *)grealloc(y, size * sizeof(double));
curve = (GBool *)grealloc(curve, size * sizeof(GBool));
}
x[n] = x1;
y[n] = y1;
curve[n] = gFalse;
++n;
}
void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
double x3, double y3) {
if (n+3 > size) {
size += 16;
x = (double *)grealloc(x, size * sizeof(double));
y = (double *)grealloc(y, size * sizeof(double));
curve = (GBool *)grealloc(curve, size * sizeof(GBool));
}
x[n] = x1;
y[n] = y1;
x[n+1] = x2;
y[n+1] = y2;
x[n+2] = x3;
y[n+2] = y3;
curve[n] = curve[n+1] = gTrue;
curve[n+2] = gFalse;
n += 3;
}
GfxPath::GfxPath() {
justMoved = gFalse;
size = 16;
n = 0;
subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
}
GfxPath::~GfxPath() {
int i;
for (i = 0; i < n; ++i)
delete subpaths[i];
gfree(subpaths);
}
// Used for copy().
GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
GfxSubpath **subpaths1, int n1, int size1) {
int i;
justMoved = justMoved1;
firstX = firstX1;
firstY = firstY1;
size = size1;
n = n1;
subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
for (i = 0; i < n; ++i)
subpaths[i] = subpaths1[i]->copy();
}
void GfxPath::moveTo(double x, double y) {
justMoved = gTrue;
firstX = x;
firstY = y;
}
void GfxPath::lineTo(double x, double y) {
if (justMoved) {
if (n >= size) {
size += 16;
subpaths = (GfxSubpath **)
grealloc(subpaths, size * sizeof(GfxSubpath *));
}
subpaths[n] = new GfxSubpath(firstX, firstY);
++n;
justMoved = gFalse;
}
subpaths[n-1]->lineTo(x, y);
}
void GfxPath::curveTo(double x1, double y1, double x2, double y2,
double x3, double y3) {
if (justMoved) {
if (n >= size) {
size += 16;
subpaths = (GfxSubpath **)
grealloc(subpaths, size * sizeof(GfxSubpath *));
}
subpaths[n] = new GfxSubpath(firstX, firstY);
++n;
justMoved = gFalse;
}
subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
}
//------------------------------------------------------------------------
// GfxState
//------------------------------------------------------------------------
GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
int rotate, GBool upsideDown) {
double k;
px1 = px1a;
py1 = py1a;
px2 = px2a;
py2 = py2a;
k = (double)dpi / 72.0;
if (rotate == 90) {
ctm[0] = 0;
ctm[1] = upsideDown ? k : -k;
ctm[2] = k;
ctm[3] = 0;
ctm[4] = -k * py1;
ctm[5] = k * (upsideDown ? -px1 : px2);
pageWidth = (int)(k * (py2 - py1));
pageHeight = (int)(k * (px2 - px1));
} else if (rotate == 180) {
ctm[0] = -k;
ctm[1] = 0;
ctm[2] = 0;
ctm[3] = upsideDown ? k : -k;
ctm[4] = k * px2;
ctm[5] = k * (upsideDown ? -py1 : py2);
pageWidth = (int)(k * (px2 - px1));
pageHeight = (int)(k * (py2 - py1));
} else if (rotate == 270) {
ctm[0] = 0;
ctm[1] = upsideDown ? -k : k;
ctm[2] = -k;
ctm[3] = 0;
ctm[4] = k * py2;
ctm[5] = k * (upsideDown ? px2 : -px1);
pageWidth = (int)(k * (py2 - py1));
pageHeight = (int)(k * (px2 - px1));
} else {
ctm[0] = k;
ctm[1] = 0;
ctm[2] = 0;
ctm[3] = upsideDown ? -k : k;
ctm[4] = -k * px1;
ctm[5] = k * (upsideDown ? py2 : -py1);
pageWidth = (int)(k * (px2 - px1));
pageHeight = (int)(k * (py2 - py1));
}
fillColorSpace = new GfxColorSpace(colorGray);
strokeColorSpace = new GfxColorSpace(colorGray);
fillColor.setGray(0);
strokeColor.setGray(0);
lineWidth = 1;
lineDash = NULL;
lineDashLength = 0;
lineDashStart = 0;
flatness = 0;
lineJoin = 0;
lineCap = 0;
miterLimit = 10;
font = NULL;
fontSize = 0;
textMat[0] = 1; textMat[1] = 0;
textMat[2] = 0; textMat[3] = 1;
textMat[4] = 0; textMat[5] = 0;
charSpace = 0;
wordSpace = 0;
horizScaling = 1;
leading = 0;
rise = 0;
render = 0;
path = new GfxPath();
curX = curY = 0;
lineX = lineY = 0;
saved = NULL;
}
GfxState::~GfxState() {
if (fillColorSpace)
delete fillColorSpace;
if (strokeColorSpace)
delete strokeColorSpace;
gfree(lineDash);
delete path;
if (saved)
delete saved;
}
// Used for copy();
GfxState::GfxState(GfxState *state) {
memcpy(this, state, sizeof(GfxState));
if (fillColorSpace)
fillColorSpace = state->fillColorSpace->copy();
if (strokeColorSpace)
strokeColorSpace = state->strokeColorSpace->copy();
if (lineDashLength > 0) {
lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
}
path = state->path->copy();
saved = NULL;
}
double GfxState::transformWidth(double w) {
double x, y;
x = ctm[0] + ctm[2];
y = ctm[1] + ctm[3];
return w * sqrt(0.5 * (x * x + y * y));
}
double GfxState::getTransformedFontSize() {
double x1, y1, x2, y2;
x1 = textMat[2] * fontSize;
y1 = textMat[3] * fontSize;
x2 = ctm[0] * x1 + ctm[2] * y1;
y2 = ctm[1] * x1 + ctm[3] * y1;
return sqrt(x2 * x2 + y2 * y2);
}
void GfxState::getFontTransMat(double *m11, double *m12,
double *m21, double *m22) {
*m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
*m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
*m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
*m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
}
void GfxState::concatCTM(double a, double b, double c,
double d, double e, double f) {
double a1 = ctm[0];
double b1 = ctm[1];
double c1 = ctm[2];
double d1 = ctm[3];
ctm[0] = a * a1 + b * c1;
ctm[1] = a * b1 + b * d1;
ctm[2] = c * a1 + d * c1;
ctm[3] = c * b1 + d * d1;
ctm[4] = e * a1 + f * c1 + ctm[4];
ctm[5] = e * b1 + f * d1 + ctm[5];
}
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
if (fillColorSpace)
delete fillColorSpace;
fillColorSpace = colorSpace;
}
void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
if (strokeColorSpace)
delete strokeColorSpace;
strokeColorSpace = colorSpace;
}
void GfxState::setLineDash(double *dash, int length, double start) {
if (lineDash)
gfree(lineDash);
lineDash = dash;
lineDashLength = length;
lineDashStart = start;
}
void GfxState::clearPath() {
delete path;
path = new GfxPath();
}
void GfxState::textShift(double tx) {
double dx, dy;
textTransformDelta(tx, 0, &dx, &dy);
curX += dx;
curY += dy;
}
GfxState *GfxState::save() {
GfxState *newState;
newState = copy();
newState->saved = this;
return newState;
}
GfxState *GfxState::restore() {
GfxState *oldState;
if (saved) {
oldState = saved;
saved = NULL;
delete this;
} else {
oldState = this;
}
return oldState;
}