aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/darwin/draw.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/darwin/draw.m')
-rw-r--r--src/libui_sdl/libui/darwin/draw.m454
1 files changed, 0 insertions, 454 deletions
diff --git a/src/libui_sdl/libui/darwin/draw.m b/src/libui_sdl/libui/darwin/draw.m
deleted file mode 100644
index 262ad3e..0000000
--- a/src/libui_sdl/libui/darwin/draw.m
+++ /dev/null
@@ -1,454 +0,0 @@
-// 6 september 2015
-#import "uipriv_darwin.h"
-
-struct uiDrawPath {
- CGMutablePathRef path;
- uiDrawFillMode fillMode;
- BOOL ended;
-};
-
-uiDrawPath *uiDrawNewPath(uiDrawFillMode mode)
-{
- uiDrawPath *p;
-
- p = uiNew(uiDrawPath);
- p->path = CGPathCreateMutable();
- p->fillMode = mode;
- return p;
-}
-
-void uiDrawFreePath(uiDrawPath *p)
-{
- CGPathRelease((CGPathRef) (p->path));
- uiFree(p);
-}
-
-void uiDrawPathNewFigure(uiDrawPath *p, double x, double y)
-{
- if (p->ended)
- userbug("You cannot call uiDrawPathNewFigure() on a uiDrawPath that has already been ended. (path; %p)", p);
- CGPathMoveToPoint(p->path, NULL, x, y);
-}
-
-void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative)
-{
- double sinStart, cosStart;
- double startx, starty;
-
- if (p->ended)
- userbug("You cannot call uiDrawPathNewFigureWithArc() on a uiDrawPath that has already been ended. (path; %p)", p);
- sinStart = sin(startAngle);
- cosStart = cos(startAngle);
- startx = xCenter + radius * cosStart;
- starty = yCenter + radius * sinStart;
- CGPathMoveToPoint(p->path, NULL, startx, starty);
- uiDrawPathArcTo(p, xCenter, yCenter, radius, startAngle, sweep, negative);
-}
-
-void uiDrawPathLineTo(uiDrawPath *p, double x, double y)
-{
- // TODO refine this to require being in a path
- if (p->ended)
- implbug("attempt to add line to ended path in uiDrawPathLineTo()");
- CGPathAddLineToPoint(p->path, NULL, x, y);
-}
-
-void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative)
-{
- bool cw;
-
- // TODO likewise
- if (p->ended)
- implbug("attempt to add arc to ended path in uiDrawPathArcTo()");
- if (sweep > 2 * uiPi)
- sweep = 2 * uiPi;
- cw = false;
- if (negative)
- cw = true;
- CGPathAddArc(p->path, NULL,
- xCenter, yCenter,
- radius,
- startAngle, startAngle + sweep,
- cw);
-}
-
-void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY)
-{
- // TODO likewise
- if (p->ended)
- implbug("attempt to add bezier to ended path in uiDrawPathBezierTo()");
- CGPathAddCurveToPoint(p->path, NULL,
- c1x, c1y,
- c2x, c2y,
- endX, endY);
-}
-
-void uiDrawPathCloseFigure(uiDrawPath *p)
-{
- // TODO likewise
- if (p->ended)
- implbug("attempt to close figure of ended path in uiDrawPathCloseFigure()");
- CGPathCloseSubpath(p->path);
-}
-
-void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height)
-{
- if (p->ended)
- userbug("You cannot call uiDrawPathAddRectangle() on a uiDrawPath that has already been ended. (path; %p)", p);
- CGPathAddRect(p->path, NULL, CGRectMake(x, y, width, height));
-}
-
-void uiDrawPathEnd(uiDrawPath *p)
-{
- p->ended = TRUE;
-}
-
-struct uiDrawContext {
- CGContextRef c;
- CGFloat height; // needed for text; see below
-};
-
-uiDrawContext *newContext(CGContextRef ctxt, CGFloat height)
-{
- uiDrawContext *c;
-
- c = uiNew(uiDrawContext);
- c->c = ctxt;
- c->height = height;
- return c;
-}
-
-void freeContext(uiDrawContext *c)
-{
- uiFree(c);
-}
-
-// a stroke is identical to a fill of a stroked path
-// we need to do this in order to stroke with a gradient; see http://stackoverflow.com/a/25034854/3408572
-// doing this for other brushes works too
-void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p)
-{
- CGLineCap cap;
- CGLineJoin join;
- CGPathRef dashPath;
- CGFloat *dashes;
- size_t i;
- uiDrawPath p2;
-
- if (!path->ended)
- userbug("You cannot call uiDrawStroke() on a uiDrawPath that has not been ended. (path: %p)", path);
-
- switch (p->Cap) {
- case uiDrawLineCapFlat:
- cap = kCGLineCapButt;
- break;
- case uiDrawLineCapRound:
- cap = kCGLineCapRound;
- break;
- case uiDrawLineCapSquare:
- cap = kCGLineCapSquare;
- break;
- }
- switch (p->Join) {
- case uiDrawLineJoinMiter:
- join = kCGLineJoinMiter;
- break;
- case uiDrawLineJoinRound:
- join = kCGLineJoinRound;
- break;
- case uiDrawLineJoinBevel:
- join = kCGLineJoinBevel;
- break;
- }
-
- // create a temporary path identical to the previous one
- dashPath = (CGPathRef) path->path;
- if (p->NumDashes != 0) {
- dashes = (CGFloat *) uiAlloc(p->NumDashes * sizeof (CGFloat), "CGFloat[]");
- for (i = 0; i < p->NumDashes; i++)
- dashes[i] = p->Dashes[i];
- dashPath = CGPathCreateCopyByDashingPath(path->path,
- NULL,
- p->DashPhase,
- dashes,
- p->NumDashes);
- uiFree(dashes);
- }
- // the documentation is wrong: this produces a path suitable for calling CGPathCreateCopyByStrokingPath(), not for filling directly
- // the cast is safe; we never modify the CGPathRef and always cast it back to a CGPathRef anyway
- p2.path = (CGMutablePathRef) CGPathCreateCopyByStrokingPath(dashPath,
- NULL,
- p->Thickness,
- cap,
- join,
- p->MiterLimit);
- if (p->NumDashes != 0)
- CGPathRelease(dashPath);
-
- // always draw stroke fills using the winding rule
- // otherwise intersecting figures won't draw correctly
- p2.fillMode = uiDrawFillModeWinding;
- p2.ended = path->ended;
- uiDrawFill(c, &p2, b);
- // and clean up
- CGPathRelease((CGPathRef) (p2.path));
-}
-
-// for a solid fill, we can merely have Core Graphics fill directly
-static void fillSolid(CGContextRef ctxt, uiDrawPath *p, uiDrawBrush *b)
-{
- // TODO this uses DeviceRGB; switch to sRGB
- CGContextSetRGBFillColor(ctxt, b->R, b->G, b->B, b->A);
- switch (p->fillMode) {
- case uiDrawFillModeWinding:
- CGContextFillPath(ctxt);
- break;
- case uiDrawFillModeAlternate:
- CGContextEOFillPath(ctxt);
- break;
- }
-}
-
-// for a gradient fill, we need to clip to the path and then draw the gradient
-// see http://stackoverflow.com/a/25034854/3408572
-static void fillGradient(CGContextRef ctxt, uiDrawPath *p, uiDrawBrush *b)
-{
- CGGradientRef gradient;
- CGColorSpaceRef colorspace;
- CGFloat *colors;
- CGFloat *locations;
- size_t i;
-
- // gradients need a color space
- // for consistency with windows, use sRGB
- colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
-
- // make the gradient
- colors = uiAlloc(b->NumStops * 4 * sizeof (CGFloat), "CGFloat[]");
- locations = uiAlloc(b->NumStops * sizeof (CGFloat), "CGFloat[]");
- for (i = 0; i < b->NumStops; i++) {
- colors[i * 4 + 0] = b->Stops[i].R;
- colors[i * 4 + 1] = b->Stops[i].G;
- colors[i * 4 + 2] = b->Stops[i].B;
- colors[i * 4 + 3] = b->Stops[i].A;
- locations[i] = b->Stops[i].Pos;
- }
- gradient = CGGradientCreateWithColorComponents(colorspace, colors, locations, b->NumStops);
- uiFree(locations);
- uiFree(colors);
-
- // because we're mucking with clipping, we need to save the graphics state and restore it later
- CGContextSaveGState(ctxt);
-
- // clip
- switch (p->fillMode) {
- case uiDrawFillModeWinding:
- CGContextClip(ctxt);
- break;
- case uiDrawFillModeAlternate:
- CGContextEOClip(ctxt);
- break;
- }
-
- // draw the gradient
- switch (b->Type) {
- case uiDrawBrushTypeLinearGradient:
- CGContextDrawLinearGradient(ctxt,
- gradient,
- CGPointMake(b->X0, b->Y0),
- CGPointMake(b->X1, b->Y1),
- kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
- break;
- case uiDrawBrushTypeRadialGradient:
- CGContextDrawRadialGradient(ctxt,
- gradient,
- CGPointMake(b->X0, b->Y0),
- // make the start circle radius 0 to make it a point
- 0,
- CGPointMake(b->X1, b->Y1),
- b->OuterRadius,
- kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
- break;
- }
-
- // and clean up
- CGContextRestoreGState(ctxt);
- CGGradientRelease(gradient);
- CGColorSpaceRelease(colorspace);
-}
-
-void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b)
-{
- if (!path->ended)
- userbug("You cannot call uiDrawStroke() on a uiDrawPath that has not been ended. (path: %p)", path);
- CGContextAddPath(c->c, (CGPathRef) (path->path));
- switch (b->Type) {
- case uiDrawBrushTypeSolid:
- fillSolid(c->c, path, b);
- return;
- case uiDrawBrushTypeLinearGradient:
- case uiDrawBrushTypeRadialGradient:
- fillGradient(c->c, path, b);
- return;
-// case uiDrawBrushTypeImage:
- // TODO
- return;
- }
- userbug("Unknown brush type %d passed to uiDrawFill().", b->Type);
-}
-
-static void m2c(uiDrawMatrix *m, CGAffineTransform *c)
-{
- c->a = m->M11;
- c->b = m->M12;
- c->c = m->M21;
- c->d = m->M22;
- c->tx = m->M31;
- c->ty = m->M32;
-}
-
-static void c2m(CGAffineTransform *c, uiDrawMatrix *m)
-{
- m->M11 = c->a;
- m->M12 = c->b;
- m->M21 = c->c;
- m->M22 = c->d;
- m->M31 = c->tx;
- m->M32 = c->ty;
-}
-
-void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y)
-{
- CGAffineTransform c;
-
- m2c(m, &c);
- c = CGAffineTransformTranslate(c, x, y);
- c2m(&c, m);
-}
-
-void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y)
-{
- CGAffineTransform c;
- double xt, yt;
-
- m2c(m, &c);
- xt = x;
- yt = y;
- scaleCenter(xCenter, yCenter, &xt, &yt);
- c = CGAffineTransformTranslate(c, xt, yt);
- c = CGAffineTransformScale(c, x, y);
- c = CGAffineTransformTranslate(c, -xt, -yt);
- c2m(&c, m);
-}
-
-void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount)
-{
- CGAffineTransform c;
-
- m2c(m, &c);
- c = CGAffineTransformTranslate(c, x, y);
- c = CGAffineTransformRotate(c, amount);
- c = CGAffineTransformTranslate(c, -x, -y);
- c2m(&c, m);
-}
-
-void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount)
-{
- fallbackSkew(m, x, y, xamount, yamount);
-}
-
-void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src)
-{
- CGAffineTransform c;
- CGAffineTransform d;
-
- m2c(dest, &c);
- m2c(src, &d);
- c = CGAffineTransformConcat(c, d);
- c2m(&c, dest);
-}
-
-// there is no test for invertibility; CGAffineTransformInvert() is merely documented as returning the matrix unchanged if it isn't invertible
-// therefore, special care must be taken to catch matrices who are their own inverses
-// TODO figure out which matrices these are and do so
-int uiDrawMatrixInvertible(uiDrawMatrix *m)
-{
- CGAffineTransform c, d;
-
- m2c(m, &c);
- d = CGAffineTransformInvert(c);
- return CGAffineTransformEqualToTransform(c, d) == false;
-}
-
-int uiDrawMatrixInvert(uiDrawMatrix *m)
-{
- CGAffineTransform c, d;
-
- m2c(m, &c);
- d = CGAffineTransformInvert(c);
- if (CGAffineTransformEqualToTransform(c, d))
- return 0;
- c2m(&d, m);
- return 1;
-}
-
-void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y)
-{
- CGAffineTransform c;
- CGPoint p;
-
- m2c(m, &c);
- p = CGPointApplyAffineTransform(CGPointMake(*x, *y), c);
- *x = p.x;
- *y = p.y;
-}
-
-void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y)
-{
- CGAffineTransform c;
- CGSize s;
-
- m2c(m, &c);
- s = CGSizeApplyAffineTransform(CGSizeMake(*x, *y), c);
- *x = s.width;
- *y = s.height;
-}
-
-void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m)
-{
- CGAffineTransform cm;
-
- m2c(m, &cm);
- CGContextConcatCTM(c->c, cm);
-}
-
-void uiDrawClip(uiDrawContext *c, uiDrawPath *path)
-{
- if (!path->ended)
- userbug("You cannot call uiDrawCilp() on a uiDrawPath that has not been ended. (path: %p)", path);
- CGContextAddPath(c->c, (CGPathRef) (path->path));
- switch (path->fillMode) {
- case uiDrawFillModeWinding:
- CGContextClip(c->c);
- break;
- case uiDrawFillModeAlternate:
- CGContextEOClip(c->c);
- break;
- }
-}
-
-// TODO figure out what besides transforms these save/restore on all platforms
-void uiDrawSave(uiDrawContext *c)
-{
- CGContextSaveGState(c->c);
-}
-
-void uiDrawRestore(uiDrawContext *c)
-{
- CGContextRestoreGState(c->c);
-}
-
-void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout)
-{
- doDrawText(c->c, c->height, x, y, layout);
-}