…tive/camera
The Scale, AffineScale, TransformPerspective, and TransformCamera grid
tests produced empty cells in the screenshot pipelines because each
test had a structural defect:
- Scale + AffineScale crossed the axes in the scale formula
(xScale=0.01*height, yScale=0.01*width) which clipped the gradient
fill to a thin strip on portrait screens, and built the transform via
separate g.translate + g.scale calls -- but g.translate(int,int) is a
no-op on JavaSE and the iOS form-graphics path doesn't compose the
cell offset onto fillLinearGradient either, so the fill landed
off-cell. Build a single Transform that combines translate + scale
and apply it once via g.setTransform.
- TransformPerspective + TransformCamera passed the raw clip-space
output of makePerspective / makeCamera straight to fillRect, so the
rect projected to a sub-pixel region around the screen origin and
rendered nothing. They also used the static
Transform.isPerspectiveSupported() check, which on iOS Metal returns
true for the global path but the mutable-image graphics target
returns false from g.isPerspectiveTransformSupported(), so the
bottom 2 cells of the 2x2 grid silently no-oped. Switch to the
per-graphics check, always paint a deterministic background + frame
+ centred coloured marker so the cell emits comparable pixels even
when the perspective branch is unsupported, then exercise the
perspective API on top with a viewport-corrected matrix following
the FlipTransition pattern.
Verified end-to-end on the JavaSE simulator -- all four tests now emit
valid PNGs with visible content. Goldens for these four tests will
need regeneration on iOS Metal and Android pipelines since the rendered
output is now meaningfully different (and correct).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Four graphics screenshot tests in
scripts/hellocodenameone/common/.../tests/graphics/produced empty cells in the iOS and Android screenshot pipelines because each test had a structural defect.xScale = 0.01 * bounds.heightwas applied to the X axis (andyScalefromwidthto Y) — axes swapped, so the 100×100 logical fill was clipped to a thin strip on portrait screens. Also relied ong.translate+g.scaleseparately, which doesn't compose becauseg.translate(int, int)is a no-op on JavaSE and the iOS form-graphics path doesn't carry the translate intofillLinearGradient.makePerspective/makeCamerastraight tofillRect, so the rect projected to a sub-pixel region around the screen origin and rendered nothing visible. Also used the staticTransform.isPerspectiveSupported()(the global check) instead of the per-graphicsg.isPerspectiveTransformSupported()— on iOS Metal, mutable-image graphics return false for the per-graphics check, so the bottom 2 cells of each 2×2 grid silently no-oped.Fixes
All four tests now:
Transform(translate × scale) applied viag.setTransform(t)instead ofg.translate+g.scale.FlipTransition.paint()pattern.g.isPerspectiveTransformSupported()and emit a clear "No perspective" / "No camera" label when the per-graphics target doesn't support perspective.Verified end-to-end on the JavaSE simulator — all four tests now emit valid 65–72 KB PNGs with visible content (previously the cells were mostly empty).
Test plan
graphics-scale,graphics-affine-scale,graphics-transform-perspective,graphics-transform-cameraon each pipeline (the new pixel output differs from the previously broken goldens)🤖 Generated with Claude Code