ref: split svgRect and svgRoundedRect

This commit is contained in:
relikd
2025-12-08 21:36:27 +01:00
parent 96884474ac
commit 3a14c90f37
3 changed files with 54 additions and 49 deletions

View File

@@ -75,14 +75,14 @@ static void DrawGradient(CGContextRef c, CGFloat size, NSColor *color) {
*/ */
static inline void AddRSSIconPath(CGContextRef c, CGFloat size, BOOL connection) { static inline void AddRSSIconPath(CGContextRef c, CGFloat size, BOOL connection) {
FlipCoordinateSystem(c, size); FlipCoordinateSystem(c, size);
svgAddCircle(c, size/100, 13, 87, 13, NO); svgCircle(c, size/100, 13, 87, 13, NO);
svgAddPath(c, size/100, "M0,55v-20c43,0,65,22,65,65h-20c0-30-15-45-45-45Z"); svgPath(c, size/100, "M0,55v-20c43,0,65,22,65,65h-20c0-30-15-45-45-45Z");
if (connection) { if (connection) {
svgAddPath(c, size/100, "M0,20V0c67,0,100,33,100,100h-20C80,47,53,20,0,20Z"); svgPath(c, size/100, "M0,20V0c67,0,100,33,100,100h-20C80,47,53,20,0,20Z");
} else { } else {
// pause icon // pause icon
svgAddRect(c, size/100, CGRectMake(60, 0, 15, 50), 0); svgRect(c, size/100, CGRectMake(60, 0, 15, 50));
svgAddRect(c, size/100, CGRectMake(85, 0, 15, 50), 0); svgRect(c, size/100, CGRectMake(85, 0, 15, 50));
} }
} }
@@ -91,7 +91,7 @@ static void RoundedRSS_Monochrome(CGRect r, BOOL connection) {
CGContextRef c = NSGraphicsContext.currentContext.CGContext; CGContextRef c = NSGraphicsContext.currentContext.CGContext;
CGContextSetFillColorWithColor(c, [NSColor menuBarIconColor].CGColor); CGContextSetFillColorWithColor(c, [NSColor menuBarIconColor].CGColor);
// background rounded rect // background rounded rect
svgAddRect(c, 1, r, ShorterSide(r.size) * 0.4/2); svgRoundedRect(c, 1, r, ShorterSide(r.size) * 0.4/2);
// RSS icon // RSS icon
SetContentScale(c, r.size, 0.7); SetContentScale(c, r.size, 0.7);
AddRSSIconPath(c, ShorterSide(r.size), connection); AddRSSIconPath(c, ShorterSide(r.size), connection);
@@ -104,7 +104,7 @@ static void RoundedRSS_Gradient(CGRect r, NSColor *color) {
CGContextRef c = NSGraphicsContext.currentContext.CGContext; CGContextRef c = NSGraphicsContext.currentContext.CGContext;
CGContextSetFillColorWithColor(c, NSColor.whiteColor.CGColor); CGContextSetFillColorWithColor(c, NSColor.whiteColor.CGColor);
// background rounded rect // background rounded rect
svgAddRect(c, 1, r, ShorterSide(r.size) * 0.4/2); svgRoundedRect(c, 1, r, ShorterSide(r.size) * 0.4/2);
// Gradient // Gradient
CGContextSaveGState(c); CGContextSaveGState(c);
CGContextClip(c); CGContextClip(c);
@@ -130,7 +130,7 @@ static void Appearance_MenuBarIcon(CGRect r) {
// menu bar // menu bar
CGContextSetAlpha(c, .23); CGContextSetAlpha(c, .23);
const CGFloat barHeightInset = round(size*.06); const CGFloat barHeightInset = round(size*.06);
svgAddRect(c, 1, CGRectInset(r, 0, barHeightInset), 0); svgRect(c, 1, CGRectInset(r, 0, barHeightInset));
CGContextFillPath(c); CGContextFillPath(c);
const CGFloat offset = round(size*.75); const CGFloat offset = round(size*.75);
@@ -140,18 +140,18 @@ static void Appearance_MenuBarIcon(CGRect r) {
// left neighbor // left neighbor
CGContextTranslateCTM(c, -offset, 0); CGContextTranslateCTM(c, -offset, 0);
svgAddRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner); svgRoundedRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner);
CGContextFillPath(c); CGContextFillPath(c);
// right neighbor // right neighbor
CGContextTranslateCTM(c, +2*offset, 0); CGContextTranslateCTM(c, +2*offset, 0);
svgAddRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner); svgRoundedRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner);
CGContextFillPath(c); CGContextFillPath(c);
// main icon // main icon
CGContextSetAlpha(c, 1); CGContextSetAlpha(c, 1);
CGContextTranslateCTM(c, -offset, 0); CGContextTranslateCTM(c, -offset, 0);
svgAddRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner); svgRoundedRect(c, 1, CGRectInset(r, iconInset, iconInset), iconCorner);
SetContentScale(c, r.size, .47); SetContentScale(c, r.size, .47);
AddRSSIconPath(c, size, YES); AddRSSIconPath(c, size, YES);
CGContextEOFillPath(c); CGContextEOFillPath(c);
@@ -164,13 +164,13 @@ static void Appearance_MainMenu(CGRect r) {
CGContextSetFillColorWithColor(c, [NSColor controlTextColor].CGColor); CGContextSetFillColorWithColor(c, [NSColor controlTextColor].CGColor);
FlipCoordinateSystem(c, r.size.height); FlipCoordinateSystem(c, r.size.height);
// menu // menu
svgAddRect(c, size/16, CGRectMake(0, 0, 16, 3), 0); svgRect(c, size/16, CGRectMake(0, 0, 16, 3));
svgAddRect(c, size/16, CGRectMake(5, 4, 9, 12), 0); svgRect(c, size/16, CGRectMake(5, 4, 9, 12));
svgAddRect(c, size/16, CGRectMake(6, 3, 7, 12), 0); svgRect(c, size/16, CGRectMake(6, 3, 7, 12));
// entries // entries
svgAddRect(c, size/16, CGRectMake(6, 12, 6, 1), 0); svgRect(c, size/16, CGRectMake(6, 12, 6, 1));
svgAddRect(c, size/16, CGRectMake(6, 9, 6, 1), 0); svgRect(c, size/16, CGRectMake(6, 9, 6, 1));
svgAddRect(c, size/16, CGRectMake(6, 6, 6, 1), 0); svgRect(c, size/16, CGRectMake(6, 6, 6, 1));
CGContextEOFillPath(c); CGContextEOFillPath(c);
} }
@@ -181,9 +181,9 @@ static void Appearance_Group(CGRect r) {
FlipCoordinateSystem(c, r.size.height); FlipCoordinateSystem(c, r.size.height);
SetContentScale(c, r.size, 0.92); SetContentScale(c, r.size, 0.92);
// folder path // folder path
svgAddPath(c, size/100, "M15,87c-12,0-15-3-15-15V21c0-10,3-13,13-13h11c10,0,8,8,18,8h43c12,0,15,3,15,15v41c0,12-3,15-15,15H15Z"); svgPath(c, size/100, "M15,87c-12,0-15-3-15-15V21c0-10,3-13,13-13h11c10,0,8,8,18,8h43c12,0,15,3,15,15v41c0,12-3,15-15,15H15Z");
// line // line
svgAddPath(c, size/100, "M7,32h86Z"); svgPath(c, size/100, "M7,32h86Z");
CGContextSetLineWidth(c, size * 0.08); CGContextSetLineWidth(c, size * 0.08);
CGContextSetStrokeColorWithColor(c, [NSColor controlTextColor].CGColor); CGContextSetStrokeColorWithColor(c, [NSColor controlTextColor].CGColor);
CGContextStrokePath(c); CGContextStrokePath(c);
@@ -205,12 +205,12 @@ static void Appearance_Article(CGRect r) {
CGContextSetFillColorWithColor(c, [NSColor controlTextColor].CGColor); CGContextSetFillColorWithColor(c, [NSColor controlTextColor].CGColor);
FlipCoordinateSystem(c, r.size.height); FlipCoordinateSystem(c, r.size.height);
// text lines // text lines
svgAddRect(c, size/16, CGRectMake(0, 14, 16, 1), 0); svgRect(c, size/16, CGRectMake(0, 14, 16, 1));
svgAddRect(c, size/16, CGRectMake(0, 10, 16, 1), 0); svgRect(c, size/16, CGRectMake(0, 10, 16, 1));
svgAddRect(c, size/16, CGRectMake(9, 6, 7, 1), 0); svgRect(c, size/16, CGRectMake(9, 6, 7, 1));
svgAddRect(c, size/16, CGRectMake(9, 2, 7, 1), 0); svgRect(c, size/16, CGRectMake(9, 2, 7, 1));
// picture // picture
//svgAddRect(c, size/16, CGRectMake(1, 1, 7, 7), 0); //svgRect(c, size/16, CGRectMake(1, 1, 7, 7));
// RSS icon // RSS icon
CGContextTranslateCTM(c, size/16 * 1, size/16 * 1); CGContextTranslateCTM(c, size/16 * 1, size/16 * 1);
CGContextScaleCTM(c, 7.0/16, 7.0/16); CGContextScaleCTM(c, 7.0/16, 7.0/16);
@@ -251,7 +251,7 @@ static void DrawRegexIcon(CGRect r) {
const CGFloat size = ShorterSide(r.size); const CGFloat size = ShorterSide(r.size);
CGContextRef c = NSGraphicsContext.currentContext.CGContext; CGContextRef c = NSGraphicsContext.currentContext.CGContext;
svgAddRect(c, 1, r, .2 * size); svgRoundedRect(c, 1, r, .2 * size);
CGContextSetFillColorWithColor(c, NSColor.redColor.CGColor); CGContextSetFillColorWithColor(c, NSColor.redColor.CGColor);
CGContextFillPath(c); CGContextFillPath(c);
@@ -259,13 +259,13 @@ static void DrawRegexIcon(CGRect r) {
FlipCoordinateSystem(c, r.size.height); FlipCoordinateSystem(c, r.size.height);
SetContentScale(c, r.size, 0.8); SetContentScale(c, r.size, 0.8);
// "(" // "("
svgAddPath(c, size/1000, "m184 187c-140 205-134 432-1 622l-66 44c-159-221-151-499 0-708z"); svgPath(c, size/1000, "m184 187c-140 205-134 432-1 622l-66 44c-159-221-151-499 0-708z");
// "." // "."
svgAddCircle(c, size/1000, 315, 675, 70, NO); svgCircle(c, size/1000, 315, 675, 70, NO);
// "*" // "*"
svgAddPath(c, size/1000, "m652 277 107-35 21 63-109 36 68 92-54 39-68-93-66 91-52-41 67-88-109-37 21-63 108 37v-113h66v112z"); svgPath(c, size/1000, "m652 277 107-35 21 63-109 36 68 92-54 39-68-93-66 91-52-41 67-88-109-37 21-63 108 37v-113h66v112z");
// ")" // ")"
svgAddPath(c, size/1000, "m816 813c140-205 134-430 1-621l66-45c159 221 151 499 0 708z"); svgPath(c, size/1000, "m816 813c140-205 134-430 1-621l66-45c159 221 151 499 0 708z");
CGContextSetFillColorWithColor(c, NSColor.whiteColor.CGColor); CGContextSetFillColorWithColor(c, NSColor.whiteColor.CGColor);
CGContextFillPath(c); CGContextFillPath(c);

View File

@@ -1,5 +1,6 @@
@import Cocoa; @import Cocoa;
void svgAddPath(CGContextRef context, CGFloat scale, const char * path); void svgPath(CGContextRef context, CGFloat scale, const char * path);
void svgAddCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise); void svgCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise);
void svgAddRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius); void svgRoundedRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius);
void svgRect(CGContextRef context, CGFloat scale, CGRect rect);

