diff --git a/gtkarea/ui.h b/gtkarea/ui.h index 387a7f1f..4cc6097d 100644 --- a/gtkarea/ui.h +++ b/gtkarea/ui.h @@ -55,8 +55,6 @@ enum uiDrawLineJoin { // so we're good to use it too! #define uiDrawDefaultMiterLimit 10.0 -// TODOs -// - os x: FillPath/EOFillPath functions enum uiDrawFillMode { uiDrawFillModeWinding, // TODO rename to EvenOdd? @@ -71,6 +69,7 @@ struct uiDrawStrokeParams { }; void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t); +// TODO verify these aren't alpha premultiplied anywhere void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t); void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t); diff --git a/macarea/draw.c b/macarea/draw.c new file mode 100644 index 00000000..87a620cc --- /dev/null +++ b/macarea/draw.c @@ -0,0 +1,133 @@ +// 6 september 2015 +#include "area.h" + +struct uiDrawContext { + CGContextRef c; + + BOOL useRGBA; + CGFloat r; + CGFloat g; + CGFloat b; + CGFloat a; +}; + +uiDrawContext *newContext(CGContextRef ctxt) +{ + uiDrawContext *c; + + // TODO use uiNew + c = (uiDrawContext *) malloc(sizeof (uiDrawContext)); + c->c = ctxt; + return c; +} + +void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b) +{ + c->useRGB = YES; + c->r = ((CGFloat) r) / 255; + c->g = ((CGFloat) g) / 255; + c->b = ((CGFloat) b) / 255; + c->a = 1.0; + CGContextBeginPath(c->c); +} + +void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + c->useRGB = YES; + c->r = ((CGFloat) r) / 255; + c->g = ((CGFloat) g) / 255; + c->b = ((CGFloat) b) / 255; + c->a = ((CGFloat) a) / 255; + CGContextBeginPath(c->c); +} + +void uiDrawMoveTo(uiDrawContext *c, intmax_t x, intmax_t y) +{ + CGContextMoveToPoint(c->c, x, y); +} + +void uiDrawLineTo(uiDrawContext *c, intmax_t x, intmax_t y) +{ + CGContextAddLineToPoint(c->c, x, y); +} + +void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height) +{ + CGContextAddRect(c->c, TODO(x, y, width, height)); +} + +void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart) +{ + if (!lineFromCurrentPointToStart) { + // TODO + } + CGContextAddArc(c->c, + xCenter, yCenter, + radius, + startAngle, endAngle, + 0); +} + +void uiDrawBezierTo(uiDrawContext *c, intmax_t c1x, intmax_t c1y, intmax_t c2x, intmax_t c2y, intmax_t endX, intmax_t endY) +{ + CGContextAddCurveToPoint(c->c, + c1x, c1y, + c2x, c2y, + endX, endY); +} + +void uiDrawCloseFigure(uiDrawContext *c) +{ + CGContextClosePath(c->c); +} + +void uiDrawStroke(uiDrawContext *c, uiDrawStrokeParams *p) +{ + switch (p->Cap) { + case uiDrawLineCapFlat: + CGContextSetLineCap(c->c, kCGLineCapButt); + break; + case uiDrawLineCapRound: + CGContextSetLineCap(c->c, kCGLineCapRound); + break; + case uiDrawLineCapSquare: + CGContextSetLineCap(c->c, kCGLineCapSquare); + break; + } + switch (p->Join) { + case uiDrawLineJoinMiter: + CGContextSetLineJoin(c->cr, kCGLineJoinMiter); + CGContextSetMiterLimit(c->c, p->MiterLimit); + break; + case uiDrawLineJoinRound: + CGContextSetLineJoin(c->cr, kCGLineJoinRound); + break; + case uiDrawLineJoinBevel: + CGContextSetLineJoin(c->cr, kCGLineJoinBevel); + break; + } + CGContextSetLineWidth(c->c, p->Thickness); + if (c->useRGB) + CGContextSetRGBStrokeColor(c->c, c->r, c->g, c->b, c->a); + else { + // TODO + } + CGContextStrokePath(c->cr); +} + +void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode) +{ + if (c->useRGB) + CGContextSetRGBFillColor(c->c, c->r, c->g, c->b, c->a); + else { + // TODO + } + switch (mode) { + case uiDrawFillModeWinding: + CGContextFillPath(c->c); + break; + case uiDrawFillModeAlternate: + CGContextEOFillPath(c->c); + break; + } +} diff --git a/macarea/ui.h b/macarea/ui.h new file mode 100644 index 00000000..4cc6097d --- /dev/null +++ b/macarea/ui.h @@ -0,0 +1,138 @@ +// 4 september 2015 + +typedef struct uiArea uiArea; +typedef struct uiAreaHandler uiAreaHandler; +typedef struct uiAreaDrawParams uiAreaDrawParams; + +typedef struct uiDrawContext uiDrawContext; + +struct uiAreaHandler { + void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *); + uintmax_t (*HScrollMax)(uiAreaHandler *, uiArea *); + uintmax_t (*VScrollMax)(uiAreaHandler *, uiArea *); +}; + +struct uiAreaDrawParams { + uiDrawContext *Context; + + intmax_t ClientWidth; + intmax_t ClientHeight; + + intmax_t ClipX; + intmax_t ClipY; + intmax_t ClipWidth; + intmax_t ClipHeight; + + int DPIX; + int DPIY; + + intmax_t HScrollPos; + intmax_t VScrollPos; +}; + +// TODO proper sources +// TODO dotting/dashing + +typedef struct uiDrawStrokeParams uiDrawStrokeParams; +typedef enum uiDrawLineCap uiDrawLineCap; +typedef enum uiDrawLineJoin uiDrawLineJoin; +typedef enum uiDrawFillMode uiDrawFillMode; + +enum uiDrawLineCap { + uiDrawLineCapFlat, + uiDrawLineCapRound, + uiDrawLineCapSquare, +}; + +enum uiDrawLineJoin { + uiDrawLineJoinMiter, + uiDrawLineJoinRound, + uiDrawLineJoinBevel, +}; + +// this is the default for botoh cairo and GDI +// Core Graphics doesn't explicitly specify a default, but NSBezierPath allows you to choose one, and this is the initial value +// so we're good to use it too! +#define uiDrawDefaultMiterLimit 10.0 + +enum uiDrawFillMode { + uiDrawFillModeWinding, + // TODO rename to EvenOdd? + uiDrawFillModeAlternate, +}; + +struct uiDrawStrokeParams { + uiDrawLineCap Cap; + uiDrawLineJoin Join; + intmax_t Thickness; + double MiterLimit; +}; + +void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t); +// TODO verify these aren't alpha premultiplied anywhere +void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t); + +void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t); +void uiDrawLineTo(uiDrawContext *, intmax_t, intmax_t); +void uiDrawRectangle(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t); +// notes: angles are both relative to 0 and go counterclockwise +void uiDrawArcTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, double, double, int); +// TODO behavior when there is no initial point on Windows and OS X +void uiDrawBezierTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t); +void uiDrawCloseFigure(uiDrawContext *); + +void uiDrawStroke(uiDrawContext *, uiDrawStrokeParams *); +void uiDrawFill(uiDrawContext *, uiDrawFillMode); + +// path functions +// cairo gdi core graphics +// move_to MoveToEx MoveToPoint +// line_to LineTo AddLineToPoint +// arc Arc/ArcTo/AngleArc/Pie AddArc/AddArcToPoint/AddEllipseInRect +// arc_negative Arc/ArcTo/AngleArc/Pie AddArc/AddArcToPoint +// curve_to PolyBezier/PolyBezierTo AddCurveToPoint +// rectangle Rectangle AddRect +// [arc functions?] Chord [arc functions?] +// [combination] RoundRect [same way as cairo?] +// [TODO pango] TextOut/ExtTextOut [TODO core text] +// [TODO] [TODO] AddQuadCurveToPoint + +// on sources: +// cairo: +// - RGB +// - RGBA +// - images +// - linear gradients, RGB or RGBA +// - rounded gradients, RGB or RGBA +// gdi: +// - RGB +// - hatches +// - images +// we can create a linear gradient image, but RGB only, and of finite size +// core graphics: +// - arbitrary patterns +// - solid colors, arbitrary spaces +// - shadows + +// arcs +// cairo_arc/arc_negative +// - parameters: center, radius, angle1 radians, angle2 radins +// - if angle2 < angle1, TODO +// - if angle2 > angle1, TODO +// - line segment from current point to beginning of arc +// - arc: clockwise, arc_negative: counterclockwise +// - circular +// GDI Arc/Pie +// - parameters: bounding box, start point, end point +// - current position not used/changed +// - either clockwise or counterclockwise +// - elliptical +// GDI ArcTo +// - same as Arc except line segment from current point to beginning of arc +// - there does not appear to be a PieTo +// GDI AngleArc +// - parameters: center, radius, angle1 degrees, angle2 degrees +// - line segment from current position to beginning of arc +// - counterclockwise +// - circular +// - can be used to draw pies too; MSDN example demonstrates diff --git a/winarea/ui.h b/winarea/ui.h index 387a7f1f..4cc6097d 100644 --- a/winarea/ui.h +++ b/winarea/ui.h @@ -55,8 +55,6 @@ enum uiDrawLineJoin { // so we're good to use it too! #define uiDrawDefaultMiterLimit 10.0 -// TODOs -// - os x: FillPath/EOFillPath functions enum uiDrawFillMode { uiDrawFillModeWinding, // TODO rename to EvenOdd? @@ -71,6 +69,7 @@ struct uiDrawStrokeParams { }; void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t); +// TODO verify these aren't alpha premultiplied anywhere void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t); void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t);