Skip to content

v0.27.0

Choose a tag to compare

@nanbu nanbu released this 12 Sep 04:19
· 20 commits to main since this release

The last minor release before the 1.0 release candidate. Numbers gains pictures, shapes, text boxes, charts, the
print setup and a table's exact position on the canvas. The public surface has its final naming pass, and the
renames under Changed break source: each is a compile error at the line to change, mapped in
Migrating to 1.0. ReadOptions.cellLimit now holds for every reader, the codecs read and
write faster with the same bytes, and the documentation is English throughout, with a getting-started guide, a
cookbook whose recipes CI builds and runs, and llms.txt.

Added

  • Pictures, shapes and text boxes in Numbers (spec Appendix B.83). sheet.images and sheet.shapes are read
    from a Numbers sheet's canvas — the TSD.ImageArchive with its bytes under Data/, the TSWP.ShapeInfoArchive
    with its text, fill and outline — and written back as canvas objects: a picture becomes a data record and an
    image archive, a shape or a text box a rectangle path with a text storage of its own, every reference into the
    stylesheet declared the way Numbers declares it. Numbers places objects at a point, so an anchor reads back as
    .absolute; a cell anchor is written by summing the first table's rows and columns. Only the rectangle and the
    text box are drawn as measured — any other geometry is written as a rectangle and named (degraded), as is a
    text alignment. The reader's report for what stays out (a chart, a movie, a group, a picture that is not PNG /
    JPEG / GIF) is unchanged. ODS furigana was measured and stays reported: LibreOffice Calc discards text:ruby
    in a cell (spec Appendix B.70).

  • The print setup in Numbers (spec Appendix B.84). The sheet archive's own words are read and written:
    orientation, scale, margins, the first page number and the odd header / footer in Numbers' three zones (&L,
    &C, &R). &P becomes Numbers' page number — drawn in the centre of the footer, and said so when it was
    asked for elsewhere; other codes are dropped and named; even / first-page variants are dropped. The paper
    size, fit-to-pages, the print area, title rows and page breaks stay reported, now each by name. A Numbers
    document reads back with the footer Numbers prints (&C&P) and its scale (72 %).

  • Where a table stands on a Numbers canvas (spec Appendix B.85). Table.position (a CanvasPoint in points)
    is read exactly and written back; sheet.addTable(named:at:) places one. A table with a non-default anchor
    goes on the default 98 × 20 pt grid, and one with neither goes below the previous table as before.

  • The paper and the title rows in Numbers (spec Appendix B.86). The paper size goes onto the document (one per
    document; a sheet asking for another is said so) and comes back; title rows / columns from row 1 / column 1
    become the first table's header rows / columns repeated on every printed page. The print area and page breaks
    have no place and stay reported.

  • Ten shape geometries in Numbers (spec Appendix B.87): rectangle, rounded rectangle, ellipse, diamond,
    triangle, the four arrows and a line are drawn as bezier paths and recognised on the way back. Other presets
    are still rectangles, named with the list of what is drawn.

  • Charts in Numbers (spec Appendix B.88). sheet.charts is read from a Numbers canvas — the kind, title and
    legend, and each series' values, categories and name reference followed back through the chart mediator's
    formulas to the table cells — and written: a column, bar, line or pie chart becomes a chart drawable over the
    template's style preset, with its cached grid, its mediator and its registration with the calculation engine.
    Numbers opens the written chart, saves it again and exports it to Excel with the chart intact (judged). Chart
    gains frame (a CanvasRect in points); the XLSX and ODS writers place a chart that
    only has a frame over the cells it covers. A chart whose data is not linked to a table stays reported.

Changed

