- Personal site: knutsen.co
- Personal git server: git.knutsen.co
- Sourcehut: git.sr.ht/~knutsen
- PGP
693BD1EE8BD77B43
- SSH
4b:42:d8:30:43:65:53:21:be:53:97:49:bc:5f:96:44
- ETH
0x1C7fC5d267C3CEBc4AC875abB424b29dE5113071
- Urbit
~minten-migmug
Haskell 2D Graphics
License: GNU General Public License v3.0
693BD1EE8BD77B43
4b:42:d8:30:43:65:53:21:be:53:97:49:bc:5f:96:44
0x1C7fC5d267C3CEBc4AC875abB424b29dE5113071
~minten-migmug
Text is not a rectangle with a texture (although it actually is), that would be misleading to conventional fill
and stroke
functions, which would behave like this is a rectangle, and not stroke/fill the actual text.
Text is handled separately, and is regarded as a primitive geometry.
Handle alignment, shaping, styling, sizing, fonts, hinting, option, all within a big record which can be translated to what harfbuzz understands.
functions like text
should be incredibly simple (in contrast) however.
text :: Font -> String -> Shape
More shapes in shapes package. Squircle continuous rounded rectangle with opengl triangle strip. https://www.desmos.com/calculator/sy6c5tuake
As well as regular polygons, with their polygoid (?) rounded variants.
https://www.desmos.com/calculator/qyf9pvxosz
https://www.desmos.com/calculator/uwrivivhmo
https://www.johndcook.com/blog/2020/07/05/squircle-corner-radius/
https://www.figma.com/blog/desperately-seeking-squircles/
Change translate/scale/rotate to structural tagging/datatypes instead of actually computing transformations on each vertex.
This can not only be used to optimise certain operations, but can have different behaviours implemented for more nuanced geometry. For example, accounting for primitives, like triangles, rectangles, and text.
Especially since some geometries are secretly CPU rasterised textures, such as with font/text shaping.
Make transformations separate data types which can be destructured by the back-end, to perform the educated, more optimal transformation.
In this idea, transformations are tags, and shapes are not just vertices.
All shapes thus originally sit at the origin, and are transformed therefrom.
Basic idea:
data TextShaping = { textFont :: Font, textSize :: Distance, textAlign :: TextAlign } -- etc.
data Geometry = Vertices [Point] -- first point should be at (0,0)?
| Circle Distance
| Arc Distance Radians
| Rectangle Distance Distance
| Text TextShaping String
data StrokeOffs = Inside | Outside | Middle
data Stroke = Stroke { strokeThickness :: Distance
, strokeText :: Texture
, strokeOffs :: StrokeOffs
, strokeCap :: StrokeCap
}
data Shape = Shape { geometry :: Geometry
, filling :: Color
, stroke :: Stroke
data Picture = Picture [Shape] deriving (Groupoid, Monoid)
data Transformation t where
Translation :: Transformable t => Distance -> Distance -> t -> Transformation t
Rotation :: Transformable t => Radians -> t -> Transformation t
Scaling :: Transformable t => Scalar -> t -> Transformation t
-- These functions should be used, not the constructors,
-- Since special cases need to be handled, such as consolidating
-- repeated transformations of the same kind, and handling
-- raw vertex transformation from other kinds.
class Transformable t where
translate :: Distance -> Distance -> t -> t
rotate :: Radians -> t -> t
scale :: Scalar -> t -> t
instance Transformable (Transformation t) where
translate dx dy (Translation dx' dy' geo) = Translation (dx + dx') (dy + dy') geo
translate dx dy geo = Translation dx dy geo
rotate ϑ (Rotation ϑ' geo) = Rotation (ϑ + ϑ') geo
rotate ϑ geo = Rotation ϑ geo
scale x (Scaling x' geo) = Scaling (x * x') geo
scale x geo = Scaling x geo
instance Transformable Shape where
-- ...
instance Transformable Picture where
-- ... maps on all shapes.
-- &c.
Transformations are according to the shapes origin, which is set to be what (would be) the shapes first vertex.
Finding a shapes geometric centre is perfectly left up for a specialising function, which can then have sibling functions which transforms a shape such that the shape actual/geometric centre is at the origin, such that all later/subsequent transformations are relative to the shapes centre.
Circles can be computed pixel perfect, but for OpenGL backend, picking an optimal vertex count based on size is a better idea, i.e. circle vertices are picked later, intelligently.
If the Picture we're drawing is itself immediately transformed, take that as a viewport transformation, which is more optimal for GL (maybe don't do this, maybe provide separate functionality?)
HSL, HSB, hex codes, colour blends, saturation, lightness, brightness, hue modifying functions, etc.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.