-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New unmanaged API, with infallible options for certain parts #57
Merged
Conversation
This file contains 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
This moves Surface and ImageSurface to an unmanaged, infallible design: * Allocators are no longer stored in the surface. * Anything that needs an allocator (e.g., init, deinit, and downsample) requires the same allocator to be used across the lifetime of the surface, as you would expect with unmanaged patterns within Zig. * The only function that returns an error now is init. Every other function has a well-defined failure mode. Particularly, getPixel will return null on out-of-bounds requests, and setPixel will no-op. Additionally every pixel is valid on a surface for setPixel and paintPixel, using copySrc now instead of fromPixel (essentially making mismatched pixel types a cast). Additionally, ImageSurface has gotten an initBuffer initializer. Using this function, the only sanity checking that's done is that you're using non-negative values for width and height; negative values cause a panic instead of an error. Otherwise, you are expected to have supplied the appropriately sized buffer for the appropriate type. There is a counterpart downsampleBuffer to use when you use this bring-your-own-buffer approach, so you don't have to supply an allocator to anything else (as if you did, it would be an illegal operation). Note that due to the current state of the language and ptrCast-ing between slices of different alignments, initBuffer is currently not exposed in the union interface. As such, if you want to use initBuffer, you have to call the type function directly and then use asSurfaceInterface.
Surface: move to unmanaged and infallible design
This commit changes Path to be a fully unmanaged struct, which essentially means changing its backing ArrayList to ArrayListUnmanaged. All general calls to Path now require an allocator, which is then passed to the ArrayListUnmanaged calls. In addition to this work, however, we have broken off a number of the calls to have AssumeCapacity counterparts, and also added initBuffer. Most of these calls are completely infallible (not just memory infallible, since they no longer require checking for allocation errors); the only fallible calls that remain are the ones that require a current point. This also does a couple of other things: * arc has now been split into arc and arcNegative, similar to Cairo - one draws clockwise, the other draws counter-clockwise. * tolerance for arc calculations have now been removed from the arc calls., instead being a setting in the Path itself. Both of these things vastly simplifies the use of the arc calls, and sets the stage for further refactoring (specifically, the Context will be managing synchronizing tolerance between it and its embedded Path). Additionally, Path.close has had an ineffectual check for an initial point moved to an assert. We had this put in an else clause when capturing the optional before, but since the refactor and a move to including the AssumeCapacity counterparts, this has proven unnecessary. This makes closeAssumeCapacity completely infallible. Finally, we have introduced a *completely infallible* interface to Path called StaticPath. This type function wraps a buffer of a comptime-known node length, with functions that call out to the AssumeCapacity counterparts. Any of the calls that do require a current point are safety-checked undefined behavior when they are called without a current point.
Path: move to unmanaged design, introduce StaticPath
This makes the public painter interfaces public, and setting them up so that they can be used in an unmanaged way. The idioms of the new "fill" and "stroke" operations are set up so that take take a required allocator, surface, pattern, and nodes to plot. Additionally, an options struct is supplied to both which contain optional arguments for both operations, with defaults that are in line with what is currently available to both in the Context. This allows for default behavior of these various operations should the user wish to do so.
This is a pretty minimal change that brings Pattern idioms in line with Surface idioms. Since we have not implemented anything else other than single-pixel surfaces yet, this is a pretty simple change; OpaquePattern is already not a reference, so all that's needed adjusting is the args in the painter functions, and setting getPixel to not return an error. The getPixel API may eventually change depending on what the expectation will be for patterns for returning pixels potentially out of bound from a pattern that represents something with boundaries, such as a surface.
painter: public interface and small pattern tweaks
This commit is the final piece of the current API overhaul - the managed Context. This is now the place where all managed drawing operations are expected to take place. It pulls together all of our umnanaged components - surfaces, patterns, paths, and painter operations, and provides a managed frontend to these operations, doing things such as holding an allocator for said unmanaged operations (that need one), and providing synchronization of settings such as transformation matrices and tolerance. Helpers have been added to get and set every setting within the context; it's now considered unsupported behavior for a consumer to set a field directly on a context (or need to set one directly, for that matter, which should help steer further updates). If someone requires functionality that the Context is incapable of providing or would be considered unsuitable for the context, the recommendation is to now use the individual components in an unmanaged way. For this, the Context serves as an example for how this can be done.
Context: new managed interface
vancluever
changed the title
Unmanaged infallible
New unmanaged API, with infallible options for certain parts
Nov 8, 2024
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.
This merges our long-running feature branch that re-tools the API under our new architecture. With this setup:
Surface
is now unmanaged, with an option to use an infallible version through the use ofinitBuffer
,Pattern
is now infallible, simply through the use of a simple single-pixel source for the time being, although the intention is to ensure this continues to be the case as we add more complex patterns,Path
is now unmanaged, with an option to use an infallible version throughStaticPath
,painter
package, with a purely unmanaged interface (but not infallible unfortunately, see below),Context
is now the only remaining managed interface, which pulls all the above components together.This completes #44 for the time being, leaving only drawing (e.g.,
z2d.painter.fill()
andz2d.painter.stroke()
) as being the only functionality that remains memory fallible with no option to make it infallible. This is due to the fairly large and indeterminate amount of memory required during these operations - polygons currently are a bit too large size-wise and there can be any number of them during a particular operation, which makes me hesitant to make aFixedBufferAllocator
for them. We additionally need surfaces for compositing, which require memory, although arguably much less after #50, (although #53 re-introduced the allocator for a fallback on edge finding to make the FBA much more reasonably sized as well).I'm expecting that plotting and rasterization will continue to be improved upon in further releases, and that through this, we could possibly get to a truly infallible model here as well.