From b2d9eb251b405b55573450b37de7b4f9486ac24a Mon Sep 17 00:00:00 2001 From: Xeek Date: Sat, 17 Sep 2016 20:00:17 -0500 Subject: [PATCH 1/3] Added nvgRoundedRectEx so that the rectangle's corners can have varying radii. nvgRoundRect changed to utilize nvgRoundedRectEx. --- src/nanovg.c | 32 ++++++++++++++++++++------------ src/nanovg.h | 4 ++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/nanovg.c b/src/nanovg.c index c388696..ae17dd4 100644 --- a/src/nanovg.c +++ b/src/nanovg.c @@ -2119,22 +2119,30 @@ void nvgRect(NVGcontext* ctx, float x, float y, float w, float h) void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r) { - if (r < 0.1f) { - nvgRect(ctx, x,y,w,h); + nvgRoundedRectEx(ctx, x, y, w, h, r, r, r, r); +} + +void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4) +{ + if(r1 < 0.1f && r2 < 0.1f && r3 < 0.1f && r4 < 0.1f) { + nvgRect(ctx, x, y, w, h); return; } else { - float rx = nvg__minf(r, nvg__absf(w)*0.5f) * nvg__signf(w), ry = nvg__minf(r, nvg__absf(h)*0.5f) * nvg__signf(h); + float r1x = nvg__minf(r1, nvg__absf(w)*0.5f) * nvg__signf(w), r1y = nvg__minf(r1, nvg__absf(h)*0.5f) * nvg__signf(h); + float r2x = nvg__minf(r2, nvg__absf(w)*0.5f) * nvg__signf(w), r2y = nvg__minf(r2, nvg__absf(h)*0.5f) * nvg__signf(h); + float r3x = nvg__minf(r3, nvg__absf(w)*0.5f) * nvg__signf(w), r3y = nvg__minf(r3, nvg__absf(h)*0.5f) * nvg__signf(h); + float r4x = nvg__minf(r4, nvg__absf(w)*0.5f) * nvg__signf(w), r4y = nvg__minf(r4, nvg__absf(h)*0.5f) * nvg__signf(h); float vals[] = { - NVG_MOVETO, x, y+ry, - NVG_LINETO, x, y+h-ry, - NVG_BEZIERTO, x, y+h-ry*(1-NVG_KAPPA90), x+rx*(1-NVG_KAPPA90), y+h, x+rx, y+h, - NVG_LINETO, x+w-rx, y+h, - NVG_BEZIERTO, x+w-rx*(1-NVG_KAPPA90), y+h, x+w, y+h-ry*(1-NVG_KAPPA90), x+w, y+h-ry, - NVG_LINETO, x+w, y+ry, - NVG_BEZIERTO, x+w, y+ry*(1-NVG_KAPPA90), x+w-rx*(1-NVG_KAPPA90), y, x+w-rx, y, - NVG_LINETO, x+rx, y, - NVG_BEZIERTO, x+rx*(1-NVG_KAPPA90), y, x, y+ry*(1-NVG_KAPPA90), x, y+ry, + NVG_MOVETO, x, y + r4y, + NVG_LINETO, x, y + h - r1y, + NVG_BEZIERTO, x, y + h - r1y*(1 - NVG_KAPPA90), x + r1x*(1 - NVG_KAPPA90), y + h, x + r1x, y + h, + NVG_LINETO, x + w - r2x, y + h, + NVG_BEZIERTO, x + w - r2x*(1 - NVG_KAPPA90), y + h, x + w, y + h - r2y*(1 - NVG_KAPPA90), x + w, y + h - r2y, + NVG_LINETO, x + w, y + r3y, + NVG_BEZIERTO, x + w, y + r3y*(1 - NVG_KAPPA90), x + w - r3x*(1 - NVG_KAPPA90), y, x + w - r3x, y, + NVG_LINETO, x + r4x, y, + NVG_BEZIERTO, x + r4x*(1 - NVG_KAPPA90), y, x, y + r4y*(1 - NVG_KAPPA90), x, y + r4y, NVG_CLOSE }; nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); diff --git a/src/nanovg.h b/src/nanovg.h index e8a59fa..63b4940 100644 --- a/src/nanovg.h +++ b/src/nanovg.h @@ -489,6 +489,10 @@ void nvgRect(NVGcontext* ctx, float x, float y, float w, float h); // Creates new rounded rectangle shaped sub-path. void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r); +// Creates new rounded rectangle shaped sub-path with more radius control for each corner. +// r1 is bottom left, r2 is bottom right, r3, is top right, r4 is top left. +void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4); + // Creates new ellipse shaped sub-path. void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry); From 34621d4ad23a9930486157373892578c39684f89 Mon Sep 17 00:00:00 2001 From: Xeek Date: Sun, 18 Sep 2016 10:47:58 -0500 Subject: [PATCH 2/3] Renamed nvgRoundedRectEx to nvgRoundedRectVarying, using variables for duplicated calls to nvg__absf, renamed the radius parameters & variables to be more descriptive, changed the order of radius parameters to follow CSS order, and finally corrected the if/else style suggested by @memononen. --- src/nanovg.c | 37 +++++++++++++++++++------------------ src/nanovg.h | 2 +- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/nanovg.c b/src/nanovg.c index ae17dd4..51f972c 100644 --- a/src/nanovg.c +++ b/src/nanovg.c @@ -2119,30 +2119,31 @@ void nvgRect(NVGcontext* ctx, float x, float y, float w, float h) void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r) { - nvgRoundedRectEx(ctx, x, y, w, h, r, r, r, r); + nvgRoundedRectVarying(ctx, x, y, w, h, r, r, r, r); } -void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4) +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft) { - if(r1 < 0.1f && r2 < 0.1f && r3 < 0.1f && r4 < 0.1f) { + if(radTopLeft < 0.1f && radTopRight < 0.1f && radBottomRight < 0.1f && radBottomLeft < 0.1f) { nvgRect(ctx, x, y, w, h); return; - } - else { - float r1x = nvg__minf(r1, nvg__absf(w)*0.5f) * nvg__signf(w), r1y = nvg__minf(r1, nvg__absf(h)*0.5f) * nvg__signf(h); - float r2x = nvg__minf(r2, nvg__absf(w)*0.5f) * nvg__signf(w), r2y = nvg__minf(r2, nvg__absf(h)*0.5f) * nvg__signf(h); - float r3x = nvg__minf(r3, nvg__absf(w)*0.5f) * nvg__signf(w), r3y = nvg__minf(r3, nvg__absf(h)*0.5f) * nvg__signf(h); - float r4x = nvg__minf(r4, nvg__absf(w)*0.5f) * nvg__signf(w), r4y = nvg__minf(r4, nvg__absf(h)*0.5f) * nvg__signf(h); + } else { + float halfw = nvg__absf(w)*0.5f; + float halfh = nvg__absf(h)*0.5f; + float rxBL = nvg__minf(radBottomLeft, halfw) * nvg__signf(w), ryBL = nvg__minf(radBottomLeft, halfh) * nvg__signf(h); + float rxBR = nvg__minf(radBottomRight, halfw) * nvg__signf(w), ryBR = nvg__minf(radBottomRight, halfh) * nvg__signf(h); + float rxTR = nvg__minf(radTopRight, halfw) * nvg__signf(w), ryTR = nvg__minf(radTopRight, halfh) * nvg__signf(h); + float rxTL = nvg__minf(radTopLeft, halfw) * nvg__signf(w), ryTL = nvg__minf(radTopLeft, halfh) * nvg__signf(h); float vals[] = { - NVG_MOVETO, x, y + r4y, - NVG_LINETO, x, y + h - r1y, - NVG_BEZIERTO, x, y + h - r1y*(1 - NVG_KAPPA90), x + r1x*(1 - NVG_KAPPA90), y + h, x + r1x, y + h, - NVG_LINETO, x + w - r2x, y + h, - NVG_BEZIERTO, x + w - r2x*(1 - NVG_KAPPA90), y + h, x + w, y + h - r2y*(1 - NVG_KAPPA90), x + w, y + h - r2y, - NVG_LINETO, x + w, y + r3y, - NVG_BEZIERTO, x + w, y + r3y*(1 - NVG_KAPPA90), x + w - r3x*(1 - NVG_KAPPA90), y, x + w - r3x, y, - NVG_LINETO, x + r4x, y, - NVG_BEZIERTO, x + r4x*(1 - NVG_KAPPA90), y, x, y + r4y*(1 - NVG_KAPPA90), x, y + r4y, + NVG_MOVETO, x, y + ryTL, + NVG_LINETO, x, y + h - ryBL, + NVG_BEZIERTO, x, y + h - ryBL*(1 - NVG_KAPPA90), x + rxBL*(1 - NVG_KAPPA90), y + h, x + rxBL, y + h, + NVG_LINETO, x + w - rxBR, y + h, + NVG_BEZIERTO, x + w - rxBR*(1 - NVG_KAPPA90), y + h, x + w, y + h - ryBR*(1 - NVG_KAPPA90), x + w, y + h - ryBR, + NVG_LINETO, x + w, y + ryTR, + NVG_BEZIERTO, x + w, y + ryTR*(1 - NVG_KAPPA90), x + w - rxTR*(1 - NVG_KAPPA90), y, x + w - rxTR, y, + NVG_LINETO, x + rxTL, y, + NVG_BEZIERTO, x + rxTL*(1 - NVG_KAPPA90), y, x, y + ryTL*(1 - NVG_KAPPA90), x, y + ryTL, NVG_CLOSE }; nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); diff --git a/src/nanovg.h b/src/nanovg.h index 63b4940..5bb0e52 100644 --- a/src/nanovg.h +++ b/src/nanovg.h @@ -491,7 +491,7 @@ void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r // Creates new rounded rectangle shaped sub-path with more radius control for each corner. // r1 is bottom left, r2 is bottom right, r3, is top right, r4 is top left. -void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4); +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft); // Creates new ellipse shaped sub-path. void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry); From bb385e6b8fd837bec70998b1a608a3e6f1ddd591 Mon Sep 17 00:00:00 2001 From: Xeek Date: Sun, 18 Sep 2016 10:47:58 -0500 Subject: [PATCH 3/3] Renamed nvgRoundedRectEx to nvgRoundedRectVarying, using variables for duplicated calls to nvg__absf, renamed the radius parameters & variables to be more descriptive, changed the order of radius parameters to follow CSS order, and finally corrected the if/else style suggested by @memononen. --- src/nanovg.c | 37 +++++++++++++++++++------------------ src/nanovg.h | 5 ++--- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/nanovg.c b/src/nanovg.c index ae17dd4..51f972c 100644 --- a/src/nanovg.c +++ b/src/nanovg.c @@ -2119,30 +2119,31 @@ void nvgRect(NVGcontext* ctx, float x, float y, float w, float h) void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r) { - nvgRoundedRectEx(ctx, x, y, w, h, r, r, r, r); + nvgRoundedRectVarying(ctx, x, y, w, h, r, r, r, r); } -void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4) +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft) { - if(r1 < 0.1f && r2 < 0.1f && r3 < 0.1f && r4 < 0.1f) { + if(radTopLeft < 0.1f && radTopRight < 0.1f && radBottomRight < 0.1f && radBottomLeft < 0.1f) { nvgRect(ctx, x, y, w, h); return; - } - else { - float r1x = nvg__minf(r1, nvg__absf(w)*0.5f) * nvg__signf(w), r1y = nvg__minf(r1, nvg__absf(h)*0.5f) * nvg__signf(h); - float r2x = nvg__minf(r2, nvg__absf(w)*0.5f) * nvg__signf(w), r2y = nvg__minf(r2, nvg__absf(h)*0.5f) * nvg__signf(h); - float r3x = nvg__minf(r3, nvg__absf(w)*0.5f) * nvg__signf(w), r3y = nvg__minf(r3, nvg__absf(h)*0.5f) * nvg__signf(h); - float r4x = nvg__minf(r4, nvg__absf(w)*0.5f) * nvg__signf(w), r4y = nvg__minf(r4, nvg__absf(h)*0.5f) * nvg__signf(h); + } else { + float halfw = nvg__absf(w)*0.5f; + float halfh = nvg__absf(h)*0.5f; + float rxBL = nvg__minf(radBottomLeft, halfw) * nvg__signf(w), ryBL = nvg__minf(radBottomLeft, halfh) * nvg__signf(h); + float rxBR = nvg__minf(radBottomRight, halfw) * nvg__signf(w), ryBR = nvg__minf(radBottomRight, halfh) * nvg__signf(h); + float rxTR = nvg__minf(radTopRight, halfw) * nvg__signf(w), ryTR = nvg__minf(radTopRight, halfh) * nvg__signf(h); + float rxTL = nvg__minf(radTopLeft, halfw) * nvg__signf(w), ryTL = nvg__minf(radTopLeft, halfh) * nvg__signf(h); float vals[] = { - NVG_MOVETO, x, y + r4y, - NVG_LINETO, x, y + h - r1y, - NVG_BEZIERTO, x, y + h - r1y*(1 - NVG_KAPPA90), x + r1x*(1 - NVG_KAPPA90), y + h, x + r1x, y + h, - NVG_LINETO, x + w - r2x, y + h, - NVG_BEZIERTO, x + w - r2x*(1 - NVG_KAPPA90), y + h, x + w, y + h - r2y*(1 - NVG_KAPPA90), x + w, y + h - r2y, - NVG_LINETO, x + w, y + r3y, - NVG_BEZIERTO, x + w, y + r3y*(1 - NVG_KAPPA90), x + w - r3x*(1 - NVG_KAPPA90), y, x + w - r3x, y, - NVG_LINETO, x + r4x, y, - NVG_BEZIERTO, x + r4x*(1 - NVG_KAPPA90), y, x, y + r4y*(1 - NVG_KAPPA90), x, y + r4y, + NVG_MOVETO, x, y + ryTL, + NVG_LINETO, x, y + h - ryBL, + NVG_BEZIERTO, x, y + h - ryBL*(1 - NVG_KAPPA90), x + rxBL*(1 - NVG_KAPPA90), y + h, x + rxBL, y + h, + NVG_LINETO, x + w - rxBR, y + h, + NVG_BEZIERTO, x + w - rxBR*(1 - NVG_KAPPA90), y + h, x + w, y + h - ryBR*(1 - NVG_KAPPA90), x + w, y + h - ryBR, + NVG_LINETO, x + w, y + ryTR, + NVG_BEZIERTO, x + w, y + ryTR*(1 - NVG_KAPPA90), x + w - rxTR*(1 - NVG_KAPPA90), y, x + w - rxTR, y, + NVG_LINETO, x + rxTL, y, + NVG_BEZIERTO, x + rxTL*(1 - NVG_KAPPA90), y, x, y + ryTL*(1 - NVG_KAPPA90), x, y + ryTL, NVG_CLOSE }; nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); diff --git a/src/nanovg.h b/src/nanovg.h index 63b4940..bb0d341 100644 --- a/src/nanovg.h +++ b/src/nanovg.h @@ -489,9 +489,8 @@ void nvgRect(NVGcontext* ctx, float x, float y, float w, float h); // Creates new rounded rectangle shaped sub-path. void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r); -// Creates new rounded rectangle shaped sub-path with more radius control for each corner. -// r1 is bottom left, r2 is bottom right, r3, is top right, r4 is top left. -void nvgRoundedRectEx(NVGcontext* ctx, float x, float y, float w, float h, float r1, float r2, float r3, float r4); +// Creates new rounded rectangle shaped sub-path with varying radii for each corner. +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft); // Creates new ellipse shaped sub-path. void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry);