1
// --------------------------------------------------------------------
2
// Output device writing XML stream
3
// --------------------------------------------------------------------
6
This file is part of the extensible drawing editor Ipe.
7
Copyright (C) 1993-2004 Otfried Cheong
9
Ipe is free software; you can redistribute it and/or modify it
10
under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
14
As a special exception, you have permission to link Ipe with the
15
CGAL library and distribute executables, as long as you follow the
16
requirements of the Gnu General Public License in regard to all of
17
the software in the executable aside from CGAL.
19
Ipe is distributed in the hope that it will be useful, but WITHOUT
20
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
22
License for more details.
24
You should have received a copy of the GNU General Public License
25
along with Ipe; if not, you can find it at
26
"http://www.gnu.org/copyleft/gpl.html", or write to the Free
27
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37
#include "globalparams.h"
43
#include "charcodetounicode.h"
44
#include "unicodemap.h"
49
#include "xmloutputdev.h"
54
// assignment in condition
58
//------------------------------------------------------------------------
60
//------------------------------------------------------------------------
62
XmlOutputDev::XmlOutputDev(char *fileName, XRef *xrefA, Catalog *,
63
int /* firstPage */, int /* lastPage */,
68
if (!(f = ocfopen(fileName, "w"))) {
69
error(-1, "Couldn't open output file '%s'", fileName);
81
writePSFmt("<ipe creator=\"pdftoipe %s\">\n", PDFTOIPE_VERSION);
82
// initialize sequential page number
86
XmlOutputDev::~XmlOutputDev()
95
// ----------------------------------------------------------
97
void XmlOutputDev::startPage(int pageNum, GfxState *state)
101
writePSFmt("<-- Page: %d %d -->\n", pageNum, seqPage);
103
// rotate, translate, and scale page
104
x1 = (int)(state->getX1() + 0.5);
105
y1 = (int)(state->getY1() + 0.5);
106
x2 = (int)(state->getX2() + 0.5);
107
y2 = (int)(state->getY2() + 0.5);
108
writePSFmt("<page mediabox=\"%d %d %d %d\">\n", x1, y1, x2, y2);
112
void XmlOutputDev::endPage()
115
writePS("</page>\n");
118
// --------------------------------------------------------------------
120
void XmlOutputDev::stroke(GfxState *state)
124
state->getStrokeRGB(&rgb);
125
writePSFmt("<path stroke=\"%g %g %g\"", rgb.r, rgb.g, rgb.b);
126
writePSFmt(" pen=\"%g\"", state->getTransformedLineWidth());
132
state->getLineDash(&dash, &length, &start);
134
writePS(" dash=\"[");
135
for (i = 0; i < length; ++i)
136
writePSFmt("%g%s", state->transformWidth(dash[i]),
137
(i == length-1) ? "" : " ");
138
writePSFmt("] %g\"", state->transformWidth(start));
141
if (state->getLineJoin() > 0)
142
writePSFmt(" join=\"%d\"", state->getLineJoin());
143
if (state->getLineCap())
144
writePSFmt(" cap=\"%d\"", state->getLineCap());
148
writePS("</path>\n");
151
void XmlOutputDev::fill(GfxState *state)
155
state->getFillRGB(&rgb);
156
writePSFmt("<path fill=\"%g %g %g\" fillrule=\"wind\">\n",
157
rgb.r, rgb.g, rgb.b);
159
writePS("</path>\n");
162
void XmlOutputDev::eoFill(GfxState *state)
166
state->getFillRGB(&rgb);
167
writePSFmt("<path fill=\"%g %g %g\">\n", rgb.r, rgb.g, rgb.b);
169
writePS("</path>\n");
172
void XmlOutputDev::doPath(GfxState *state)
174
GfxPath *path = state->getPath();
178
n = path->getNumSubpaths();
180
double x, y, x1, y1, x2, y2;
181
for (i = 0; i < n; ++i) {
182
subpath = path->getSubpath(i);
183
m = subpath->getNumPoints();
184
state->transform(subpath->getX(0), subpath->getY(0), &x, &y);
185
writePSFmt("%g %g m\n", x, y);
188
if (subpath->getCurve(j)) {
189
state->transform(subpath->getX(j), subpath->getY(j), &x, &y);
190
state->transform(subpath->getX(j+1), subpath->getY(j+1), &x1, &y1);
191
state->transform(subpath->getX(j+2), subpath->getY(j+2), &x2, &y2);
192
writePSFmt("%g %g %g %g %g %g c\n", x, y, x1, y1, x2, y2);
195
state->transform(subpath->getX(j), subpath->getY(j), &x, &y);
196
writePSFmt("%g %g l\n", x, y);
200
if (subpath->isClosed()) {
206
// --------------------------------------------------------------------
208
void XmlOutputDev::updateTextPos(GfxState *)
213
void XmlOutputDev::drawChar(GfxState *state, double /*x*/, double /*y*/,
214
double /*dx*/, double /*dy*/,
215
double /*originX*/, double /*originY*/,
216
CharCode, Unicode *u, int uLen)
218
// check for invisible text -- this is used by Acrobat Capture
219
if ((state->getRender() & 3) == 3) {
225
if (!(font = state->getFont())) {
228
(void) font; // placate compiler
233
mat = state->getTextMat();
234
double x = state->getLineX();
235
double y = state->getLineY();
236
// writePSFmt("%g %g %g %g %g %g %g %g\n",
237
// mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], x, y);
238
double tx = mat[0] * x + mat[2] * y + mat[4];
239
double ty = mat[1] * x + mat[3] * y + mat[5];
242
state->getFillRGB(&rgb);
244
writePSFmt("<text stroke=\"%g %g %g\" pos=\"%g %g\" size=\"normal\">",
245
rgb.r, rgb.g, rgb.b, tx, ty);
251
for (int i = 0; i < uLen; ++i)
255
void XmlOutputDev::finishText()
260
writePS("</text>\n");
265
// --------------------------------------------------------------------
267
void XmlOutputDev::drawImageMask(GfxState *, Object */*ref*/, Stream */*str*/,
268
int /*width*/, int /*height*/,
269
GBool /*invert*/, GBool /*inlineImg*/)
271
// mask is a one-bit image
272
// not yet implemented
275
void XmlOutputDev::drawImage(GfxState *state, Object * /*ref*/, Stream *str,
276
int width, int height, GfxImageColorMap *colorMap,
277
int * /*maskColors*/, GBool inlineImg)
285
writePSFmt("<image width=\"%d\" height=\"%d\"", width, height);
288
mat = state->getCTM();
289
double tx = mat[0] + mat[2] + mat[4];
290
double ty = mat[1] + mat[3] + mat[5];
291
writePSFmt(" rect=\"%g %g %g %g\"", mat[4], mat[5], tx, ty);
293
if (str->getKind() == strDCT && !inlineImg &&
294
3 <= colorMap->getNumPixelComps() && colorMap->getNumPixelComps() <= 4) {
296
std::vector<char> buffer;
298
str = ((DCTStream *)str)->getRawStream();
301
while ((c = str->getChar()) != EOF)
302
buffer.push_back(char(c));
305
if (colorMap->getNumPixelComps() == 3)
306
writePS(" ColorSpace=\"DeviceRGB\"");
308
writePS(" ColorSpace=\"DeviceCMYK\"");
309
writePS(" BitsPerComponent=\"8\"");
310
writePS(" Filter=\"DCTDecode\"");
311
writePSFmt(" length=\"%d\"", buffer.size());
314
for (unsigned int i = 0; i < buffer.size(); ++i)
315
writePSFmt("%02x", buffer[i] & 0xff);
318
} else if (colorMap->getNumPixelComps() == 1 && colorMap->getBits() == 1) {
319
// 1 bit depth -- not implemented in Ipe
324
size = height * ((width + 7) / 8);
325
for (i = 0; i < size; ++i) {
326
writePSFmt("%02x", (str->getChar() ^ 0xff));
330
} else if (colorMap->getNumPixelComps() == 1) {
331
// write as gray level image
332
writePS(" ColorSpace=\"DeviceGray\"");
333
writePS(" BitsPerComponent=\"8\"");
337
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
338
colorMap->getBits());
342
for (y = 0; y < height; ++y) {
345
p = imgStr->getLine();
346
for (x = 0; x < width; ++x) {
348
colorMap->getGray(p, &gray);
349
writePSFmt("%02x", (int)(gray * 255 + 0.5));
350
p += colorMap->getNumPixelComps();
356
// write as RGB image
357
writePS(" ColorSpace=\"DeviceRGB\"");
358
writePS(" BitsPerComponent=\"8\"");
362
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
363
colorMap->getBits());
367
for (y = 0; y < height; ++y) {
370
p = imgStr->getLine();
371
for (x = 0; x < width; ++x) {
372
colorMap->getRGB(p, &rgb);
373
writePSFmt("%02x", (int)(rgb.r * 255 + 0.5));
374
writePSFmt("%02x", (int)(rgb.g * 255 + 0.5));
375
writePSFmt("%02x", (int)(rgb.b * 255 + 0.5));
376
p += colorMap->getNumPixelComps();
381
writePS("\n</image>\n");
384
// --------------------------------------------------------------------
386
void XmlOutputDev::writePSChar(int code)
390
else if (code == '>')
392
else if (code == '&')
394
else if (code < 0x80)
395
writePSFmt("%c", code);
396
else if (code < 0x800) {
398
(((code & 0x7c0) >> 6) | 0xc0),
399
((code & 0x03f) | 0x80));
401
// Do we never need to write UCS larger than 0x10000?
403
(((code & 0x0f000) >> 12) | 0xe0),
404
(((code & 0xfc0) >> 6) | 0x80),
405
((code & 0x03f) | 0x80));
409
void XmlOutputDev::writePS(char *s)
411
fwrite(s, 1, strlen(s), outputStream);
414
void XmlOutputDev::writePSFmt(const char *fmt, ...)
420
vsprintf(buf, fmt, args);
422
fwrite(buf, 1, strlen(buf), outputStream);
425
// --------------------------------------------------------------------