Created Date: 30 Jan, 2024 15:55
Last Modified Date: 01 Feb, 2024 15:58


Introduction

This release is a mixture of new development and fixes, almost all inspired by customer support requests, the wide range of which tells us that Mako is being put to work in lots of different ways.

Solutions for specific support issues included in this release are labelled MAKOSUP-XXXXX. The link is live and can be followed to the (new cloud-based) Mako support portal but will work only for the customer who reported it.

Issues addressed

MAKO-4675

MAKOSUP-11289 Converting PDF document to PDF/X-1a using Mako 7.1.0

This was caused by a bug that is now fixed.

MAKO-4674

MAKOSUP-11292 Problem rasterizing pdf.

When generating an alpha channel, an exception was thrown when a separation colour space was used with a process component as the name. Now fixed.

MAKO-4676

MAKOSUP-11293 Problem rasterizing PDF

The customer exhibit had an unusual arrangement of separation (spot) colors that caused a rendering issue. Now fixed.

MAKO-4696

MAKOSUP-11307 Accessing the Page Content causes RIP error

The customer exhibit had a badly broken xref (cross-reference) table, so much so that it prevented Mako’s usual repair function from completing normally. Now fixed.

MAKO-4701

MAKOSUP-11308 Importing a TIFF results in broken DOM?

The customer exhibit was a TIFF in a Lab colorspace, which until this release Mako did not support. The TIFF input class has now been extended to support Lab, automatically generating a Lab colorspace with a D65 whitepoint.

MAKO-4702

MAKOSUP-11309 Showing/Flattening annotations fails

This issue was caused by the lack of annotation ‘appearances’, content to provide a visual for display or printing. Mako can generate appearances for common annotation types, but in this case, template content for the annotation types used was absent. This is rectified in this release and the customer exhibit processes normally.

A new method, createNormalAppearance(), can be used to generate an appearance when one is not already available. This code demonstrates how to use it.


/* -----------------------------------------------------------------------
 * <copyright file="RenderAnnotationsCS.cs" company="Global Graphics Software Ltd">
 *  Copyright (c) 2022-2024 Global Graphics Software Ltd. All rights reserved.
 * </copyright>
 * <summary>
 *  This example is provided on an "as is" basis and without warranty of any kind.
 *  Global Graphics Software Ltd. does not warrant or make any representations
 *  regarding the use or results of use of this example.
 * </summary>
 * -----------------------------------------------------------------------
 */

using JawsMako;

namespace RenderAnnotationsCS;

internal class Program
{
    static void Main(string[] args)
    {
        try
        {
            var mako = IJawsMako.create();
            IJawsMako.enableAllFeatures(mako);
            var page = IInput.create(mako, eFileFormat.eFFPDF).open(@"..\..\..\..\TestFiles\annots.pdf").getDocument().getPage(0);

            // Render without annotations
            var renderer = IJawsRenderer.create(mako);
            var renderedImage = renderer.render(page.getContent());
            IDOMPNGImage.encode(mako, renderedImage, IOutputStream.createToFile(mako, "rendered_without_annotsCS.png"));

            // Generate appearances and add to page
            FlattenAnnotations(ref page);

            renderedImage = renderer.render(page.getContent());
            IDOMPNGImage.encode(mako, renderedImage, IOutputStream.createToFile(mako, "rendered_with_annotsCS.png"));
        }
        catch (MakoException e)
        {
            Console.WriteLine($"Mako exception thrown: {e.m_msg}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Exception thrown: {e}");
        }
    }

    static void FlattenAnnotations(ref IPage page)
    {
        CEDLVectIAnnotation annotations = page.getAnnotations();
        foreach (var annotation in annotations.toVector())
        {
            IMarkupAnnotation markup = IMarkupAnnotation.fromRCObject(annotation.toRCObject());
            if (markup is null)
                continue;

            IAnnotationAppearance appearance;
            if (markup.hasNormalAppearance())
                appearance = markup.getAppearance(eAppearanceUsage.eAUNormal);
            else
            {
                try
                {
                    appearance = markup.createNormalAppearance();
                }
                catch (MakoException)
                {
                    continue;
                }
            }

            page.edit().appendChild(appearance.getScaledAppearance(markup.getRect()));
        }
    }
}

