PDF underlay is Now Standard with Teigha

Sergey Sherstnev

July 19, 2018

With released Teigha 2019, ODA members have a new way of importing .pdf files as underlays using Teigha’s new PdfiumModule module. The module is based on the Pdfium library developed by Google. Pdfium is available as open source and free of charge. Previously ODA members could import .pdf files as underlays using the PdfVIModule module but at an additional cost.

In addition to being free, PdfiumModule is faster than PdfVIModule (from several percentage points to several times faster, depending on the .pdf file), has cross-platform support, and has possibilities for future customization because of source code accessibility. Below is a table that compares the available configurations of Teigha products that PdfiumModule and PdfVIModule can be used with:

Configuration PdfiumModule PdfVIModule
Visual Studio 2015 and above (vc14, vc15) Yes Discontinued
Visual Studio 2013 and below (vc9, vc10, vc11, vc12) No Discontinued
Linux GCC 4.7 and below (4.1, 4.2, 4.4, 4.7) No Discontinued
Linux GCC 4.8 and above Yes Discontinued
Mas OS X Yes Discontinued
iOS Yes No
Android Yes No
Note that PdfiumModule also supports the static configurations of platforms listed in this table

 

Here we can see that PdfiumModule can be used on every platform with C++ 11 support in both dynamic and static configurations.

The main features of PdfiumModule are:

  • Rendering .pdf files as bitmaps for rendered .dwg files
  • Handling SnapPoints for PdfUnderlays

Rendering and handling SnapPoints takes into account PDF layer states, in contrast with PdfModuleVI that does not handle PDF layer states fully.

Switching to PdfiumModule from PdfModuleVI

Using PdfiumModule is the same as PdfModuleVI, so moving to Pdfium is easy. Here is an example of creating a PdfUnderlay:

OdDbUnderlayReferencePtr loadPdfToUnderlayInModelSpace(OdDbHostAppServices* pHostApp)
{
  OdRxModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdPdfModuleVIModuleName);
  if (pModule.isNull())
   throw OdError(eNullObjectPointer);

  OdString shortFileName = OD_T("test.pdf");
  OdString inputPdfFile = pHostApp->findFile(shortFileName);
  OdDbDatabasePtr pDb = pHostApp->createDatabase();
  // Try to load pdf file
  OdDbUnderlayHostPEPtr pHost 
       = OdDbPdfDefinition::desc()->getX(OdDbUnderlayHostPE::desc());

  if (pHost.isNull())
    throw OdError(eNullObjectPointer);

  OdDbUnderlayFilePtr pUnderlayFile;
  OdResult res = pHost->load(*pDb, inputPdfFile, "", pUnderlayFile);
  if (res != eOk)
    throw OdError(res);

  // Create pdf definition, add it to dictionary
  OdDbUnderlayDefinitionPtr pDef = OdDbPdfDefinition::createObject();
  pDef->setSourceFileName(inputPdfFile);
  pDef->setItemName( "1" ); // Page number

  OdString dictName = OD_T("MyPdfUnderlay - ") + activeLayout;
  OdDbObjectId definitionId = pDef->postDefinitionToDb(pDb, dictName);

  // Add Pdf underlay reference to model space
  OdDbUnderlayReferencePtr pRef = OdDbPdfReference::createObject();

  pRef->setDatabaseDefaults(pDb);

  OdDbBlockTableRecordPtr pSpace 
     = pDb->getModelSpaceId().safeOpenObject(OdDb::kForWrite);
  pSpace->appendOdDbEntity(pRef);
  pRef->setDefinitionId(definitionId);

  return pRef;
}

Just replace this:

OdRxModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdPdfModuleVIModuleName);

With this:

OdRxModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdPdfiumModuleName);

And you’re done.