Search code examples
c++pdfxpsmako-sdk

How can I tile an image within a given area of a page in my document, using the Mako SDK?


I'm looking to use an image for tilling, to fill and area of my page, in my document.

I've seen that there is an IDOMImage and IDOMImageBrush, but I'm not sure how to use them in order to scale and tile my source image.

How can I do this with the Mako SDK?


Solution

  • Mako can tile an image into a given area, and also flip alternate tiles to create a pattern. Use a scaling transform to control its size. This code shows you how.

    // Declare an output pointer
    IOutputPtr output;
    
    // Create new assembly, document and page
    IDocumentAssemblyPtr assembly = IDocumentAssembly::create(jawsMako);
    IDocumentPtr document = IDocument::create(jawsMako);
    IPagePtr page = IPage::create(jawsMako);
    
    // Add the page to the document, and the document to the assembly
    document->appendPage(page);
    assembly->appendDocument(document);
    
    // Create a fixed page to work with
    double pageWidth = 10 * 96.0;
    double pageHeight = 20 * 96.0;
    IDOMFixedPagePtr fixedPage = IDOMFixedPage::create(jawsMako, pageWidth, pageHeight);
    
    // Load the image file into an image
    IDOMImagePtr image = IDOMJPEGImage::create(jawsMako, IInputStream::createFromFile(jawsMako, imageFilePath));
    
    // Find its dimensions
    IImageFramePtr frame;
    image->getFirstImageFrame(jawsMako, frame);
    double imageWidth = frame->getWidth();
    double imageHeight = frame->getHeight();
    
    // Create a rect to hold the image
    FRect printBounds(0.0, 0.0, pageWidth, pageHeight);
    
    // Create a transformation matrix to scale the image, taking into account the page proportions
    // Scaling factor is a float ranging from 0.0 to 1.0
    double pageWidthHeightRatio = pageWidth / pageHeight;
    FMatrix transform;
    transform.scale(scalingFactor, scalingFactor * pageWidthHeightRatio);
    
    // Stick the image in a brush
    IDOMBrushPtr imageBrush = IDOMImageBrush::create(jawsMako, image, FRect(), printBounds, transform, 1.0, eFlipXY);
    
    // And now create a path using the image brush
    IDOMPathNodePtr path = IDOMPathNode::createFilled(jawsMako, IDOMPathGeometry::create(jawsMako, printBounds), imageBrush);
    
    // Add the path to the fixed page
    fixedPage->appendChild(path);
    
    // This becomes the page contents
    page->setContent(fixedPage);
    
    // Write to the output
    output = IPDFOutput::create(jawsMako);
    output->writeAssembly(assembly, outputFilePath);
    

    Using this code, with this image:

    Original Image

    Produced this tilled image:

    Tiled Image

    The code uses an enum, eTileXY. These are the available tiling options:

    eTilingMode Tiling mode type enumeration.

    eNoTile
    No tiling. If the area to be painted is larger than the image, just paint the image once (in the location specified by the brush's viewport), and leave the remaining area transparent.

    eTile
    Tile image without any flipping or rotating of the image. A square image consisting of a single diagonal line between opposite corners would produce diagonal lines when tiled in this mode.

    eFlipX
    Tile image such that alternate columns of tiles are flipped horizontally. A square image consisting of a single diagonal line between opposite corners would produce chevrons running horizontally across the area when tiled in this mode.

    eFlipY
    Tile image such that alternate rows of tiles are flipped vertically. A square image consisting of a single diagonal line between opposite corners would produce chevrons running vertically across the area when tiled in this mode.

    eFlipXY
    Tile image such that alternate columns of tiles are flipped horizontally AND alternate rows of tiles are flipped vertically. A square image consisting of a single diagonal line between opposite corners would produce a grid of squares balanced on their points when tiled in this mode.