1 //========================================================================
2 //
3 // PreScanOutputDev.cc
4 //
5 // Copyright 2005 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 #include <aconf.h>
10 
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14 
15 #include <math.h>
16 #include "GlobalParams.h"
17 #include "Page.h"
18 #include "Gfx.h"
19 #include "GfxFont.h"
20 #include "Link.h"
21 #include "PreScanOutputDev.h"
22 
23 //------------------------------------------------------------------------
24 // PreScanOutputDev
25 //------------------------------------------------------------------------
26 
PreScanOutputDev()27 PreScanOutputDev::PreScanOutputDev() {
28   clearStats();
29 }
30 
~PreScanOutputDev()31 PreScanOutputDev::~PreScanOutputDev() {
32 }
33 
startPage(int pageNum,GfxState * state)34 void PreScanOutputDev::startPage(int pageNum, GfxState *state) {
35 }
36 
endPage()37 void PreScanOutputDev::endPage() {
38 }
39 
stroke(GfxState * state)40 void PreScanOutputDev::stroke(GfxState *state) {
41   double *dash;
42   int dashLen;
43   double dashStart;
44 
45   check(state->getStrokeColorSpace(), state->getStrokeColor(),
46 	state->getStrokeOpacity(), state->getBlendMode());
47   state->getLineDash(&dash, &dashLen, &dashStart);
48   if (dashLen != 0) {
49     gdi = gFalse;
50   }
51 }
52 
fill(GfxState * state)53 void PreScanOutputDev::fill(GfxState *state) {
54   check(state->getFillColorSpace(), state->getFillColor(),
55 	state->getFillOpacity(), state->getBlendMode());
56 }
57 
eoFill(GfxState * state)58 void PreScanOutputDev::eoFill(GfxState *state) {
59   check(state->getFillColorSpace(), state->getFillColor(),
60 	state->getFillOpacity(), state->getBlendMode());
61 }
62 
tilingPatternFill(GfxState * state,Gfx * gfx,Object * strRef,int paintType,Dict * resDict,double * mat,double * bbox,int x0,int y0,int x1,int y1,double xStep,double yStep)63 void PreScanOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx,
64 					 Object *strRef,
65 					 int paintType, Dict *resDict,
66 					 double *mat, double *bbox,
67 					 int x0, int y0, int x1, int y1,
68 					 double xStep, double yStep) {
69   if (paintType == 1) {
70     gfx->drawForm(strRef, resDict, mat, bbox);
71   } else {
72     check(state->getFillColorSpace(), state->getFillColor(),
73 	  state->getFillOpacity(), state->getBlendMode());
74   }
75 }
76 
functionShadedFill(GfxState * state,GfxFunctionShading * shading)77 GBool PreScanOutputDev::functionShadedFill(GfxState *state,
78 					   GfxFunctionShading *shading) {
79   if (shading->getColorSpace()->getMode() != csDeviceGray &&
80       shading->getColorSpace()->getMode() != csCalGray) {
81     gray = gFalse;
82   }
83   mono = gFalse;
84   if (state->getFillOpacity() != 1 ||
85       state->getBlendMode() != gfxBlendNormal) {
86     transparency = gTrue;
87   }
88   return gTrue;
89 }
90 
axialShadedFill(GfxState * state,GfxAxialShading * shading)91 GBool PreScanOutputDev::axialShadedFill(GfxState *state,
92 					GfxAxialShading *shading) {
93   if (shading->getColorSpace()->getMode() != csDeviceGray &&
94       shading->getColorSpace()->getMode() != csCalGray) {
95     gray = gFalse;
96   }
97   mono = gFalse;
98   if (state->getFillOpacity() != 1 ||
99       state->getBlendMode() != gfxBlendNormal) {
100     transparency = gTrue;
101   }
102   return gTrue;
103 }
104 
radialShadedFill(GfxState * state,GfxRadialShading * shading)105 GBool PreScanOutputDev::radialShadedFill(GfxState *state,
106 					 GfxRadialShading *shading) {
107   if (shading->getColorSpace()->getMode() != csDeviceGray &&
108       shading->getColorSpace()->getMode() != csCalGray) {
109     gray = gFalse;
110   }
111   mono = gFalse;
112   if (state->getFillOpacity() != 1 ||
113       state->getBlendMode() != gfxBlendNormal) {
114     transparency = gTrue;
115   }
116   return gTrue;
117 }
118 
clip(GfxState * state)119 void PreScanOutputDev::clip(GfxState *state) {
120   //~ check for a rectangle "near" the edge of the page;
121   //~   else set gdi to false
122 }
123 
eoClip(GfxState * state)124 void PreScanOutputDev::eoClip(GfxState *state) {
125   //~ see clip()
126 }
127 
beginStringOp(GfxState * state)128 void PreScanOutputDev::beginStringOp(GfxState *state) {
129   int render;
130   GfxFont *font;
131   double m11, m12, m21, m22;
132   GBool simpleTTF;
133 
134   render = state->getRender();
135   if (!(render & 1)) {
136     check(state->getFillColorSpace(), state->getFillColor(),
137 	  state->getFillOpacity(), state->getBlendMode());
138   }
139   if ((render & 3) == 1 || (render & 3) == 2) {
140     check(state->getStrokeColorSpace(), state->getStrokeColor(),
141 	  state->getStrokeOpacity(), state->getBlendMode());
142   }
143 
144   font = state->getFont();
145   state->getFontTransMat(&m11, &m12, &m21, &m22);
146   //~ this should check for external fonts that are non-TrueType
147   simpleTTF = fabs(m11 + m22) < 0.01 &&
148               m11 > 0 &&
149               fabs(m12) < 0.01 &&
150               fabs(m21) < 0.01 &&
151               fabs(state->getHorizScaling() - 1) < 0.001 &&
152               (font->getType() == fontTrueType ||
153 	       font->getType() == fontTrueTypeOT);
154   if (simpleTTF) {
155     //~ need to create a FoFiTrueType object, and check for a Unicode cmap
156   }
157   if (state->getRender() != 0 || !simpleTTF) {
158     gdi = gFalse;
159   }
160 }
161 
endStringOp(GfxState * state)162 void PreScanOutputDev::endStringOp(GfxState *state) {
163 }
164 
beginType3Char(GfxState * state,double x,double y,double dx,double dy,CharCode code,Unicode * u,int uLen)165 GBool PreScanOutputDev::beginType3Char(GfxState *state, double x, double y,
166 				       double dx, double dy,
167 				       CharCode code, Unicode *u, int uLen) {
168   // return false so all Type 3 chars get rendered (no caching)
169   return gFalse;
170 }
171 
endType3Char(GfxState * state)172 void PreScanOutputDev::endType3Char(GfxState *state) {
173 }
174 
drawImageMask(GfxState * state,Object * ref,Stream * str,int width,int height,GBool invert,GBool inlineImg,GBool interpolate)175 void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
176 				     int width, int height, GBool invert,
177 				     GBool inlineImg, GBool interpolate) {
178   check(state->getFillColorSpace(), state->getFillColor(),
179 	state->getFillOpacity(), state->getBlendMode());
180   if (state->getFillColorSpace()->getMode() == csPattern) {
181     patternImgMask = gTrue;
182   }
183   gdi = gFalse;
184 
185   if (inlineImg) {
186     str->reset();
187     str->discardChars(height * ((width + 7) / 8));
188     str->close();
189   }
190 }
191 
drawImage(GfxState * state,Object * ref,Stream * str,int width,int height,GfxImageColorMap * colorMap,int * maskColors,GBool inlineImg,GBool interpolate)192 void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
193 				 int width, int height,
194 				 GfxImageColorMap *colorMap,
195 				 int *maskColors, GBool inlineImg,
196 				 GBool interpolate) {
197   GfxColorSpace *colorSpace;
198 
199   colorSpace = colorMap->getColorSpace();
200   if (colorSpace->getMode() == csIndexed) {
201     colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
202   }
203   if (colorSpace->getMode() == csDeviceGray ||
204       colorSpace->getMode() == csCalGray) {
205     if (colorMap->getBits() > 1) {
206       mono = gFalse;
207     }
208   } else {
209     gray = gFalse;
210     mono = gFalse;
211   }
212   if (state->getFillOpacity() != 1 ||
213       state->getBlendMode() != gfxBlendNormal) {
214     transparency = gTrue;
215   }
216   gdi = gFalse;
217 
218   if (inlineImg) {
219     str->reset();
220     str->discardChars(height * ((width * colorMap->getNumPixelComps() *
221 				 colorMap->getBits() + 7) / 8));
222     str->close();
223   }
224 }
225 
drawMaskedImage(GfxState * state,Object * ref,Stream * str,int width,int height,GfxImageColorMap * colorMap,Stream * maskStr,int maskWidth,int maskHeight,GBool maskInvert,GBool interpolate)226 void PreScanOutputDev::drawMaskedImage(GfxState *state, Object *ref,
227 				       Stream *str,
228 				       int width, int height,
229 				       GfxImageColorMap *colorMap,
230 				       Stream *maskStr,
231 				       int maskWidth, int maskHeight,
232 				       GBool maskInvert, GBool interpolate) {
233   GfxColorSpace *colorSpace;
234 
235   colorSpace = colorMap->getColorSpace();
236   if (colorSpace->getMode() == csIndexed) {
237     colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
238   }
239   if (colorSpace->getMode() == csDeviceGray ||
240       colorSpace->getMode() == csCalGray) {
241     if (colorMap->getBits() > 1) {
242       mono = gFalse;
243     }
244   } else {
245     gray = gFalse;
246     mono = gFalse;
247   }
248   if (state->getFillOpacity() != 1 ||
249       state->getBlendMode() != gfxBlendNormal) {
250     transparency = gTrue;
251   }
252   gdi = gFalse;
253 }
254 
drawSoftMaskedImage(GfxState * state,Object * ref,Stream * str,int width,int height,GfxImageColorMap * colorMap,Stream * maskStr,int maskWidth,int maskHeight,GfxImageColorMap * maskColorMap,GBool interpolate)255 void PreScanOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
256 					   Stream *str,
257 					   int width, int height,
258 					   GfxImageColorMap *colorMap,
259 					   Stream *maskStr,
260 					   int maskWidth, int maskHeight,
261 					   GfxImageColorMap *maskColorMap,
262 					   GBool interpolate) {
263   GfxColorSpace *colorSpace;
264 
265   colorSpace = colorMap->getColorSpace();
266   if (colorSpace->getMode() == csIndexed) {
267     colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
268   }
269   if (colorSpace->getMode() != csDeviceGray &&
270       colorSpace->getMode() != csCalGray) {
271     gray = gFalse;
272   }
273   mono = gFalse;
274   transparency = gTrue;
275   gdi = gFalse;
276 }
277 
beginTransparencyGroup(GfxState * state,double * bbox,GfxColorSpace * blendingColorSpace,GBool isolated,GBool knockout,GBool forSoftMask)278 void PreScanOutputDev::beginTransparencyGroup(
279 			   GfxState *state, double *bbox,
280 			   GfxColorSpace *blendingColorSpace,
281 			   GBool isolated, GBool knockout,
282 			   GBool forSoftMask) {
283   transparency = gTrue;
284   gdi = gFalse;
285 }
286 
check(GfxColorSpace * colorSpace,GfxColor * color,double opacity,GfxBlendMode blendMode)287 void PreScanOutputDev::check(GfxColorSpace *colorSpace, GfxColor *color,
288 			     double opacity, GfxBlendMode blendMode) {
289   GfxRGB rgb;
290 
291   if (colorSpace->getMode() == csPattern) {
292     mono = gFalse;
293     gray = gFalse;
294     gdi = gFalse;
295   } else {
296     colorSpace->getRGB(color, &rgb);
297     if (rgb.r != rgb.g || rgb.g != rgb.b || rgb.b != rgb.r) {
298       mono = gFalse;
299       gray = gFalse;
300     } else if (!((rgb.r == 0 && rgb.g == 0 && rgb.b == 0) ||
301 		 (rgb.r == gfxColorComp1 &&
302 		  rgb.g == gfxColorComp1 &&
303 		  rgb.b == gfxColorComp1))) {
304       mono = gFalse;
305     }
306   }
307   if (opacity != 1 || blendMode != gfxBlendNormal) {
308     transparency = gTrue;
309   }
310 }
311 
clearStats()312 void PreScanOutputDev::clearStats() {
313   mono = gTrue;
314   gray = gTrue;
315   transparency = gFalse;
316   patternImgMask = gFalse;
317   gdi = gTrue;
318 }
319