PBMOutputDev.cpp
1//========================================================================
2//
3// PBMOutputDev.cpp
4//
5// Copyright 1998-2002 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <aconf.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <stddef.h>
18#include <string.h>
19#include "gmem.h"
20#include "GString.h"
21#include "Object.h"
22#include "Stream.h"
23#include "GfxState.h"
24#include "GfxFont.h"
25#include "Error.h"
26#include "PBMOutputDev.h"
27
28//------------------------------------------------------------------------
29
30PBMOutputDev *PBMOutputDev::makePBMOutputDev(char *displayName,
31 char *fileRootA) {
32 Display *displayA;
33 Pixmap pixmapA;
34 Window dummyWinA;
35 int screenA;
36 int invertA;
37 unsigned long black, white;
38 PBMOutputDev *out;
39
40 if (!(displayA = XOpenDisplay(displayName))) {
41 fprintf(stderr, "Couldn't open display '%s'\n", displayName);
42 exit(1);
43 }
44 screenA = DefaultScreen(displayA);
45
46 black = BlackPixel(displayA, screenA);
47 white = WhitePixel(displayA, screenA);
48 if ((black & 1) == (white & 1)) {
49 fprintf(stderr, "Weird black/white pixel colors\n");
50 XCloseDisplay(displayA);
51 return NULL;
52 }
53 invertA = (white & 1) == 1 ? 0xff : 0x00;
54
55 dummyWinA = XCreateSimpleWindow(displayA, RootWindow(displayA, screenA),
56 0, 0, 1, 1, 0,
57 black, white);
58 pixmapA = XCreatePixmap(displayA, dummyWinA, 1, 1, 1);
59 out = new PBMOutputDev(displayA, screenA, pixmapA, dummyWinA,
60 invertA, fileRootA);
61 return out;
62}
63
64void PBMOutputDev::killPBMOutputDev(PBMOutputDev *out) {
65 Display *displayA;
66 Pixmap pixmapA;
67 Window dummyWinA;
68
69 displayA = out->display;
70 pixmapA = out->pixmap;
71 dummyWinA = out->dummyWin;
72
73 delete out;
74
75 // these have to be done *after* the XOutputDev (parent of the
76 // PBMOutputDev) is deleted, since XOutputDev::~XOutputDev() needs
77 // them
78 XFreePixmap(displayA, pixmapA);
79 XDestroyWindow(displayA, dummyWinA);
80 XCloseDisplay(displayA);
81}
82
83PBMOutputDev::PBMOutputDev(Display *displayA, int screenA,
84 Pixmap pixmapA, Window dummyWinA,
85 int invertA, char *fileRootA):
86 XOutputDev(displayA, screenA,
87 DefaultVisual(displayA, screenA),
88 DefaultColormap(displayA, screenA),
89 gFalse,
90 WhitePixel(displayA, DefaultScreen(displayA)),
91 gFalse, 1, 1)
92{
93 display = displayA;
94 screen = screenA;
95 pixmap = pixmapA;
96 dummyWin = dummyWinA;
97 invert = invertA;
98 fileRoot = fileRootA;
99 fileName = (char *)gmalloc(strlen(fileRoot) + 20);
100}
101
102PBMOutputDev::~PBMOutputDev() {
103 gfree(fileName);
104}
105
106void PBMOutputDev::startPage(int pageNum, GfxState *state) {
107 curPage = pageNum;
108 width = (int)(state->getPageWidth() + 0.5);
109 height = (int)(state->getPageHeight() + 0.5);
110 XFreePixmap(display, pixmap);
111 pixmap = XCreatePixmap(display, dummyWin, width, height, 1);
112 setPixmap(pixmap, width, height);
113 XOutputDev::startPage(pageNum, state);
114}
115
116void PBMOutputDev::endPage() {
117 XImage *image;
118 FILE *f;
119 int p;
120 int x, y, i;
121
122 image = XCreateImage(display, DefaultVisual(display, screen),
123 1, ZPixmap, 0, NULL, width, height, 8, 0);
124 image->data = (char *)gmalloc(height * image->bytes_per_line);
125 XGetSubImage(display, pixmap, 0, 0, width, height, 1, ZPixmap,
126 image, 0, 0);
127
128 sprintf(fileName, "%s-%06d.pbm", fileRoot, curPage);
129 if (!(f = fopen(fileName, "wb"))) {
130 fprintf(stderr, "Couldn't open output file '%s'\n", fileName);
131 goto err;
132 }
133 fprintf(f, "P4\n");
134 fprintf(f, "%d %d\n", width, height);
135
136 for (y = 0; y < height; ++y) {
137 for (x = 0; x+8 <= width; x += 8) {
138 p = 0;
139 for (i = 0; i < 8; ++i)
140 p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
141 p ^= invert;
142 fputc((char)p, f);
143 }
144 if (width & 7) {
145 p = 0;
146 for (i = 0; i < (width & 7); ++i)
147 p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
148 p <<= 8 - (width & 7);
149 p ^= invert;
150 fputc((char)p, f);
151 }
152 }
153
154 fclose(f);
155
156 err:
157 gfree(image->data);
158 image->data = NULL;
159 XDestroyImage(image);
160
161 XOutputDev::endPage();
162}