C#
/* -----------------------------------------------------------------------
 * <copyright file="RenderAnnotations.cpp" company="Global Graphics Software Ltd">
 *  Copyright (c) 2022-2024 Global Graphics Software Ltd. All rights reserved.
 * </copyright>
 * <summary>
 *  This example is provided on an "as is" basis and without warranty of any kind.
 *  Global Graphics Software Ltd. does not warrant or make any representations
 *  regarding the use or results of use of this example.
 * </summary>
 * -----------------------------------------------------------------------
 */

#include <iostream>

#include <jawsmako/jawsmako.h>
#include <jawsmako/pdfoutput.h>

using namespace JawsMako;
using namespace EDL;

void flattenAnnotations(const IPagePtr& page)
{
    CAnnotationVect annotations = page->getAnnotations();
    for (const auto& annotation : annotations)
    {
        const IMarkupAnnotationPtr markup = obj2IMarkupAnnotation(annotation);
        if (!markup)
            continue;

        IAnnotationAppearancePtr appearance;
        if (markup->hasNormalAppearance())
            appearance = markup->getAppearance(eAUNormal);
        else
        {
            try
            {
                appearance = markup->createNormalAppearance();
            }
            catch (IEDLError& e)
            {
                // if the annotation type has no template, ignore and carry on
                if (e.getErrorCode() == JM_ERR_UNSUPPORTED)
                    continue;
            }
        }

        page->edit()->appendChild(appearance->getScaledAppearance(markup->getRect()));
    }
}

