Skip to content

Feature: add -drawBackgroundInContext: and draw the CAGradientLayer axial gradient - #100

Open
DTW-Thalion wants to merge 31 commits into
gnustep:masterfrom
DTW-Thalion:feature/cagradientlayer-drawing
Open

DTW-Thalion wants to merge 31 commits into
gnustep:masterfrom
DTW-Thalion:feature/cagradientlayer-drawing

Conversation

@DTW-Thalion

Copy link
Copy Markdown
Contributor

CAGradientLayer held colors, locations, startPoint, endPoint and type and drew none of them, in either drawing path.

A shape layer and a gradient layer sit on opposite sides of the contents: with an image set as contents, a shape layer's fill is drawn over it and a gradient under it. So #99's seam is not one a gradient can use. CALayer gains -drawBackgroundInContext:, called from -renderInContext: after the background colour and before the contents, and from -drawInContext: before -drawContentInContext:. CAGradientLayer overrides it. CALayerAddRoundedRect stops being static, since the gradient is clipped to the rounded rect.

Axial gradients are drawn. Fewer than two colours draws nothing, as does a locations array whose count does not match colors. A corner radius rounds the gradient whether or not the layer masks to its bounds. Radial and conic are not drawn. Setting colors does not ask for a display, which is what Apple does.

Stacked on #99, and on #57 for the class. The tests are Tests/quartzcore/CAGradientLayer/drawing.m, which runs against Apple QuartzCore, with a set each in CALayer/subclass.m and CARenderer/renderer.m, skipped there. Tests/quartzcore went from 559 passed and 21 failed to 580 and 0.

Add name, borderWidth, cornerRadius, rasterizationScale, doubleSided,
the two scaling filters and -replaceSublayer:with:, with the values
Apple starts them at.
The source and the header held the copyright banner and nothing else, so
there was no class to message.

Adds colors, locations, startPoint, endPoint and type, with the values Apple
gives a fresh gradient layer: no colours, no locations, a start point of
0.5,0, an end point of 0.5,1 and a type of axial.  Adds the three type names
axial, radial and conic, and the entries their sections of AppleSupport.h
and AppleSupportRevert.h were left empty for.

This covers the properties.  A gradient layer does not draw itself yet.

Tests/quartzcore/CAGradientLayer/gradient.m: 17 assertions.
Nothing in the framework ever set a projection or a viewport, so the vertices
-_renderLayer:withTransform: builds, which are the layer's bounds in points,
were taken as normalised device coordinates.  A layer two units or more
across covered the whole drawable whatever its bounds said, -[CARenderer
setBounds:] made no difference to what was drawn, and a sublayer, which is
translated by half its superlayer's size to sit relative to its corner, was
put outside the clip volume and never seen at all.

-render now maps the renderer's bounds onto the drawable with an orthographic
projection, so a point is a point, and puts the previous projection back
afterwards along with the rest of the state it restores.

The offscreen passes are not addressed.  Rasterization draws into a 512 by
512 framebuffer expecting to work in its pixels, and the shadow blur draws a
quad from -256 to 256 expecting the origin in the middle; each needs a
projection of its own, and neither is reached by a layer that is not
rasterized and casts no shadow.
…Layer

Adds mask, filters, backgroundFilters, compositingFilter, contentsCenter,
edgeAntialiasingMask, minificationFilterBias, allowsEdgeAntialiasing,
allowsGroupOpacity and drawsAsynchronously, with the defaults Apple answers,
and CAEdgeAntialiasingMask with its four edge constants.

-setMask: takes the masked layer as the mask's superlayer and removes the
mask from any tree it was in. contentsCenter is named in
+automaticallyNotifiesObserversForKey: so that KVO does not corrupt it.
-setContentsRect: read back uninitialised memory. contentsRect was the one
struct-typed key registered for implicit animation that
+automaticallyNotifiesObserversForKey: did not exclude, so GNUstep replaced
its setter with one that mishandles a CGRect argument. It is excluded now and
gets the observable setter the other struct properties have.
…erties are

Both now have a hand-written setter and a synthesized getter, which clang
warns about for an atomic property. NONATOMIC_GSONLY is what bounds, position,
anchorPoint, transform, sublayerTransform and shadowOffset already use, and it
leaves the declaration unchanged outside GNUstep.
…Layer

-contentsAreFlipped answers whether an odd number of layers from this one up
to the root have geometryFlipped set.

-shouldArchiveValueForKey: answers whether a property has been given a value.
A new CAArchivingObserver watches the properties a layer archives and notes
each one as it is set. allowsEdgeAntialiasing and allowsGroupOpacity are noted
at init because Apple reads them from the application bundle. frame and
superlayer are never noted.
Adds autoresizingMask, the seven kCALayer sizing constants,
-resizeWithOldSuperlayerSize: and -resizeSublayersWithOldSize:. -setBounds:
passes the old size on when the size changes, so the change carries down the
tree.

Each of the three parts of an axis is worth a third of the change. A part
that does not give way hands its third to the margins that do, or to the
extent where neither margin does. The leading margin then goes down to the
point below and the extent takes up the slack.
Draws a layer and the tree under it into a Core Graphics context, which is a
second way to draw a layer tree, beside the OpenGL renderer.

The layer that is asked draws in the coordinates of the context as they
stand, so its position and its transform do not come into it, while every
sublayer is placed by its position, anchor point, transform and bounds
origin. The background colour, the contents and masksToBounds are honoured,
opacity multiplies each drawing operation, and a hidden layer is left out.
-drawInContext: is not called, so a layer that has never been displayed draws
nothing.
@DTW-Thalion
DTW-Thalion requested a review from ivucica as a code owner August 4, 2026 17:45
@ivucica
ivucica removed their request for review August 8, 2026 07:59
@DTW-Thalion
DTW-Thalion marked this pull request as draft August 10, 2026 19:10
@DTW-Thalion
DTW-Thalion marked this pull request as ready for review September 21, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant