131 lines
2.8 KiB
Go
131 lines
2.8 KiB
Go
package main
|
|
|
|
/*
|
|
#cgo CFLAGS: -x objective-c
|
|
#cgo LDFLAGS: -framework AppKit -framework CoreGraphics
|
|
|
|
#import <AppKit/AppKit.h>
|
|
#import <stdlib.h>
|
|
|
|
unsigned char* renderSVGToPixels(const void* svgBytes, int svgLen, int targetW, int targetH) {
|
|
@autoreleasepool {
|
|
NSData *data = [NSData dataWithBytesNoCopy:(void*)svgBytes length:svgLen freeWhenDone:NO];
|
|
NSImage *svgImage = [[NSImage alloc] initWithData:data];
|
|
if (!svgImage) return NULL;
|
|
|
|
int w = targetW;
|
|
int h = targetH;
|
|
int rowBytes = w * 4;
|
|
int totalBytes = rowBytes * h;
|
|
|
|
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
|
|
initWithBitmapDataPlanes:NULL
|
|
pixelsWide:w
|
|
pixelsHigh:h
|
|
bitsPerSample:8
|
|
samplesPerPixel:4
|
|
hasAlpha:YES
|
|
isPlanar:NO
|
|
colorSpaceName:NSDeviceRGBColorSpace
|
|
bytesPerRow:rowBytes
|
|
bitsPerPixel:32];
|
|
|
|
[NSGraphicsContext saveGraphicsState];
|
|
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
|
|
[NSGraphicsContext setCurrentContext:ctx];
|
|
|
|
[[NSColor clearColor] set];
|
|
NSRectFill(NSMakeRect(0, 0, w, h));
|
|
|
|
[svgImage drawInRect:NSMakeRect(0, 0, w, h)
|
|
fromRect:NSZeroRect
|
|
operation:NSCompositingOperationSourceOver
|
|
fraction:1.0];
|
|
|
|
[NSGraphicsContext restoreGraphicsState];
|
|
|
|
unsigned char* result = (unsigned char*)malloc(totalBytes);
|
|
if (result) {
|
|
memcpy(result, [rep bitmapData], totalBytes);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"os"
|
|
"unsafe"
|
|
)
|
|
|
|
func main() {
|
|
svgPath := "static/vectors/Former.svg"
|
|
outPath := "build/appicon.png"
|
|
size := 1024
|
|
|
|
svgData, err := os.ReadFile(svgPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to read SVG: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
pixels := C.renderSVGToPixels(
|
|
unsafe.Pointer(&svgData[0]),
|
|
C.int(len(svgData)),
|
|
C.int(size),
|
|
C.int(size),
|
|
)
|
|
if pixels == nil {
|
|
fmt.Fprintln(os.Stderr, "SVG rendering failed")
|
|
os.Exit(1)
|
|
}
|
|
defer C.free(unsafe.Pointer(pixels))
|
|
|
|
rawLen := size * size * 4
|
|
raw := unsafe.Slice((*byte)(unsafe.Pointer(pixels)), rawLen)
|
|
|
|
img := image.NewNRGBA(image.Rect(0, 0, size, size))
|
|
for y := 0; y < size; y++ {
|
|
for x := 0; x < size; x++ {
|
|
i := (y*size + x) * 4
|
|
r, g, b, a := raw[i], raw[i+1], raw[i+2], raw[i+3]
|
|
if a > 0 && a < 255 {
|
|
scale := 255.0 / float64(a)
|
|
r = clamp(float64(r) * scale)
|
|
g = clamp(float64(g) * scale)
|
|
b = clamp(float64(b) * scale)
|
|
}
|
|
img.SetNRGBA(x, y, color.NRGBA{R: r, G: g, B: b, A: a})
|
|
}
|
|
}
|
|
|
|
f, err := os.Create(outPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to create output: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
defer f.Close()
|
|
|
|
if err := png.Encode(f, img); err != nil {
|
|
fmt.Fprintf(os.Stderr, "PNG encode failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf("Generated %s (%dx%d) from %s\n", outPath, size, size, svgPath)
|
|
}
|
|
|
|
func clamp(v float64) uint8 {
|
|
if v > 255 {
|
|
return 255
|
|
}
|
|
if v < 0 {
|
|
return 0
|
|
}
|
|
return uint8(v)
|
|
}
|