Skip to content

To PDF

When printing on a non-white medium or on a special medium like fabric or glass, printing your design over an underlayer helps achieve the desired result. An underlayer will typically be printed using a special ink and be of the exact shape of your design.

When exporting to PDF, you can specify that an underlayer be automatically generated in the ExportOptions. An underlayer will be generated by detecting the contour of all elements on a page and inserting a new block with the shape of the detected contour. This new block will be positioned behind all existing block. After exporting, the new block will be removed. The result will be a PDF file containing an additional shape of the same shape as your design and sitting behind it.

The ink to be used by the printer is specified in the ExportOptions with a spot color. You can also adjust the scale of the underlayer shape with a negative or positive offset, in design units.

Setup the scene

We first create a new scene with a graphic block that has a color fill.

val scene = engine.scene.create()
val page = engine.block.create(DesignBlockType.Page)
engine.block.setWidth(page, value = 800F)
engine.block.setHeight(page, value = 600F)
engine.block.appendChild(parent = scene, child = page)
val block = engine.block.create(DesignBlockType.Graphic)
engine.block.setShape(block, shape = engine.block.createShape(ShapeType.Star))
engine.block.setPositionX(block, value = 350F)
engine.block.setPositionY(block, value = 400F)
engine.block.setWidth(block, value = 100F)
engine.block.setHeight(block, value = 100F)
val fill = engine.block.createFill(FillType.Color)
engine.block.setFill(block, fill = fill)
val rgbaBlue = Color.fromRGBA(r = 0F, g = 0F, b = 1F, a = 1F)
engine.block.setColor(fill, property = "fill/color/value", value = rgbaBlue)

Add the underlayer’s spot color

Here we instantiate a spot color with the known name of the ink the printer should use for the underlayer. The visual color approximation is not so important, so long as the name matches what the printer expects.

engine.editor.setSpotColor(name = "RDG_WHITE", Color.fromRGBA(r = 0.8F, g = 0.8F, b = 0.8F))

Exporting with an underlayer

We enable the automatic generation of an underlayer on export with the option exportPdfWithUnderlayer = true. We specify the ink to use with underlayerSpotColorName = 'RDG_WHITE'. In this instance, we make the underlayer a bit smaller than our design so we specify an offset of 2 design units (e.g. millimeters) with underlayerOffset = -2.0.

val mimeType = MimeType.PDF
val options = ExportOptions(
exportPdfWithUnderlayer = true,
underlayerSpotColorName = "RDG_WHITE",
underlayerOffset = -2.0F,
)
val blob = engine.block.export(scene, mimeType = mimeType, options = options)
withContext(Dispatchers.IO) {
File.createTempFile("underlayer_example", ".pdf").apply {
outputStream().channel.write(blob)
}
}

Full Code

Here’s the full code:

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ly.img.engine.Color
import ly.img.engine.DesignBlockType
import ly.img.engine.Engine
import ly.img.engine.ExportOptions
import ly.img.engine.FillType
import ly.img.engine.MimeType
import ly.img.engine.ShapeType
import java.io.File
fun underlayer(
license: String,
userId: String,
) = CoroutineScope(Dispatchers.Main).launch {
val engine = Engine.getInstance(id = "ly.img.engine.example")
engine.start(license = license, userId = userId)
engine.bindOffscreen(width = 100, height = 100)
val scene = engine.scene.create()
val page = engine.block.create(DesignBlockType.Page)
engine.block.setWidth(page, value = 800F)
engine.block.setHeight(page, value = 600F)
engine.block.appendChild(parent = scene, child = page)
val block = engine.block.create(DesignBlockType.Graphic)
engine.block.setShape(block, shape = engine.block.createShape(ShapeType.Star))
engine.block.setPositionX(block, value = 350F)
engine.block.setPositionY(block, value = 400F)
engine.block.setWidth(block, value = 100F)
engine.block.setHeight(block, value = 100F)
val fill = engine.block.createFill(FillType.Color)
engine.block.setFill(block, fill = fill)
val rgbaBlue = Color.fromRGBA(r = 0F, g = 0F, b = 1F, a = 1F)
engine.block.setColor(fill, property = "fill/color/value", value = rgbaBlue)
engine.editor.setSpotColor(name = "RDG_WHITE", Color.fromRGBA(r = 0.8F, g = 0.8F, b = 0.8F))
val mimeType = MimeType.PDF
val options = ExportOptions(
exportPdfWithUnderlayer = true,
underlayerSpotColorName = "RDG_WHITE",
underlayerOffset = -2.0F,
)
val blob = engine.block.export(scene, mimeType = mimeType, options = options)
withContext(Dispatchers.IO) {
File.createTempFile("underlayer_example", ".pdf").apply {
outputStream().channel.write(blob)
}
}
engine.stop()
}