Repository navigation
Round the corners of a table cell with border-radius (#603) - #734
Open
gravitypdf-bot wants to merge 2 commits into
Open
gravitypdf-bot wants to merge 2 commits into
gravitypdf-bot wants to merge 2 commits into
Conversation
A cell's border-radius was read and never used, so rounded table cards and cells came out square. In the separated borders model a cell's backgrounds, its row's showing through it included, are now clipped to its rounded border box, and its border is stroked side by side along the corners as an image's is, with double and the 3D styles in the tones a square cell takes. Under border-collapse: collapse CSS ignores the radius, so the cell is drawn as before; simple tables and columns stay square too. Standard CSS mode only. The backgrounds are clipped after they are collected rather than where each is built, so the painting code shared by _tableWrite() and TableHeaderFooter() is left as it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed cell's border lean (#603) The cell box carries the background counts, the clip is built only when a background needs it, each stroke box is built once, drawing state is reset once per side, and the alpha is reset only after a translucent border. RoundedBox::scale() divides radii by a table's shrink factor for images and cells alike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #603
Part of #552, part of #520
Problem
mPDF read
border-radiuson a table cell and never used it, so rounded table cards and cells came out square:td { border: 1mm solid #00f; border-radius: 3mm; background: #0f0 },border-collapse: separatetd { border-radius: 50% }on a 60 × 10 mm celltd { border: 3mm groove #36c; border-radius: 5mm }tr { background: #fcc },td { border-radius: 5mm }td { border-radius: 3mm },border-collapse: collapseFix
Tag\Tdreads the radius longhands withBorderRadius::parse(), in standard mode only, into$cell['border_radius']. Repeated header and footer rows copy it.Mpdf::roundedCellBox()gives the cell's border box (its slot less half the border-spacing on each side, which is the box a square cell's background already fills). It scales the radii by the table's shrink factor, resolves percentages against the box withBorderRadius::resolve(), and fits them withRoundedBox::fit(). It returns null underborder-collapse: collapse, for simple tables, inside columns, and when every corner comes out square. In those cases nothing changes.tableBackgroundsand painted later. SoroundedCellBox()counts each layer of the table's level, and once the cell is doneclipRoundedCellBackgrounds()gives every entry added since a clip path round the rounded box. That covers the cell's colour, gradient and image, and the row's colour, gradient and image showing through it. A row gradient or image already had a square per-cell clip in the separated model, and the rounded one takes its place.PrintTableBackgrounds()now honoursclippathon a plain colour too, as it already did for gradients and images. Doing it this way leaves the background-building code in_tableWrite()andTableHeaderFooter()untouched, and Draw every layer of a multiple background (#609) #723 rewrites that code.paintRoundedCellBorder()strokes each side along the corners withRoundedBox::side(), asPaintImgBorder()does for a rounded image.dashedanddottedkeep their dashes.doubleis drawn as two strokes, each a third of the border's width.groove,ridge,insetandoutsettake the two tones_tableRect()gives a square cell (ColorConverter::lighten()anddarken()): one tone on the outer half of the top and left, the other on the inner half, and the other way round on the bottom and right. The tones change at the diagonal of each corner.RoundedBox::scale()divides radii by a shrink factor.imageBox()androundedCellBox()both use it.Decisions.
border-radiusdoes not apply in the collapsing border model, on cells or on the table, so a collapsed cell is drawn exactly as before.<columns>, mPDF moves what was drawn by matching the first coordinate of each write. A curved path doesn't survive that, so cells stay square there. Block borders and image borders are also skipped in columns.simpleTablesdraws every cell with the table's border and ignores the cell's own border, so the cell's radius is ignored too.Legacy mode
Under
'cssMode' => 'legacy',Tddoesn't read the radius, so output is byte-identical to before. I checked a document of rounded cells in every border style: same bytes before and after.TableCellBorderRadiusTest::testTheLegacyModeKeepsTheCellSquarecovers this.Not in this PR
border-radiuson the table itself. The table's border is drawn per cell, one edge segment at a time (_tableRect()with'table'corners in_tableWrite()andTableHeaderFooter()). Its background is painted per page segment. Rounding it means drawing the outer border as one path per page and clipping every background in the table to it. That is a separate change.border-radius,box-shadowand 3D border styles on every element, blurtext-shadow, and drawoutline#603: inline-element radius, shadows on cells, tables, inline elements and images, 3D styles on blocks and inline elements,text-shadowblur, andoutline(Draw the outline of blocks, table cells, images and inline elements (#603) #727).doubleand the 3D styles as one solid line.paintRoundedCellBorder()could be shared withPaintImgBorder()when 3D styles on images are done.Tests
tests/Mpdf/TableCellBorderRadiusTest.phpreads the clip path and border strokes from the page stream:doubleandgroovedraw two strokes per side, andgrooveuses two colours.border-collapse: collapse, legacy mode, andborder-radius: 0.With the
src/changes reverted, 10 of the 15 fail. The five that pass check that nothing changes.tests/Snapshots/TableCellBorderRadiusSnapshotTest.php(fixturetable-cell-border-radius) draws twelve cells, each under a caption saying what it should show: solid, 50% ellipse,6mm 0, dashed, dotted, double, groove, ridge, inset, outset, a gradient, and a row background through a cell with none. It ends with a collapsed cell that stays square. Against the pre-fixsrc/it fails (RMSE 0.07). No existing fixture changed.Checks
composer test: OK, 12748 tests, 31 skipped (none of them snapshots;--group snapshot: 219 tests OK)composer cs: clean--memory-limit=2G): 23 errors, all already ongravitypdf(Regenerate the PHPStan baseline for PHPStan 2.3, so the Lint job passes again #716 regenerates the baseline). None are new.Expected conflicts: #723 (multiple backgrounds) touches
PrintTableBackgrounds()and the cell background blocks. This PR adds one line before and one after each of those blocks, so any conflict should be small. #727 (outline) editsTag/Td.phpandMpdf.phparound cell painting. #721 and #710 touchTag/Td.phpand_tableWrite()elsewhere.🤖 Generated with Claude Code