3
// Based SplashOutputDev.cc : Copyright 2003 Glyph & Cog, LLC
5
// Copyright 2005 AXE,Inc.
7
// 2007,2008 Modified by BBR Inc.
8
//========================================================================
11
#ifdef HAVE_CPP_POPPLER_VERSION_H
12
#include "cpp/poppler-version.h"
15
#ifdef USE_GCC_PRAGMAS
16
#pragma implementation
21
#include "goo/gfile.h"
22
#include "GlobalParams.h"
23
#include "OPVPError.h"
28
#include "CharCodeToUnicode.h"
29
#include "FontEncodingTables.h"
30
#include "fofi/FoFiTrueType.h"
31
#include "splash/SplashMath.h"
33
#include "splash/SplashBitmap.h"
34
#include "splash/SplashGlyphBitmap.h"
35
#include "splash/SplashPattern.h"
36
#include "splash/SplashScreen.h"
37
#include "splash/SplashErrorCodes.h"
38
#include "splash/SplashFontEngine.h"
39
#include "splash/SplashFont.h"
40
#include "splash/SplashFontFile.h"
41
#include "splash/SplashFontFileID.h"
42
#include "OPVPSplashPath.h"
43
#include "OPVPSplashState.h"
45
#include "OPVPOutputDev.h"
47
#define SLICE_FOR_PATTERN 1000
49
//------------------------------------------------------------------------
51
//------------------------------------------------------------------------
53
struct SplashOutFontSubst {
58
//------------------------------------------------------------------------
60
#define soutRound(x) ((int)(x + 0.5))
62
//------------------------------------------------------------------------
63
// SplashOutFontFileID
64
//------------------------------------------------------------------------
66
class SplashOutFontFileID: public SplashFontFileID {
69
SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; }
71
~SplashOutFontFileID() {}
73
GBool matches(SplashFontFileID *id) {
74
return ((SplashOutFontFileID *)id)->r.num == r.num &&
75
((SplashOutFontFileID *)id)->r.gen == r.gen;
78
void setSubstIdx(int substIdxA) { substIdx = substIdxA; }
79
int getSubstIdx() { return substIdx; }
87
//------------------------------------------------------------------------
89
//------------------------------------------------------------------------
91
struct T3FontCacheTag {
93
Gushort mru; // valid bit (0x8000) and MRU index
99
T3FontCache(Ref *fontID, double m11A, double m12A,
100
double m21A, double m22A,
101
int glyphXA, int glyphYA, int glyphWA, int glyphHA,
104
GBool matches(Ref *idA, double m11A, double m12A,
105
double m21A, double m22A)
106
{ return fontID.num == idA->num && fontID.gen == idA->gen &&
107
m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
109
Ref fontID; // PDF font ID
110
double m11, m12, m21, m22; // transform matrix
111
int glyphX, glyphY; // pixel offset of glyph bitmaps
112
int glyphW, glyphH; // size of glyph bitmaps, in pixels
113
int glyphSize; // size of glyph bitmaps, in bytes
114
int cacheSets; // number of sets in cache
115
int cacheAssoc; // cache associativity (glyphs per set)
116
Guchar *cacheData; // glyph pixmap cache
117
T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
120
T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
121
double m21A, double m22A,
122
int glyphXA, int glyphYA, int glyphWA, int glyphHA,
136
glyphSize = glyphW * glyphH;
138
glyphSize = ((glyphW + 7) >> 3) * glyphH;
141
if (glyphSize <= 256) {
143
} else if (glyphSize <= 512) {
145
} else if (glyphSize <= 1024) {
150
cacheData = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
151
cacheTags = (T3FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
152
sizeof(T3FontCacheTag));
153
for (i = 0; i < cacheSets * cacheAssoc; ++i) {
154
cacheTags[i].mru = i & (cacheAssoc - 1);
158
T3FontCache::~T3FontCache() {
163
struct T3GlyphStack {
164
Gushort code; // character code
165
double x, y; // position to draw the glyph
168
T3FontCache *cache; // font cache for the current font
169
T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph
170
Guchar *cacheData; // pointer to cache data for the glyph
173
SplashBitmap *origBitmap;
175
double origCTM4, origCTM5;
177
T3GlyphStack *next; // next object on stack
180
//------------------------------------------------------------------------
182
//------------------------------------------------------------------------
184
OPVPOutputDev::OPVPOutputDev()
192
needFontUpdate = gFalse;
196
scaleWidth = scaleHeight = -1;
205
void OPVPOutputDev::setScale(double w, double h,
206
double leftMarginA, double bottomMarginA, int rotateA,
207
int yoffsetA, int sliceHeightA)
211
leftMargin = leftMarginA;
212
bottomMargin = bottomMarginA;
215
sliceHeight = sliceHeightA;
218
int OPVPOutputDev::init(SplashColorMode colorModeA,
221
SplashColor paperColorA,
222
const char *driverName,
224
const char *printerModel,
226
const char *optionKeys[],
227
const char *optionVals[]) {
232
if ((result = oprs->init(driverName, outputFD, printerModel,
233
nOptions,optionKeys,optionVals)) < 0) {
234
opvpError(-1,"OPRS initialization fail");
237
colorMode = colorModeA;
238
if ((result = oprs->setColorMode(colorMode,colorProfile)) < 0) {
239
opvpError(-1,"Can't setColorMode");
242
reverseVideo = reverseVideoA;
243
splashColorCopy(paperColor,paperColorA);
248
OPVPOutputDev::~OPVPOutputDev() {
251
for (i = 0; i < nT3Fonts; ++i) {
252
delete t3FontCache[i];
265
void OPVPOutputDev::startDoc(XRef *xrefA) {
272
fontEngine = new SplashFontEngine(
274
globalParams->getEnableT1lib(),
276
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
277
globalParams->getEnableFreeType(),
281
globalParams->getAntialias());
282
for (i = 0; i < nT3Fonts; ++i) {
283
delete t3FontCache[i];
288
void OPVPOutputDev::startPage(int pageNum, GfxState *state) {
292
if (scaleWidth > 0 && scaleHeight > 0) {
293
double *ctm = state->getCTM();
297
state->setCTM(0,ctm[1],ctm[2],0,leftMargin,bottomMargin-yoffset);
300
state->setCTM(ctm[0],0,0,ctm[3],paperWidth-leftMargin,
301
bottomMargin-yoffset);
304
state->setCTM(0,ctm[1],ctm[2],0,paperWidth-leftMargin,
305
-bottomMargin+paperHeight-yoffset);
308
state->setCTM(ctm[0],0,0,ctm[3],leftMargin,
309
-bottomMargin+paperHeight-yoffset);
312
state->concatCTM(scaleWidth,0.0,0.0,scaleHeight,0,0);
314
w = (int)(state->getPageWidth()+0.5);
315
h = (int)(state->getPageHeight()+0.5);
319
oprs->initGS(colorMode,w,h,paperColor);
322
(*underlayCbk)(underlayCbkData);
326
void OPVPOutputDev::endPage() {
330
void OPVPOutputDev::saveState(GfxState *state) {
334
void OPVPOutputDev::restoreState(GfxState *state) {
335
oprs->restoreState();
336
needFontUpdate = gTrue;
339
void OPVPOutputDev::updateAll(GfxState *state) {
340
updateLineDash(state);
341
updateLineJoin(state);
342
updateLineCap(state);
343
updateLineWidth(state);
344
updateFlatness(state);
345
updateMiterLimit(state);
346
updateFillColor(state);
347
updateStrokeColor(state);
348
needFontUpdate = gTrue;
351
void OPVPOutputDev::updateCTM(GfxState *state, double m11, double m12,
352
double m21, double m22,
353
double m31, double m32) {
354
updateLineDash(state);
355
updateLineJoin(state);
356
updateLineCap(state);
357
updateLineWidth(state);
360
void OPVPOutputDev::transLineDash(GfxState *state, SplashCoord **adash,
361
int *adashLength, SplashCoord *aphase) {
364
static SplashCoord dash[20];
367
state->getLineDash(&dashPattern, adashLength, &dashStart);
368
if (*adashLength > 20) {
371
for (i = 0; i < *adashLength; ++i) {
372
dash[i] = (SplashCoord)state->transformWidth(dashPattern[i]);
378
*aphase = (SplashCoord)state->transformWidth(dashStart);
381
void OPVPOutputDev::updateSplashLineDash(GfxState *state, Splash *splash) {
386
transLineDash(state, &dash, &dashLength, &phase);
387
splash->setLineDash(dash, dashLength, phase);
390
void OPVPOutputDev::updateLineDash(GfxState *state) {
395
transLineDash(state, &dash, &dashLength, &phase);
396
oprs->setLineDash(dash, dashLength, phase);
399
void OPVPOutputDev::updateFlatness(GfxState *state) {
400
oprs->setFlatness(state->getFlatness());
403
void OPVPOutputDev::updateLineJoin(GfxState *state) {
404
oprs->setLineJoin(state->getLineJoin());
407
void OPVPOutputDev::updateLineCap(GfxState *state) {
408
oprs->setLineCap(state->getLineCap());
411
void OPVPOutputDev::updateMiterLimit(GfxState *state) {
412
oprs->setMiterLimit(state->getMiterLimit());
415
void OPVPOutputDev::updateLineWidth(GfxState *state) {
416
oprs->setLineWidth(state->getTransformedLineWidth());
419
void OPVPOutputDev::updateFillColor(GfxState *state) {
423
state->getFillGray(&gray);
424
state->getFillRGB(&rgb);
425
oprs->setFillPattern(getColor(gray, &rgb));
428
void OPVPOutputDev::updateStrokeColor(GfxState *state) {
432
state->getStrokeGray(&gray);
433
state->getStrokeRGB(&rgb);
434
oprs->setStrokePattern(getColor(gray, &rgb));
438
SplashPattern *OPVPOutputDev::getColor(double gray, GfxRGB *rgb,
441
SplashPattern *OPVPOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
443
SplashPattern *pattern;
445
GfxColorComp r, g, b;
448
gray = gfxColorComp1 - gray;
449
r = gfxColorComp1 - rgb->r;
450
g = gfxColorComp1 - rgb->g;
451
b = gfxColorComp1 - rgb->b;
458
pattern = NULL; // make gcc happy
460
case splashModeMono1:
461
case splashModeMono8:
462
color1[0] = colToByte(gray);
463
pattern = new SplashSolidColor(color1);
466
color1[0] = colToByte(r);
467
color1[1] = colToByte(g);
468
color1[2] = colToByte(b);
469
pattern = new SplashSolidColor(color1);
472
case splashModeCMYK8:
473
color[0] = colToByte(cmyk->c);
474
color[1] = colToByte(cmyk->m);
475
color[2] = colToByte(cmyk->y);
476
color[3] = colToByte(cmyk->k);
477
pattern = new SplashSolidColor(color);
481
opvpError(-1, "no supported color mode");
488
void OPVPOutputDev::updateFont(GfxState *state) {
489
needFontUpdate = gTrue;
492
void OPVPOutputDev::doUpdateFont(GfxState *state) {
494
GfxFontType fontType;
495
SplashOutFontFileID *id;
496
SplashFontFile *fontFile;
497
SplashFontSrc *fontsrc = NULL;
500
Object refObj, strObj;
504
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
509
double m11, m12, m21, m22;
512
GBool recreateFont = gFalse;
514
needFontUpdate = gFalse;
520
if (!(gfxFont = state->getFont())) {
523
fontType = gfxFont->getType();
524
if (fontType == fontType3) {
528
// check the font file cache
529
id = new SplashOutFontFileID(gfxFont->getID());
530
if ((fontFile = fontEngine->getFontFile(id))) {
535
// if there is an embedded font, write it to disk
536
if (gfxFont->getEmbeddedFontID(&embRef)) {
537
tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
541
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
544
fileName = globalParams->findSystemFontFile(gfxFont,&sftype,
547
opvpError(-1, "Couldn't find a font for '%s'",
548
gfxFont->getName() ? gfxFont->getName()->getCString()
555
fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
559
fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
564
// if there is an external font file, use it
565
} else if (!(fileName = gfxFont->getExtFontFile())) {
566
DisplayFontParam *dfp;
567
// look for a display font mapping or a substitute font
569
if (gfxFont->getName()) {
570
dfp = globalParams->getDisplayFont(gfxFont);
573
opvpError(-1, "Couldn't find a font for '%s'",
574
gfxFont->getName() ? gfxFont->getName()->getCString()
580
fileName = dfp->t1.fileName;
581
fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
584
fileName = dfp->tt.fileName;
585
fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
586
faceIndex = dfp->tt.faceIndex;
592
fontsrc = new SplashFontSrc;
594
fontsrc->setFile(fileName, gFalse);
596
fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
598
// load the font file
601
if (!(fontFile = fontEngine->loadType1Font(
604
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
607
((Gfx8BitFont *)gfxFont)->getEncoding()))) {
608
opvpError(-1, "Couldn't create a font for '%s'",
609
gfxFont->getName() ? gfxFont->getName()->getCString()
615
if (!(fontFile = fontEngine->loadType1CFont(
618
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
621
((Gfx8BitFont *)gfxFont)->getEncoding()))) {
622
opvpError(-1, "Couldn't create a font for '%s'",
623
gfxFont->getName() ? gfxFont->getName()->getCString()
629
if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
632
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
635
((Gfx8BitFont *)gfxFont)->getEncoding()))) {
636
opvpError(-1, "Couldn't create a font for '%s'",
637
gfxFont->getName() ? gfxFont->getName()->getCString()
645
ff = FoFiTrueType::load(fileName->getCString());
647
ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
649
codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
656
if (!(fontFile = fontEngine->loadTrueTypeFont(
660
opvpError(-1, "Couldn't create a font for '%s'",
661
gfxFont->getName() ? gfxFont->getName()->getCString()
668
if (!(fontFile = fontEngine->loadCIDFont(
671
opvpError(-1, "Couldn't create a font for '%s'",
672
gfxFont->getName() ? gfxFont->getName()->getCString()
677
case fontCIDType0COT:
678
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
679
n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
681
codeToGID = (int *)gmallocn(n, sizeof(int));
682
memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
687
if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
689
fontsrc,codeToGID,n))) {
691
if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
695
opvpError(-1, "Couldn't create a font for '%s'",
696
gfxFont->getName() ? gfxFont->getName()->getCString()
705
if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
706
n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
708
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
709
codeToGID = (int *)gmallocn(n, sizeof(int));
710
memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
713
codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
714
memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
715
n * sizeof(Gushort));
720
ff = FoFiTrueType::load(fileName->getCString());
722
ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
725
codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
728
if (!(fontFile = fontEngine->loadTrueTypeFont(
731
codeToGID, n, faceIndex))) {
732
opvpError(-1, "Couldn't create a font for '%s'",
733
gfxFont->getName() ? gfxFont->getName()->getCString()
739
// this shouldn't happen
742
fontFile->doAdjustMatrix = gTrue;
745
// get the font matrix
746
state->getFontTransMat(&m11, &m12, &m21, &m22);
747
m11 *= state->getHorizScaling();
748
m12 *= state->getHorizScaling();
750
// create the scaled font
751
fontMat[0] = m11; fontMat[1] = m12;
752
fontMat[2] = m21; fontMat[3] = m22;
753
font = fontEngine->getFont(fontFile, fontMat, oprs->getMatrix());
755
// for substituted fonts: adjust the font matrix -- compare the
756
// width of 'm' in the original font and the substituted font
757
if (fontFile->doAdjustMatrix && !gfxFont->isCIDFont()) {
761
for (code = 0; code < 256; ++code) {
762
if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
763
name[0] == 'm' && name[1] == '\0') {
768
w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
769
w2 = font->getGlyphAdvance(code);
770
if (!gfxFont->isSymbolic() && w2 > 0) {
771
// if real font is substantially narrower than substituted
772
// font, reduce the font size accordingly
773
if (w1 > 0.01 && w1 < 0.9 * w2) {
777
recreateFont = gTrue;
785
fontMat[0] = m11; fontMat[1] = m12;
786
fontMat[2] = m21; fontMat[3] = m22;
787
font = fontEngine->getFont(fontFile, fontMat, oprs->getMatrix());
790
if (fontsrc && !fontsrc->isFile)
797
if (fontsrc && !fontsrc->isFile)
802
void OPVPOutputDev::stroke(GfxState *state) {
803
OPVPSplashPath *path;
806
/* check None separate color */
807
if ((cs = state->getStrokeColorSpace()) == NULL) return;
808
if (cs->getMode() == csSeparation) {
811
name = (dynamic_cast<GfxSeparationColorSpace *>(cs))->getName();
812
if (name == NULL) return;
813
if (name->cmp("None") == 0) return;
816
path = convertPath(state, state->getPath());
821
void OPVPOutputDev::fill(GfxState *state) {
822
OPVPSplashPath *path;
825
/* check None separate color */
826
if ((cs = state->getFillColorSpace()) == NULL) return;
827
if (cs->getMode() == csSeparation) {
830
name = (dynamic_cast<GfxSeparationColorSpace *>(cs))->getName();
831
if (name == NULL) return;
832
if (name->cmp("None") == 0) return;
835
path = convertPath(state, state->getPath());
836
oprs->fill(path, gFalse);
840
void OPVPOutputDev::eoFill(GfxState *state) {
841
OPVPSplashPath *path;
844
/* check None separate color */
845
if ((cs = state->getFillColorSpace()) == NULL) return;
846
if (cs->getMode() == csSeparation) {
849
name = (dynamic_cast<GfxSeparationColorSpace *>(cs))->getName();
850
if (name == NULL) return;
851
if (name->cmp("None") == 0) return;
854
path = convertPath(state, state->getPath());
855
oprs->fill(path, gTrue);
859
void OPVPOutputDev::clip(GfxState *state) {
860
OPVPSplashPath *path;
862
path = convertPath(state, state->getPath());
863
oprs->clipToPath(path, gFalse);
867
void OPVPOutputDev::eoClip(GfxState *state) {
868
OPVPSplashPath *path;
870
path = convertPath(state, state->getPath());
871
oprs->clipToPath(path, gTrue);
875
OPVPSplashPath *OPVPOutputDev::bitmapToPath(SplashBitmap *bitmapA,
876
int width, int height)
879
OPVPSplashPath *path;
883
path = new OPVPSplashPath();
885
for (y = 0;y < height;y++) {
886
for (x = 0;x < width;x++) {
887
bitmapA->getPixel(x,y,pix);
891
for (x++;x < width;x++) {
892
bitmapA->getPixel(x,y,pix);
901
path->lineTo(x2,(y+1));
902
path->lineTo(x1,(y+1));
910
void OPVPOutputDev::clipToStrokePath(GfxState *state) {
911
SplashBitmap *tbitmap;
914
OPVPSplashPath *path, *path2;
916
// use splash for makeStrokePath
917
// create dummy bitmap for creating splash
918
tbitmap = new SplashBitmap(1, 1, 1, splashModeMono1, gFalse);
919
tsplash = new Splash(tbitmap, gFalse);
920
// set line parameters
922
updateSplashLineDash(state, tsplash);
923
tsplash->setLineJoin(state->getLineJoin());
924
tsplash->setLineCap(state->getLineCap());
925
tsplash->setMiterLimit(state->getMiterLimit());
926
tsplash->setLineWidth(state->getTransformedLineWidth());
928
path = convertPath(state, state->getPath());
929
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
930
spath = tsplash->makeStrokePath(path,0);
932
spath = tsplash->makeStrokePath(path);
934
path2 = new OPVPSplashPath(spath);
939
oprs->clipToPath(path2, gFalse);
943
OPVPSplashPath *OPVPOutputDev::convertPath(GfxState *state, GfxPath *path) {
944
OPVPSplashPath *sPath;
946
double x1, y1, x2, y2, x3, y3;
949
sPath = new OPVPSplashPath();
950
for (i = 0; i < path->getNumSubpaths(); ++i) {
951
subpath = path->getSubpath(i);
952
if (subpath->getNumPoints() > 0) {
953
state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
954
sPath->moveTo((SplashCoord)x1, (SplashCoord)y1);
956
while (j < subpath->getNumPoints()) {
957
if (subpath->getCurve(j)) {
958
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
959
state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
960
state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
961
sPath->curveTo((SplashCoord)x1, (SplashCoord)y1,
962
(SplashCoord)x2, (SplashCoord)y2,
963
(SplashCoord)x3, (SplashCoord)y3);
966
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
967
sPath->lineTo((SplashCoord)x1, (SplashCoord)y1);
971
if (subpath->isClosed()) {
979
void OPVPOutputDev::drawChar(GfxState *state, double x, double y,
980
double dx, double dy,
981
double originX, double originY,
982
CharCode code, int nBytes,
983
Unicode *u, int uLen) {
986
OPVPSplashPath *path;
989
// check for invisible text -- this is used by Acrobat Capture
990
render = state->getRender();
995
if (needFontUpdate) {
1004
state->transform(x,y,&x1,&y1);
1007
if (!(render & 1)) {
1008
oprs->fillChar((SplashCoord)x1, (SplashCoord)y1, code, font, u, fontMat);
1012
if ((render & 3) == 1 || (render & 3) == 2) {
1013
if ((spath = font->getGlyphPath(code))) {
1014
path = new OPVPSplashPath(spath);
1016
path->closeAllSubPath();
1017
path->offset((SplashCoord)x1, (SplashCoord)y1);
1021
opvpError(-1,"No glyph outline infomation");
1027
if ((spath = font->getGlyphPath(code)) != NULL) {
1028
path = new OPVPSplashPath(spath);
1030
path->offset((SplashCoord)x1, (SplashCoord)y1);
1032
textClipPath->append(path);
1035
textClipPath = path;
1038
opvpError(-1,"No glyph outline infomation");
1043
GBool OPVPOutputDev::beginType3Char(GfxState *state, double x, double y,
1044
double dx, double dy,
1045
CharCode code, Unicode *u, int uLen) {
1046
/* In a vector mode, cache is not needed */
1050
void OPVPOutputDev::endType3Char(GfxState *state) {
1051
/* In a vector mode, cache is not needed */
1055
void OPVPOutputDev::type3D0(GfxState *state, double wx, double wy) {
1056
/* In a vector mode, cache is not needed */
1060
void OPVPOutputDev::type3D1(GfxState *state, double wx, double wy,
1061
double llx, double lly, double urx, double ury) {
1064
void OPVPOutputDev::drawType3Glyph(T3FontCache *t3Font,
1065
T3FontCacheTag *tag, Guchar *data,
1066
double x, double y) {
1067
SplashGlyphBitmap glyph;
1069
glyph.x = -t3Font->glyphX;
1070
glyph.y = -t3Font->glyphY;
1071
glyph.w = t3Font->glyphW;
1072
glyph.h = t3Font->glyphH;
1073
glyph.aa = colorMode != splashModeMono1;
1075
glyph.freeData = gFalse;
1076
oprs->fillGlyph((SplashCoord)x, (SplashCoord)y, &glyph);
1079
void OPVPOutputDev::endTextObject(GfxState *state) {
1081
oprs->clipToPath(textClipPath, gFalse);
1082
delete textClipPath;
1083
textClipPath = NULL;
1087
struct SplashOutImageMaskData {
1088
ImageStream *imgStr;
1090
int width, height, y;
1093
GBool OPVPOutputDev::imageMaskSrc(void *data, SplashColorPtr line) {
1094
SplashOutImageMaskData *imgMaskData = (SplashOutImageMaskData *)data;
1099
if (imgMaskData->y == imgMaskData->height) {
1102
for (x = 0, p = imgMaskData->imgStr->getLine(), q = line;
1103
x < imgMaskData->width;
1105
*q++ = *p++ ^ imgMaskData->invert;
1111
void OPVPOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
1112
int width, int height, GBool invert,
1117
SplashOutImageMaskData imgMaskData;
1119
ctm = state->getCTM();
1124
mat[4] = ctm[2] + ctm[4];
1125
mat[5] = ctm[3] + ctm[5];
1127
imgMaskData.imgStr = new ImageStream(str, width, 1, 1);
1128
imgMaskData.imgStr->reset();
1129
imgMaskData.invert = invert ? 0 : 1;
1130
imgMaskData.width = width;
1131
imgMaskData.height = height;
1134
oprs->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat,
1135
t3GlyphStack != NULL);
1137
while (imgMaskData.y < height) {
1138
imgMaskData.imgStr->getLine();
1143
delete imgMaskData.imgStr;
1146
struct SplashOutImageData {
1147
ImageStream *imgStr;
1148
GfxImageColorMap *colorMap;
1149
SplashColorPtr lookup;
1151
SplashColorMode colorMode;
1152
int width, height, y;
1155
GBool OPVPOutputDev::imageSrc(void *data, SplashColorPtr line,
1158
SplashOutImageData *imgData = (SplashOutImageData *)data;
1160
SplashColorPtr q, col;
1168
if (imgData->y == imgData->height) {
1172
nComps = imgData->colorMap->getNumPixelComps();
1174
if (imgData->lookup) {
1175
switch (imgData->colorMode) {
1176
case splashModeMono1:
1177
case splashModeMono8:
1178
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1181
*q++ = imgData->lookup[*p];
1184
case splashModeRGB8:
1185
case splashModeBGR8:
1186
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1189
col = &imgData->lookup[3 * *p];
1196
case splashModeCMYK8:
1197
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1200
col = &imgData->lookup[4 * *p];
1213
switch (imgData->colorMode) {
1214
case splashModeMono1:
1215
case splashModeMono8:
1216
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1219
imgData->colorMap->getGray(p, &gray);
1220
*q++ = colToByte(gray);
1223
case splashModeRGB8:
1224
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1227
imgData->colorMap->getRGB(p, &rgb);
1228
*q++ = colToByte(rgb.r);
1229
*q++ = colToByte(rgb.g);
1230
*q++ = colToByte(rgb.b);
1233
case splashModeBGR8:
1234
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1237
imgData->colorMap->getRGB(p, &rgb);
1238
*q++ = colToByte(rgb.b);
1239
*q++ = colToByte(rgb.g);
1240
*q++ = colToByte(rgb.r);
1244
case splashModeCMYK8:
1245
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1248
imgData->colorMap->getCMYK(p, &cmyk);
1249
*q++ = colToByte(cmyk.c);
1250
*q++ = colToByte(cmyk.m);
1251
*q++ = colToByte(cmyk.y);
1252
*q++ = colToByte(cmyk.k);
1266
GBool OPVPOutputDev::alphaImageSrc(void *data, SplashColorPtr line,
1267
Guchar *alphaLine) {
1268
SplashOutImageData *imgData = (SplashOutImageData *)data;
1270
SplashColorPtr q, col;
1279
if (imgData->y == imgData->height) {
1283
nComps = imgData->colorMap->getNumPixelComps();
1285
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1289
for (i = 0; i < nComps; ++i) {
1290
if (p[i] < imgData->maskColors[2*i] ||
1291
p[i] > imgData->maskColors[2*i+1]) {
1296
if (imgData->lookup) {
1297
switch (imgData->colorMode) {
1298
case splashModeMono1:
1299
case splashModeMono8:
1301
*q++ = imgData->lookup[*p];
1303
case splashModeRGB8:
1305
col = &imgData->lookup[3 * *p];
1310
case splashModeBGR8:
1311
col = &imgData->lookup[3 * *p];
1318
case splashModeCMYK8:
1320
col = &imgData->lookup[4 * *p];
1332
switch (imgData->colorMode) {
1333
case splashModeMono1:
1334
case splashModeMono8:
1335
imgData->colorMap->getGray(p, &gray);
1337
*q++ = colToByte(gray);
1339
case splashModeRGB8:
1340
imgData->colorMap->getRGB(p, &rgb);
1342
*q++ = colToByte(rgb.r);
1343
*q++ = colToByte(rgb.g);
1344
*q++ = colToByte(rgb.b);
1346
case splashModeBGR8:
1347
imgData->colorMap->getRGB(p, &rgb);
1348
*q++ = colToByte(rgb.b);
1349
*q++ = colToByte(rgb.g);
1350
*q++ = colToByte(rgb.r);
1354
case splashModeCMYK8:
1355
imgData->colorMap->getCMYK(p, &cmyk);
1357
*q++ = colToByte(cmyk.c);
1358
*q++ = colToByte(cmyk.m);
1359
*q++ = colToByte(cmyk.y);
1360
*q++ = colToByte(cmyk.k);
1374
void OPVPOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
1375
int width, int height,
1376
GfxImageColorMap *colorMap,
1378
int *maskColors, GBool inlineImg) {
1381
SplashOutImageData imgData;
1382
SplashColorMode srcMode;
1383
SplashImageSource src;
1392
ctm = state->getCTM();
1397
mat[4] = ctm[2] + ctm[4];
1398
mat[5] = ctm[3] + ctm[5];
1400
imgData.imgStr = new ImageStream(str, width,
1401
colorMap->getNumPixelComps(),
1402
colorMap->getBits());
1403
imgData.imgStr->reset();
1404
imgData.colorMap = colorMap;
1405
imgData.maskColors = maskColors;
1406
imgData.colorMode = colorMode;
1407
imgData.width = width;
1408
imgData.height = height;
1411
// special case for one-channel (monochrome/gray/separation) images:
1412
// build a lookup table here
1413
imgData.lookup = NULL;
1414
if (colorMap->getNumPixelComps() == 1) {
1415
n = 1 << colorMap->getBits();
1416
switch (colorMode) {
1417
case splashModeMono1:
1418
case splashModeMono8:
1419
imgData.lookup = (SplashColorPtr)gmalloc(n);
1420
for (i = 0; i < n; ++i) {
1422
colorMap->getGray(&pix, &gray);
1423
imgData.lookup[i] = colToByte(gray);
1426
case splashModeRGB8:
1427
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1428
for (i = 0; i < n; ++i) {
1430
colorMap->getRGB(&pix, &rgb);
1431
imgData.lookup[3*i] = colToByte(rgb.r);
1432
imgData.lookup[3*i+1] = colToByte(rgb.g);
1433
imgData.lookup[3*i+2] = colToByte(rgb.b);
1436
case splashModeBGR8:
1437
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1438
for (i = 0; i < n; ++i) {
1440
colorMap->getRGB(&pix, &rgb);
1441
imgData.lookup[3*i] = colToByte(rgb.b);
1442
imgData.lookup[3*i+1] = colToByte(rgb.g);
1443
imgData.lookup[3*i+2] = colToByte(rgb.r);
1447
case splashModeCMYK8:
1448
imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
1449
for (i = 0; i < n; ++i) {
1451
colorMap->getCMYK(&pix, &cmyk);
1452
imgData.lookup[4*i] = colToByte(cmyk.c);
1453
imgData.lookup[4*i+1] = colToByte(cmyk.m);
1454
imgData.lookup[4*i+2] = colToByte(cmyk.y);
1455
imgData.lookup[4*i+3] = colToByte(cmyk.k);
1465
if (colorMode == splashModeMono1) {
1466
srcMode = splashModeMono8;
1468
srcMode = colorMode;
1470
src = maskColors ? &alphaImageSrc : &imageSrc;
1471
oprs->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse,
1472
width, height, mat);
1474
while (imgData.y < height) {
1475
imgData.imgStr->getLine();
1480
gfree(imgData.lookup);
1481
delete imgData.imgStr;
1485
struct SplashOutMaskedImageData {
1486
ImageStream *imgStr;
1487
GfxImageColorMap *colorMap;
1489
SplashColorPtr lookup;
1490
SplashColorMode colorMode;
1491
int width, height, y;
1494
GBool OPVPOutputDev::maskedImageSrc(void *data, SplashColorPtr line,
1495
Guchar *alphaLine) {
1496
SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data;
1498
SplashColor maskColor;
1499
SplashColorPtr q, col;
1508
if (imgData->y == imgData->height) {
1512
nComps = imgData->colorMap->getNumPixelComps();
1514
for (x = 0, p = imgData->imgStr->getLine(), q = line;
1517
imgData->mask->getPixel(x, imgData->y, maskColor);
1518
alpha = maskColor[0] ? 0xff : 0x00;
1519
if (imgData->lookup) {
1520
switch (imgData->colorMode) {
1521
case splashModeMono1:
1522
case splashModeMono8:
1524
*q++ = imgData->lookup[*p];
1526
case splashModeRGB8:
1528
col = &imgData->lookup[3 * *p];
1533
case splashModeBGR8:
1534
col = &imgData->lookup[3 * *p];
1541
case splashModeCMYK8:
1543
col = &imgData->lookup[4 * *p];
1555
switch (imgData->colorMode) {
1556
case splashModeMono1:
1557
case splashModeMono8:
1558
imgData->colorMap->getGray(p, &gray);
1560
*q++ = colToByte(gray);
1562
case splashModeRGB8:
1563
imgData->colorMap->getRGB(p, &rgb);
1565
*q++ = colToByte(rgb.r);
1566
*q++ = colToByte(rgb.g);
1567
*q++ = colToByte(rgb.b);
1569
case splashModeBGR8:
1570
imgData->colorMap->getRGB(p, &rgb);
1571
*q++ = colToByte(rgb.b);
1572
*q++ = colToByte(rgb.g);
1573
*q++ = colToByte(rgb.r);
1577
case splashModeCMYK8:
1578
imgData->colorMap->getCMYK(p, &cmyk);
1580
*q++ = colToByte(cmyk.c);
1581
*q++ = colToByte(cmyk.m);
1582
*q++ = colToByte(cmyk.y);
1583
*q++ = colToByte(cmyk.k);
1597
void OPVPOutputDev::drawMaskedImage(GfxState *state, Object *ref,
1598
Stream *str, int width, int height,
1599
GfxImageColorMap *colorMap,
1601
Stream *maskStr, int maskWidth,
1602
int maskHeight, GBool maskInvert,
1603
GBool maskInterpolate) {
1606
SplashOutMaskedImageData imgData;
1607
SplashOutImageMaskData imgMaskData;
1608
SplashColorMode srcMode;
1609
SplashBitmap *maskBitmap;
1611
SplashColor maskColor;
1620
//----- scale the mask image to the same size as the source image
1622
mat[0] = (SplashCoord)width;
1625
mat[3] = (SplashCoord)height;
1628
imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
1629
imgMaskData.imgStr->reset();
1630
imgMaskData.invert = maskInvert ? 0 : 1;
1631
imgMaskData.width = maskWidth;
1632
imgMaskData.height = maskHeight;
1634
maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse);
1635
maskSplash = new Splash(maskBitmap, gFalse);
1637
maskSplash->clear(maskColor);
1639
maskSplash->setFillPattern(new SplashSolidColor(maskColor));
1640
maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
1641
maskWidth, maskHeight, mat, gFalse);
1642
delete imgMaskData.imgStr;
1646
//----- draw the source image
1648
ctm = state->getCTM();
1653
mat[4] = ctm[2] + ctm[4];
1654
mat[5] = ctm[3] + ctm[5];
1656
imgData.imgStr = new ImageStream(str, width,
1657
colorMap->getNumPixelComps(),
1658
colorMap->getBits());
1659
imgData.imgStr->reset();
1660
imgData.colorMap = colorMap;
1661
imgData.mask = maskBitmap;
1662
imgData.colorMode = colorMode;
1663
imgData.width = width;
1664
imgData.height = height;
1667
// special case for one-channel (monochrome/gray/separation) images:
1668
// build a lookup table here
1669
imgData.lookup = NULL;
1670
if (colorMap->getNumPixelComps() == 1) {
1671
n = 1 << colorMap->getBits();
1672
switch (colorMode) {
1673
case splashModeMono1:
1674
case splashModeMono8:
1675
imgData.lookup = (SplashColorPtr)gmalloc(n);
1676
for (i = 0; i < n; ++i) {
1678
colorMap->getGray(&pix, &gray);
1679
imgData.lookup[i] = colToByte(gray);
1682
case splashModeRGB8:
1683
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1684
for (i = 0; i < n; ++i) {
1686
colorMap->getRGB(&pix, &rgb);
1687
imgData.lookup[3*i] = colToByte(rgb.r);
1688
imgData.lookup[3*i+1] = colToByte(rgb.g);
1689
imgData.lookup[3*i+2] = colToByte(rgb.b);
1692
case splashModeBGR8:
1693
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1694
for (i = 0; i < n; ++i) {
1696
colorMap->getRGB(&pix, &rgb);
1697
imgData.lookup[3*i] = colToByte(rgb.b);
1698
imgData.lookup[3*i+1] = colToByte(rgb.g);
1699
imgData.lookup[3*i+2] = colToByte(rgb.r);
1703
case splashModeCMYK8:
1704
imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
1705
for (i = 0; i < n; ++i) {
1707
colorMap->getCMYK(&pix, &cmyk);
1708
imgData.lookup[4*i] = colToByte(cmyk.c);
1709
imgData.lookup[4*i+1] = colToByte(cmyk.m);
1710
imgData.lookup[4*i+2] = colToByte(cmyk.y);
1711
imgData.lookup[4*i+3] = colToByte(cmyk.k);
1721
switch (colorMode) {
1722
case splashModeMono1:
1723
case splashModeMono8:
1724
srcMode = splashModeMono8;
1726
case splashModeRGB8:
1727
srcMode = splashModeRGB8;
1729
case splashModeBGR8:
1730
srcMode = splashModeBGR8;
1733
case splashModeCMYK8:
1734
srcMode = splashModeCMYK8;
1739
srcMode = splashModeRGB8;
1742
oprs->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue,
1743
width, height, mat);
1746
gfree(imgData.lookup);
1747
delete imgData.imgStr;
1751
void OPVPOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
1752
Stream *str, int width, int height,
1753
GfxImageColorMap *colorMap,
1756
int maskWidth, int maskHeight,
1757
GfxImageColorMap *maskColorMap,
1758
GBool maskInterpolate) {
1761
SplashOutImageData imgData;
1762
SplashOutImageData imgMaskData;
1763
SplashColorMode srcMode;
1764
SplashBitmap *maskBitmap;
1766
SplashColor maskColor;
1775
ctm = state->getCTM();
1780
mat[4] = ctm[2] + ctm[4];
1781
mat[5] = ctm[3] + ctm[5];
1783
//----- set up the soft mask
1785
imgMaskData.imgStr = new ImageStream(maskStr, maskWidth,
1786
maskColorMap->getNumPixelComps(),
1787
maskColorMap->getBits());
1788
imgMaskData.imgStr->reset();
1789
imgMaskData.colorMap = maskColorMap;
1790
imgMaskData.maskColors = NULL;
1791
imgMaskData.colorMode = splashModeMono8;
1792
imgMaskData.width = maskWidth;
1793
imgMaskData.height = maskHeight;
1795
n = 1 << maskColorMap->getBits();
1796
imgMaskData.lookup = (SplashColorPtr)gmalloc(n);
1797
for (i = 0; i < n; ++i) {
1799
maskColorMap->getGray(&pix, &gray);
1800
imgMaskData.lookup[i] = colToByte(gray);
1802
maskBitmap = new SplashBitmap(maskWidth,maskHeight,
1803
1, splashModeMono8, gFalse);
1804
maskSplash = new Splash(maskBitmap, gFalse);
1806
maskSplash->clear(maskColor);
1807
maskSplash->drawImage(&imageSrc, &imgMaskData,
1808
splashModeMono8, gFalse, maskWidth, maskHeight, mat);
1809
delete imgMaskData.imgStr;
1811
gfree(imgMaskData.lookup);
1813
oprs->setSoftMask(maskBitmap);
1815
//----- draw the source image
1817
imgData.imgStr = new ImageStream(str, width,
1818
colorMap->getNumPixelComps(),
1819
colorMap->getBits());
1820
imgData.imgStr->reset();
1821
imgData.colorMap = colorMap;
1822
imgData.maskColors = NULL;
1823
imgData.colorMode = colorMode;
1824
imgData.width = width;
1825
imgData.height = height;
1828
// special case for one-channel (monochrome/gray/separation) images:
1829
// build a lookup table here
1830
imgData.lookup = NULL;
1831
if (colorMap->getNumPixelComps() == 1) {
1832
n = 1 << colorMap->getBits();
1833
switch (colorMode) {
1834
case splashModeMono1:
1835
case splashModeMono8:
1836
imgData.lookup = (SplashColorPtr)gmalloc(n);
1837
for (i = 0; i < n; ++i) {
1839
colorMap->getGray(&pix, &gray);
1840
imgData.lookup[i] = colToByte(gray);
1843
case splashModeRGB8:
1844
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1845
for (i = 0; i < n; ++i) {
1847
colorMap->getRGB(&pix, &rgb);
1848
imgData.lookup[3*i] = colToByte(rgb.r);
1849
imgData.lookup[3*i+1] = colToByte(rgb.g);
1850
imgData.lookup[3*i+2] = colToByte(rgb.b);
1853
case splashModeBGR8:
1854
imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
1855
for (i = 0; i < n; ++i) {
1857
colorMap->getRGB(&pix, &rgb);
1858
imgData.lookup[3*i] = colToByte(rgb.b);
1859
imgData.lookup[3*i+1] = colToByte(rgb.g);
1860
imgData.lookup[3*i+2] = colToByte(rgb.r);
1864
case splashModeCMYK8:
1865
imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
1866
for (i = 0; i < n; ++i) {
1868
colorMap->getCMYK(&pix, &cmyk);
1869
imgData.lookup[4*i] = colToByte(cmyk.c);
1870
imgData.lookup[4*i+1] = colToByte(cmyk.m);
1871
imgData.lookup[4*i+2] = colToByte(cmyk.y);
1872
imgData.lookup[4*i+3] = colToByte(cmyk.k);
1882
switch (colorMode) {
1883
case splashModeMono1:
1884
case splashModeMono8:
1885
srcMode = splashModeMono8;
1887
case splashModeRGB8:
1888
srcMode = splashModeRGB8;
1890
case splashModeBGR8:
1891
srcMode = splashModeBGR8;
1894
case splashModeCMYK8:
1895
srcMode = splashModeCMYK8;
1900
srcMode = splashModeRGB8;
1903
oprs->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat);
1905
oprs->setSoftMask(NULL);
1906
gfree(imgData.lookup);
1907
delete imgData.imgStr;
1911
int OPVPOutputDev::getBitmapWidth() {
1912
return bitmap->getWidth();
1915
int OPVPOutputDev::getBitmapHeight() {
1916
return bitmap->getHeight();
1919
void OPVPOutputDev::xorRectangle(int x0, int y0, int x1, int y1,
1920
SplashPattern *pattern) {
1921
/* no need in printing */
1924
void OPVPOutputDev::setFillColor(int r, int g, int b) {
1931
rgb.r = byteToCol(r);
1932
rgb.g = byteToCol(g);
1933
rgb.b = byteToCol(b);
1934
gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
1935
if (gray > gfxColorComp1) {
1936
gray = gfxColorComp1;
1939
cmyk.c = gfxColorComp1 - rgb.r;
1940
cmyk.m = gfxColorComp1 - rgb.g;
1941
cmyk.y = gfxColorComp1 - rgb.b;
1943
oprs->setFillPattern(getColor(gray, &rgb, &cmyk));
1945
oprs->setFillPattern(getColor(gray, &rgb));
1949
int OPVPOutputDev::OPVPStartJob(char *jobInfo)
1951
return oprs->OPVPStartJob(jobInfo);
1954
int OPVPOutputDev::OPVPEndJob()
1956
return oprs->OPVPEndJob();
1959
int OPVPOutputDev::OPVPStartDoc(char *docInfo)
1961
return oprs->OPVPStartDoc(docInfo);
1964
int OPVPOutputDev::OPVPEndDoc()
1966
return oprs->OPVPEndDoc();
1969
int OPVPOutputDev::OPVPStartPage(char *pageInfo,
1970
int rasterWidth, int rasterHeight)
1972
paperWidth = rasterWidth;
1973
paperHeight = rasterHeight;
1974
return oprs->OPVPStartPage(pageInfo,rasterWidth);
1977
int OPVPOutputDev::OPVPEndPage()
1979
return oprs->OPVPEndPage();
1982
int OPVPOutputDev::outSlice()
1984
return oprs->outSlice();
1987
void OPVPOutputDev::psXObject(Stream *psStream, Stream *level1Stream)
1989
opvpError(-1,"psXObject is found, but it is not supported");