// 9 october 2015 #include "test.h" // TODO // - test multiple clips // - test saving and restoring clips // - copy tests from https://github.com/Microsoft/WinObjC struct drawtest { const char *name; void (*draw)(uiAreaDrawParams *p); // TODO mouse event }; static void drawOriginal(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush brush; uiDrawStrokeParams sp; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; brush.Type = uiDrawBrushTypeSolid; brush.A = 1; brush.R = 1; brush.G = 0; brush.B = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, p->ClipX + 5, p->ClipY + 5); uiDrawPathLineTo(path, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5); uiDrawPathEnd(path); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.Thickness = 1; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); brush.R = 0; brush.G = 0; brush.B = 0.75; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, p->ClipX, p->ClipY); uiDrawPathLineTo(path, p->ClipX + p->ClipWidth, p->ClipY); uiDrawPathLineTo(path, 50, 150); uiDrawPathLineTo(path, 50, 50); uiDrawPathCloseFigure(path); uiDrawPathEnd(path); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinRound; sp.Thickness = 5; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); brush.R = 0; brush.G = 0.75; brush.B = 0; brush.A = 0.5; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 120, 80, 50, 50); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &brush); uiDrawFreePath(path); brush.A = 1; brush.R = 0; brush.G = 0.5; brush.B = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 5.5, 10.5); uiDrawPathLineTo(path, 5.5, 50.5); uiDrawPathEnd(path); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.Thickness = 1; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); brush.R = 0.5; brush.G = 0.75; brush.B = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 400, 100); uiDrawPathArcTo(path, 400, 100, 50, 30. * (uiPi / 180.), 300. * (uiPi / 180.), 0); // the sweep test below doubles as a clockwise test so a checkbox isn't needed anymore uiDrawPathLineTo(path, 400, 100); uiDrawPathNewFigureWithArc(path, 510, 100, 50, 30. * (uiPi / 180.), 300. * (uiPi / 180.), 0); uiDrawPathCloseFigure(path); // and now with 330 to make sure sweeps work properly uiDrawPathNewFigure(path, 400, 210); uiDrawPathArcTo(path, 400, 210, 50, 30. * (uiPi / 180.), 330. * (uiPi / 180.), 0); uiDrawPathLineTo(path, 400, 210); uiDrawPathNewFigureWithArc(path, 510, 210, 50, 30. * (uiPi / 180.), 330. * (uiPi / 180.), 0); uiDrawPathCloseFigure(path); uiDrawPathEnd(path); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.Thickness = 1; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); brush.R = 0; brush.G = 0.5; brush.B = 0.75; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 300, 300); uiDrawPathBezierTo(path, 350, 320, 310, 390, 435, 372); uiDrawPathEnd(path); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.Thickness = 1; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); } static void drawArcs(uiAreaDrawParams *p) { uiDrawPath *path; int start = 20; int step = 20; int rad = 25; int x, y; double angle; double add; int i; uiDrawBrush brush; uiDrawStrokeParams sp; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); add = (2.0 * uiPi) / 12; x = start + rad; y = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigureWithArc(path, x, y, rad, 0, angle, 0); angle += add; x += 2 * rad + step; } y += 2 * rad + step; x = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigure(path, x, y); uiDrawPathArcTo(path, x, y, rad, 0, angle, 0); angle += add; x += 2 * rad + step; } y += 2 * rad + step; x = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigureWithArc(path, x, y, rad, (uiPi / 4), angle, 0); angle += add; x += 2 * rad + step; } y += 2 * rad + step; x = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigure(path, x, y); uiDrawPathArcTo(path, x, y, rad, (uiPi / 4), angle, 0); angle += add; x += 2 * rad + step; } y += 2 * rad + step; x = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigureWithArc(path, x, y, rad, uiPi + (uiPi / 5), angle, 0); angle += add; x += 2 * rad + step; } y += 2 * rad + step; x = start + rad; angle = 0; for (i = 0; i < 13; i++) { uiDrawPathNewFigure(path, x, y); uiDrawPathArcTo(path, x, y, rad, uiPi + (uiPi / 5), angle, 0); angle += add; x += 2 * rad + step; } uiDrawPathEnd(path); brush.Type = uiDrawBrushTypeSolid; brush.R = 0; brush.G = 0; brush.B = 0; brush.A = 1; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.Thickness = 1; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &brush, &sp); uiDrawFreePath(path); } // Direct2D Documentation Code static void d2dColorToRGB(uint32_t color, double *r, double *g, double *b) { uint8_t rr, gg, bb; rr = (color & 0xFF0000) >> 16; gg = (color & 0x00FF00) >> 8; bb = color & 0x0000FF; *r = ((double) rr) / 255.0; *g = ((double) gg) / 255.0; *b = ((double) bb) / 255.0; } #define d2dBlack 0x000000 #define d2dLightSlateGray 0x778899 #define d2dCornflowerBlue 0x6495ED #define d2dWhite 0xFFFFFF #define d2dYellowGreen 0x9ACD32 #define d2dYellow 0xFFFF00 #define d2dForestGreen 0x228B22 #define d2dOliveDrab 0x6B8E23 #define d2dLightSkyBlue 0x87CEFA static void d2dSolidBrush(uiDrawBrush *brush, uint32_t color, double alpha) { brush->Type = uiDrawBrushTypeSolid; d2dColorToRGB(color, &(brush->R), &(brush->G), &(brush->B)); brush->A = alpha; } static void d2dClear(uiAreaDrawParams *p, uint32_t color, double alpha) { uiDrawPath *path; uiDrawBrush brush; d2dSolidBrush(&brush, color, alpha); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 0, 0, p->AreaWidth, p->AreaHeight); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &brush); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/hh780340%28v=vs.85%29.aspx // also at https://msdn.microsoft.com/en-us/library/windows/desktop/dd535473%28v=vs.85%29.aspx static void drawD2DW8QS(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush brush; d2dSolidBrush(&brush, d2dBlack, 1.0); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 100, 100, (p->AreaWidth - 100) - 100, (p->AreaHeight - 100) - 100); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &brush); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx static void drawD2DSimpleApp(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush lightSlateGray; uiDrawBrush cornflowerBlue; uiDrawStrokeParams sp; int x, y; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; d2dSolidBrush(&lightSlateGray, d2dLightSlateGray, 1.0); d2dSolidBrush(&cornflowerBlue, d2dCornflowerBlue, 1.0); d2dClear(p, d2dWhite, 1.0); sp.Thickness = 0.5; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; for (x = 0; x < p->AreaWidth; x += 10) { path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, x, 0); uiDrawPathLineTo(path, x, p->AreaHeight); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &lightSlateGray, &sp); uiDrawFreePath(path); } for (y = 0; y < p->AreaHeight; y += 10) { path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 0, y); uiDrawPathLineTo(path, p->AreaWidth, y); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &lightSlateGray, &sp); uiDrawFreePath(path); } double left, top, right, bottom; left = p->AreaWidth / 2.0 - 50.0; right = p->AreaWidth / 2.0 + 50.0; top = p->AreaHeight / 2.0 - 50.0; bottom = p->AreaHeight / 2.0 + 50.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, left, top, right - left, bottom - top); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &lightSlateGray); uiDrawFreePath(path); left = p->AreaWidth / 2.0 - 100.0; right = p->AreaWidth / 2.0 + 100.0; top = p->AreaHeight / 2.0 - 100.0; bottom = p->AreaHeight / 2.0 + 100.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, left, top, right - left, bottom - top); uiDrawPathEnd(path); sp.Thickness = 1.0; uiDrawStroke(p->Context, path, &cornflowerBlue, &sp); uiDrawFreePath(path); } // TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd372260(v=vs.85).aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756654%28v=vs.85%29.aspx // TODO? all subsections too? https://msdn.microsoft.com/en-us/library/windows/desktop/hh973240%28v=vs.85%29.aspx // TODO differing examples of? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756651%28v=vs.85%29.aspx // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756680%28v=vs.85%29.aspx static void drawD2DSolidBrush(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush black; uiDrawBrush yellowGreen; uiDrawStrokeParams sp; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; d2dSolidBrush(&black, d2dBlack, 1.0); d2dSolidBrush(&yellowGreen, d2dYellowGreen, 1.0); path = uiDrawNewPath(uiDrawFillModeWinding); // the example doesn't define a rectangle // 150x150 seems to be right given the other examples though uiDrawPathAddRectangle(path, 25, 25, 150, 150); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &yellowGreen); sp.Thickness = 1.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &black, &sp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756678%28v=vs.85%29.aspx static void drawD2DLinearBrush(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush black; uiDrawBrush gradient; uiDrawBrushGradientStop stops[2]; uiDrawStrokeParams sp; uiDrawMatrix m; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; // leave some room uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 25, 25); uiDrawTransform(p->Context, &m); gradient.Type = uiDrawBrushTypeLinearGradient; gradient.X0 = 0; gradient.Y0 = 0; gradient.X1 = 150; gradient.Y1 = 150; stops[0].Pos = 0.0; d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); stops[0].A = 1.0; stops[1].Pos = 1.0; d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); stops[1].A = 1.0; gradient.Stops = stops; gradient.NumStops = 2; d2dSolidBrush(&black, d2dBlack, 1.0); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 0, 0, 150, 150); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &gradient); sp.Thickness = 1.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &black, &sp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756679%28v=vs.85%29.aspx // TODO expand this to change the origin point with a mouse click (not in the original but useful to have) static void drawD2DRadialBrush(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush black; uiDrawBrush gradient; uiDrawBrushGradientStop stops[2]; uiDrawStrokeParams sp; uiDrawMatrix m; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; // leave some room uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 25, 25); uiDrawTransform(p->Context, &m); gradient.Type = uiDrawBrushTypeRadialGradient; gradient.X0 = 75; gradient.Y0 = 75; gradient.X1 = 75; gradient.Y1 = 75; gradient.OuterRadius = 75; stops[0].Pos = 0.0; d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); stops[0].A = 1.0; stops[1].Pos = 1.0; d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); stops[1].A = 1.0; gradient.Stops = stops; gradient.NumStops = 2; d2dSolidBrush(&black, d2dBlack, 1.0); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 150, 75); uiDrawPathArcTo(path, 75, 75, 75, 0, 2 * uiPi, 0); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &gradient); sp.Thickness = 1.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &black, &sp); uiDrawFreePath(path); } // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756677%28v=vs.85%29.aspx // TODO? other pages have some of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd756653%28v=vs.85%29.aspx // from https://msdn.microsoft.com/en-us/library/windows/desktop/ee264309%28v=vs.85%29.aspx static void drawD2DPathGeometries(uiAreaDrawParams *p) { uiDrawPath *leftMountain; uiDrawPath *rightMountain; uiDrawPath *sun; uiDrawPath *sunRays; uiDrawPath *river; uiDrawBrush radial; uiDrawBrush scene; uiDrawStrokeParams sp; uiDrawBrushGradientStop stops[2]; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; // TODO this is definitely wrong but the example doesn't have the right brush in it radial.Type = uiDrawBrushTypeRadialGradient; radial.X0 = 75; radial.Y0 = 75; radial.X1 = 75; radial.Y1 = 75; radial.OuterRadius = 75; stops[0].Pos = 0.0; d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); stops[0].A = 1.0; stops[1].Pos = 1.0; d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); stops[1].A = 1.0; radial.Stops = stops; radial.NumStops = 2; leftMountain = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(leftMountain, 346, 255); uiDrawPathLineTo(leftMountain, 267, 177); uiDrawPathLineTo(leftMountain, 236, 192); uiDrawPathLineTo(leftMountain, 212, 160); uiDrawPathLineTo(leftMountain, 156, 255); uiDrawPathLineTo(leftMountain, 346, 255); uiDrawPathCloseFigure(leftMountain); uiDrawPathEnd(leftMountain); rightMountain = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(rightMountain, 575, 263); uiDrawPathLineTo(rightMountain, 481, 146); uiDrawPathLineTo(rightMountain, 449, 181); uiDrawPathLineTo(rightMountain, 433, 159); uiDrawPathLineTo(rightMountain, 401, 214); uiDrawPathLineTo(rightMountain, 381, 199); uiDrawPathLineTo(rightMountain, 323, 263); uiDrawPathLineTo(rightMountain, 575, 263); uiDrawPathCloseFigure(rightMountain); uiDrawPathEnd(rightMountain); sun = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(sun, (440.0 - 270.0) / 2 + 270.0, 255, 85, uiPi, uiPi, 0); uiDrawPathCloseFigure(sun); uiDrawPathEnd(sun); // the original examples had these as hollow figures // we don't support them, so we'll have to stroke it separately sunRays = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(sunRays, 299, 182); uiDrawPathBezierTo(sunRays, 299, 182, 294, 176, 285, 178); uiDrawPathBezierTo(sunRays, 276, 179, 272, 173, 272, 173); uiDrawPathNewFigure(sunRays, 354, 156); uiDrawPathBezierTo(sunRays, 354, 156, 358, 149, 354, 142); uiDrawPathBezierTo(sunRays, 349, 134, 354, 127, 354, 127); uiDrawPathNewFigure(sunRays, 322, 164); uiDrawPathBezierTo(sunRays, 322, 164, 322, 156, 314, 152); uiDrawPathBezierTo(sunRays, 306, 149, 305, 141, 305, 141); uiDrawPathNewFigure(sunRays, 385, 164); uiDrawPathBezierTo(sunRays, 385, 164, 392, 161, 394, 152); uiDrawPathBezierTo(sunRays, 395, 144, 402, 141, 402, 142); uiDrawPathNewFigure(sunRays, 408, 182); uiDrawPathBezierTo(sunRays, 408, 182, 416, 184, 422, 178); uiDrawPathBezierTo(sunRays, 428, 171, 435, 173, 435, 173); uiDrawPathEnd(sunRays); river = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(river, 183, 392); uiDrawPathBezierTo(river, 238, 284, 472, 345, 356, 303); uiDrawPathBezierTo(river, 237, 261, 333, 256, 333, 256); uiDrawPathBezierTo(river, 335, 257, 241, 261, 411, 306); uiDrawPathBezierTo(river, 574, 350, 288, 324, 296, 392); uiDrawPathEnd(river); d2dClear(p, d2dWhite, 1.0); // TODO draw the grid uiDrawFill(p->Context, sun, &radial); d2dSolidBrush(&scene, d2dBlack, 1.0); sp.Thickness = 1.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, sun, &scene, &sp); uiDrawStroke(p->Context, sunRays, &scene, &sp); d2dSolidBrush(&scene, d2dOliveDrab, 1.0); uiDrawFill(p->Context, leftMountain, &scene); d2dSolidBrush(&scene, d2dBlack, 1.0); uiDrawStroke(p->Context, leftMountain, &scene, &sp); d2dSolidBrush(&scene, d2dLightSkyBlue, 1.0); uiDrawFill(p->Context, river, &scene); d2dSolidBrush(&scene, d2dBlack, 1.0); uiDrawStroke(p->Context, river, &scene, &sp); d2dSolidBrush(&scene, d2dYellowGreen, 1.0); uiDrawFill(p->Context, rightMountain, &scene); d2dSolidBrush(&scene, d2dBlack, 1.0); uiDrawStroke(p->Context, rightMountain, &scene, &sp); uiDrawFreePath(leftMountain); uiDrawFreePath(rightMountain); uiDrawFreePath(sun); uiDrawFreePath(sunRays); uiDrawFreePath(river); } // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756690%28v=vs.85%29.aspx // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756681%28v=vs.85%29.aspx static void drawD2DGeometryGroup(uiAreaDrawParams *p) { uiDrawPath *alternate; uiDrawPath *winding; uiDrawBrush fill; uiDrawBrush stroke; uiDrawStrokeParams sp; uiDrawMatrix m; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; alternate = uiDrawNewPath(uiDrawFillModeAlternate); uiDrawPathNewFigureWithArc(alternate, 105, 105, 25, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(alternate, 105, 105, 50, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(alternate, 105, 105, 75, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(alternate, 105, 105, 100, 0, 2 * uiPi, 0); uiDrawPathEnd(alternate); winding = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(winding, 105, 105, 25, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(winding, 105, 105, 50, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(winding, 105, 105, 75, 0, 2 * uiPi, 0); uiDrawPathNewFigureWithArc(winding, 105, 105, 100, 0, 2 * uiPi, 0); uiDrawPathEnd(winding); d2dClear(p, d2dWhite, 1.0); // TODO grid // TODO the example doesn't provide these d2dSolidBrush(&fill, d2dForestGreen, 1.0); d2dSolidBrush(&stroke, d2dCornflowerBlue, 1.0); sp.Thickness = 1.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawFill(p->Context, alternate, &fill); uiDrawStroke(p->Context, alternate, &stroke, &sp); // TODO text uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 300, 0); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, winding, &fill); uiDrawStroke(p->Context, winding, &stroke, &sp); // // TODO text uiDrawFreePath(winding); uiDrawFreePath(alternate); } // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756676%28v=vs.85%29.aspx // TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370971%28v=vs.85%29.aspx // TODO are there even examples here? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370966%28v=vs.85%29.aspx // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756687%28v=vs.85%29.aspx static void drawD2DRotate(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush original; uiDrawBrush fill; uiDrawBrush transform; uiDrawStrokeParams originalsp; uiDrawStrokeParams transformsp; uiDrawMatrix m; originalsp.Dashes = NULL; originalsp.NumDashes = 0; originalsp.DashPhase = 0; transformsp.Dashes = NULL; transformsp.NumDashes = 0; transformsp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 438.0, 301.5, 498.0 - 438.0, 361.5 - 301.5); uiDrawPathEnd(path); // TODO the example doesn't specify what these should be d2dSolidBrush(&original, d2dBlack, 1.0); d2dSolidBrush(&fill, d2dWhite, 0.5); d2dSolidBrush(&transform, d2dForestGreen, 1.0); // TODO this needs to be dashed originalsp.Thickness = 1.0; originalsp.Cap = uiDrawLineCapFlat; originalsp.Join = uiDrawLineJoinMiter; originalsp.MiterLimit = uiDrawDefaultMiterLimit; transformsp.Thickness = 1.0; transformsp.Cap = uiDrawLineCapFlat; transformsp.Join = uiDrawLineJoinMiter; transformsp.MiterLimit = uiDrawDefaultMiterLimit; // save for when we do the translated one uiDrawSave(p->Context); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixRotate(&m, 468.0, 331.5, 45.0 * (uiPi / 180)); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawRestore(p->Context); // translate to test the corner axis uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, -200, -200); uiDrawTransform(p->Context, &m); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixRotate(&m, 438.0, 301.5, 45.0 * (uiPi / 180)); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756688%28v=vs.85%29.aspx static void drawD2DScale(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush original; uiDrawBrush fill; uiDrawBrush transform; uiDrawStrokeParams originalsp; uiDrawStrokeParams transformsp; uiDrawMatrix m; originalsp.Dashes = NULL; originalsp.NumDashes = 0; originalsp.DashPhase = 0; transformsp.Dashes = NULL; transformsp.NumDashes = 0; transformsp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 438.0, 80.5, 498.0 - 438.0, 140.5 - 80.5); uiDrawPathEnd(path); // TODO the example doesn't specify what these should be d2dSolidBrush(&original, d2dBlack, 1.0); d2dSolidBrush(&fill, d2dWhite, 0.5); d2dSolidBrush(&transform, d2dForestGreen, 1.0); // TODO this needs to be dashed originalsp.Thickness = 1.0; originalsp.Cap = uiDrawLineCapFlat; originalsp.Join = uiDrawLineJoinMiter; originalsp.MiterLimit = uiDrawDefaultMiterLimit; transformsp.Thickness = 1.0; transformsp.Cap = uiDrawLineCapFlat; transformsp.Join = uiDrawLineJoinMiter; transformsp.MiterLimit = uiDrawDefaultMiterLimit; // save for when we do the translated one uiDrawSave(p->Context); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixScale(&m, 438.0, 80.5, 1.3, 1.3); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawRestore(p->Context); // for testing purposes, show what happens if we scale about (0, 0) uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, -300, 50); uiDrawTransform(p->Context, &m); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixScale(&m, 0, 0, 1.3, 1.3); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756689%28v=vs.85%29.aspx // TODO counterclockwise?! void drawD2DSkew(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush original; uiDrawBrush fill; uiDrawBrush transform; uiDrawStrokeParams originalsp; uiDrawStrokeParams transformsp; uiDrawMatrix m; originalsp.Dashes = NULL; originalsp.NumDashes = 0; originalsp.DashPhase = 0; transformsp.Dashes = NULL; transformsp.NumDashes = 0; transformsp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 126.0, 301.5, 186.0 - 126.0, 361.5 - 301.5); uiDrawPathEnd(path); // TODO the example doesn't specify what these should be d2dSolidBrush(&original, d2dBlack, 1.0); d2dSolidBrush(&fill, d2dWhite, 0.5); d2dSolidBrush(&transform, d2dForestGreen, 1.0); // TODO this needs to be dashed originalsp.Thickness = 1.0; originalsp.Cap = uiDrawLineCapFlat; originalsp.Join = uiDrawLineJoinMiter; originalsp.MiterLimit = uiDrawDefaultMiterLimit; transformsp.Thickness = 1.0; transformsp.Cap = uiDrawLineCapFlat; transformsp.Join = uiDrawLineJoinMiter; transformsp.MiterLimit = uiDrawDefaultMiterLimit; // save for when we do the translated one uiDrawSave(p->Context); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixSkew(&m, 126.0, 301.5, 45.0 * (uiPi / 180), 0); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawRestore(p->Context); // for testing purposes, show what happens if we skew about (0, 0) uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 0, -200); uiDrawTransform(p->Context, &m); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixSkew(&m, 0, 0, 45.0 * (uiPi / 180), 0); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756691%28v=vs.85%29.aspx static void drawD2DTranslate(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush original; uiDrawBrush fill; uiDrawBrush transform; uiDrawStrokeParams originalsp; uiDrawStrokeParams transformsp; uiDrawMatrix m; originalsp.Dashes = NULL; originalsp.NumDashes = 0; originalsp.DashPhase = 0; transformsp.Dashes = NULL; transformsp.NumDashes = 0; transformsp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 126.0, 80.5, 186.0 - 126.0, 140.5 - 80.5); uiDrawPathEnd(path); // TODO the example doesn't specify what these should be d2dSolidBrush(&original, d2dBlack, 1.0); d2dSolidBrush(&fill, d2dWhite, 0.5); d2dSolidBrush(&transform, d2dForestGreen, 1.0); // TODO this needs to be dashed originalsp.Thickness = 1.0; originalsp.Cap = uiDrawLineCapFlat; originalsp.Join = uiDrawLineJoinMiter; originalsp.MiterLimit = uiDrawDefaultMiterLimit; transformsp.Thickness = 1.0; transformsp.Cap = uiDrawLineCapFlat; transformsp.Join = uiDrawLineJoinMiter; transformsp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 20, 10); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756672%28v=vs.85%29.aspx // TODO the points seem off static void drawD2DMultiTransforms(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush original; uiDrawBrush fill; uiDrawBrush transform; uiDrawStrokeParams originalsp; uiDrawStrokeParams transformsp; uiDrawMatrix mtranslate; uiDrawMatrix mrotate; originalsp.Dashes = NULL; originalsp.NumDashes = 0; originalsp.DashPhase = 0; transformsp.Dashes = NULL; transformsp.NumDashes = 0; transformsp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 300.0, 40.0, 360.0 - 300.0, 100.0 - 40.0); uiDrawPathEnd(path); // TODO the example doesn't specify what these should be d2dSolidBrush(&original, d2dBlack, 1.0); d2dSolidBrush(&fill, d2dWhite, 0.5); d2dSolidBrush(&transform, d2dForestGreen, 1.0); // TODO this needs to be dashed originalsp.Thickness = 1.0; originalsp.Cap = uiDrawLineCapFlat; originalsp.Join = uiDrawLineJoinMiter; originalsp.MiterLimit = uiDrawDefaultMiterLimit; transformsp.Thickness = 1.0; transformsp.Cap = uiDrawLineCapFlat; transformsp.Join = uiDrawLineJoinMiter; transformsp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawMatrixSetIdentity(&mtranslate); uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0); uiDrawMatrixSetIdentity(&mrotate); uiDrawMatrixRotate(&mrotate, 330.0, 70.0, 45.0 * (uiPi / 180)); // save for when we do the opposite one uiDrawSave(p->Context); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawTransform(p->Context, &mrotate); uiDrawTransform(p->Context, &mtranslate); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawRestore(p->Context); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 40.0, 40.0, 100.0 - 40.0, 100.0 - 40.0); uiDrawPathEnd(path); uiDrawMatrixSetIdentity(&mtranslate); uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0); uiDrawMatrixSetIdentity(&mrotate); uiDrawMatrixRotate(&mrotate, 70.0, 70.0, 45.0 * (uiPi / 180)); uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawTransform(p->Context, &mtranslate); uiDrawTransform(p->Context, &mrotate); uiDrawFill(p->Context, path, &fill); uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756675%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756673%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756684%28v=vs.85%29.aspx // TODO dashing https://msdn.microsoft.com/en-us/library/windows/desktop/dd756683%28v=vs.85%29.aspx // from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx static void drawD2DComplexShape(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush black; uiDrawBrush gradient; uiDrawBrushGradientStop stops[2]; uiDrawStrokeParams sp; uiDrawMatrix m; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 0, 0); uiDrawPathLineTo(path, 200, 0); uiDrawPathBezierTo(path, 150, 50, 150, 150, 200, 200); uiDrawPathLineTo(path, 0, 200); uiDrawPathBezierTo(path, 50, 150, 50, 50, 0, 0); uiDrawPathCloseFigure(path); uiDrawPathEnd(path); d2dSolidBrush(&black, d2dBlack, 1.0); stops[0].Pos =0.0; stops[0].R = 0.0; stops[0].G = 1.0; stops[0].B = 1.0; stops[0].A = 0.25; stops[1].Pos = 1.0; stops[1].R = 0.0; stops[1].G = 0.0; stops[1].B = 1.0; stops[1].A = 1.0; gradient.Type = uiDrawBrushTypeLinearGradient; gradient.X0 = 100; gradient.Y0 = 0; gradient.X1 = 100; gradient.Y1 = 200; gradient.Stops = stops; gradient.NumStops = 2; uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 20, 20); uiDrawTransform(p->Context, &m); sp.Thickness = 10.0; sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; uiDrawStroke(p->Context, path, &black, &sp); uiDrawFill(p->Context, path, &gradient); uiDrawFreePath(path); } // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756692%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756685%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756674%28v=vs.85%29.aspx // TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/ee329947%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/ff485857%28v=vs.85%29.aspx // TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756755%28v=vs.85%29.aspx // TODO go through the API reference and spot examples that aren't listed // TODO all of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd368187%28v=vs.85%29.aspx // cairo Samples Page (http://cairographics.org/samples/) static void crsourcergba(uiDrawBrush *brush, double r, double g, double b, double a) { brush->Type = uiDrawBrushTypeSolid; brush->R = r; brush->G = g; brush->B = b; brush->A = a; } // arc static void drawCSArc(uiAreaDrawParams *p) { double xc = 128.0; double yc = 128.0; double radius = 100.0; double angle1 = 45.0 * (uiPi / 180.0); double angle2 = 180.0 * (uiPi / 180.0); uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; sp.Thickness = 10.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle1, angle2 - angle1, 0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); crsourcergba(&source, 1, 0.2, 0.2, 0.6); sp.Thickness = 6.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, 10.0, 0, 2 * uiPi, 0); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &source); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle1, 0, 0); uiDrawPathLineTo(path, xc, yc); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle2, 0, 0); uiDrawPathLineTo(path, xc, yc); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // arc negative static void drawCSArcNegative(uiAreaDrawParams *p) { double xc = 128.0; double yc = 128.0; double radius = 100.0; double angle1 = 45.0 * (uiPi / 180.0); double angle2 = 180.0 * (uiPi / 180.0); uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; sp.Thickness = 10.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle1, angle2 - angle1, 1); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); crsourcergba(&source, 1, 0.2, 0.2, 0.6); sp.Thickness = 6.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, 10.0, 0, 2 * uiPi, 0); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &source); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle1, 0, 0); uiDrawPathLineTo(path, xc, yc); uiDrawPathNewFigureWithArc(path, xc, yc, radius, angle2, 0, 0); uiDrawPathLineTo(path, xc, yc); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // clip static void drawCSClip(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigureWithArc(path, 128.0, 128.0, 76.8, 0, 2 * uiPi, 0); uiDrawPathEnd(path); uiDrawClip(p->Context, path); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 0, 0, 256, 256); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &source); uiDrawFreePath(path); crsourcergba(&source, 0, 1, 0, 1); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 0, 0); uiDrawPathLineTo(path, 256, 256); uiDrawPathNewFigure(path, 256, 0); uiDrawPathLineTo(path, 0, 256); uiDrawPathEnd(path); sp.Thickness = 10.0; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // TODO clip image // curve rectangle static void drawCSCurveRectangle(uiAreaDrawParams *p) { double x0 = 25.6, /* parameters like cairo_rectangle */ y0 = 25.6, rect_width = 204.8, rect_height = 204.8, radius = 102.4; /* and an approximate curvature radius */ double x1,y1; uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); x1=x0+rect_width; y1=y0+rect_height; if (!rect_width || !rect_height) return; if (rect_width/2 < radius) { if (rect_height/2Context, path, &source); crsourcergba(&source, 0.5, 0, 0, 0.5); sp.Thickness = 10.0; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // curve to static void drawCSCurveTo(uiAreaDrawParams *p) { double x=25.6, y=128.0; double x1=102.4, y1=230.4, x2=153.6, y2=25.6, x3=230.4, y3=128.0; uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, x, y); uiDrawPathBezierTo(path, x1, y1, x2, y2, x3, y3); uiDrawPathEnd(path); sp.Thickness = 10.0; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); crsourcergba(&source, 1, 0.2, 0.2, 0.6); sp.Thickness = 6.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, x, y); uiDrawPathLineTo(path, x1, y1); uiDrawPathNewFigure(path, x2, y2); uiDrawPathLineTo(path, x3, y3); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // dash static void drawCSDash(uiAreaDrawParams *p) { double dashes[] = { 50.0, /* ink */ 10.0, /* skip */ 10.0, /* ink */ 10.0 /* skip*/ }; int ndash = sizeof (dashes)/sizeof(dashes[0]); double offset = -50.0; uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = dashes; sp.NumDashes = ndash; sp.DashPhase = offset; sp.Thickness = 10.0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 128.0, 25.6); uiDrawPathLineTo(path, 230.4, 230.4); uiDrawPathLineTo(path, 230.4 -102.4, 230.4 + 0.0); uiDrawPathBezierTo(path, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // fill and stroke2 static void drawCSFillAndStroke2(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 128.0, 25.6); uiDrawPathLineTo(path, 230.4, 230.4); uiDrawPathLineTo(path, 230.4 - 102.4, 230.4 + 0.0); uiDrawPathBezierTo(path, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); uiDrawPathCloseFigure(path); uiDrawPathNewFigure(path, 64.0, 25.6); uiDrawPathLineTo(path, 64.0 + 51.2, 25.6 + 51.2); uiDrawPathLineTo(path, 64.0 + 51.2 -51.2, 25.6 + 51.2 + 51.2); uiDrawPathLineTo(path, 64.0 + 51.2 -51.2 -51.2, 25.6 + 51.2 + 51.2 -51.2); uiDrawPathCloseFigure(path); uiDrawPathEnd(path); sp.Thickness = 10.0; crsourcergba(&source, 0, 0, 1, 1); uiDrawFill(p->Context, path, &source); crsourcergba(&source, 0, 0, 0, 1); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // fill style static void drawCSFillStyle(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; uiDrawMatrix m; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; sp.Thickness = 6; path = uiDrawNewPath(uiDrawFillModeAlternate); uiDrawPathAddRectangle(path, 12, 12, 232, 70); uiDrawPathNewFigureWithArc(path, 64, 64, 40, 0, 2*uiPi, 0); uiDrawPathNewFigureWithArc(path, 192, 64, 40, 0, -2*uiPi, 1); uiDrawPathEnd(path); crsourcergba(&source, 0, 0.7, 0, 1); uiDrawFill(p->Context, path, &source); crsourcergba(&source, 0, 0, 0, 1); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); uiDrawMatrixSetIdentity(&m); uiDrawMatrixTranslate(&m, 0, 128); uiDrawTransform(p->Context, &m); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, 12, 12, 232, 70); uiDrawPathNewFigureWithArc(path, 64, 64, 40, 0, 2*uiPi, 0); uiDrawPathNewFigureWithArc(path, 192, 64, 40, 0, -2*uiPi, 1); uiDrawPathEnd(path); crsourcergba(&source, 0, 0, 0.9, 1); uiDrawFill(p->Context, path, &source); crsourcergba(&source, 0, 0, 0, 1); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // TOOD gradient (radial gradient with two circles) // TODO image // TODO imagepattern // multi segment caps static void drawCSMultiCaps(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 50.0, 75.0); uiDrawPathLineTo(path, 200.0, 75.0); uiDrawPathNewFigure(path, 50.0, 125.0); uiDrawPathLineTo(path, 200.0, 125.0); uiDrawPathNewFigure(path, 50.0, 175.0); uiDrawPathLineTo(path, 200.0, 175.0); uiDrawPathEnd(path); sp.Thickness = 30.0; sp.Cap = uiDrawLineCapRound; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // rounded rectangle static void drawCSRoundRect(uiAreaDrawParams *p) { double x = 25.6, /* parameters like cairo_rectangle */ y = 25.6, width = 204.8, height = 204.8, aspect = 1.0, /* aspect ratio */ corner_radius = height / 10.0; /* and corner curvature radius */ double radius = corner_radius / aspect; double degrees = uiPi / 180.0; uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; path = uiDrawNewPath(uiDrawFillModeWinding); // top right corner uiDrawPathNewFigureWithArc(path, x + width - radius, y + radius, radius, -90 * degrees, uiPi / 2, 0); // bottom right corner uiDrawPathArcTo(path, x + width - radius, y + height - radius, radius, 0 * degrees, uiPi / 2, 0); // bottom left corner uiDrawPathArcTo(path, x + radius, y + height - radius, radius, 90 * degrees, uiPi / 2, 0); // top left corner uiDrawPathArcTo(path, x + radius, y + radius, radius, 180 * degrees, uiPi / 2, 0); uiDrawPathCloseFigure(path); uiDrawPathEnd(path); crsourcergba(&source, 0.5, 0.5, 1, 1); uiDrawFill(p->Context, path, &source); crsourcergba(&source, 0.5, 0, 0, 0.5); sp.Thickness = 10.0; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // set line cap static void drawCSSetLineCap(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; sp.Thickness = 30.0; sp.Cap = uiDrawLineCapFlat; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 64.0, 50.0); uiDrawPathLineTo(path, 64.0, 200.0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); sp.Cap = uiDrawLineCapRound; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 128.0, 50.0); uiDrawPathLineTo(path, 128.0, 200.0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); sp.Cap = uiDrawLineCapSquare; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 192.0, 50.0); uiDrawPathLineTo(path, 192.0, 200.0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); // draw helping lines // keep the square cap to match the reference picture on the cairo website crsourcergba(&source, 1, 0.2, 0.2, 1); sp.Thickness = 2.56; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 64.0, 50.0); uiDrawPathLineTo(path, 64.0, 200.0); uiDrawPathNewFigure(path, 128.0, 50.0); uiDrawPathLineTo(path, 128.0, 200.0); uiDrawPathNewFigure(path, 192.0, 50.0); uiDrawPathLineTo(path, 192.0, 200.0); uiDrawPathEnd(path); uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // set line join static void drawCSSetLineJoin(uiAreaDrawParams *p) { uiDrawBrush source; uiDrawStrokeParams sp; uiDrawPath *path; crsourcergba(&source, 0, 0, 0, 1); sp.Cap = uiDrawLineCapFlat; sp.Join = uiDrawLineJoinMiter; sp.MiterLimit = uiDrawDefaultMiterLimit; sp.Dashes = NULL; sp.NumDashes = 0; sp.DashPhase = 0; sp.Thickness = 40.96; path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 76.8, 84.48); uiDrawPathLineTo(path, 76.8 + 51.2, 84.48 -51.2); uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 84.48 - 51.2 + 51.2); uiDrawPathEnd(path); sp.Join = uiDrawLineJoinMiter; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 76.8, 161.28); uiDrawPathLineTo(path, 76.8 + 51.2, 161.28 -51.2); uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 161.28 - 51.2 + 51.2); uiDrawPathEnd(path); sp.Join = uiDrawLineJoinBevel; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, 76.8, 238.08); uiDrawPathLineTo(path, 76.8 + 51.2, 238.08 -51.2); uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 238.08 - 51.2 + 51.2); uiDrawPathEnd(path); sp.Join = uiDrawLineJoinRound; uiDrawStroke(p->Context, path, &source, &sp); uiDrawFreePath(path); } // TODO text // TODO text align center // TODO text extents // Quartz 2D Programming Guide static void cgaddrect(uiDrawPath *path, uiAreaDrawParams *p, double x, double y, double width, double height) { uiDrawPathAddRectangle(path, x, p->AreaHeight - y - height, width, height); } // Graphics Contexts > Creating a Window Graphics Context in Mac OS X static void drawQ2DCreateWindowGC(uiAreaDrawParams *p) { uiDrawPath *path; uiDrawBrush brush; crsourcergba(&brush, 1, 0, 0, 1); path = uiDrawNewPath(uiDrawFillModeWinding); cgaddrect(path, p, 0, 0, 200, 100); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &brush); uiDrawFreePath(path); crsourcergba(&brush, 0, 0, 1, .5); path = uiDrawNewPath(uiDrawFillModeWinding); cgaddrect(path, p, 0, 0, 100, 200); uiDrawPathEnd(path); uiDrawFill(p->Context, path, &brush); uiDrawFreePath(path); } // TODO Patterns page? // TODO Shadows page? // TODO Gradients page (includes some circle-circle radial gradients) // TODO Transparency Layers page? // TODO Core Graphics Layer Drawing page? // Cocoa Drawing Guide // TODO Advanced Drawing Techniques page? // TODO Text page, if any? static const struct drawtest tests[] = { { "Original uiArea test", drawOriginal }, { "Arc test", drawArcs }, { "Direct2D: Direct2D Quickstart for Windows 8", drawD2DW8QS }, { "Direct2D: Creating a Simple Direct2D Application", drawD2DSimpleApp }, { "Direct2D: How to Create a Solid Color Brush", drawD2DSolidBrush }, { "Direct2D: How to Create a Linear Gradient Brush", drawD2DLinearBrush }, { "Direct2D: How to Create a Radial Gradient Brush", drawD2DRadialBrush }, { "Direct2D: Path Geometries Overview", drawD2DPathGeometries }, { "Direct2D: How to Create Geometry Groups", drawD2DGeometryGroup }, { "Direct2D: How to Rotate an Object", drawD2DRotate }, { "Direct2D: How to Scale an Object", drawD2DScale }, { "Direct2D: How to Skew an Object", drawD2DSkew }, { "Direct2D: How to Translate an Object", drawD2DTranslate }, { "Direct2D: How to Apply Multiple Transforms to an Object", drawD2DMultiTransforms }, { "Direct2D: How to Draw and Fill a Complex Shape", drawD2DComplexShape }, { "cairo samples: arc", drawCSArc }, { "cairo samples: arc negative", drawCSArcNegative }, { "cairo samples: clip", drawCSClip }, { "cairo samples: curve rectangle", drawCSCurveRectangle }, { "cairo samples: curve to", drawCSCurveTo }, { "cairo samples: dash", drawCSDash }, { "cairo samples: fill and stroke2", drawCSFillAndStroke2 }, { "cairo samples: fill style", drawCSFillStyle }, { "cairo samples: multi segment caps", drawCSMultiCaps }, { "cairo samples: rounded rectangle", drawCSRoundRect }, { "cairo samples: set line cap", drawCSSetLineCap }, { "cairo samples: set line join", drawCSSetLineJoin }, { "Quartz 2D PG: Creating a Window Graphics Context in Mac OS X", drawQ2DCreateWindowGC }, { NULL, NULL }, }; void runDrawTest(int n, uiAreaDrawParams *p) { (*(tests[n].draw))(p); } void populateComboboxWithTests(uiCombobox *c) { size_t i; for (i = 0; tests[i].name != NULL; i++) uiComboboxAppend(c, tests[i].name); }