unsigned int PdfPage::GetPageNumber() const { unsigned int nPageNumber = 0; PdfObject* pParent = m_pObject->GetIndirectKey( "Parent" ); PdfReference ref = m_pObject->Reference(); while( pParent ) { const PdfArray& kids = pParent->GetIndirectKey( "Kids" )->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() && (*it).GetReference() != ref ) { PdfObject* pNode = m_pObject->GetOwner()->GetObject( (*it).GetReference() ); if( pNode->GetDictionary().GetKey( PdfName::KeyType )->GetName() == PdfName( "Pages" ) ) nPageNumber += static_cast<int>(pNode->GetDictionary().GetKey( "Count" )->GetNumber()); else // if we do not have a page tree node, // we most likely have a page object: // so the page count is 1 ++nPageNumber; ++it; } ref = pParent->Reference(); pParent = pParent->GetIndirectKey( "Parent" ); } return ++nPageNumber; }
PDFFont PDFAnalyzer::getFontInfo(PdfObject* fontObj) { PDFFont currFont; PdfObject* subtype = fontObj->GetIndirectKey("Subtype"); if (subtype && subtype->IsName()) { PdfObject* fontDesc = fontObj->GetIndirectKey("FontDescriptor"); if (subtype->GetName() == "Type1") currFont.fontType = F_Type1; else if (subtype->GetName() == "MMType1") currFont.fontType = F_MMType1; else if (subtype->GetName() == "TrueType") currFont.fontType = F_TrueType; else if (subtype->GetName() == "Type3") { currFont.fontType = F_Type3; currFont.isEmbedded = true; fontDesc = NULL; } else if (subtype->GetName() == "Type0") { PdfObject* descendantFonts = fontObj->GetIndirectKey("DescendantFonts"); if (descendantFonts && descendantFonts->IsArray()) { PdfObject descendantFont = descendantFonts->GetArray()[0]; descendantFont.SetOwner(descendantFonts->GetOwner()); PdfObject* subtypeDescFont = descendantFont.GetIndirectKey("Subtype"); fontDesc = descendantFont.MustGetIndirectKey("FontDescriptor"); if (subtypeDescFont && subtypeDescFont->IsName()) { if (subtypeDescFont->GetName() == "CIDFontType0") currFont.fontType = F_CIDFontType0; else if (subtypeDescFont->GetName() == "CIDFontType2") currFont.fontType = F_CIDFontType2; } } } if (fontDesc) { PdfObject* fontFile = fontDesc->GetIndirectKey("FontFile"); PdfObject* fontFile2 = fontDesc->GetIndirectKey("FontFile2"); PdfObject* fontFile3 = fontDesc->GetIndirectKey("FontFile3"); if (fontFile && fontFile->HasStream()) currFont.isEmbedded = true; if (fontFile2 && fontFile2->HasStream()) currFont.isEmbedded = true; if (fontFile3 && fontFile3->HasStream()) { currFont.isEmbedded = true; PdfObject* ff3Subtype = fontFile3->GetIndirectKey("Subtype"); if (ff3Subtype && ff3Subtype->IsName() && ff3Subtype->GetName() == "OpenType") currFont.isOpenType = true; } } } return currFont; }
void PdfeFontType3::initGlyphs( const PdfObject* pFont ) { // CharProcs and Resources objects. PdfObject* pCharProcs = pFont->GetIndirectKey( "CharProcs" ); PdfObject* pResources = pFont->GetIndirectKey( "Resources" ); // No CharProcs: exception raised. if( !pCharProcs || !pCharProcs->IsDictionary() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Entries missing in the Type 3 font dictionary." ); } // Resize space vectors. m_mapCIDToGID.resize( m_lastCID-m_firstCID+1, 0 ); m_glyphs.resize( m_lastCID-m_firstCID+1, PdfeGlyphType3() ); // Look at each character. PdfName cname; PdfObject* pGlyph; for( pdfe_cid c = m_firstCID ; c <= m_lastCID ; ++c ) { // Get character name and search it in CharProcs. cname = this->fromCIDToName( c ); pGlyph = pCharProcs->GetIndirectKey( cname ); // If found, set GID to c-m_firstCID+1 and create glyph. if( pGlyph ) { m_mapCIDToGID[c-m_firstCID] = c-m_firstCID+1; m_glyphs[c-m_firstCID] = PdfeGlyphType3( cname, pGlyph, pResources ); } } }
void PdfDestination::Init( PdfObject* pObject, PdfDocument* pDocument ) { bool bValueExpected = false; PdfObject* pValue = NULL; if ( pObject->GetDataType() == ePdfDataType_Array ) { m_array = pObject->GetArray(); m_pObject = pObject; } else if( pObject->GetDataType() == ePdfDataType_String ) { PdfNamesTree* pNames = pDocument->GetNamesTree( ePdfDontCreateObject ); if( !pNames ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } pValue = pNames->GetValue( "Dests", pObject->GetString() ); bValueExpected = true; } else if( pObject->GetDataType() == ePdfDataType_Name ) { PdfMemDocument* pMemDoc = dynamic_cast<PdfMemDocument*>(pDocument); if ( !pMemDoc ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "For reading from a document, only use PdfMemDocument." ); } PdfObject* pCatalog = pMemDoc->GetCatalog(); if ( !pCatalog ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } PdfObject* pDests = pCatalog->GetIndirectKey( PdfName( "Dests" ) ); if( !pDests ) { // The error code has been chosen for its distinguishability. PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidKey, "No PDF-1.1-compatible destination dictionary found." ); } pValue = pDests->GetIndirectKey( pObject->GetName() ); bValueExpected = true; } else { PdfError::LogMessage( eLogSeverity_Error, "Unsupported object given to" " PdfDestination::Init of type %s", pObject->GetDataTypeString() ); m_array = PdfArray(); // needed to prevent crash on method calls // needed for GetObject() use w/o checking its return value for NULL m_pObject = pDocument->GetObjects()->CreateObject( m_array ); } if ( bValueExpected ) { if( !pValue ) { PODOFO_RAISE_ERROR( ePdfError_InvalidName ); } if( pValue->IsArray() ) m_array = pValue->GetArray(); else if( pValue->IsDictionary() ) m_array = pValue->GetDictionary().GetKey( "D" )->GetArray(); m_pObject = pValue; } }
PdfFont* PdfFontFactory::CreateFont( FT_Library*, PdfObject* pObject ) { PdfFontMetrics* pMetrics = NULL; PdfFont* pFont = NULL; PdfObject* pDescriptor = NULL; PdfObject* pEncoding = NULL; if( pObject->GetDictionary().GetKey( PdfName::KeyType )->GetName() != PdfName("Font") ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } const PdfName & rSubType = pObject->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); if( rSubType == PdfName("Type0") ) { // The PDF reference states that DescendantFonts must be an array, // some applications (e.g. MS Word) put the array into an indirect object though. const PdfArray & descendant = pObject->GetIndirectKey( "DescendantFonts" )->GetArray(); PdfObject* pFontObject = pObject->GetOwner()->GetObject( descendant[0].GetReference() ); pDescriptor = pFontObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); // OC 15.08.2010 BugFix: Parameter pFontObject added: TODO: untested pMetrics = new PdfFontMetricsObject( pFontObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontCID( pMetrics, pPdfEncoding, pObject, false ); } } else if( rSubType == PdfName("Type1") ) { // TODO: Old documents do not have a FontDescriptor for // the 14 standard fonts. This suggestions is // deprecated now, but give us problems with old documents. pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); // OC 13.08.2010: Handle missing FontDescriptor for the 14 standard fonts: if( !pDescriptor ) { // Check if its a PdfFontType1Base14 PdfObject* pBaseFont = NULL; pBaseFont = pObject->GetIndirectKey( "BaseFont" ); const char* pszBaseFontName = pBaseFont->GetName().GetName().c_str(); PdfFontMetricsBase14* pMetrics = PODOFO_Base14FontDef_FindBuiltinData(pszBaseFontName); if ( pMetrics != NULL ) { // pEncoding may be undefined, found a valid pdf with // 20 0 obj // << // /Type /Font // /BaseFont /ZapfDingbats // /Subtype /Type1 // >> // endobj // If pEncoding is null then // use StandardEncoding for Courier, Times, Helvetica font families // and special encodings for Symbol and ZapfDingbats const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding!= NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( !pMetrics->IsSymbol() ) pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); else if ( strcmp(pszBaseFontName, "Symbol") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalSymbolEncodingInstance(); else if ( strcmp(pszBaseFontName, "ZapfDingbats") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalZapfDingbatsEncodingInstance(); return new PdfFontType1Base14(pMetrics, pPdfEncoding, pObject); } } const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding != NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( pDescriptor ) { // OC 18.08.2010 TODO: Encoding has to be taken from the font's built-in encoding // Its extremely complicated to interpret the type1 font programs // so i try to determine if its a symbolic font by reading the FontDescriptor Flags // Flags & 4 --> Symbolic, Flags & 32 --> Nonsymbolic pdf_int32 lFlags = static_cast<pdf_int32>(pDescriptor->GetDictionary().GetKeyAsLong( "Flags", 0L )); if ( lFlags & 32 ) // Nonsymbolic, otherwise pEncoding remains NULL pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); } if ( pPdfEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontType1( pMetrics, pPdfEncoding, pObject ); } } else if( rSubType == PdfName("TrueType") ) { pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontTrueType( pMetrics, pPdfEncoding, pObject ); } } return pFont; }
bool PDFAnalyzer::inspectCanvas(PdfCanvas* canvas, QList<PDFColorSpace> & usedColorSpaces, bool & hasTransparency, QList<PDFFont> & usedFonts, QList<PDFImage> & imgs) { // this method can be used to get used color spaces, detect transparency, and get used fonts in either PdfPage or PdfXObject PdfObject* colorSpaceRes; PdfObject* xObjects; PdfObject* transGroup; PdfObject* extGState; PdfObject* fontRes; QMap<PdfName, PDFColorSpace> processedNamedCS; QMap<PdfName, PDFFont> processedNamedFont; QList<PdfName> processedNamedXObj; QList<PdfName> processedNamedGS; try { // get hold of a PdfObject pointer of this canvas // needed for the finding resources code below to work PdfPage* page = dynamic_cast<PdfPage*>(canvas); PdfObject* canvasObject = page?(page->GetObject()):((dynamic_cast<PdfXObject*>(canvas))->GetObject()); // find a resource with ColorSpace entry PdfObject* resources = canvas->GetResources(); for (PdfObject* par = canvasObject; par && !resources; par = par->GetIndirectKey("Parent")) { resources = par->GetIndirectKey("Resources"); } colorSpaceRes = resources?resources->GetIndirectKey("ColorSpace"):NULL; xObjects = resources?resources->GetIndirectKey("XObject"):NULL; extGState = resources?resources->GetIndirectKey("ExtGState"):NULL; fontRes = resources?resources->GetIndirectKey("Font"):NULL; // getting the transparency group of this content stream (if available) transGroup = canvasObject?canvasObject->GetIndirectKey("Group"):NULL; if (transGroup) { PdfObject* subtype = transGroup->GetIndirectKey("S"); if (subtype && subtype->GetName() == "Transparency") { // having transparency group means there's transparency in the PDF hasTransparency = true; // reporting the color space used in transparency group (Section 7.5.5, PDF 1.6 Spec) PdfObject* cs = transGroup->GetIndirectKey("CS"); if (cs) { PDFColorSpace retval = getCSType(cs); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); } } } } catch (PdfError & e) { qDebug() << "Error in analyzing stream's resources."; e.PrintErrorMsg(); return false; } try { // start parsing the content stream PdfContentsTokenizer tokenizer(canvas); EPdfContentsType t; const char * kwText; PdfVariant var; bool readToken; int tokenNumber = 0; QList<PdfVariant> args; bool inlineImgDict = false; QStack<PDFGraphicState> gsStack; PDFGraphicState currGS; while ((readToken = tokenizer.ReadNext(t, kwText, var))) { ++tokenNumber; if (t == ePdfContentsType_Variant) { args.append(var); } else if (t == ePdfContentsType_Keyword) { QString kw(kwText); switch(kwNameMap.value(kw, KW_Undefined)) { case KW_q: gsStack.push(currGS); break; case KW_Q: currGS = gsStack.pop(); break; case KW_cm: { if (args.size() == 6) { double mt[6]; for (int i=0; i<6; ++i) { mt[i] = args[i].GetReal(); } QMatrix transMatrix(mt[0], mt[1], mt[2], mt[3], mt[4], mt[5]); currGS.ctm = transMatrix*currGS.ctm; } } break; case KW_w: currGS.lineWidth = args[0].GetReal(); break; case KW_J: currGS.lineCap = args[0].GetNumber(); break; case KW_j: currGS.lineJoin = args[0].GetNumber(); break; case KW_M: currGS.lineJoin = args[0].GetReal(); break; case KW_d: { currGS.dashPattern.first.clear(); PdfArray dashArr = args[0].GetArray(); for (int i=0; i<dashArr.size(); ++i) currGS.dashPattern.first.append(dashArr[i].GetNumber()); currGS.dashPattern.second = args[0].GetNumber(); } break; case KW_g: if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); currGS.fillCS = CS_DeviceGray; currGS.fillColor.clear(); currGS.fillColor.append(args[0].GetReal()); break; case KW_G: if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); currGS.strokeCS = CS_DeviceGray; currGS.strokeColor.clear(); currGS.strokeColor.append(args[0].GetReal()); break; case KW_rg: if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); currGS.fillCS = CS_DeviceRGB; currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_RG: if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); currGS.strokeCS = CS_DeviceRGB; currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_k: if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); currGS.fillCS = CS_DeviceCMYK; currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_K: if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); currGS.strokeCS = CS_DeviceCMYK; currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_cs: { if (args.size() == 1 && args[0].IsName()) { if (args[0].GetName() == "DeviceGray") { currGS.fillCS = CS_DeviceGray; currGS.fillColor.clear(); currGS.fillColor.append(0); if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); } else if (args[0].GetName() == "DeviceRGB") { currGS.fillCS = CS_DeviceRGB; currGS.fillColor.clear(); for (int i=0; i<3; ++i) currGS.fillColor.append(0); if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); } else if (args[0].GetName() == "DeviceCMYK") { currGS.fillCS = CS_DeviceCMYK; currGS.fillColor.clear(); for (int i=0; i<3; ++i) currGS.fillColor.append(0); currGS.fillColor.append(1); if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); } else if (args[0].GetName() == "Pattern") { currGS.fillCS = CS_Pattern; if (!usedColorSpaces.contains(CS_Pattern)) usedColorSpaces.append(CS_Pattern); } else { if (processedNamedCS.contains(args[0].GetName())) { currGS.fillCS = processedNamedCS.value(args[0].GetName()); } else { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(args[0].GetName())) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(args[0].GetName()); PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); currGS.fillCS = retval; processedNamedCS.insert(args[0].GetName(), retval); } else { qDebug() << "Supplied colorspace is undefined!"; return false; } } } } else { qDebug() << "Wrong syntax in specifying color space!"; return false; } } break; case KW_CS: { if (args.size() == 1 && args[0].IsName()) { if (args[0].GetName() == "DeviceGray") { currGS.strokeCS = CS_DeviceGray; currGS.strokeColor.clear(); currGS.strokeColor.append(0); if (!usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); } else if (args[0].GetName() == "DeviceRGB") { currGS.fillCS = CS_DeviceRGB; currGS.strokeColor.clear(); for (int i=0; i<3; ++i) currGS.strokeColor.append(0); if (!usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); } else if (args[0].GetName() == "DeviceCMYK") { currGS.fillCS = CS_DeviceCMYK; currGS.strokeColor.clear(); for (int i=0; i<3; ++i) currGS.strokeColor.append(0); currGS.strokeColor.append(1); if (!usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); } else if (args[0].GetName() == "Pattern") { currGS.fillCS = CS_Pattern; if (!usedColorSpaces.contains(CS_Pattern)) usedColorSpaces.append(CS_Pattern); } else { if (processedNamedCS.contains(args[0].GetName())) { currGS.strokeCS = processedNamedCS.value(args[0].GetName()); } else { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(args[0].GetName())) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(args[0].GetName()); PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); currGS.strokeCS = retval; processedNamedCS.insert(args[0].GetName(), retval); } else { qDebug() << "Supplied colorspace is undefined!"; return false; } } } } else { qDebug() << "Wrong syntax in specifying color space!"; return false; } } break; case KW_sc: currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) currGS.fillColor.append(args[i].GetReal()); break; case KW_SC: currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) currGS.strokeColor.append(args[i].GetReal()); break; case KW_scn: currGS.fillColor.clear(); for (int i=0; i<args.size(); ++i) { if (args[i].IsReal() || args[i].IsNumber()) currGS.fillColor.append(args[i].GetReal()); } break; case KW_SCN: currGS.strokeColor.clear(); for (int i=0; i<args.size(); ++i) { if (args[i].IsReal() || args[i].IsNumber()) currGS.strokeColor.append(args[i].GetReal()); } break; case KW_Do: // image or form XObject { if (!processedNamedXObj.contains(args[0].GetName())) { if (args.size() == 1 && args[0].IsName() && xObjects) { PdfObject* xObject = xObjects->GetIndirectKey(args[0].GetName()); PdfObject* subtypeObject = xObject?xObject->GetIndirectKey("Subtype"):NULL; if (subtypeObject && subtypeObject->IsName()) { if (subtypeObject->GetName() == "Image") { PdfObject* imgColorSpace = xObject->GetIndirectKey("ColorSpace"); if (imgColorSpace) { PDFColorSpace retval = getCSType(imgColorSpace); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); } PdfObject* sMaskObj = xObject->GetIndirectKey("SMask"); if (sMaskObj) hasTransparency = true; PDFImage img; img.imgName = args[0].GetName().GetEscapedName().c_str(); double width = xObject->GetIndirectKey("Width")->GetReal(); double height = xObject->GetIndirectKey("Height")->GetReal(); img.dpiX = qRound(width/(currGS.ctm.m11()/72)); img.dpiY = qRound(height/(currGS.ctm.m22()/72)); imgs.append(img); } else if (subtypeObject->GetName() == "Form") { PdfXObject xObj(xObject); inspectCanvas(&xObj, usedColorSpaces, hasTransparency, usedFonts, imgs); // recursive call } } else { qDebug() << "Supplied external object is undefined!"; return false; } processedNamedXObj.append(args[0].GetName()); } else { qDebug() << "Wrong syntax for Do operator or there's no XObject defined!"; return false; } } } break; case KW_BI: inlineImgDict = true; break; case KW_ID: if (inlineImgDict) { PdfName colorspace("ColorSpace"); PdfName cs("CS"); if (args.contains(colorspace) || args.contains(cs)) { int csIdx = args.contains(colorspace)?args.indexOf(colorspace):args.indexOf(cs); if (args[csIdx+1].IsName()) { PdfName csName = args[csIdx+1].GetName(); if ((csName == "G" || csName == "DeviceGray") && !usedColorSpaces.contains(CS_DeviceGray)) usedColorSpaces.append(CS_DeviceGray); else if ((csName == "RGB" || csName == "DeviceRGB") && !usedColorSpaces.contains(CS_DeviceRGB)) usedColorSpaces.append(CS_DeviceRGB); else if ((csName == "CMYK" || csName == "DeviceCMYK") && !usedColorSpaces.contains(CS_DeviceCMYK)) usedColorSpaces.append(CS_DeviceCMYK); else if (!processedNamedCS.contains(csName)) { if (colorSpaceRes && colorSpaceRes->GetIndirectKey(csName)) { PdfObject* csEntry = colorSpaceRes->GetIndirectKey(csName); if (csEntry) { PDFColorSpace retval = getCSType(csEntry); if (retval != CS_Unknown && !usedColorSpaces.contains(retval)) usedColorSpaces.append(retval); processedNamedCS.insert(csName, retval); } } else { qDebug() << "Supplied colorspace for inline image is undefined!"; return false; } } } } PdfName height("Height"); PdfName h("H"); PdfName width("Width"); PdfName w("W"); if ((args.contains(height) || args.contains(h)) && (args.contains(width) || args.contains(w))) { int heightIdx = args.contains(height)?args.indexOf(height):args.indexOf(h); int widthIdx = args.contains(width)?args.indexOf(width):args.indexOf(w); double height = args[heightIdx+1].GetReal(); double width = args[widthIdx+1].GetReal(); PDFImage img; img.imgName = "Inline Image"; img.dpiX = qRound(width/(currGS.ctm.m11()/72)); img.dpiY = qRound(height/(currGS.ctm.m22()/72)); imgs.append(img); } inlineImgDict = false; } break; case KW_gs: { if (!processedNamedGS.contains(args[0].GetName())) { if (args.size() == 1 && args[0].IsName() && extGState) { PdfObject* extGStateObj = extGState->GetIndirectKey(args[0].GetName()); if (extGStateObj) { inspectExtGStateObj(extGStateObj, usedColorSpaces, hasTransparency, usedFonts, currGS); } else { qDebug() << "Named graphic state used with gs operator is undefined in current ExtGState"; return false; } processedNamedGS.append(args[0].GetName()); } else { qDebug() << "Wrong syntax in applying extended graphic state (gs operator) or there's no ExtGState defined!"; return false; } } } break; case KW_Tf: { if (processedNamedFont.contains(args[0].GetName())) { currGS.font.first = processedNamedFont.value(args[0].GetName()); currGS.font.second = args[1].GetReal(); } else { if (args.size() == 2 && args[0].IsName() && fontRes) { PdfObject* fontObj = fontRes->GetIndirectKey(args[0].GetName()); if (fontObj) { PDFFont retval = getFontInfo(fontObj); usedFonts.append(retval); processedNamedFont.insert(args[0].GetName(), retval); currGS.font.first = retval; currGS.font.second = args[1].GetReal(); } else { qDebug() << "The specified font cannot be found in current Resources!"; return false; } } else { qDebug() << "Wrong syntax in use of Tf operator or there's no Font defined in current Resources dictionary!"; return false; } } } break; case KW_Undefined: default: break; } args.clear(); } } } catch (PdfError & e) { qDebug() << "Error in parsing content stream"; e.PrintErrorMsg(); return false; } return true; }