The last look at the public surface before 1.0 (spec Appendix B.89). Each change is a rename or a narrowing that the
compiler points at; no alias is kept.

  • SheetImage.Anchor.absolute(x:y:width:height:)SheetImage.Anchor.absolute(CanvasRect) — one rectangle type
    for a position on the canvas, the one Chart.frame already uses.
  • addSparkline(_:data:at:)addSparkline(_:dataRange:at:), now with a CellRef twin beside the A1 string, and
    SparklineGroup.Sparkline(dataRange:location:)SparklineGroup.Sparkline(dataRange:at:) — one label per role.
  • addTable(named:anchor:)addTable(named:at:) — the same label as the canvas-point form, told apart by type.
  • IconSet.Icon.setIconSet.Icon.setName, the word IconSet.name uses for the same kind of value.
  • PhoneticText.Run.start and endPhoneticText.Run.range, a Range<Int> of UTF-16 code units made with
    Run(_:over:). The reader clamps a file whose eb comes before its sb instead of trapping on it.
  • DataBar.isGradientDataBar.gradient, the attribute's own word, like percent and reverse.
  • Alignment.wrapTextAlignment.wrapsText and Alignment.shrinkToFitAlignment.shrinksToFit — the two
    imperative Bools 0.24.0's pass missed, spelled the way its fitToPagefitsToPage already is. A test now scans the
    whole public surface for the naming rules, so the next one is caught when it is written.
  • No longer public, because each answered a codec's question rather than a caller's: CommentThread.mirrorPrefix,
    Chart.anchorOrFrameCells, Chart.Kind.drawable (ask isDrawable), Shape.Geometry.presets (ask isPreset)
    and DataBar.usesExtension.
  • A shape made with Shape(_:) and appended by hand covers cell A1 as a span instead of borrowing a picture's
    .original size, so the XLSX and Numbers writers draw it at the same size.
  • The warning for preserved parts a conversion cannot carry names what they hold, from the inventory
    (…; what they hold: pivot 2, slicer 1); the ODS writer's no longer guesses "charts, drawings, VBA…".
  • Cell.init takes thread: like every other extra; CanvasPoint and CanvasRect are Codable;
    PreservationSummary is Hashable; assigning Theme.colors normalises to AARRGGBB, as the initialiser does.

Fixed

  • ReadOptions.cellLimit stops XLSX, Numbers and delimited-text reads too (spec Appendix B.90). It was documented
    as the cell budget for untrusted input in every format, but only the ODS reader counted. One budget covers the
    workbook, sheets parsed side by side included; a sheet that reaches it keeps the cells read so far and says so
    with a degraded warning. With no limit set, nothing is counted.

Performance

  • XLSX reads and writes a quarter to a third faster (spec Appendix B.91). Measured on a million cells, the old
    and the new build run alternately five times each at the same time: write 1.54 → 1.09 s and 254 → 214 MB peak,
    read 2.61 → 1.85 s at 216 MB, row-by-row read 1.85 → 1.35 s at 13 MB, row-by-row write 1.84 → 1.51 s at 11 MB,
    open-edit-save 3.87 → 2.59 s and 255 → 211 MB. A cell with the default style is written without hashing its style
    and read without copying one, a number is trimmed only when its ends are not plain ASCII, a read cell is stored
    once, a dense sheet's rows are written straight from its extent, dated cells share one style per format, and the
    writers' style caches are bounded. The bytes written are unchanged.
  • ODS, CSV and Numbers too (spec Appendix B.91), measured the same way: write ODS 3.39 → 2.25 s, row-by-row
    write ODS 3.52 → 2.50 s, read ODS 3.59 → 3.16 s, read CSV 1.76 → 1.32 s, row-by-row read CSV 1.31 → 0.87 s, write
    CSV 0.88 → 0.65 s, write Numbers 3.90 → 2.20 s, row-by-row write Numbers 3.57 → 3.07 s, each at the peak memory it
    had. The ODS writer works out a cell's style facts once per style, delimited text tests its rules on bytes with one
    locale, and the Numbers writer encodes an integer without long division and its style keys once per style.
  • Fewer copies in the model's own cells (spec Appendix B.91): a cell a reader or an append creates is made without
    comparing the default style with itself, and delimited text reserves its table for the fields it parsed. Building
    the model 0.57 → 0.47 s at 203 MB; read CSV 1.27 → 1.12 s and 238 → 165 MB peak; the XLSX, ODS and Numbers readers
    5–7% faster at the same peak.

Full changelog: 0.26.0...0.27.0