Skip to main content
Skip table of contents

Basics

The Mako SDK is a simple C++ SDK. The beauty of the APIs is that simple operations are just that, really simple. As your experience grows, the APIs grow with you too, facilitating complex document manipulations, rendering and transforms.

Using the API

The Mako SDK APIs are all grouped under the JawsMako namespace. This can be referenced to reduce the verbosity of the code. Most of the Mako functionality is under the jawsmako.h header file, so don't forget to include that too.

CPP
#include <jawsmako/jawsmako.h>
using namespace JawsMako;

Creating a Mako Instance

Most APIs in Mako that create instances or resources will require a Mako instance. The Mako instance should also be a singleton, or in other words, there should one instance of IJawsMako in a single process at any one time. If multiple instances are used in a single process, an EDL panic exception may be raised.

Creating an instance of an IJawsMako is simple.

CPP
IJawsMakoPtr jawsMako = IJawsMako::create();

There are also overloads to the create method to set the temporary directory that Mako uses, along with its cache directory and temporary store parameters.

These can be useful in virtualized, cloud or Docker environments.

Pointers

The API makes extensive use of smart pointers. If an object uses a smart pointer, it will end with the suffix Ptr, for example IDOMIMagePtr. These can be a great help when developing in C++ as it reduces the burden of tracking ownership and ensuring correct memory de-allocation.

Opening a Document

Opening a document with the Mako SDK couldn't be simpler. All it takes is a few simple lines.

CPP
IJawsMako::enableAllFeatures(jawsMako);
IDocumentAssemblyPtr assembly = IPDFInput::create(jawsMako)->open(pdfPath);

In the case above, we create a new instance of JawsMako. From here, we enable all its features (including using PDF as in input format). The last step is to create an IPDFInput instance and open the PDF at the path specified by pdfPath.

Opening the path returns an IDocumentAssembly

You can access the document within the assembly by adding one additional line.

CPP
IDocumentPtr document = assembly->getDocument(0)

This gets the first document within the assembly.

Did you know?

An IDocumentAssembly can have more than one document inside it. PDFs have only one document, but other supported PDLs (page description languages) such as PCL/XL or XPS allow multiple documents, or 'Fixed Documents' within one assembly.

Document Pages

Once you have an IDocument, enumerating or modifying the pages is easy.

CPP
for (uint32 pageIndex = 0; pageIndex < document->getNumPages(); pageIndex++)
{
	// Get the page and do something with it
	IPagePtr page = document.getPage(pageIndex);
}

Once you have an IPage, you can begin querying the content.

Enumerating Page Content

Accessing the Page Content DOM

Once you have a page, you can enumerate its content. A Mako page exposes its content using a DOM (document object model). To get the root of the page, simply call either page::getContent(), or page::edit(), depending on whether you wish to read or edit the page data. This will return the root node of the DOM, which is an IDOMFixedPagePtr.

CPP
// Use this when you are reading the page content.
IDOMFixedPagePtr fixedPage = page->getContent();

// Use this when you want to edit the page content. This will give a hint to 
// Mako to retain the page in memory, even under low memory conditions.
IDOMFixedPagePtr fixedPage = page->getContent();

// If a page has been edited, you can revert changes by:
page->revert();

Enumerating DOM Nodes

Once we have the root of the DOM, IDOMFixedPagePtr, you can access further nodes in the DOM by using a number of different methods, including:

CPP
IDOMNodePtr firstChild = node->getFirstChild();
IDOMNodePtr lastChild = node->getLastChild();

IDOMNodePtr nextChild = node->getNextChild(firstChild);
IDOMNodePtr previousChild = node->getPreviousChild(lastChild);

IDOMNodePtr nextSibling = node->getNextSibling();
IDOMNodePtr nextSibling = node->getPreviousSibling();

Once you have an IDOMNodePtr, you can see which type it is, and cast it appropriately, by calling
node->getNodeType().

Below is an example of seeing whether a node is a path node, and casting it appropriately.

CPP
if (node->getNodeType() == eDOMPathNode)
{
	IDOMPathNode pathNode = edlobj2IDOMPathNode(node);
	// Do something with our path node...
}

For more details on casting, see the casting page.

There are also additional methods which allow all child nodes of a specific type to be returned in one call. 

For example, the following code can be used to get all child path nodes. 

CPP
IDOMFixedPagePtr fixedPage = page->getContent();

CEDLVector<IDOMNodePtr> pathNodes;
page->getContent()->findChildrenOfType(eDOMPathNode, pathNodes);

for (const auto& node : pathNodes)
{
    const auto pathNode = edlobj2IDOMPathNode(node);
	// Do something with our path node...
}

Custom Transforms

As an alternative, custom transforms can also be used to enumerate content. In this case, when a custom transform is implemented, you choose the methods to override, depending on which node types you want to review or edit.


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.