A spot colour is a named ink rather than a mixture of the process four. In a PDF it is a Separation colour space: a name, an alternate colour space for rendering without the ink, and a tint transform between the two.
\Com\Tecnick\Color\Spot is the registry. \Com\Tecnick\Color\Pdf extends it, so one object provides the parser, the registry and the writers.
Registering One
<?php
require_once __DIR__ . '/vendor/autoload.php';
$pdf = new \Com\Tecnick\Color\Pdf();
$key = $pdf->addSpotColorFromArray('PANTONE 032 C', [
'cyan' => 0.0,
'magenta' => 0.91,
'yellow' => 0.86,
'key' => 0.0,
]);
echo $key, "\n";
echo $pdf->getSpotColorObj('PANTONE 032 C')->getCssColor(), "\n";
echo $pdf->encodeSpotColorName('PANTONE 032 C'), "\n";
pantone032c
cmyk(0%,91%,86%,0%)
PANTONE#20032#20C
addSpotColor() takes a Cmyk object where addSpotColorFromArray() takes the components. Both return the registry key, which is what lookups match on: the name lowercased with every character outside [a-z0-9] dropped, so PANTONE 032 C keys as pantone032c. The name is stored as given and escaped when written to the PDF, where it becomes /PANTONE#20032#20C.
Lab Separations
$pdf->addSpotLabColor('My Lab Spot', 50.0, 10.0, -20.0);
echo $pdf->getSpotLabColorObj('My Lab Spot')->getCssColor(), "\n";
// the stored CMYK equivalent
echo $pdf->getSpotColorObj('My Lab Spot')->getCssColor(), "\n";
lab(50% 10 -20)
cmyk(22.3139%,24.8788%,0%,40.0602%)
addSpotLabColor() takes L*, a* and b* and up to four option arrays: white point, black point, range and col0. Those describe the Lab colour space written into the PDF. The CMYK equivalent stored alongside is computed under D65 regardless of the white point passed. It is what getSpotColorObj() returns and what a device colour falls back to.
A Lab alternate space describes the ink independently of any device. The CMYK one stores a device approximation, which is what a viewer renders when the ink is absent.
The Defaults
Eleven names are known without being registered:
| Swatch | Key | Name | C M Y K | Hex | CSS name |
|---|---|---|---|---|---|
none | None | 0.000000 0.000000 0.000000 0.000000 | #ffffff | not a CSS name | |
all | All | 1.000000 1.000000 1.000000 1.000000 | #000000 | not a CSS name | |
cyan | Cyan | 1.000000 0.000000 0.000000 0.000000 | #00ffff | #00ffff | |
magenta | Magenta | 0.000000 1.000000 0.000000 0.000000 | #ff00ff | #ff00ff | |
yellow | Yellow | 0.000000 0.000000 1.000000 0.000000 | #ffff00 | #ffff00 | |
key | Key | 0.000000 0.000000 0.000000 1.000000 | #000000 | not a CSS name | |
white | White | 0.000000 0.000000 0.000000 0.000000 | #ffffff | #ffffff | |
black | Black | 0.000000 0.000000 0.000000 1.000000 | #000000 | #000000 | |
red | Red | 0.000000 1.000000 1.000000 0.000000 | #ff0000 | #ff0000 | |
green | Green | 1.000000 0.000000 1.000000 0.000000 | #00ff00 | #008000 | |
blue | Blue | 1.000000 1.000000 0.000000 0.000000 | #0000ff | #0000ff |
Eight of them are also CSS colour names and, by default, resolve to the spot colour rather than the device colour. Seven agree with their CSS namesake. green does not: the spot Green is the full-intensity #00ff00, CSS green is the half-intensity #008000.
// the spot Green
echo $pdf->getColorObject('green')->getRgbHexColor(), "\n";
// the CSS green
echo $pdf->getColorObject('green', false)->getRgbHexColor(), "\n";
// 'key', 'all' and 'none' are spot-only names
var_dump($pdf->getColorObject('key', false));
echo '[', $pdf->getPdfFillColor('key', 1, false), "]\n";
#00ff00
#008000
NULL
[]
key, all and none are spot-only. With $allowSpot = false they do not resolve at all: getColorObject() returns null and the colour getters return an empty string.
none paints nothing and all paints on every plate, which is how registration marks are drawn. Both resolve from a plain colour string while $allowSpot is true.
Registration Is Explicit
// getColorObject() resolves without registering
$pdf->getColorObject('cyan');
echo count($pdf->getSpotColors()), "\n";
// getPdfFillColor() registers
$pdf->getPdfFillColor('cyan');
echo count($pdf->getSpotColors()), "\n";
0
1
getColorObject() resolves a spot colour without registering it. getPdfColor() and its wrappers register it, since the content stream will reference it. getPdfSpotObjects() therefore emits a resource for every spot colour the document uses and for no others.
Emitting Them
Objects first, resources second. The resource dictionary references object numbers, and a spot colour whose object was never written has none.
try {
echo $pdf->getPdfSpotResources();
} catch (\Com\Tecnick\Color\Exception $exc) {
echo $exc->getMessage(), "\n";
}
$pon = 10;
$pdf->getPdfSpotObjects($pon);
echo $pdf->getPdfSpotResources();
unable to reference a spot color that has no PDF object, call getPdfSpotObjects() first: pantone032c
/ColorSpace << /CS1 11 0 R >>
getPdfSpotObjects() takes the object number counter by reference, writes one object per registered spot colour, and leaves the counter on the last number it used. Put the output in the document body and the resource dictionary in the page resources.
11 0 obj
[/Separation /PANTONE#20032#20C /DeviceCMYK <</Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] /C1 [0.000000 0.910000 0.860000 0.000000] /FunctionType 2 /Domain [0 1] /N 1>>]
endobj
12 0 obj
[/Separation /My#20Lab#20Spot [/Lab << /WhitePoint [0.950500 1.000000 1.089000] /BlackPoint [0.000000 0.000000 0.000000] /Range [-128.000000 127.000000 -128.000000 127.000000]>>] << /FunctionType 2 /Domain [0 1] /Range [0.000000 100.000000 -128.000000 127.000000 -128.000000 127.000000] /C0 [100.000000 0.000000 0.000000] /C1 [50.000000 10.000000 -20.000000] /N 1>>]
endobj
/ColorSpace << /CS1 11 0 R /CS2 12 0 R >>
The two objects are 564 bytes and the resource dictionary 42 bytes. $pon went in at 10 and came out at 12.
getPdfSpotResourcesByKeys() writes a dictionary for a subset of the registered keys.
See Also
- tc-lib-color : the library overview.
- PDF Output : the operators, including the spot tint.
- CMYK : the usual alternate colour space.
- CIE Lab : the device-independent alternative.
- Standards : PDF/X and output intents.
- API reference : the generated class documentation.