View File

@@ -146,11 +146,17 @@ static void tinySVG_parse(const char * code, CGFloat scale, CGMutablePathRef pat
} }
} }
/// Helper method to scale `rect` according to svg size.
static inline CGRect scaledRect(CGRect rect, CGFloat scale) {
if (scale == 1.0) { return rect; }
return CGRectMake(rect.origin.x * scale, rect.origin.y * scale, rect.size.width * scale, rect.size.height * scale);
}
# pragma mark - External API # pragma mark - External API
/// calls @c tinySVG_path and handles @c CGPath creation and release. /// calls @c tinySVG_path and handles @c CGPath creation and release.
void svgAddPath(CGContextRef context, CGFloat scale, const char * code) { void svgPath(CGContextRef context, CGFloat scale, const char * code) {
CGMutablePathRef path = CGPathCreateMutable(); CGMutablePathRef path = CGPathCreateMutable();
tinySVG_parse(code, scale, path); tinySVG_parse(code, scale, path);
CGContextAddPath(context, path); CGContextAddPath(context, path);
@@ -158,26 +164,24 @@ void svgAddPath(CGContextRef context, CGFloat scale, const char * code) {
} }
/// calls @c CGPathAddArc with full circle /// calls @c CGPathAddArc with full circle
void svgAddCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise) { void svgCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise) {
// No `CGContextAddArc` because that doesnt work well with overlapping counter-clockwise
CGMutablePathRef tmp = CGPathCreateMutable(); CGMutablePathRef tmp = CGPathCreateMutable();
CGPathAddArc(tmp, NULL, x * scale, y * scale, radius * scale, 0, M_PI * 2, clockwise); CGPathAddArc(tmp, NULL, x * scale, y * scale, radius * scale, 0, M_PI * 2, clockwise);
CGContextAddPath(context, tmp); CGContextAddPath(context, tmp);
CGPathRelease(tmp); CGPathRelease(tmp);
} }
/// Calls @c CGContextAddRect or @c CGPathAddRoundedRect (optional). /// Calls @c CGPathAddRoundedRect
/// @param cornerRadius Use @c <=0 for no corners. Use half of @c min(w,h) for a full circle. /// @param cornerRadius Use half of @c min(w,h) for a full circle.
void svgAddRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius) { void svgRoundedRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius) {
if (scale != 1.0) {
rect = CGRectMake(rect.origin.x * scale, rect.origin.y * scale,
rect.size.width * scale, rect.size.height * scale);
}
if (cornerRadius > 0) {
CGMutablePathRef tmp = CGPathCreateMutable(); CGMutablePathRef tmp = CGPathCreateMutable();
CGPathAddRoundedRect(tmp, NULL, rect, cornerRadius * scale, cornerRadius * scale); CGPathAddRoundedRect(tmp, NULL, scaledRect(rect, scale), cornerRadius * scale, cornerRadius * scale);
CGContextAddPath(context, tmp); CGContextAddPath(context, tmp);
CGPathRelease(tmp); CGPathRelease(tmp);
} else {
CGContextAddRect(context, rect);
} }
/// Calls @c CGContextAddRect
void svgRect(CGContextRef context, CGFloat scale, CGRect rect) {
CGContextAddRect(context, scaledRect(rect, scale));
} }