pcb-to-stencil/cmd/genicon/main.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/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)
}