int main()
{
    try
    {
        const auto mako = IJawsMako::create();
        mako->enableAllFeatures(mako);
        const auto page = IInput::create(mako, eFFPDF)->open(R"(TestFiles\annots.pdf)")->getDocument()->getPage(0);

        // Render without annotations
        const auto renderer = IJawsRenderer::create(mako);
        auto renderedImage = renderer->render(page->getContent());
        IDOMPNGImage::encode(mako, renderedImage, IOutputStream::createToFile(mako, "rendered_without_annots.png"));

        // Generate appearances and add to page
        flattenAnnotations(page);

        renderedImage = renderer->render(page->getContent());
        IDOMPNGImage::encode(mako, renderedImage, IOutputStream::createToFile(mako, "rendered_with_annots.png"));
    }
    catch (IError& e)
    {
        const String errorFormatString = getEDLErrorString(e.getErrorCode());
        std::wcerr << L"Exception thrown: " << e.getErrorDescription(errorFormatString) << std::endl;
        return static_cast<int>(e.getErrorCode());
    }
    catch (std::exception& e)
    {
        std::wcerr << L"std::exception thrown: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

CPP


MAKO-4717

MAKOSUP-11316 Problem rasterizing PDF in CMYK color space

This was an alpha channel generation issue that is fixed in this release.

MAKO-4716

MAKOSUP-11311 Segmentation fault on Alpine Linux

A previous change to Mako led to a situation where stack space was exhausted on platforms with a small default stack size, as is the case with Alpine Linux. Now fixed.

MAKO-4723

MAKOSUP-11323 Mako fails to render PDF/X-1

The issue with the customer file was traced to a floating-point error when processing a Type 1 Shading. Now fixed.

MAKO-4745

MAKOSUP-11333 Access violation during deallocation of IJawsRenderer

Fixing a bug in the FreeType library solved this problem.

New features and improvements

MAKO-4670

MAKOSUP-11252 Overprint ignored by renderSeparations if an ICC profile is used

The customer needed to render to a CMYK ICC profile but to treat DeviceCMYK as colors on the device, so that overprint would not be ignored. To simplify this process, a new API is added: setIgnoreMatchingDeviceIntercept(bool ignoreDeviceIntercept). As the name suggests, it allows intercept color spaces for a matching Device space to be ignored. The new API’s documentation explains more:

In the renderer, when a Device color space (DeviceRGB, DeviceCMYK, or DeviceGray) is seen, it is interpreted according to the intercept colour space set in the IColorManager instance via the setDevice*Intercept() routines.

This may not always be desirable. Consider the case where a CMYK ICC profile is used as the output color space for rendering. If the DeviceCMYK intercept does not match that profile, then any DeviceCMYK content would be color converted from the intercept color space to the output profile.

This behavior is contrary to what would ordinarily be seen in a standalone RIP where it is expected that if the output is a CMYK profile, then any DeviceCMYK content would be passed through without conversion.

Although the required result can be achieved in Mako by using IColorManager::setDeviceCMYKIntercept() to apply the output ICC profile as the DeviceCMYK intercept, this is a global setting and it may not always be possible to do so.

When ignoreDeviceintercept is set, then the renderer will do the following:

      • If the output is a CMYK color space, then any DeviceCMYK content will be interpreted as matching that space
      • If the output is an RGB color space, then any DeviceRGB content will be interpreted as matching that space.
      • If the output is a Gray color space, then any DeviceGray content will be interpreted as matching that space.

MAKO-4662

A different method for vector flattening to maintain Beziers, strokes, and text

This is the final major improvement to the vector-based transparency flattener built into Mako (IRendererTransform->setEnableVectorMode()). Previously, curves were approximated with a series of straight lines (polylines); with this improvement, a Bezier is described instead which not only improves the quality of the result, is more economic in terms of the number of objects needed to describe a given figure. Additionally, text is no longer routinely converted to curves when it intersects a region of transparency on the page. This retains the ability to copy textual content from the PDF and helps to maintain accessibility.

MAKO-4691

Add an option to set any fonts that take part in vector flattening to embed on output

A new IRendererTransform API, setMarkVectorFlattenedFontsForEmbedding(bool) is added to enable font embedding of fonts involved in vector-based transparency flattening. This is to help ensure the output is correct should the font be unavailable on the target system or device.

MAKO-4651

Support version of ILayoutFontWeight that accepts a range of weights

ILayoutFontWeight selects a font by weight, i.e. how bold it is. An enum, eFontWeight, offers sensible choices such as eBold, eExtraBlack etc. These can now be included in a range, supplied either as two single values (ILayoutFontWeight::createFromRange() or a CUInt16Vect containing those values ILayoutFontWeight::createFromVect(). (A CUint16Vect is a vector of two 16-bit integer values.)

The purpose of this API is to make it possible to write cross-platform code that can pick a font based on typographic properties alone.

MAKO-4624

Duplicate glyph names when adding to CFF font.

Improvement to ensure there is no duplication of glyph names when processing CFF (Compact Font Format) information, in OpenType fonts.

MAKO-4555

Correct code hint for ILayoutTextRun::create()

An error in the Doxygen comments for this method are corrected.

MAKO-4641

Support IPDFPageInserter and IPDFPageExtractor classes in C#, Java & Python

These classes were added in an earlier version of Mako but until now were not available in the C#, Java and Python APIs. A simple C# example can be found in the Knowledge Base.

MAKO-4668

Enable IJawsRenderer::renderSeparations to ignore prescribed spot components

IJawsRenderer::renderSeparations offers a means to retain spot colors in the output. When retainedSpotColors is specified, a separation is produced for that color, and content making use of that spot color is excluded from the process (i.e., CMYK) separations.

Until now, if you wanted to exclude a spot from the process separations but had no use for the spot separation, it was necessary to produce one then throw it away.

The new parameter is ignoreSpotColors. When specified, the identified spot color(s) is/are excluded from the process separations, but no separation is produced.

MAKO-4742

Add API to CInkInfo to set the inkName

In C++, it’s possible to create an instance of the CInkInfo class and set the ink name property, but this wasn’t possible in C# (or Java /Python). The addition of CInkInfo.setInkName() addresses this shortcoming.

MAKO-4539


Form deduplication

As part of work aimed at optimizing PDFs, significant improvements have been made to the IFormDeduplicatorTransform. This custom transform looks for and eliminates duplicate form objects (XObjects) in a PDF. Besides reducing file size, such preprocessing can significantly reduce the work a PDF consumer such as a RIP has to do, thereby improving performance.

In practice, it was found that it couldn’t always detect equivalency where functionally equivalent forms are used in different locations or under different matrix translations. The changes in this release overcome this limitation, improving optimization of the PDF still further. Such optimization is highly effective for long labels and packaging jobs with a high occurrence of repeated content.

MAKO-4652

ILayoutFont: Improve performance when finding fonts.

The font discovery APIs in the ILayout class revealed some poor performance when scanning a system for fonts. This change addresses that issue leading to much improved performance of multiple font queries.

MAKO-4611

Add default font specification to ILayoutParagraph

New parameters are now available when creating an ILayoutParagraph to specify a default font, its size and color for any run in the paragraph that doesn’t specify these explicitly. There are associated get/set methods for these too. Existing ILayoutTextRun APIs have been edited to allow these parameters to be excluded, signalling that they should inherit from the parent ILayoutParagraph.

Other

MAKO-4660

MAKOSUP-11282 Support for Windows ARM64 (C++)

In response to a customer request, we have added a Windows ARM64 build to the Mako distributions. Both dynamically- and statically-linked builds are now available, complete with NuGet packages.

MAKO-4724

MAKOSUP-11317 Add macOS to cross-platform JAR

To simplify deployment, a customer requested a single JAR with both Windows and Linux Java libraries for Mako. This was included in the Mako 7.1.0 release. Now another customer has asked for the same, with the addition of macOS. This is delivered in this release and can be found in the SWIG/CrossPlatformJAR folder. As the macOS library is a universal binary (ARM & Intel) and therefore quite large, two configurations are provided: the original Windows & Linux combination and another with Windows, Linux & macOS.

MAKO-4708

Update Alpine version to 3.17

A customer issue led us to consider updating the version of Alpine Linux with which we build Mako. This we have done in this release, updating from v3.9 (which is out of support) to v3.17.

MAKO-4694

Remove the IDOMCharPathGroup::get/setBlendMode() methods

These methods are removed as they don’t work as intended and applying a transparency group has the same effect.

MAKO-4725


Update .NET dependency in SWIG builds

  • Linux: The .NET build of Mako for Linux is updated to .NET 7.0, from .NET 3.1 that is no longer supported.
  • macOS: The examples now reference .NET 8.0

MAKO-4636

Remove the IJawsRenderer::renderAntiAliasedToFrameBuffer API

This API was deprecated in Mako 7.1.0 and is removed in this release.

Distribution

MAKO Version 7.2.0 is built for the following platforms:

  • iOS
  • macOS
  • Linux (for Debian-based distributions, eg Ubuntu 22.04 LTS, Mint)
  • Linux (for Debian Bullseye)
  • Linux (for Debian Buster)
  • Linux (for Alpine Linux v3.17)
  • Linux (Centos)
  • Linux (Red Hat Enterprise v7.0)
  • Linux (Red Hat Enterprise v8.4)
  • Linux (for Debian Buster) (arm32v7 for Raspberry Pi)
  • Linux (for Debian Bullseye) (arm64v8 for Raspberry Pi)
  • Windows (static and dynamic libs, VS 2019 (V142), x86, x64 and ARM64)
  • Windows (static and dynamic libs, VS 2017 (V141), x64)
  • Windows UWP/WinRT

N.B. The Android build is excluded from this release. Contact Mako support if you need Mako for Android.

Mako supports the following programming languages.

  • C++ (Mako is written in C++)
  • C# (.Net Core (multiple platforms) and .Net Framework (Windows only))
  • Java (built with OpenJDK11 and therefore compatible with later versions.)
  • Python (v3.8 / 3.9)

The alternatives to C++ are built using SWIG (www.swig.org) which provides a translation to the native libraries. They found in these distribution folders, found in the SWIG folder:

  • Linux_SWIG_(C#-Java-Python)
  • Linux_Centos7_SWIG_(C#-Java-Python)
  • Linux_Centos8_SWIG_(C#-Java-Python)
  • Linux_Ubuntu_SWIG_(C#-Java-Python)
  • macOS_SWIG_(C#-Java-Python)
  • Windows_SWIG_(C#-Java-Python)

Cross-platform Java build

The folder SWIG/CrossPlatformJAR contains Java builds that combine the implementations for multiple platforms into a single JAR package, thereby simplifying deployment. The folder contains two combinations, one for Windows & Linux and another for Windows, Linux and macOS. A pre-built sample app (makoconverter.jar) is included.

ColorLogic

Mako is available with the ColorLogic CMM, supplied by our Hybrid Group sister company, ColorLogic Gmbh. All builds can be found in the ColorLogic folder. C++ builds are available for Windows, macOS and Linux, and there is also a Windows SWIG build for development with C#, Java or Python that uses the ColorLogic CMM.