1 //========================================================================
5 // Copyright 2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
17 #include "goo/gfile.h"
18 #include "GlobalParams.h"
23 #include "CharCodeToUnicode.h"
24 #include "FontEncodingTables.h"
25 #include "fofi/FoFiTrueType.h"
26 #include "splash/SplashBitmap.h"
27 #include "splash/SplashGlyphBitmap.h"
28 #include "splash/SplashPattern.h"
29 #include "splash/SplashScreen.h"
30 #include "splash/SplashPath.h"
31 #include "splash/SplashState.h"
32 #include "splash/SplashErrorCodes.h"
33 #include "splash/SplashFontEngine.h"
34 #include "splash/SplashFont.h"
35 #include "splash/SplashFontFile.h"
36 #include "splash/SplashFontFileID.h"
37 #include "splash/Splash.h"
38 #include "SplashOutputDev.h"
40 //------------------------------------------------------------------------
42 //------------------------------------------------------------------------
44 static void splashOutBlendMultiply(SplashColorPtr src
, SplashColorPtr dest
,
45 SplashColorPtr blend
, SplashColorMode cm
) {
48 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
49 // note: floor(x / 255) = x >> 8 (for 16-bit x)
50 blend
[i
] = (dest
[i
] * src
[i
]) >> 8;
54 static void splashOutBlendScreen(SplashColorPtr src
, SplashColorPtr dest
,
55 SplashColorPtr blend
, SplashColorMode cm
) {
58 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
59 // note: floor(x / 255) = x >> 8 (for 16-bit x)
60 blend
[i
] = dest
[i
] + src
[i
] - ((dest
[i
] * src
[i
]) >> 8);
64 static void splashOutBlendOverlay(SplashColorPtr src
, SplashColorPtr dest
,
65 SplashColorPtr blend
, SplashColorMode cm
) {
68 //~ not sure if this is right
69 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
70 // note: floor(x / 255) = x >> 8 (for 16-bit x)
71 blend
[i
] = dest
[i
] < 0x80 ? ((dest
[i
] * src
[i
]) >> 8)
72 : dest
[i
] + src
[i
] - ((dest
[i
] * src
[i
]) >> 8);
76 static void splashOutBlendDarken(SplashColorPtr src
, SplashColorPtr dest
,
77 SplashColorPtr blend
, SplashColorMode cm
) {
80 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
81 blend
[i
] = dest
[i
] < src
[i
] ? dest
[i
] : src
[i
];
85 static void splashOutBlendLighten(SplashColorPtr src
, SplashColorPtr dest
,
86 SplashColorPtr blend
, SplashColorMode cm
) {
89 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
90 blend
[i
] = dest
[i
] > src
[i
] ? dest
[i
] : src
[i
];
94 static void splashOutBlendColorDodge(SplashColorPtr src
, SplashColorPtr dest
,
99 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
100 x
= dest
[i
] + src
[i
];
101 blend
[i
] = x
<= 255 ? x
: 255;
105 static void splashOutBlendColorBurn(SplashColorPtr src
, SplashColorPtr dest
,
106 SplashColorPtr blend
, SplashColorMode cm
) {
109 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
110 x
= dest
[i
] - (255 - src
[i
]);
111 blend
[i
] = x
>= 0 ? x
: 0;
115 static void splashOutBlendHardLight(SplashColorPtr src
, SplashColorPtr dest
,
116 SplashColorPtr blend
, SplashColorMode cm
) {
119 //~ not sure if this is right
120 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
121 // note: floor(x / 255) = x >> 8 (for 16-bit x)
122 blend
[i
] = src
[i
] < 0x80
123 ? ((dest
[i
] * (src
[i
] * 2)) >> 8)
124 : 0xff - (((0xff - dest
[i
]) * (0x1ff - src
[i
] * 2)) >> 8);
128 static void splashOutBlendSoftLight(SplashColorPtr src
, SplashColorPtr dest
,
129 SplashColorPtr blend
, SplashColorMode cm
) {
132 //~ not sure if this is right
133 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
135 x
= dest
[i
] - (0x80 - src
[i
]);
136 blend
[i
] = x
>= 0 ? x
: 0;
138 x
= dest
[i
] + (src
[i
] - 0x80);
139 blend
[i
] = x
<= 255 ? x
: 255;
144 static void splashOutBlendDifference(SplashColorPtr src
, SplashColorPtr dest
,
145 SplashColorPtr blend
,
146 SplashColorMode cm
) {
149 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
150 blend
[i
] = dest
[i
] < src
[i
] ? src
[i
] - dest
[i
] : dest
[i
] - src
[i
];
154 static void splashOutBlendExclusion(SplashColorPtr src
, SplashColorPtr dest
,
155 SplashColorPtr blend
, SplashColorMode cm
) {
158 //~ not sure what this is supposed to do
159 for (i
= 0; i
< splashColorModeNComps
[cm
]; ++i
) {
160 blend
[i
] = dest
[i
] < src
[i
] ? src
[i
] - dest
[i
] : dest
[i
] - src
[i
];
164 static void cvtRGBToHSV(Guchar r
, Guchar g
, Guchar b
, int *h
, int *s
, int *v
) {
165 int cmax
, cmid
, cmin
, x
;
168 if (g
>= b
) { x
= 0; cmax
= r
; cmid
= g
; cmin
= b
; }
169 else if (b
>= r
) { x
= 4; cmax
= b
; cmid
= r
; cmin
= g
; }
170 else { x
= 5; cmax
= r
; cmid
= b
; cmin
= g
; }
172 if (r
>= b
) { x
= 1; cmax
= g
; cmid
= r
; cmin
= b
; }
173 else if (g
>= b
) { x
= 2; cmax
= g
; cmid
= b
; cmin
= r
; }
174 else { x
= 3; cmax
= b
; cmid
= g
; cmin
= r
; }
181 *h
+= ((cmax
- cmid
) * 60) / (cmax
- cmin
);
183 *h
+= ((cmid
- cmin
) * 60) / (cmax
- cmin
);
185 *s
= (255 * (cmax
- cmin
)) / cmax
;
190 static void cvtHSVToRGB(int h
, int s
, int v
, Guchar
*r
, Guchar
*g
, Guchar
*b
) {
191 int x
, f
, cmax
, cmid
, cmin
;
200 cmid
= (v
* 255 - ((s
* f
) / 60)) >> 8;
202 cmid
= (v
* (255 - ((s
* (60 - f
)) / 60))) >> 8;
204 // note: floor(x / 255) = x >> 8 (for 16-bit x)
205 cmin
= (v
* (255 - s
)) >> 8;
207 case 0: *r
= cmax
; *g
= cmid
; *b
= cmin
; break;
208 case 1: *g
= cmax
; *r
= cmid
; *b
= cmin
; break;
209 case 2: *g
= cmax
; *b
= cmid
; *r
= cmin
; break;
210 case 3: *b
= cmax
; *g
= cmid
; *r
= cmin
; break;
211 case 4: *b
= cmax
; *r
= cmid
; *g
= cmin
; break;
212 case 5: *r
= cmax
; *b
= cmid
; *g
= cmin
; break;
217 static void splashOutBlendHue(SplashColorPtr src
, SplashColorPtr dest
,
218 SplashColorPtr blend
, SplashColorMode cm
) {
219 int hs
, ss
, vs
, hd
, sd
, vd
;
225 case splashModeMono1
:
226 case splashModeMono8
:
230 case splashModeRGB8Qt
:
231 cvtRGBToHSV(src
[0], src
[1], src
[2], &hs
, &ss
, &vs
);
232 cvtRGBToHSV(dest
[0], dest
[1], dest
[2], &hd
, &sd
, &vd
);
233 cvtHSVToRGB(hs
, sd
, vd
, &blend
[0], &blend
[1], &blend
[2]);
236 cvtRGBToHSV(src
[2], src
[1], src
[0], &hs
, &ss
, &vs
);
237 cvtRGBToHSV(dest
[2], dest
[1], dest
[0], &hd
, &sd
, &vd
);
238 cvtHSVToRGB(hs
, sd
, vd
, &blend
[2], &blend
[1], &blend
[0]);
241 case splashModeCMYK8
:
242 //~ (0xff - ...) should be clipped
243 cvtRGBToHSV(0xff - (src
[0] + src
[3]),
244 0xff - (src
[1] + src
[3]),
245 0xff - (src
[2] + src
[3]), &hs
, &ss
, &vs
);
246 cvtRGBToHSV(0xff - (dest
[0] + dest
[3]),
247 0xff - (dest
[1] + dest
[3]),
248 0xff - (dest
[2] + dest
[3]), &hd
, &sd
, &vd
);
249 cvtHSVToRGB(hs
, sd
, vd
, &r
, &g
, &b
);
250 //~ should do black generation
263 static void splashOutBlendSaturation(SplashColorPtr src
, SplashColorPtr dest
,
264 SplashColorPtr blend
,
265 SplashColorMode cm
) {
266 int hs
, ss
, vs
, hd
, sd
, vd
;
272 case splashModeMono1
:
273 case splashModeMono8
:
277 case splashModeRGB8Qt
:
278 cvtRGBToHSV(src
[0], src
[1], src
[2], &hs
, &ss
, &vs
);
279 cvtRGBToHSV(dest
[0], dest
[1], dest
[2], &hd
, &sd
, &vd
);
280 cvtHSVToRGB(hd
, ss
, vd
, &blend
[0], &blend
[1], &blend
[2]);
283 cvtRGBToHSV(src
[2], src
[1], src
[0], &hs
, &ss
, &vs
);
284 cvtRGBToHSV(dest
[2], dest
[1], dest
[0], &hd
, &sd
, &vd
);
285 cvtHSVToRGB(hd
, ss
, vd
, &blend
[2], &blend
[1], &blend
[0]);
288 case splashModeCMYK8
:
289 //~ (0xff - ...) should be clipped
290 cvtRGBToHSV(0xff - (src
[0] + src
[3]),
291 0xff - (src
[1] + src
[3]),
292 0xff - (src
[2] + src
[3]), &hs
, &ss
, &vs
);
293 cvtRGBToHSV(0xff - (dest
[0] + dest
[3]),
294 0xff - (dest
[1] + dest
[3]),
295 0xff - (dest
[2] + dest
[3]), &hd
, &sd
, &vd
);
296 cvtHSVToRGB(hd
, ss
, vd
, &r
, &g
, &b
);
297 //~ should do black generation
310 static void splashOutBlendColor(SplashColorPtr src
, SplashColorPtr dest
,
311 SplashColorPtr blend
, SplashColorMode cm
) {
312 int hs
, ss
, vs
, hd
, sd
, vd
;
318 case splashModeMono1
:
319 case splashModeMono8
:
323 case splashModeRGB8Qt
:
324 cvtRGBToHSV(src
[0], src
[1], src
[2], &hs
, &ss
, &vs
);
325 cvtRGBToHSV(dest
[0], dest
[1], dest
[2], &hd
, &sd
, &vd
);
326 cvtHSVToRGB(hs
, ss
, vd
, &blend
[0], &blend
[1], &blend
[2]);
329 cvtRGBToHSV(src
[2], src
[1], src
[0], &hs
, &ss
, &vs
);
330 cvtRGBToHSV(dest
[2], dest
[1], dest
[0], &hd
, &sd
, &vd
);
331 cvtHSVToRGB(hs
, ss
, vd
, &blend
[2], &blend
[1], &blend
[0]);
334 case splashModeCMYK8
:
335 //~ (0xff - ...) should be clipped
336 cvtRGBToHSV(0xff - (src
[0] + src
[3]),
337 0xff - (src
[1] + src
[3]),
338 0xff - (src
[2] + src
[3]), &hs
, &ss
, &vs
);
339 cvtRGBToHSV(0xff - (dest
[0] + dest
[3]),
340 0xff - (dest
[1] + dest
[3]),
341 0xff - (dest
[2] + dest
[3]), &hd
, &sd
, &vd
);
342 cvtHSVToRGB(hs
, ss
, vd
, &r
, &g
, &b
);
343 //~ should do black generation
356 static void splashOutBlendLuminosity(SplashColorPtr src
, SplashColorPtr dest
,
357 SplashColorPtr blend
,
358 SplashColorMode cm
) {
359 int hs
, ss
, vs
, hd
, sd
, vd
;
365 case splashModeMono1
:
366 case splashModeMono8
:
370 case splashModeRGB8Qt
:
371 cvtRGBToHSV(src
[0], src
[1], src
[2], &hs
, &ss
, &vs
);
372 cvtRGBToHSV(dest
[0], dest
[1], dest
[2], &hd
, &sd
, &vd
);
373 cvtHSVToRGB(hd
, sd
, vs
, &blend
[0], &blend
[1], &blend
[2]);
376 cvtRGBToHSV(src
[2], src
[1], src
[0], &hs
, &ss
, &vs
);
377 cvtRGBToHSV(dest
[2], dest
[1], dest
[0], &hd
, &sd
, &vd
);
378 cvtHSVToRGB(hd
, sd
, vs
, &blend
[2], &blend
[1], &blend
[0]);
381 case splashModeCMYK8
:
382 //~ (0xff - ...) should be clipped
383 cvtRGBToHSV(0xff - (src
[0] + src
[3]),
384 0xff - (src
[1] + src
[3]),
385 0xff - (src
[2] + src
[3]), &hs
, &ss
, &vs
);
386 cvtRGBToHSV(0xff - (dest
[0] + dest
[3]),
387 0xff - (dest
[1] + dest
[3]),
388 0xff - (dest
[2] + dest
[3]), &hd
, &sd
, &vd
);
389 cvtHSVToRGB(hd
, sd
, vs
, &r
, &g
, &b
);
390 //~ should do black generation
403 // NB: This must match the GfxBlendMode enum defined in GfxState.h.
404 SplashBlendFunc splashOutBlendFuncs
[] = {
406 &splashOutBlendMultiply
,
407 &splashOutBlendScreen
,
408 &splashOutBlendOverlay
,
409 &splashOutBlendDarken
,
410 &splashOutBlendLighten
,
411 &splashOutBlendColorDodge
,
412 &splashOutBlendColorBurn
,
413 &splashOutBlendHardLight
,
414 &splashOutBlendSoftLight
,
415 &splashOutBlendDifference
,
416 &splashOutBlendExclusion
,
418 &splashOutBlendSaturation
,
419 &splashOutBlendColor
,
420 &splashOutBlendLuminosity
423 //------------------------------------------------------------------------
424 // SplashOutFontFileID
425 //------------------------------------------------------------------------
427 class SplashOutFontFileID
: public SplashFontFileID
{
430 SplashOutFontFileID(Ref
*rA
) { r
= *rA
; }
432 ~SplashOutFontFileID() {}
434 GBool
matches(SplashFontFileID
*id
) {
435 return ((SplashOutFontFileID
*)id
)->r
.num
== r
.num
&&
436 ((SplashOutFontFileID
*)id
)->r
.gen
== r
.gen
;
444 //------------------------------------------------------------------------
446 //------------------------------------------------------------------------
448 struct T3FontCacheTag
{
450 Gushort mru
; // valid bit (0x8000) and MRU index
456 T3FontCache(Ref
*fontID
, double m11A
, double m12A
,
457 double m21A
, double m22A
,
458 int glyphXA
, int glyphYA
, int glyphWA
, int glyphHA
,
461 GBool
matches(Ref
*idA
, double m11A
, double m12A
,
462 double m21A
, double m22A
)
463 { return fontID
.num
== idA
->num
&& fontID
.gen
== idA
->gen
&&
464 m11
== m11A
&& m12
== m12A
&& m21
== m21A
&& m22
== m22A
; }
466 Ref fontID
; // PDF font ID
467 double m11
, m12
, m21
, m22
; // transform matrix
468 int glyphX
, glyphY
; // pixel offset of glyph bitmaps
469 int glyphW
, glyphH
; // size of glyph bitmaps, in pixels
470 int glyphSize
; // size of glyph bitmaps, in bytes
471 int cacheSets
; // number of sets in cache
472 int cacheAssoc
; // cache associativity (glyphs per set)
473 Guchar
*cacheData
; // glyph pixmap cache
474 T3FontCacheTag
*cacheTags
; // cache tags, i.e., char codes
477 T3FontCache::T3FontCache(Ref
*fontIDA
, double m11A
, double m12A
,
478 double m21A
, double m22A
,
479 int glyphXA
, int glyphYA
, int glyphWA
, int glyphHA
,
493 glyphSize
= glyphW
* glyphH
;
495 glyphSize
= ((glyphW
+ 7) >> 3) * glyphH
;
498 if (glyphSize
<= 256) {
500 } else if (glyphSize
<= 512) {
502 } else if (glyphSize
<= 1024) {
507 cacheData
= (Guchar
*)gmallocn(cacheSets
* cacheAssoc
, glyphSize
);
508 cacheTags
= (T3FontCacheTag
*)gmallocn(cacheSets
* cacheAssoc
,
509 sizeof(T3FontCacheTag
));
510 for (i
= 0; i
< cacheSets
* cacheAssoc
; ++i
) {
511 cacheTags
[i
].mru
= i
& (cacheAssoc
- 1);
515 T3FontCache::~T3FontCache() {
520 struct T3GlyphStack
{
521 Gushort code
; // character code
522 double x
, y
; // position to draw the glyph
525 T3FontCache
*cache
; // font cache for the current font
526 T3FontCacheTag
*cacheTag
; // pointer to cache tag for the glyph
527 Guchar
*cacheData
; // pointer to cache data for the glyph
530 SplashBitmap
*origBitmap
;
532 double origCTM4
, origCTM5
;
534 T3GlyphStack
*next
; // next object on stack
537 //------------------------------------------------------------------------
539 //------------------------------------------------------------------------
541 SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA
,
544 SplashColorPtr paperColorA
,
545 GBool bitmapTopDownA
,
546 GBool allowAntialiasA
) {
547 colorMode
= colorModeA
;
548 bitmapRowPad
= bitmapRowPadA
;
549 bitmapTopDown
= bitmapTopDownA
;
550 allowAntialias
= allowAntialiasA
;
551 reverseVideo
= reverseVideoA
;
552 splashColorCopy(paperColor
, paperColorA
);
556 bitmap
= new SplashBitmap(1, 1, bitmapRowPad
, colorMode
, bitmapTopDown
);
557 splash
= new Splash(bitmap
);
558 splash
->clear(paperColor
);
566 needFontUpdate
= gFalse
;
570 SplashOutputDev::~SplashOutputDev() {
573 for (i
= 0; i
< nT3Fonts
; ++i
) {
574 delete t3FontCache
[i
];
587 void SplashOutputDev::startDoc(XRef
*xrefA
) {
594 fontEngine
= new SplashFontEngine(
596 globalParams
->getEnableT1lib(),
598 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
599 globalParams
->getEnableFreeType(),
602 globalParams
->getAntialias() &&
603 colorMode
!= splashModeMono1
);
604 for (i
= 0; i
< nT3Fonts
; ++i
) {
605 delete t3FontCache
[i
];
610 void SplashOutputDev::startPage(int pageNum
, GfxState
*state
) {
614 w
= state
? (int)(state
->getPageWidth() + 0.5) : 1;
615 h
= state
? (int)(state
->getPageHeight() + 0.5) : 1;
620 if (!bitmap
|| w
!= bitmap
->getWidth() || h
!= bitmap
->getHeight()) {
624 bitmap
= new SplashBitmap(w
, h
, bitmapRowPad
, colorMode
, bitmapTopDown
);
626 splash
= new Splash(bitmap
);
628 case splashModeMono1
:
629 case splashModeMono8
:
634 case splashModeRGB8Qt
:
635 color
[0] = color
[1] = color
[2] = 0;
637 case splashModeAMono8
:
641 case splashModeARGB8
:
643 color
[1] = color
[2] = color
[3] = 0;
645 case splashModeBGRA8
:
646 color
[0] = color
[1] = color
[2] = 0;
650 case splashModeCMYK8
:
651 color
[0] = color
[1] = color
[2] = color
[3] = 0;
653 case splashModeACMYK8
:
655 color
[1] = color
[2] = color
[3] = color
[4] = 0;
659 splash
->setStrokePattern(new SplashSolidColor(color
));
660 splash
->setFillPattern(new SplashSolidColor(color
));
661 splash
->setLineCap(splashLineCapButt
);
662 splash
->setLineJoin(splashLineJoinMiter
);
663 splash
->setLineDash(NULL
, 0, 0);
664 splash
->setMiterLimit(10);
665 splash
->setFlatness(1);
666 splash
->clear(paperColor
);
669 void SplashOutputDev::endPage() {
672 void SplashOutputDev::drawLink(Link
*link
, Catalog
*catalog
) {
673 double x1
, y1
, x2
, y2
;
674 LinkBorderStyle
*borderStyle
;
683 SplashCoord dashList
[20];
687 link
->getRect(&x1
, &y1
, &x2
, &y2
);
688 borderStyle
= link
->getBorderStyle();
689 if (borderStyle
->getWidth() > 0) {
690 borderStyle
->getColor(&r
, &g
, &b
);
694 gray
= dblToCol(0.299 * r
+ 0.587 * g
+ 0.114 * b
);
695 if (gray
> gfxColorComp1
) {
696 gray
= gfxColorComp1
;
699 cmyk
.c
= gfxColorComp1
- rgb
.r
;
700 cmyk
.m
= gfxColorComp1
- rgb
.g
;
701 cmyk
.y
= gfxColorComp1
- rgb
.b
;
703 splash
->setStrokePattern(getColor(gray
, &rgb
, &cmyk
));
705 splash
->setStrokePattern(getColor(gray
, &rgb
));
707 splash
->setLineWidth((SplashCoord
)borderStyle
->getWidth());
708 borderStyle
->getDash(&dash
, &dashLength
);
709 if (borderStyle
->getType() == linkBorderDashed
&& dashLength
> 0) {
710 if (dashLength
> 20) {
713 for (i
= 0; i
< dashLength
; ++i
) {
714 dashList
[i
] = (SplashCoord
)dash
[i
];
716 splash
->setLineDash(dashList
, dashLength
, 0);
718 path
= new SplashPath();
719 if (borderStyle
->getType() == linkBorderUnderlined
) {
720 cvtUserToDev(x1
, y1
, &x
, &y
);
721 path
->moveTo((SplashCoord
)x
, (SplashCoord
)y
);
722 cvtUserToDev(x2
, y1
, &x
, &y
);
723 path
->lineTo((SplashCoord
)x
, (SplashCoord
)y
);
725 cvtUserToDev(x1
, y1
, &x
, &y
);
726 path
->moveTo((SplashCoord
)x
, (SplashCoord
)y
);
727 cvtUserToDev(x2
, y1
, &x
, &y
);
728 path
->lineTo((SplashCoord
)x
, (SplashCoord
)y
);
729 cvtUserToDev(x2
, y2
, &x
, &y
);
730 path
->lineTo((SplashCoord
)x
, (SplashCoord
)y
);
731 cvtUserToDev(x1
, y2
, &x
, &y
);
732 path
->lineTo((SplashCoord
)x
, (SplashCoord
)y
);
735 splash
->stroke(path
);
740 void SplashOutputDev::saveState(GfxState
*state
) {
744 void SplashOutputDev::restoreState(GfxState
*state
) {
745 splash
->restoreState();
746 needFontUpdate
= gTrue
;
749 void SplashOutputDev::updateAll(GfxState
*state
) {
750 updateLineDash(state
);
751 updateLineJoin(state
);
752 updateLineCap(state
);
753 updateLineWidth(state
);
754 updateFlatness(state
);
755 updateMiterLimit(state
);
756 updateFillColor(state
);
757 updateStrokeColor(state
);
758 needFontUpdate
= gTrue
;
761 void SplashOutputDev::updateCTM(GfxState
*state
, double m11
, double m12
,
762 double m21
, double m22
,
763 double m31
, double m32
) {
764 updateLineDash(state
);
765 updateLineJoin(state
);
766 updateLineCap(state
);
767 updateLineWidth(state
);
770 void SplashOutputDev::updateLineDash(GfxState
*state
) {
774 SplashCoord dash
[20];
778 state
->getLineDash(&dashPattern
, &dashLength
, &dashStart
);
779 if (dashLength
> 20) {
782 for (i
= 0; i
< dashLength
; ++i
) {
783 dash
[i
] = (SplashCoord
)state
->transformWidth(dashPattern
[i
]);
788 phase
= (SplashCoord
)state
->transformWidth(dashStart
);
789 splash
->setLineDash(dash
, dashLength
, phase
);
792 void SplashOutputDev::updateFlatness(GfxState
*state
) {
793 splash
->setFlatness(state
->getFlatness());
796 void SplashOutputDev::updateLineJoin(GfxState
*state
) {
797 splash
->setLineJoin(state
->getLineJoin());
800 void SplashOutputDev::updateLineCap(GfxState
*state
) {
801 splash
->setLineCap(state
->getLineCap());
804 void SplashOutputDev::updateMiterLimit(GfxState
*state
) {
805 splash
->setMiterLimit(state
->getMiterLimit());
808 void SplashOutputDev::updateLineWidth(GfxState
*state
) {
809 splash
->setLineWidth(state
->getTransformedLineWidth());
812 void SplashOutputDev::updateFillColor(GfxState
*state
) {
819 state
->getFillGray(&gray
);
820 state
->getFillRGB(&rgb
);
822 state
->getFillCMYK(&cmyk
);
823 splash
->setFillPattern(getColor(gray
, &rgb
, &cmyk
));
825 splash
->setFillPattern(getColor(gray
, &rgb
));
829 void SplashOutputDev::updateStrokeColor(GfxState
*state
) {
836 state
->getStrokeGray(&gray
);
837 state
->getStrokeRGB(&rgb
);
839 state
->getStrokeCMYK(&cmyk
);
840 splash
->setStrokePattern(getColor(gray
, &rgb
, &cmyk
));
842 splash
->setStrokePattern(getColor(gray
, &rgb
));
847 SplashPattern
*SplashOutputDev::getColor(GfxGray gray
, GfxRGB
*rgb
,
850 SplashPattern
*SplashOutputDev::getColor(GfxGray gray
, GfxRGB
*rgb
) {
852 SplashPattern
*pattern
;
853 SplashColor color0
, color1
;
854 GfxColorComp r
, g
, b
;
857 gray
= gfxColorComp1
- gray
;
858 r
= gfxColorComp1
- rgb
->r
;
859 g
= gfxColorComp1
- rgb
->g
;
860 b
= gfxColorComp1
- rgb
->b
;
867 pattern
= NULL
; // make gcc happy
869 case splashModeMono1
:
872 pattern
= new SplashHalftone(color0
, color1
,
873 splash
->getScreen()->copy(),
874 (SplashCoord
)colToDbl(gray
));
876 case splashModeMono8
:
877 color1
[0] = colToByte(gray
);
878 pattern
= new SplashSolidColor(color1
);
880 case splashModeAMono8
:
882 color1
[1] = colToByte(gray
);
883 pattern
= new SplashSolidColor(color1
);
886 case splashModeRGB8Qt
:
887 color1
[0] = colToByte(r
);
888 color1
[1] = colToByte(g
);
889 color1
[2] = colToByte(b
);
890 pattern
= new SplashSolidColor(color1
);
893 color1
[2] = colToByte(r
);
894 color1
[1] = colToByte(g
);
895 color1
[0] = colToByte(b
);
896 pattern
= new SplashSolidColor(color1
);
898 case splashModeARGB8
:
900 color1
[1] = colToByte(r
);
901 color1
[2] = colToByte(g
);
902 color1
[3] = colToByte(b
);
903 pattern
= new SplashSolidColor(color1
);
905 case splashModeBGRA8
:
907 color1
[2] = colToByte(r
);
908 color1
[1] = colToByte(g
);
909 color1
[0] = colToByte(b
);
910 pattern
= new SplashSolidColor(color1
);
913 case splashModeCMYK8
:
914 color1
[0] = colToByte(cmyk
->c
);
915 color1
[1] = colToByte(cmyk
->m
);
916 color1
[2] = colToByte(cmyk
->y
);
917 color1
[3] = colToByte(cmyk
->k
);
918 pattern
= new SplashSolidColor(color1
);
920 case splashModeACMYK8
:
922 color1
[1] = colToByte(cmyk
->c
);
923 color1
[2] = colToByte(cmyk
->m
);
924 color1
[3] = colToByte(cmyk
->y
);
925 color1
[4] = colToByte(cmyk
->k
);
926 pattern
= new SplashSolidColor(color1
);
934 void SplashOutputDev::updateBlendMode(GfxState
*state
) {
935 splash
->setBlendFunc(splashOutBlendFuncs
[state
->getBlendMode()]);
938 void SplashOutputDev::updateFillOpacity(GfxState
*state
) {
939 splash
->setFillAlpha((SplashCoord
)state
->getFillOpacity());
942 void SplashOutputDev::updateStrokeOpacity(GfxState
*state
) {
943 splash
->setStrokeAlpha((SplashCoord
)state
->getStrokeOpacity());
946 void SplashOutputDev::updateFont(GfxState
*state
) {
948 GfxFontType fontType
;
949 SplashOutFontFileID
*id
;
950 SplashFontFile
*fontFile
;
951 SplashFontSrc
*fontsrc
= NULL
;
954 Object refObj
, strObj
;
959 DisplayFontParam
*dfp
;
960 CharCodeToUnicode
*ctu
;
961 double m11
, m12
, m21
, m22
;
964 int substIdx
, n
, code
, cmap
;
967 needFontUpdate
= gFalse
;
975 if (!(gfxFont
= state
->getFont())) {
978 fontType
= gfxFont
->getType();
979 if (fontType
== fontType3
) {
983 // check the font file cache
984 id
= new SplashOutFontFileID(gfxFont
->getID());
985 if ((fontFile
= fontEngine
->getFontFile(id
))) {
990 // if there is an embedded font, write it to disk
991 if (gfxFont
->getEmbeddedFontID(&embRef
)) {
992 tmpBuf
= gfxFont
->readEmbFontFile(xref
, &tmpBufLen
);
995 // if there is an external font file, use it
996 } else if (!(fileName
= gfxFont
->getExtFontFile())) {
998 // look for a display font mapping or a substitute font
1000 if (gfxFont
->getName()) {
1001 dfp
= globalParams
->getDisplayFont(gfxFont
);
1004 error(-1, "Couldn't find a font for '%s'",
1005 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1009 switch (dfp
->kind
) {
1011 fileName
= dfp
->t1
.fileName
;
1012 fontType
= gfxFont
->isCIDFont() ? fontCIDType0
: fontType1
;
1015 fileName
= dfp
->tt
.fileName
;
1016 fontType
= gfxFont
->isCIDFont() ? fontCIDType2
: fontTrueType
;
1017 faceIndex
= dfp
->tt
.faceIndex
;
1022 fontsrc
= new SplashFontSrc
;
1024 fontsrc
->setFile(fileName
, gFalse
);
1026 fontsrc
->setBuf(tmpBuf
, tmpBufLen
, gTrue
);
1028 // load the font file
1031 fontFile
= fontEngine
->loadType1Font(id
, fontsrc
,
1032 ((Gfx8BitFont
*)gfxFont
)->getEncoding());
1034 error(-1, "Couldn't create a font for '%s'",
1035 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1041 fontFile
= fontEngine
->loadType1CFont(id
, fontsrc
,
1042 ((Gfx8BitFont
*)gfxFont
)->getEncoding());
1044 error(-1, "Couldn't create a font for '%s'",
1045 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1052 ff
= FoFiTrueType::load(fileName
->getCString());
1054 ff
= new FoFiTrueType(tmpBuf
, tmpBufLen
, gFalse
);
1056 codeToGID
= ((Gfx8BitFont
*)gfxFont
)->getCodeToGIDMap(ff
);
1063 if (!(fontFile
= fontEngine
->loadTrueTypeFont(
1067 error(-1, "Couldn't create a font for '%s'",
1068 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1075 fontFile
= fontEngine
->loadCIDFont(id
, fontsrc
);
1077 error(-1, "Couldn't create a font for '%s'",
1078 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1087 // create a CID-to-GID mapping, via Unicode
1088 if ((ctu
= ((GfxCIDFont
*)gfxFont
)->getToUnicode())) {
1090 ff
= FoFiTrueType::load(fileName
->getCString());
1092 ff
= new FoFiTrueType(tmpBuf
, tmpBufLen
, gFalse
);
1094 // look for a Unicode cmap
1095 for (cmap
= 0; cmap
< ff
->getNumCmaps(); ++cmap
) {
1096 if ((ff
->getCmapPlatform(cmap
) == 3 &&
1097 ff
->getCmapEncoding(cmap
) == 1) ||
1098 ff
->getCmapPlatform(cmap
) == 0) {
1102 if (cmap
< ff
->getNumCmaps()) {
1103 // map CID -> Unicode -> GID
1104 n
= ctu
->getLength();
1105 codeToGID
= (Gushort
*)gmallocn(n
, sizeof(Gushort
));
1106 for (code
= 0; code
< n
; ++code
) {
1107 if (ctu
->mapToUnicode(code
, uBuf
, 8) > 0) {
1108 codeToGID
[code
] = ff
->mapCodeToGID(cmap
, uBuf
[0]);
1110 codeToGID
[code
] = 0;
1118 error(-1, "Couldn't find a mapping to Unicode for font '%s'",
1119 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1123 if (((GfxCIDFont
*)gfxFont
)->getCIDToGID()) {
1124 n
= ((GfxCIDFont
*)gfxFont
)->getCIDToGIDLen();
1126 codeToGID
= (Gushort
*)gmallocn(n
, sizeof(Gushort
));
1127 memcpy(codeToGID
, ((GfxCIDFont
*)gfxFont
)->getCIDToGID(),
1128 n
* sizeof(Gushort
));
1131 ff
= FoFiTrueType::load(fileName
->getCString());
1133 ff
= new FoFiTrueType(tmpBuf
, tmpBufLen
, gFalse
);
1136 codeToGID
= ((GfxCIDFont
*)gfxFont
)->getCodeToGIDMap(ff
, &n
);
1141 if (!(fontFile
= fontEngine
->loadTrueTypeFont(
1147 error(-1, "Couldn't create a font for '%s'",
1148 gfxFont
->getName() ? gfxFont
->getName()->getCString()
1154 // this shouldn't happen
1159 // get the font matrix
1160 state
->getFontTransMat(&m11
, &m12
, &m21
, &m22
);
1161 m11
*= state
->getHorizScaling();
1162 m12
*= state
->getHorizScaling();
1164 // create the scaled font
1165 mat
[0] = m11
; mat
[1] = -m12
;
1166 mat
[2] = m21
; mat
[3] = -m22
;
1167 if (fabs(mat
[0] * mat
[3] - mat
[1] * mat
[2]) < 0.01) {
1168 // avoid a singular (or close-to-singular) matrix
1169 mat
[0] = 0.01; mat
[1] = 0;
1170 mat
[2] = 0; mat
[3] = 0.01;
1172 font
= fontEngine
->getFont(fontFile
, mat
);
1174 if (fontsrc
&& !fontsrc
->isFile
)
1181 if (fontsrc
&& !fontsrc
->isFile
)
1186 void SplashOutputDev::stroke(GfxState
*state
) {
1189 path
= convertPath(state
, state
->getPath());
1190 splash
->stroke(path
);
1194 void SplashOutputDev::fill(GfxState
*state
) {
1197 path
= convertPath(state
, state
->getPath());
1198 splash
->fill(path
, gFalse
);
1202 void SplashOutputDev::eoFill(GfxState
*state
) {
1205 path
= convertPath(state
, state
->getPath());
1206 splash
->fill(path
, gTrue
);
1210 void SplashOutputDev::clip(GfxState
*state
) {
1213 path
= convertPath(state
, state
->getPath());
1214 splash
->clipToPath(path
, gFalse
);
1218 void SplashOutputDev::eoClip(GfxState
*state
) {
1221 path
= convertPath(state
, state
->getPath());
1222 splash
->clipToPath(path
, gTrue
);
1226 SplashPath
*SplashOutputDev::convertPath(GfxState
*state
, GfxPath
*path
) {
1228 GfxSubpath
*subpath
;
1229 double x1
, y1
, x2
, y2
, x3
, y3
;
1232 sPath
= new SplashPath();
1233 for (i
= 0; i
< path
->getNumSubpaths(); ++i
) {
1234 subpath
= path
->getSubpath(i
);
1235 if (subpath
->getNumPoints() > 0) {
1236 state
->transform(subpath
->getX(0), subpath
->getY(0), &x1
, &y1
);
1237 sPath
->moveTo((SplashCoord
)x1
, (SplashCoord
)y1
);
1239 while (j
< subpath
->getNumPoints()) {
1240 if (subpath
->getCurve(j
)) {
1241 state
->transform(subpath
->getX(j
), subpath
->getY(j
), &x1
, &y1
);
1242 state
->transform(subpath
->getX(j
+1), subpath
->getY(j
+1), &x2
, &y2
);
1243 state
->transform(subpath
->getX(j
+2), subpath
->getY(j
+2), &x3
, &y3
);
1244 sPath
->curveTo((SplashCoord
)x1
, (SplashCoord
)y1
,
1245 (SplashCoord
)x2
, (SplashCoord
)y2
,
1246 (SplashCoord
)x3
, (SplashCoord
)y3
);
1249 state
->transform(subpath
->getX(j
), subpath
->getY(j
), &x1
, &y1
);
1250 sPath
->lineTo((SplashCoord
)x1
, (SplashCoord
)y1
);
1254 if (subpath
->isClosed()) {
1262 void SplashOutputDev::drawChar(GfxState
*state
, double x
, double y
,
1263 double dx
, double dy
,
1264 double originX
, double originY
,
1265 CharCode code
, int nBytes
,
1266 Unicode
*u
, int uLen
) {
1271 if (needFontUpdate
) {
1278 // check for invisible text -- this is used by Acrobat Capture
1279 render
= state
->getRender();
1286 state
->transform(x
, y
, &x1
, &y1
);
1289 if (!(render
& 1)) {
1290 splash
->fillChar((SplashCoord
)x1
, (SplashCoord
)y1
, code
, font
);
1294 if ((render
& 3) == 1 || (render
& 3) == 2) {
1295 if ((path
= font
->getGlyphPath(code
))) {
1296 path
->offset((SplashCoord
)x1
, (SplashCoord
)y1
);
1297 splash
->stroke(path
);
1304 path
= font
->getGlyphPath(code
);
1305 path
->offset((SplashCoord
)x1
, (SplashCoord
)y1
);
1307 textClipPath
->append(path
);
1310 textClipPath
= path
;
1315 GBool
SplashOutputDev::beginType3Char(GfxState
*state
, double x
, double y
,
1316 double dx
, double dy
,
1317 CharCode code
, Unicode
*u
, int uLen
) {
1321 T3FontCache
*t3Font
;
1323 double x1
, y1
, xMin
, yMin
, xMax
, yMax
, xt
, yt
;
1326 if (!(gfxFont
= state
->getFont())) {
1329 fontID
= gfxFont
->getID();
1330 ctm
= state
->getCTM();
1331 state
->transform(0, 0, &xt
, &yt
);
1333 // is it the first (MRU) font in the cache?
1334 if (!(nT3Fonts
> 0 &&
1335 t3FontCache
[0]->matches(fontID
, ctm
[0], ctm
[1], ctm
[2], ctm
[3]))) {
1337 // is the font elsewhere in the cache?
1338 for (i
= 1; i
< nT3Fonts
; ++i
) {
1339 if (t3FontCache
[i
]->matches(fontID
, ctm
[0], ctm
[1], ctm
[2], ctm
[3])) {
1340 t3Font
= t3FontCache
[i
];
1341 for (j
= i
; j
> 0; --j
) {
1342 t3FontCache
[j
] = t3FontCache
[j
- 1];
1344 t3FontCache
[0] = t3Font
;
1348 if (i
>= nT3Fonts
) {
1350 // create new entry in the font cache
1351 if (nT3Fonts
== splashOutT3FontCacheSize
) {
1352 delete t3FontCache
[nT3Fonts
- 1];
1355 for (j
= nT3Fonts
; j
> 0; --j
) {
1356 t3FontCache
[j
] = t3FontCache
[j
- 1];
1359 bbox
= gfxFont
->getFontBBox();
1360 if (bbox
[0] == 0 && bbox
[1] == 0 && bbox
[2] == 0 && bbox
[3] == 0) {
1361 // broken bounding box -- just take a guess
1367 state
->transform(bbox
[0], bbox
[1], &x1
, &y1
);
1370 state
->transform(bbox
[0], bbox
[3], &x1
, &y1
);
1373 } else if (x1
> xMax
) {
1378 } else if (y1
> yMax
) {
1381 state
->transform(bbox
[2], bbox
[1], &x1
, &y1
);
1384 } else if (x1
> xMax
) {
1389 } else if (y1
> yMax
) {
1392 state
->transform(bbox
[2], bbox
[3], &x1
, &y1
);
1395 } else if (x1
> xMax
) {
1400 } else if (y1
> yMax
) {
1404 t3FontCache
[0] = new T3FontCache(fontID
, ctm
[0], ctm
[1], ctm
[2], ctm
[3],
1405 (int)floor(xMin
- xt
),
1406 (int)floor(yMin
- yt
),
1407 (int)ceil(xMax
) - (int)floor(xMin
) + 3,
1408 (int)ceil(yMax
) - (int)floor(yMin
) + 3,
1409 colorMode
!= splashModeMono1
);
1412 t3Font
= t3FontCache
[0];
1414 // is the glyph in the cache?
1415 i
= (code
& (t3Font
->cacheSets
- 1)) * t3Font
->cacheAssoc
;
1416 for (j
= 0; j
< t3Font
->cacheAssoc
; ++j
) {
1417 if ((t3Font
->cacheTags
[i
+j
].mru
& 0x8000) &&
1418 t3Font
->cacheTags
[i
+j
].code
== code
) {
1419 drawType3Glyph(t3Font
, &t3Font
->cacheTags
[i
+j
],
1420 t3Font
->cacheData
+ (i
+j
) * t3Font
->glyphSize
,
1426 // push a new Type 3 glyph record
1427 t3gs
= new T3GlyphStack();
1428 t3gs
->next
= t3GlyphStack
;
1429 t3GlyphStack
= t3gs
;
1430 t3GlyphStack
->code
= code
;
1431 t3GlyphStack
->x
= xt
;
1432 t3GlyphStack
->y
= yt
;
1433 t3GlyphStack
->cache
= t3Font
;
1434 t3GlyphStack
->cacheTag
= NULL
;
1435 t3GlyphStack
->cacheData
= NULL
;
1440 void SplashOutputDev::endType3Char(GfxState
*state
) {
1444 if (t3GlyphStack
->cacheTag
) {
1445 memcpy(t3GlyphStack
->cacheData
, bitmap
->getDataPtr(),
1446 t3GlyphStack
->cache
->glyphSize
);
1449 bitmap
= t3GlyphStack
->origBitmap
;
1450 splash
= t3GlyphStack
->origSplash
;
1451 ctm
= state
->getCTM();
1452 state
->setCTM(ctm
[0], ctm
[1], ctm
[2], ctm
[3],
1453 t3GlyphStack
->origCTM4
, t3GlyphStack
->origCTM5
);
1454 drawType3Glyph(t3GlyphStack
->cache
,
1455 t3GlyphStack
->cacheTag
, t3GlyphStack
->cacheData
,
1456 t3GlyphStack
->x
, t3GlyphStack
->y
);
1458 t3gs
= t3GlyphStack
;
1459 t3GlyphStack
= t3gs
->next
;
1463 void SplashOutputDev::type3D0(GfxState
*state
, double wx
, double wy
) {
1466 void SplashOutputDev::type3D1(GfxState
*state
, double wx
, double wy
,
1467 double llx
, double lly
, double urx
, double ury
) {
1469 T3FontCache
*t3Font
;
1471 double xt
, yt
, xMin
, xMax
, yMin
, yMax
, x1
, y1
;
1474 t3Font
= t3GlyphStack
->cache
;
1476 // check for a valid bbox
1477 state
->transform(0, 0, &xt
, &yt
);
1478 state
->transform(llx
, lly
, &x1
, &y1
);
1481 state
->transform(llx
, ury
, &x1
, &y1
);
1484 } else if (x1
> xMax
) {
1489 } else if (y1
> yMax
) {
1492 state
->transform(urx
, lly
, &x1
, &y1
);
1495 } else if (x1
> xMax
) {
1500 } else if (y1
> yMax
) {
1503 state
->transform(urx
, ury
, &x1
, &y1
);
1506 } else if (x1
> xMax
) {
1511 } else if (y1
> yMax
) {
1514 if (xMin
- xt
< t3Font
->glyphX
||
1515 yMin
- yt
< t3Font
->glyphY
||
1516 xMax
- xt
> t3Font
->glyphX
+ t3Font
->glyphW
||
1517 yMax
- yt
> t3Font
->glyphY
+ t3Font
->glyphH
) {
1518 error(-1, "Bad bounding box in Type 3 glyph");
1522 // allocate a cache entry
1523 i
= (t3GlyphStack
->code
& (t3Font
->cacheSets
- 1)) * t3Font
->cacheAssoc
;
1524 for (j
= 0; j
< t3Font
->cacheAssoc
; ++j
) {
1525 if ((t3Font
->cacheTags
[i
+j
].mru
& 0x7fff) == t3Font
->cacheAssoc
- 1) {
1526 t3Font
->cacheTags
[i
+j
].mru
= 0x8000;
1527 t3Font
->cacheTags
[i
+j
].code
= t3GlyphStack
->code
;
1528 t3GlyphStack
->cacheTag
= &t3Font
->cacheTags
[i
+j
];
1529 t3GlyphStack
->cacheData
= t3Font
->cacheData
+ (i
+j
) * t3Font
->glyphSize
;
1531 ++t3Font
->cacheTags
[i
+j
].mru
;
1536 t3GlyphStack
->origBitmap
= bitmap
;
1537 t3GlyphStack
->origSplash
= splash
;
1538 ctm
= state
->getCTM();
1539 t3GlyphStack
->origCTM4
= ctm
[4];
1540 t3GlyphStack
->origCTM5
= ctm
[5];
1542 // create the temporary bitmap
1543 if (colorMode
== splashModeMono1
) {
1544 bitmap
= new SplashBitmap(t3Font
->glyphW
, t3Font
->glyphH
, 1,
1546 splash
= new Splash(bitmap
);
1548 splash
->clear(color
);
1551 bitmap
= new SplashBitmap(t3Font
->glyphW
, t3Font
->glyphH
, 1,
1553 splash
= new Splash(bitmap
);
1555 splash
->clear(color
);
1558 splash
->setFillPattern(new SplashSolidColor(color
));
1559 splash
->setStrokePattern(new SplashSolidColor(color
));
1560 //~ this should copy other state from t3GlyphStack->origSplash?
1561 state
->setCTM(ctm
[0], ctm
[1], ctm
[2], ctm
[3],
1562 -t3Font
->glyphX
, -t3Font
->glyphY
);
1565 void SplashOutputDev::drawType3Glyph(T3FontCache
*t3Font
,
1566 T3FontCacheTag
*tag
, Guchar
*data
,
1567 double x
, double y
) {
1568 SplashGlyphBitmap glyph
;
1570 glyph
.x
= -t3Font
->glyphX
;
1571 glyph
.y
= -t3Font
->glyphY
;
1572 glyph
.w
= t3Font
->glyphW
;
1573 glyph
.h
= t3Font
->glyphH
;
1574 glyph
.aa
= colorMode
!= splashModeMono1
;
1576 glyph
.freeData
= gFalse
;
1577 splash
->fillGlyph((SplashCoord
)x
, (SplashCoord
)y
, &glyph
);
1580 void SplashOutputDev::endTextObject(GfxState
*state
) {
1582 splash
->clipToPath(textClipPath
, gFalse
);
1583 delete textClipPath
;
1584 textClipPath
= NULL
;
1588 struct SplashOutImageMaskData
{
1589 ImageStream
*imgStr
;
1591 int width
, height
, y
;
1594 GBool
SplashOutputDev::imageMaskSrc(void *data
, SplashColorPtr line
) {
1595 SplashOutImageMaskData
*imgMaskData
= (SplashOutImageMaskData
*)data
;
1600 if (imgMaskData
->y
== imgMaskData
->height
) {
1603 for (x
= 0, p
= imgMaskData
->imgStr
->getLine(), q
= line
;
1604 x
< imgMaskData
->width
;
1606 *q
++ = *p
++ ^ imgMaskData
->invert
;
1612 void SplashOutputDev::drawImageMask(GfxState
*state
, Object
*ref
, Stream
*str
,
1613 int width
, int height
, GBool invert
,
1617 SplashOutImageMaskData imgMaskData
;
1619 ctm
= state
->getCTM();
1624 mat
[4] = ctm
[2] + ctm
[4];
1625 mat
[5] = ctm
[3] + ctm
[5];
1627 imgMaskData
.imgStr
= new ImageStream(str
, width
, 1, 1);
1628 imgMaskData
.imgStr
->reset();
1629 imgMaskData
.invert
= invert
? 0 : 1;
1630 imgMaskData
.width
= width
;
1631 imgMaskData
.height
= height
;
1634 splash
->fillImageMask(&imageMaskSrc
, &imgMaskData
, width
, height
, mat
);
1636 while (imgMaskData
.y
< height
) {
1637 imgMaskData
.imgStr
->getLine();
1642 delete imgMaskData
.imgStr
;
1646 struct SplashOutImageData
{
1647 ImageStream
*imgStr
;
1648 GfxImageColorMap
*colorMap
;
1649 SplashColorPtr lookup
;
1651 SplashColorMode colorMode
;
1652 int width
, height
, y
;
1655 GBool
SplashOutputDev::imageSrc(void *data
, SplashColorPtr line
) {
1656 SplashOutImageData
*imgData
= (SplashOutImageData
*)data
;
1658 SplashColorPtr q
, col
;
1666 if (imgData
->y
== imgData
->height
) {
1670 nComps
= imgData
->colorMap
->getNumPixelComps();
1672 if (imgData
->lookup
) {
1673 switch (imgData
->colorMode
) {
1674 case splashModeMono1
:
1675 case splashModeMono8
:
1676 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1679 *q
++ = imgData
->lookup
[*p
];
1682 case splashModeRGB8
:
1683 case splashModeBGR8
:
1684 case splashModeRGB8Qt
:
1685 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1688 col
= &imgData
->lookup
[3 * *p
];
1695 case splashModeCMYK8
:
1696 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1699 col
= &imgData
->lookup
[4 * *p
];
1707 case splashModeAMono8
:
1708 case splashModeARGB8
:
1709 case splashModeBGRA8
:
1711 case splashModeACMYK8
:
1717 switch (imgData
->colorMode
) {
1718 case splashModeMono1
:
1719 case splashModeMono8
:
1720 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1723 imgData
->colorMap
->getGray(p
, &gray
);
1724 *q
++ = colToByte(gray
);
1727 case splashModeRGB8
:
1728 case splashModeRGB8Qt
:
1729 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1732 imgData
->colorMap
->getRGB(p
, &rgb
);
1733 *q
++ = colToByte(rgb
.r
);
1734 *q
++ = colToByte(rgb
.g
);
1735 *q
++ = colToByte(rgb
.b
);
1738 case splashModeBGR8
:
1739 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1742 imgData
->colorMap
->getRGB(p
, &rgb
);
1743 *q
++ = colToByte(rgb
.b
);
1744 *q
++ = colToByte(rgb
.g
);
1745 *q
++ = colToByte(rgb
.r
);
1749 case splashModeCMYK8
:
1750 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1753 imgData
->colorMap
->getCMYK(p
, &cmyk
);
1754 *q
++ = colToByte(cmyk
.c
);
1755 *q
++ = colToByte(cmyk
.m
);
1756 *q
++ = colToByte(cmyk
.y
);
1757 *q
++ = colToByte(cmyk
.k
);
1761 case splashModeAMono8
:
1762 case splashModeARGB8
:
1763 case splashModeBGRA8
:
1765 case splashModeACMYK8
:
1776 GBool
SplashOutputDev::alphaImageSrc(void *data
, SplashColorPtr line
) {
1777 SplashOutImageData
*imgData
= (SplashOutImageData
*)data
;
1779 SplashColorPtr q
, col
;
1788 if (imgData
->y
== imgData
->height
) {
1792 nComps
= imgData
->colorMap
->getNumPixelComps();
1794 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
1798 for (i
= 0; i
< nComps
; ++i
) {
1799 if (p
[i
] < imgData
->maskColors
[2*i
] ||
1800 p
[i
] > imgData
->maskColors
[2*i
+1]) {
1805 if (imgData
->lookup
) {
1806 switch (imgData
->colorMode
) {
1807 case splashModeMono1
:
1808 case splashModeMono8
:
1810 *q
++ = imgData
->lookup
[*p
];
1812 case splashModeRGB8
:
1813 case splashModeRGB8Qt
:
1815 col
= &imgData
->lookup
[3 * *p
];
1820 case splashModeBGR8
:
1821 col
= &imgData
->lookup
[3 * *p
];
1828 case splashModeCMYK8
:
1830 col
= &imgData
->lookup
[4 * *p
];
1837 case splashModeAMono8
:
1838 case splashModeARGB8
:
1839 case splashModeBGRA8
:
1841 case splashModeACMYK8
:
1847 switch (imgData
->colorMode
) {
1848 case splashModeMono1
:
1849 case splashModeMono8
:
1850 imgData
->colorMap
->getGray(p
, &gray
);
1852 *q
++ = colToByte(gray
);
1854 case splashModeRGB8
:
1855 case splashModeRGB8Qt
:
1856 imgData
->colorMap
->getRGB(p
, &rgb
);
1858 *q
++ = colToByte(rgb
.r
);
1859 *q
++ = colToByte(rgb
.g
);
1860 *q
++ = colToByte(rgb
.b
);
1862 case splashModeBGR8
:
1863 imgData
->colorMap
->getRGB(p
, &rgb
);
1864 *q
++ = colToByte(rgb
.b
);
1865 *q
++ = colToByte(rgb
.g
);
1866 *q
++ = colToByte(rgb
.r
);
1870 case splashModeCMYK8
:
1871 imgData
->colorMap
->getCMYK(p
, &cmyk
);
1873 *q
++ = colToByte(cmyk
.c
);
1874 *q
++ = colToByte(cmyk
.m
);
1875 *q
++ = colToByte(cmyk
.y
);
1876 *q
++ = colToByte(cmyk
.k
);
1879 case splashModeAMono8
:
1880 case splashModeARGB8
:
1881 case splashModeBGRA8
:
1883 case splashModeACMYK8
:
1895 void SplashOutputDev::drawImage(GfxState
*state
, Object
*ref
, Stream
*str
,
1896 int width
, int height
,
1897 GfxImageColorMap
*colorMap
,
1898 int *maskColors
, GBool inlineImg
) {
1901 SplashOutImageData imgData
;
1902 SplashColorMode srcMode
;
1903 SplashImageSource src
;
1912 ctm
= state
->getCTM();
1917 mat
[4] = ctm
[2] + ctm
[4];
1918 mat
[5] = ctm
[3] + ctm
[5];
1920 imgData
.imgStr
= new ImageStream(str
, width
,
1921 colorMap
->getNumPixelComps(),
1922 colorMap
->getBits());
1923 imgData
.imgStr
->reset();
1924 imgData
.colorMap
= colorMap
;
1925 imgData
.maskColors
= maskColors
;
1926 imgData
.colorMode
= colorMode
;
1927 imgData
.width
= width
;
1928 imgData
.height
= height
;
1931 // special case for one-channel (monochrome/gray/separation) images:
1932 // build a lookup table here
1933 imgData
.lookup
= NULL
;
1934 if (colorMap
->getNumPixelComps() == 1) {
1935 n
= 1 << colorMap
->getBits();
1936 switch (colorMode
) {
1937 case splashModeMono1
:
1938 case splashModeMono8
:
1939 imgData
.lookup
= (SplashColorPtr
)gmalloc(n
);
1940 for (i
= 0; i
< n
; ++i
) {
1942 colorMap
->getGray(&pix
, &gray
);
1943 imgData
.lookup
[i
] = colToByte(gray
);
1946 case splashModeRGB8
:
1947 case splashModeRGB8Qt
:
1948 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
1949 for (i
= 0; i
< n
; ++i
) {
1951 colorMap
->getRGB(&pix
, &rgb
);
1952 imgData
.lookup
[3*i
] = colToByte(rgb
.r
);
1953 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
1954 imgData
.lookup
[3*i
+2] = colToByte(rgb
.b
);
1957 case splashModeBGR8
:
1958 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
1959 for (i
= 0; i
< n
; ++i
) {
1961 colorMap
->getRGB(&pix
, &rgb
);
1962 imgData
.lookup
[3*i
] = colToByte(rgb
.b
);
1963 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
1964 imgData
.lookup
[3*i
+2] = colToByte(rgb
.r
);
1968 case splashModeCMYK8
:
1969 imgData
.lookup
= (SplashColorPtr
)gmalloc(4 * n
);
1970 for (i
= 0; i
< n
; ++i
) {
1972 colorMap
->getCMYK(&pix
, &cmyk
);
1973 imgData
.lookup
[4*i
] = colToByte(cmyk
.c
);
1974 imgData
.lookup
[4*i
+1] = colToByte(cmyk
.m
);
1975 imgData
.lookup
[4*i
+2] = colToByte(cmyk
.y
);
1976 imgData
.lookup
[4*i
+3] = colToByte(cmyk
.k
);
1986 switch (colorMode
) {
1987 case splashModeMono1
:
1988 case splashModeMono8
:
1989 srcMode
= maskColors
? splashModeAMono8
: splashModeMono8
;
1991 case splashModeRGB8
:
1992 case splashModeRGB8Qt
:
1993 srcMode
= maskColors
? splashModeARGB8
: splashModeRGB8
;
1995 case splashModeBGR8
:
1996 srcMode
= maskColors
? splashModeBGRA8
: splashModeBGR8
;
1999 case splashModeCMYK8
:
2000 srcMode
= maskColors
? splashModeACMYK8
: splashModeCMYK8
;
2005 srcMode
= splashModeRGB8
;
2008 src
= maskColors
? &alphaImageSrc
: &imageSrc
;
2009 splash
->drawImage(src
, &imgData
, srcMode
, width
, height
, mat
);
2011 while (imgData
.y
< height
) {
2012 imgData
.imgStr
->getLine();
2017 gfree(imgData
.lookup
);
2018 delete imgData
.imgStr
;
2022 struct SplashOutMaskedImageData
{
2023 ImageStream
*imgStr
;
2024 GfxImageColorMap
*colorMap
;
2026 SplashColorPtr lookup
;
2027 SplashColorMode colorMode
;
2028 int width
, height
, y
;
2031 GBool
SplashOutputDev::maskedImageSrc(void *data
, SplashColorPtr line
) {
2032 SplashOutMaskedImageData
*imgData
= (SplashOutMaskedImageData
*)data
;
2034 SplashColor maskColor
;
2035 SplashColorPtr q
, col
;
2044 if (imgData
->y
== imgData
->height
) {
2048 nComps
= imgData
->colorMap
->getNumPixelComps();
2050 for (x
= 0, p
= imgData
->imgStr
->getLine(), q
= line
;
2053 imgData
->mask
->getPixel(x
, imgData
->y
, maskColor
);
2054 alpha
= maskColor
[0] ? 0xff : 0x00;
2055 if (imgData
->lookup
) {
2056 switch (imgData
->colorMode
) {
2057 case splashModeMono1
:
2058 case splashModeMono8
:
2060 *q
++ = imgData
->lookup
[*p
];
2062 case splashModeRGB8
:
2063 case splashModeRGB8Qt
:
2065 col
= &imgData
->lookup
[3 * *p
];
2070 case splashModeBGR8
:
2071 col
= &imgData
->lookup
[3 * *p
];
2078 case splashModeCMYK8
:
2080 col
= &imgData
->lookup
[4 * *p
];
2087 case splashModeAMono8
:
2088 case splashModeARGB8
:
2089 case splashModeBGRA8
:
2091 case splashModeACMYK8
:
2097 switch (imgData
->colorMode
) {
2098 case splashModeMono1
:
2099 case splashModeMono8
:
2100 imgData
->colorMap
->getGray(p
, &gray
);
2102 *q
++ = colToByte(gray
);
2104 case splashModeRGB8
:
2105 case splashModeRGB8Qt
:
2106 imgData
->colorMap
->getRGB(p
, &rgb
);
2108 *q
++ = colToByte(rgb
.r
);
2109 *q
++ = colToByte(rgb
.g
);
2110 *q
++ = colToByte(rgb
.b
);
2112 case splashModeBGR8
:
2113 imgData
->colorMap
->getRGB(p
, &rgb
);
2114 *q
++ = colToByte(rgb
.b
);
2115 *q
++ = colToByte(rgb
.g
);
2116 *q
++ = colToByte(rgb
.r
);
2120 case splashModeCMYK8
:
2121 imgData
->colorMap
->getCMYK(p
, &cmyk
);
2123 *q
++ = colToByte(cmyk
.c
);
2124 *q
++ = colToByte(cmyk
.m
);
2125 *q
++ = colToByte(cmyk
.y
);
2126 *q
++ = colToByte(cmyk
.k
);
2129 case splashModeAMono8
:
2130 case splashModeARGB8
:
2131 case splashModeBGRA8
:
2133 case splashModeACMYK8
:
2145 void SplashOutputDev::drawMaskedImage(GfxState
*state
, Object
*ref
,
2146 Stream
*str
, int width
, int height
,
2147 GfxImageColorMap
*colorMap
,
2148 Stream
*maskStr
, int maskWidth
,
2149 int maskHeight
, GBool maskInvert
) {
2152 SplashOutMaskedImageData imgData
;
2153 SplashOutImageMaskData imgMaskData
;
2154 SplashColorMode srcMode
;
2155 SplashBitmap
*maskBitmap
;
2157 SplashColor maskColor
;
2166 //----- scale the mask image to the same size as the source image
2168 mat
[0] = (SplashCoord
)width
;
2171 mat
[3] = (SplashCoord
)height
;
2174 imgMaskData
.imgStr
= new ImageStream(maskStr
, maskWidth
, 1, 1);
2175 imgMaskData
.imgStr
->reset();
2176 imgMaskData
.invert
= maskInvert
? 0 : 1;
2177 imgMaskData
.width
= maskWidth
;
2178 imgMaskData
.height
= maskHeight
;
2180 maskBitmap
= new SplashBitmap(width
, height
, 1, splashModeMono1
);
2181 maskSplash
= new Splash(maskBitmap
);
2183 maskSplash
->clear(maskColor
);
2185 maskSplash
->setFillPattern(new SplashSolidColor(maskColor
));
2186 maskSplash
->fillImageMask(&imageMaskSrc
, &imgMaskData
,
2187 maskWidth
, maskHeight
, mat
);
2188 delete imgMaskData
.imgStr
;
2192 //----- draw the source image
2194 ctm
= state
->getCTM();
2199 mat
[4] = ctm
[2] + ctm
[4];
2200 mat
[5] = ctm
[3] + ctm
[5];
2202 imgData
.imgStr
= new ImageStream(str
, width
,
2203 colorMap
->getNumPixelComps(),
2204 colorMap
->getBits());
2205 imgData
.imgStr
->reset();
2206 imgData
.colorMap
= colorMap
;
2207 imgData
.mask
= maskBitmap
;
2208 imgData
.colorMode
= colorMode
;
2209 imgData
.width
= width
;
2210 imgData
.height
= height
;
2213 // special case for one-channel (monochrome/gray/separation) images:
2214 // build a lookup table here
2215 imgData
.lookup
= NULL
;
2216 if (colorMap
->getNumPixelComps() == 1) {
2217 n
= 1 << colorMap
->getBits();
2218 switch (colorMode
) {
2219 case splashModeMono1
:
2220 case splashModeMono8
:
2221 imgData
.lookup
= (SplashColorPtr
)gmalloc(n
);
2222 for (i
= 0; i
< n
; ++i
) {
2224 colorMap
->getGray(&pix
, &gray
);
2225 imgData
.lookup
[i
] = colToByte(gray
);
2228 case splashModeRGB8
:
2229 case splashModeRGB8Qt
:
2230 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
2231 for (i
= 0; i
< n
; ++i
) {
2233 colorMap
->getRGB(&pix
, &rgb
);
2234 imgData
.lookup
[3*i
] = colToByte(rgb
.r
);
2235 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
2236 imgData
.lookup
[3*i
+2] = colToByte(rgb
.b
);
2239 case splashModeBGR8
:
2240 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
2241 for (i
= 0; i
< n
; ++i
) {
2243 colorMap
->getRGB(&pix
, &rgb
);
2244 imgData
.lookup
[3*i
] = colToByte(rgb
.b
);
2245 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
2246 imgData
.lookup
[3*i
+2] = colToByte(rgb
.r
);
2250 case splashModeCMYK8
:
2251 imgData
.lookup
= (SplashColorPtr
)gmalloc(4 * n
);
2252 for (i
= 0; i
< n
; ++i
) {
2254 colorMap
->getCMYK(&pix
, &cmyk
);
2255 imgData
.lookup
[4*i
] = colToByte(cmyk
.c
);
2256 imgData
.lookup
[4*i
+1] = colToByte(cmyk
.m
);
2257 imgData
.lookup
[4*i
+2] = colToByte(cmyk
.y
);
2258 imgData
.lookup
[4*i
+3] = colToByte(cmyk
.k
);
2268 switch (colorMode
) {
2269 case splashModeMono1
:
2270 case splashModeMono8
:
2271 srcMode
= splashModeAMono8
;
2273 case splashModeRGB8
:
2274 case splashModeRGB8Qt
:
2275 srcMode
= splashModeARGB8
;
2277 case splashModeBGR8
:
2278 srcMode
= splashModeBGRA8
;
2281 case splashModeCMYK8
:
2282 srcMode
= splashModeACMYK8
;
2287 srcMode
= splashModeARGB8
;
2290 splash
->drawImage(&maskedImageSrc
, &imgData
, srcMode
, width
, height
, mat
);
2293 gfree(imgData
.lookup
);
2294 delete imgData
.imgStr
;
2298 void SplashOutputDev::drawSoftMaskedImage(GfxState
*state
, Object
*ref
,
2299 Stream
*str
, int width
, int height
,
2300 GfxImageColorMap
*colorMap
,
2302 int maskWidth
, int maskHeight
,
2303 GfxImageColorMap
*maskColorMap
) {
2306 SplashOutImageData imgData
;
2307 SplashOutImageData imgMaskData
;
2308 SplashColorMode srcMode
;
2309 SplashBitmap
*maskBitmap
;
2311 SplashColor maskColor
;
2320 ctm
= state
->getCTM();
2325 mat
[4] = ctm
[2] + ctm
[4];
2326 mat
[5] = ctm
[3] + ctm
[5];
2328 //----- set up the soft mask
2330 imgMaskData
.imgStr
= new ImageStream(maskStr
, maskWidth
,
2331 maskColorMap
->getNumPixelComps(),
2332 maskColorMap
->getBits());
2333 imgMaskData
.imgStr
->reset();
2334 imgMaskData
.colorMap
= maskColorMap
;
2335 imgMaskData
.maskColors
= NULL
;
2336 imgMaskData
.colorMode
= splashModeMono8
;
2337 imgMaskData
.width
= maskWidth
;
2338 imgMaskData
.height
= maskHeight
;
2340 n
= 1 << maskColorMap
->getBits();
2341 imgMaskData
.lookup
= (SplashColorPtr
)gmalloc(n
);
2342 for (i
= 0; i
< n
; ++i
) {
2344 maskColorMap
->getGray(&pix
, &gray
);
2345 imgMaskData
.lookup
[i
] = colToByte(gray
);
2347 maskBitmap
= new SplashBitmap(bitmap
->getWidth(), bitmap
->getHeight(),
2348 1, splashModeMono8
);
2349 maskSplash
= new Splash(maskBitmap
);
2351 maskSplash
->clear(maskColor
);
2352 maskSplash
->drawImage(&imageSrc
, &imgMaskData
,
2353 splashModeMono8
, maskWidth
, maskHeight
, mat
);
2354 delete imgMaskData
.imgStr
;
2356 gfree(imgMaskData
.lookup
);
2358 splash
->setSoftMask(maskBitmap
);
2360 //----- draw the source image
2362 imgData
.imgStr
= new ImageStream(str
, width
,
2363 colorMap
->getNumPixelComps(),
2364 colorMap
->getBits());
2365 imgData
.imgStr
->reset();
2366 imgData
.colorMap
= colorMap
;
2367 imgData
.maskColors
= NULL
;
2368 imgData
.colorMode
= colorMode
;
2369 imgData
.width
= width
;
2370 imgData
.height
= height
;
2373 // special case for one-channel (monochrome/gray/separation) images:
2374 // build a lookup table here
2375 imgData
.lookup
= NULL
;
2376 if (colorMap
->getNumPixelComps() == 1) {
2377 n
= 1 << colorMap
->getBits();
2378 switch (colorMode
) {
2379 case splashModeMono1
:
2380 case splashModeMono8
:
2381 imgData
.lookup
= (SplashColorPtr
)gmalloc(n
);
2382 for (i
= 0; i
< n
; ++i
) {
2384 colorMap
->getGray(&pix
, &gray
);
2385 imgData
.lookup
[i
] = colToByte(gray
);
2388 case splashModeRGB8
:
2389 case splashModeRGB8Qt
:
2390 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
2391 for (i
= 0; i
< n
; ++i
) {
2393 colorMap
->getRGB(&pix
, &rgb
);
2394 imgData
.lookup
[3*i
] = colToByte(rgb
.r
);
2395 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
2396 imgData
.lookup
[3*i
+2] = colToByte(rgb
.b
);
2399 case splashModeBGR8
:
2400 imgData
.lookup
= (SplashColorPtr
)gmalloc(3 * n
);
2401 for (i
= 0; i
< n
; ++i
) {
2403 colorMap
->getRGB(&pix
, &rgb
);
2404 imgData
.lookup
[3*i
] = colToByte(rgb
.b
);
2405 imgData
.lookup
[3*i
+1] = colToByte(rgb
.g
);
2406 imgData
.lookup
[3*i
+2] = colToByte(rgb
.r
);
2410 case splashModeCMYK8
:
2411 imgData
.lookup
= (SplashColorPtr
)gmalloc(4 * n
);
2412 for (i
= 0; i
< n
; ++i
) {
2414 colorMap
->getCMYK(&pix
, &cmyk
);
2415 imgData
.lookup
[4*i
] = colToByte(cmyk
.c
);
2416 imgData
.lookup
[4*i
+1] = colToByte(cmyk
.m
);
2417 imgData
.lookup
[4*i
+2] = colToByte(cmyk
.y
);
2418 imgData
.lookup
[4*i
+3] = colToByte(cmyk
.k
);
2428 switch (colorMode
) {
2429 case splashModeMono1
:
2430 case splashModeMono8
:
2431 srcMode
= splashModeMono8
;
2433 case splashModeRGB8
:
2434 case splashModeRGB8Qt
:
2435 srcMode
= splashModeRGB8
;
2437 case splashModeBGR8
:
2438 srcMode
= splashModeBGR8
;
2441 case splashModeCMYK8
:
2442 srcMode
= splashModeCMYK8
;
2447 srcMode
= splashModeRGB8
;
2450 splash
->drawImage(&imageSrc
, &imgData
, srcMode
, width
, height
, mat
);
2452 splash
->setSoftMask(NULL
);
2453 gfree(imgData
.lookup
);
2454 delete imgData
.imgStr
;
2458 void SplashOutputDev::setPaperColor(SplashColorPtr paperColorA
) {
2459 splashColorCopy(paperColor
, paperColorA
);
2462 int SplashOutputDev::getBitmapWidth() {
2463 return bitmap
->getWidth();
2466 int SplashOutputDev::getBitmapHeight() {
2467 return bitmap
->getHeight();
2470 SplashBitmap
*SplashOutputDev::takeBitmap() {
2474 bitmap
= new SplashBitmap(1, 1, bitmapRowPad
, colorMode
, bitmapTopDown
);
2478 void SplashOutputDev::getModRegion(int *xMin
, int *yMin
,
2479 int *xMax
, int *yMax
) {
2480 splash
->getModRegion(xMin
, yMin
, xMax
, yMax
);
2483 void SplashOutputDev::clearModRegion() {
2484 splash
->clearModRegion();
2487 void SplashOutputDev::setFillColor(int r
, int g
, int b
) {
2494 rgb
.r
= byteToCol(r
);
2495 rgb
.g
= byteToCol(g
);
2496 rgb
.b
= byteToCol(b
);
2497 gray
= (GfxColorComp
)(0.299 * rgb
.r
+ 0.587 * rgb
.g
+ 0.114 * rgb
.b
+ 0.5);
2498 if (gray
> gfxColorComp1
) {
2499 gray
= gfxColorComp1
;
2502 cmyk
.c
= gfxColorComp1
- rgb
.r
;
2503 cmyk
.m
= gfxColorComp1
- rgb
.g
;
2504 cmyk
.y
= gfxColorComp1
- rgb
.b
;
2506 splash
->setFillPattern(getColor(gray
, &rgb
, &cmyk
));
2508 splash
->setFillPattern(getColor(gray
, &rgb
));