* Text frames: column rules draw between columns on screen and in PDF
A frame with Column Rule on gets a bar centred in each gutter, inside the
insets, broken around paragraphs that span columns; right-to-left and
vertical frames included. object.textFrameOptions takes columnRuleWeight
and columnRuleColor (unknown swatches are an error) and an inset array
whose null sides stay; document.inspect reports the rule.
* Text Frame Options: Column Rules fields; OK changes only edited fields
The dialog shows the selected frame's options, with an inset field per
side, and sends only what the user changed, so unequal insets survive.
The rule weight is read in points.
* Column rules: tint, horizontal offset and top/bottom insets; IDML import and export
Text Frame Options gains Tint %, Top Inset, Bottom Inset and Horizontal
Offset for the rule, and object.textFrameOptions and document.inspect
take and report them. IDML reads the ColumnRule attributes of
TextFramePreference on frames and object styles and writes them when a
rule is set.
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- An RGB image with no ICC profile of its own was written as DeviceRGB
under the CMYK output intent, and the export only warned. In PDF/X-4
it now carries the sRGB profile (assets/icc/sRGB-v2-magic.icc, ICC
v2.1, CC0). JPEGs stay passed through. Untagged PNG, GIF and WebP,
and the decoded TIFF, BMP and PSD fallback, go in as RGB with the
profile. A re-encoded JPEG keeps the source's RGB profile or gets
sRGB. Grey images and images with their own profile are unchanged.
- Every image constructor asked for interpolation. PDF/X-4 and PDF/A
exports now write images without it, which also removes the
ImageInterpolation error that stopped PDF/A exports with a placed
image. Plain exports keep it.
- make_pdfx4 writes pdf:Trapped False into the XMP, matching
/Trapped/False in the document information.
- check_pdfx4 reports an image that asks for interpolation.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
A placed PNG, GIF or WebP that is cut off (an interrupted download) or
has a bad checksum made the whole PDF export fail with
"PDF writer error: Image(Image(ImageRepr {..}), None, "unexpected end of
file")", which names no file. A damaged TIFF or BMP in the same place is
skipped with the warning "image `name` could not be decoded and was
skipped", and the rest of the document is exported.
The exporter decides whether an image can be embedded by asking krilla
to open it. krilla opens PNG, GIF and WebP lazily: it reads the header,
accepts the file, and decodes the pixels only when the PDF is written,
where an error ends the export. TIFF and BMP are decoded by us first, so
they took the skip path.
lossless() now decodes the image first for every format. A file that
does not decode returns None and takes the existing skip-with-warning
path. This costs one extra decode per PNG, GIF or WebP asset: the sample
magazine (two PNGs, 820 KB) exports in 0.19 s instead of 0.17 s in a
debug build.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* PDF: PDF/A exports keep placed PNG, JPEG, GIF and WebP images by writing them without interpolation (#71)
* Tables: new tables take their paragraph's direction, and the Table panel sets a table's direction (#100)
* Text: stories made in a right-to-left-bound document fill their columns from the right (#100)
A character the applied font lacks is drawn as that font's missing-glyph
box (its .notdef, gid 0), on screen and in PDF, and Preflight lists the
characters by font ("Missing glyphs in <family> <style>: …", an error,
at most 20 named). A .notdef without an outline is drawn as a hollow box
across its advance, so a missing character never disappears. PDF draws
.notdef glyphs as paths, which PDF/A and PDF/UA accept. Kenten marks are
set in their text's font the same way.
The document setting Draw Missing Glyphs from Fallback Fonts
(DocSettings::glyph_fallback; Preferences > Composition,
document.preferences {glyphFallback}, undoable) draws them from fallback
fonts instead (the language-aware chains, then any font; kenten marks
from a fallback font, else a bullet). It is off in new documents and
IDML imports and on in files saved before it existed, which keep
drawing as they did. A missing font's substitute always uses fallback
fonts. The composition cache's signature includes the setting. Tests
whose Arabic comes from a fallback font turn the setting on.
Vertical is a story property: every frame of a thread is vertical or
horizontal together, a frame threaded onto a story takes its direction,
and frames split off by threading or breaking a thread keep theirs.
Type > Story Direction is type.storyDirection {vertical} (checked in the
menu) for the stories of the text selection or selected frames;
object.textFrameOptions {vertical} and frame.create {vertical} set the
frames' stories. Documents that stored Vertical on the frame open with
each story taking its first frame's direction. IDML StoryOrientation is
read into and written from the story, beside its column direction
(StoryDirection), which stays a separate setting.
check_pdfx4 didn't look at colour spaces, so a placed RGB PNG (or a CMYK
TIFF converted to RGB, #35) went into a PDF/X-4 file as DeviceRGB under the
CMYK output intent with an empty warnings list. PDF/X-4 lets RGB in only
when it is colour-managed: ICCBased, or DeviceRGB remapped by a DefaultRGB
colour space. DeviceCMYK and DeviceGray are the intent's own values.
The check now reads the file with hayro-syntax and, when the PDF/X output
intent's profile has four channels, walks each page: its content, the
images, forms (placed PDFs), patterns, shadings and soft masks it uses, and
the transparency groups. It reports DeviceRGB (or Indexed over it) images
with their object number and pixel size, RGB fills and strokes, RGB
gradients, RGB inline images and groups blending in RGB, each with the pages
it is on, unless a DefaultRGB is in scope. Like the other PDF/X findings
these are export warnings. The separate "some transparency groups still
blend in RGB" warning is gone: the group check covers it, with the page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A CMYK TIFF went into every PDF, PDF/X-4 included, as a DeviceRGB image:
load_image sent anything that wasn't JPEG, PNG, GIF or WebP through
designcraft_images::decode_rgba, and `image` decodes CMYK TIFFs to RGB. 100%
K came out as RGB black, which the press separates as four-colour black
(#35).
designcraft-images now reads a CMYK TIFF's ink values with the tiff crate
(the version `image` already uses): 8- or 16-bit, interleaved, opaque or
with unassociated alpha. PDF export writes them through krilla's CustomImage
as DeviceCMYK, as it does a CMYK JPEG, and leaves out the TIFF's own ICC
profile so the numbers go to the output intent's press unchanged. PDF/A
exports stay RGB. A CMYK TIFF this can't read (planar, premultiplied alpha,
another ink set, over 256 MiB) is still converted, now with a warning. The
screen keeps decoding to RGB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CMYK rewrite matches krilla's exact output; if that ever changes,
the export says so instead of silently writing RGB groups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krilla gives every transparency group it writes a DeviceRGB blending space,
including the group around a placed PDF page:
/Group<</Type/Group/S/Transparency/I true/CS/DeviceRGB>>
A print file therefore carried DeviceRGB (forbidden by PDF/X-4 under a CMYK
output intent) and blended CMYK art through RGB: a placed logo's black,
C91 M78 Y61 K97 in its own file, printed as C72 M67 Y67 K88. When the
document's transparency blend space is CMYK (the default for print) or the
export is PDF/X-4, the groups are rewritten to /CS/DeviceCMYK in place and
at the same length (the optional /Type/Group gives the room, the rest is
padded with spaces), only inside object dictionaries found through the
cross-reference table, so every offset stays valid. Booklets get the same.
Books merged by merge_pdfs are not covered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PDF/X-4 export (PDF 1.6) of a page with a placed PDF 1.7 (VectorCraft's
default, and most tools') failed at the very end with
designcraft-cli: PDF writer error: Pdf(PdfDocument(PdfDocumentRepr { .. }), VersionMismatch(Pdf17), None)
krilla refuses to embed a PDF newer than the file it writes. PDF 1.7 changed
nothing in how a page draws, so a 1.7 file now goes in as 1.6 (its header
relabelled, as qpdf --force-version=1.6 does) with a warning. A PDF 2.0
file, or one whose catalog declares 1.7, fails the export with a message
naming it. hayro-syntax moves from dev-dependencies to dependencies (krilla
already builds it) because the check names its PdfVersion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Paper] was written as DeviceRGB white (`1 1 1 rg`) even in print documents
and PDF/X-4 files: an RGB object in a CMYK print file, which print preflight
rejects. For the Print intent and for PDF/X it is now `0 0 0 0 k` (CMYK, no
ink, still knocking out what lies below); Web and Mobile documents keep RGB
white.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rasters stay below vello_cpu's u16 limits (a 65535-pixel-wide render
panicked inside it), page renders larger than 2^29 pixels decline instead of
allocating, PNG encoding never panics, and the PDF heading tag can't fail.
Both crates deny the panicking lints.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- color: Swatch.hidden — unnamed colours (applied, not listed in Swatches until added)
- engine: object.color (reuses a swatch with the same colour, else an unnamed one; fill or
stroke), swatch.addToSwatches (optionally named; users follow the rename),
swatch.addUnnamed (+ test)
- UI: Color panel with fill/stroke proxy, CMYK/RGB/Lab, channel sliders with gradient tracks and
value fields, tint slider for named swatches, spectrum ramp, Add to Swatches; Color Picker
dialog (double-click a proxy chip); Swatches hides unnamed colours
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>