feat: TinySVG + regex icon
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
54195886218E1BDB00581B79 /* NSMenu+Ext.m in Sources */ = {isa = PBXBuildFile; fileRef = 54195885218E1BDB00581B79 /* NSMenu+Ext.m */; };
|
54195886218E1BDB00581B79 /* NSMenu+Ext.m in Sources */ = {isa = PBXBuildFile; fileRef = 54195885218E1BDB00581B79 /* NSMenu+Ext.m */; };
|
||||||
541C67C32255470B004D2CE6 /* SettingsAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = 541C67C22255470B004D2CE6 /* SettingsAppearance.m */; };
|
541C67C32255470B004D2CE6 /* SettingsAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = 541C67C22255470B004D2CE6 /* SettingsAppearance.m */; };
|
||||||
54209E942117325100F3B5EF /* DrawImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 54209E932117325100F3B5EF /* DrawImage.m */; };
|
54209E942117325100F3B5EF /* DrawImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 54209E932117325100F3B5EF /* DrawImage.m */; };
|
||||||
|
54229F552E02491A0019ACB0 /* TinySVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 54229F542E02491A0019ACB0 /* TinySVG.m */; };
|
||||||
544B011A2114B41200386E5C /* ModalSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B01192114B41200386E5C /* ModalSheet.m */; };
|
544B011A2114B41200386E5C /* ModalSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B01192114B41200386E5C /* ModalSheet.m */; };
|
||||||
544B011D2114EE9100386E5C /* AppHook.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B011C2114EE9100386E5C /* AppHook.m */; };
|
544B011D2114EE9100386E5C /* AppHook.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B011C2114EE9100386E5C /* AppHook.m */; };
|
||||||
54501010230E9C8600F0B165 /* FeedDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 5450100F230E9C8600F0B165 /* FeedDownload.m */; };
|
54501010230E9C8600F0B165 /* FeedDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 5450100F230E9C8600F0B165 /* FeedDownload.m */; };
|
||||||
@@ -127,6 +128,8 @@
|
|||||||
541C67C22255470B004D2CE6 /* SettingsAppearance.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsAppearance.m; sourceTree = "<group>"; };
|
541C67C22255470B004D2CE6 /* SettingsAppearance.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsAppearance.m; sourceTree = "<group>"; };
|
||||||
54209E922117325100F3B5EF /* DrawImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawImage.h; sourceTree = "<group>"; };
|
54209E922117325100F3B5EF /* DrawImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawImage.h; sourceTree = "<group>"; };
|
||||||
54209E932117325100F3B5EF /* DrawImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawImage.m; sourceTree = "<group>"; };
|
54209E932117325100F3B5EF /* DrawImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawImage.m; sourceTree = "<group>"; };
|
||||||
|
54229F532E02491A0019ACB0 /* TinySVG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinySVG.h; sourceTree = "<group>"; };
|
||||||
|
54229F542E02491A0019ACB0 /* TinySVG.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TinySVG.m; sourceTree = "<group>"; };
|
||||||
544B01182114B41200386E5C /* ModalSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalSheet.h; sourceTree = "<group>"; };
|
544B01182114B41200386E5C /* ModalSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalSheet.h; sourceTree = "<group>"; };
|
||||||
544B01192114B41200386E5C /* ModalSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalSheet.m; sourceTree = "<group>"; };
|
544B01192114B41200386E5C /* ModalSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalSheet.m; sourceTree = "<group>"; };
|
||||||
544B011B2114EE9100386E5C /* AppHook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppHook.h; sourceTree = "<group>"; };
|
544B011B2114EE9100386E5C /* AppHook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppHook.h; sourceTree = "<group>"; };
|
||||||
@@ -429,6 +432,8 @@
|
|||||||
54209E932117325100F3B5EF /* DrawImage.m */,
|
54209E932117325100F3B5EF /* DrawImage.m */,
|
||||||
54910065233A4D4000858AE2 /* URLScheme.h */,
|
54910065233A4D4000858AE2 /* URLScheme.h */,
|
||||||
54910066233A4D4000858AE2 /* URLScheme.m */,
|
54910066233A4D4000858AE2 /* URLScheme.m */,
|
||||||
|
54229F532E02491A0019ACB0 /* TinySVG.h */,
|
||||||
|
54229F542E02491A0019ACB0 /* TinySVG.m */,
|
||||||
);
|
);
|
||||||
path = Helper;
|
path = Helper;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -628,6 +633,7 @@
|
|||||||
54195886218E1BDB00581B79 /* NSMenu+Ext.m in Sources */,
|
54195886218E1BDB00581B79 /* NSMenu+Ext.m in Sources */,
|
||||||
54910067233A4D4000858AE2 /* URLScheme.m in Sources */,
|
54910067233A4D4000858AE2 /* URLScheme.m in Sources */,
|
||||||
54F6025D21C1D4170006D338 /* OpmlFile.m in Sources */,
|
54F6025D21C1D4170006D338 /* OpmlFile.m in Sources */,
|
||||||
|
54229F552E02491A0019ACB0 /* TinySVG.m in Sources */,
|
||||||
5496B511214D6275003ED4ED /* UserPrefs.m in Sources */,
|
5496B511214D6275003ED4ED /* UserPrefs.m in Sources */,
|
||||||
546A6A2F22C585580034E806 /* SettingsAboutView.m in Sources */,
|
546A6A2F22C585580034E806 /* SettingsAboutView.m in Sources */,
|
||||||
54B517072270E990006C1B29 /* NSView+Ext.m in Sources */,
|
54B517072270E990006C1B29 /* NSView+Ext.m in Sources */,
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ static NSImageName const RSSImageMenuBarIconActive = @"RSSImageMenuBarIconActive
|
|||||||
static NSImageName const RSSImageMenuBarIconPaused = @"RSSImageMenuBarIconPaused";
|
static NSImageName const RSSImageMenuBarIconPaused = @"RSSImageMenuBarIconPaused";
|
||||||
/// Menu item, unread state icon (blue dot)
|
/// Menu item, unread state icon (blue dot)
|
||||||
static NSImageName const RSSImageMenuItemUnread = @"RSSImageMenuItemUnread";
|
static NSImageName const RSSImageMenuItemUnread = @"RSSImageMenuItemUnread";
|
||||||
|
/// Feed edit, regex editor icon @c "(.*)"
|
||||||
|
static NSImageName const RSSImageRegexIcon = @"RSSImageRegexIcon";
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - NSNotificationName constants
|
#pragma mark - NSNotificationName constants
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#import "DrawImage.h"
|
#import "DrawImage.h"
|
||||||
#import "Constants.h"
|
#import "Constants.h"
|
||||||
#import "NSColor+Ext.h"
|
#import "NSColor+Ext.h"
|
||||||
|
#import "TinySVG.h"
|
||||||
|
|
||||||
|
|
||||||
@implementation DrawSeparator
|
@implementation DrawSeparator
|
||||||
@@ -125,7 +126,6 @@ static inline void AddGroupIconPath(CGContextRef c, CGFloat size, BOOL showBackg
|
|||||||
CGPathRelease(lower);
|
CGPathRelease(lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create @c CGPath for RSS icon; a circle in the lower left bottom and two radio waves going outwards.
|
Create @c CGPath for RSS icon; a circle in the lower left bottom and two radio waves going outwards.
|
||||||
@param connection If @c NO, draw only one radio wave and a pause icon in the upper right
|
@param connection If @c NO, draw only one radio wave and a pause icon in the upper right
|
||||||
@@ -146,22 +146,9 @@ static inline void AddRSSIconPath(CGContextRef c, CGFloat size, BOOL connection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Icon Background Generators
|
#pragma mark - Icon Background
|
||||||
|
|
||||||
|
|
||||||
/// Create @c CGPath with rounded corners (optional). @param roundness Value between @c 0.0 and @c 1.0
|
|
||||||
static void AddRoundedBackgroundPath(CGContextRef c, CGRect r, CGFloat roundness) {
|
|
||||||
const CGFloat corner = ShorterSide(r.size) * (roundness / 2.0);
|
|
||||||
if (corner > 0) {
|
|
||||||
CGMutablePathRef pth = CGPathCreateMutable();
|
|
||||||
CGPathAddRoundedRect(pth, NULL, r, corner, corner);
|
|
||||||
CGContextAddPath(c, pth);
|
|
||||||
CGPathRelease(pth);
|
|
||||||
} else {
|
|
||||||
CGContextAddRect(c, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Insert and draw linear gradient with @c color saturation @c ±0.3
|
/// Insert and draw linear gradient with @c color saturation @c ±0.3
|
||||||
static void DrawGradient(CGContextRef c, CGFloat size, NSColor *color) {
|
static void DrawGradient(CGContextRef c, CGFloat size, NSColor *color) {
|
||||||
CGFloat h = 0, s = 1, b = 1, a = 1;
|
CGFloat h = 0, s = 1, b = 1, a = 1;
|
||||||
@@ -190,6 +177,12 @@ static void DrawGradient(CGContextRef c, CGFloat size, NSColor *color) {
|
|||||||
#pragma mark - CGContext Drawing & Manipulation
|
#pragma mark - CGContext Drawing & Manipulation
|
||||||
|
|
||||||
|
|
||||||
|
/// Flip coordinate system
|
||||||
|
static void FlipCoordinateSystem(CGContextRef c, CGFloat height) {
|
||||||
|
CGContextTranslateCTM(c, 0, height);
|
||||||
|
CGContextScaleCTM(c, 1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/// Scale and translate context to the center with respect to the new scale. If @c width @c != @c length align top left.
|
/// Scale and translate context to the center with respect to the new scale. If @c width @c != @c length align top left.
|
||||||
static void SetContentScale(CGContextRef c, CGSize size, CGFloat scale) {
|
static void SetContentScale(CGContextRef c, CGSize size, CGFloat scale) {
|
||||||
const CGFloat s = ShorterSide(size);
|
const CGFloat s = ShorterSide(size);
|
||||||
@@ -204,7 +197,7 @@ static void DrawRoundedFrame(CGContextRef c, CGRect r, CGColorRef color, BOOL ba
|
|||||||
CGContextSetStrokeColorWithColor(c, color);
|
CGContextSetStrokeColorWithColor(c, color);
|
||||||
CGFloat contentScale = defaultScale;
|
CGFloat contentScale = defaultScale;
|
||||||
if (background) {
|
if (background) {
|
||||||
AddRoundedBackgroundPath(c, r, corner);
|
svgAddRect(c, 1, r, ShorterSide(r.size) * corner/2);
|
||||||
if (scaling != 0.0)
|
if (scaling != 0.0)
|
||||||
contentScale *= scaling;
|
contentScale *= scaling;
|
||||||
}
|
}
|
||||||
@@ -277,6 +270,31 @@ static void DrawUnreadIcon(CGRect r, NSColor *color) {
|
|||||||
CGPathRelease(path);
|
CGPathRelease(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw "(.*)" as vector path
|
||||||
|
static void DrawRegexIcon(CGRect r) {
|
||||||
|
const CGFloat size = ShorterSide(r.size);
|
||||||
|
CGContextRef c = NSGraphicsContext.currentContext.CGContext;
|
||||||
|
|
||||||
|
svgAddRect(c, 1, r, .2 * size);
|
||||||
|
CGContextSetFillColorWithColor(c, NSColor.redColor.CGColor);
|
||||||
|
CGContextFillPath(c);
|
||||||
|
|
||||||
|
// SVG files use bottom-left corner coordinate system. Quartz uses top-left.
|
||||||
|
FlipCoordinateSystem(c, r.size.height);
|
||||||
|
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");
|
||||||
|
// "."
|
||||||
|
svgAddCircle(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");
|
||||||
|
// ")"
|
||||||
|
svgAddPath(c, size/1000, "m816 813c140-205 134-430 1-621l66-45c159 221 151 499 0 708z");
|
||||||
|
|
||||||
|
CGContextSetFillColorWithColor(c, NSColor.whiteColor.CGColor);
|
||||||
|
CGContextFillPath(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - NSImage Name Registration
|
#pragma mark - NSImage Name Registration
|
||||||
|
|
||||||
@@ -297,4 +315,5 @@ void RegisterImageViewNames(void) {
|
|||||||
Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, YES); return YES; });
|
Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, YES); return YES; });
|
||||||
Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, NO); return YES; });
|
Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, NO); return YES; });
|
||||||
Register(14, RSSImageMenuItemUnread, NSLocalizedString(@"Unread icon", nil), ^(NSRect r) { DrawUnreadIcon(r, [NSColor unreadIndicatorColor]); return YES; });
|
Register(14, RSSImageMenuItemUnread, NSLocalizedString(@"Unread icon", nil), ^(NSRect r) { DrawUnreadIcon(r, [NSColor unreadIndicatorColor]); return YES; });
|
||||||
|
Register(32, RSSImageRegexIcon, NSLocalizedString(@"Regex icon", nil), ^(NSRect r) { DrawRegexIcon(r); return YES; });
|
||||||
}
|
}
|
||||||
|
|||||||
6
baRSS/Helper/TinySVG.h
Normal file
6
baRSS/Helper/TinySVG.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@import Cocoa;
|
||||||
|
|
||||||
|
CGMutablePathRef tinySVG_path(CGFloat scale, const char * code);
|
||||||
|
void svgAddPath(CGContextRef context, CGFloat scale, const char * path);
|
||||||
|
void svgAddCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise);
|
||||||
|
void svgAddRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius);
|
||||||
174
baRSS/Helper/TinySVG.m
Normal file
174
baRSS/Helper/TinySVG.m
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
#include "TinySVG.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct SVGState {
|
||||||
|
CGFloat scale; // technically not part of parser but easier to pass along
|
||||||
|
|
||||||
|
char op;
|
||||||
|
float x, y;
|
||||||
|
bool prevDot;
|
||||||
|
|
||||||
|
float num[6];
|
||||||
|
uint8 iNum;
|
||||||
|
|
||||||
|
char buf[15];
|
||||||
|
uint8 iBuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
# pragma mark - Helper
|
||||||
|
|
||||||
|
/// if number buffer contains anything, write it to num array and start new buffer
|
||||||
|
static void finishNum(struct SVGState *state) {
|
||||||
|
if (state->iBuf > 0) {
|
||||||
|
state->buf[state->iBuf] = '\0';
|
||||||
|
state->num[state->iNum++] = (float)atof(state->buf);
|
||||||
|
state->iBuf = 0;
|
||||||
|
state->prevDot = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All numbers stored in num array, finalize SVG path operation and add path to @c CGContext
|
||||||
|
static void finishOp(CGMutablePathRef path, struct SVGState *state) {
|
||||||
|
char op = state->op;
|
||||||
|
if (op >= 'a' && op <= 'z') {
|
||||||
|
// convert relative to absolute coordinates
|
||||||
|
for (uint8 t = 0; t < state->iNum; t++) {
|
||||||
|
state->num[t] += (t % 2 || op == 'v') ? state->y : state->x;
|
||||||
|
}
|
||||||
|
// convert to upper-case
|
||||||
|
op = op - 'a' + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == 'Z') {
|
||||||
|
CGPathCloseSubpath(path);
|
||||||
|
|
||||||
|
} else if (op == 'V' && state->iNum == 1) {
|
||||||
|
state->y = state->num[0];
|
||||||
|
CGPathAddLineToPoint(path, NULL, state->x * state->scale, state->y * state->scale);
|
||||||
|
|
||||||
|
} else if (op == 'H' && state->iNum == 1) {
|
||||||
|
state->x = state->num[0];
|
||||||
|
CGPathAddLineToPoint(path, NULL, state->x * state->scale, state->y * state->scale);
|
||||||
|
|
||||||
|
} else if (op == 'M' && state->iNum == 2) {
|
||||||
|
state->x = state->num[0];
|
||||||
|
state->y = state->num[1];
|
||||||
|
CGPathMoveToPoint(path, NULL, state->x * state->scale, state->y * state->scale);
|
||||||
|
// Edge-case: "M 1 2 3 4 5 6" is valid SVG after move 1,2 all remaining points are lines (3,4 and 5,6)
|
||||||
|
// For this case we overwrite op here. It will be overwritten again if a new op starts. Else, assume line-op.
|
||||||
|
state->op = (state->op == 'm') ? 'l' : 'L';
|
||||||
|
|
||||||
|
} else if (op == 'L' && state->iNum == 2) {
|
||||||
|
state->x = state->num[0];
|
||||||
|
state->y = state->num[1];
|
||||||
|
CGPathAddLineToPoint(path, NULL, state->x * state->scale, state->y * state->scale);
|
||||||
|
|
||||||
|
} else if (op == 'C' && state->iNum == 6) {
|
||||||
|
state->x = state->num[4];
|
||||||
|
state->y = state->num[5];
|
||||||
|
CGPathAddCurveToPoint(path, NULL, state->num[0] * state->scale, state->num[1] * state->scale, state->num[2] * state->scale, state->num[3] * state->scale, state->x * state->scale, state->y * state->scale);
|
||||||
|
} else {
|
||||||
|
NSLog(@"Unsupported SVG operation %c %d", state->op, state->iNum);
|
||||||
|
}
|
||||||
|
state->iNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// current number not finished yet. Append another char to internal buffer
|
||||||
|
inline static void continueNum(char chr, struct SVGState *state) {
|
||||||
|
state->buf[state->iBuf++] = chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# pragma mark - Parser
|
||||||
|
|
||||||
|
/// very basic svg path parser.
|
||||||
|
/// @returns @c CGMutablePathRef which must be released with @c CGPathRelease()
|
||||||
|
CGMutablePathRef tinySVG_path(CGFloat scale, const char * code) {
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
|
||||||
|
struct SVGState state = {
|
||||||
|
.scale = scale,
|
||||||
|
.op = '_',
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.prevDot = false,
|
||||||
|
|
||||||
|
//.num = {0, 0, 0, 0, 0, 0},
|
||||||
|
.iNum = 0,
|
||||||
|
//.buf = " ",
|
||||||
|
.iBuf = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned long len = strlen(code);
|
||||||
|
for (unsigned long i = 0; i < len; i++) {
|
||||||
|
char chr = code[i];
|
||||||
|
if ((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z')) {
|
||||||
|
if (state.op != '_') {
|
||||||
|
finishNum(&state);
|
||||||
|
finishOp(path, &state);
|
||||||
|
}
|
||||||
|
state.op = chr;
|
||||||
|
} else if (chr >= '0' && chr <= '9') {
|
||||||
|
continueNum(chr, &state);
|
||||||
|
} else if (chr == '-' && state.iBuf == 0) {
|
||||||
|
continueNum(chr, &state);
|
||||||
|
} else if (chr == '.' && !state.prevDot) {
|
||||||
|
continueNum(chr, &state);
|
||||||
|
state.prevDot = true;
|
||||||
|
} else { // any number-separating character
|
||||||
|
finishNum(&state);
|
||||||
|
|
||||||
|
// Edge-Case: SVG can reuse the previous operation without declaration
|
||||||
|
// e.g. you can draw four lines with "L1 2 3 4 5 6 7 8"
|
||||||
|
// or two curves with "c1 2 3 4 5 6 -1 -2 -3 -4 -5 -6"
|
||||||
|
// Therefore we need to complete the operation if the number of arguments is reached
|
||||||
|
if (state.iNum == 1 && strchr("HhVv", state.op) != NULL) {
|
||||||
|
finishOp(path, &state);
|
||||||
|
} else if (state.iNum == 2 && strchr("MmLl", state.op) != NULL) {
|
||||||
|
finishOp(path, &state);
|
||||||
|
} else if (state.iNum == 6 && strchr("Cc", state.op) != NULL) {
|
||||||
|
finishOp(path, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chr == '-') {
|
||||||
|
continueNum(chr, &state);
|
||||||
|
} else if (chr == '.') {
|
||||||
|
continueNum(chr, &state);
|
||||||
|
state.prevDot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# pragma mark - External API
|
||||||
|
|
||||||
|
/// calls @c tinySVG_path and handles @c CGPath creation and release.
|
||||||
|
void svgAddPath(CGContextRef context, CGFloat scale, const char * path) {
|
||||||
|
CGMutablePathRef tmp = tinySVG_path(scale, path);
|
||||||
|
CGContextAddPath(context, tmp);
|
||||||
|
CGPathRelease(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// calls @c CGPathAddArc with full circle
|
||||||
|
void svgAddCircle(CGContextRef context, CGFloat scale, CGFloat x, CGFloat y, CGFloat radius, bool clockwise) {
|
||||||
|
CGMutablePathRef tmp = CGPathCreateMutable();
|
||||||
|
CGPathAddArc(tmp, NULL, x * scale, y * scale, radius * scale, 0, M_PI * 2, clockwise);
|
||||||
|
CGContextAddPath(context, tmp);
|
||||||
|
CGPathRelease(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls @c CGContextAddRect or @c CGPathAddRoundedRect (optional).
|
||||||
|
/// @param cornerRadius Use @c <=0 for no corners. Use half of @c min(w,h) for a full circle.
|
||||||
|
void svgAddRect(CGContextRef context, CGFloat scale, CGRect rect, CGFloat cornerRadius) {
|
||||||
|
if (cornerRadius > 0) {
|
||||||
|
CGMutablePathRef tmp = CGPathCreateMutable();
|
||||||
|
CGPathAddRoundedRect(tmp, NULL, rect, cornerRadius * scale, cornerRadius * scale);
|
||||||
|
CGContextAddPath(context, tmp);
|
||||||
|
CGPathRelease(tmp);
|
||||||
|
} else {
|
||||||
|
CGContextAddRect(context, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user