diff --git a/examples/demo.nim b/examples/demo.nim new file mode 100644 index 0000000..03dd27d --- /dev/null +++ b/examples/demo.nim @@ -0,0 +1,255 @@ +import os +import nanovg +import glfw, opengl +import perf + +type + WindowConfig = object + cornerRadiusTopLeft: float + cornerRadiusTopRight: float + cornerRadiusBottomLeft: float + cornerRadiusBottomRight: float + +# const ICON_TRASH: cint = 0x0000f1f8 +const ICON_TRASH = "" +# const ICON_TRASH = "\uf1f8" +#const ICON_TRASH: cint = 0xE729 + +proc currentSourceDir(): string {.inline.} = + return currentSourcePath.parentDir() + +# Config + +proc drawLabel(text: string, x, y, w, h: float) = + nanovg.setFontSize(50.0) + nanovg.setFont("sans") + nanovg.setFillColor(1.0, 1.0, 1.0, 1.0) + + nanovg.textAlign("left middle") + nanovg.text(x, y+h*0.5, text) + +proc drawWindow(title: string, x, y, w, h: float) = + let cornerRadius = 3.0 + withState: + nanovg.beginPath() + nanovg.pathRoundedRect(x, y, w, h, cornerRadius) + #nanovg.setFillColor(RGBA(255,255,255,192)) + nanovg.setFillColor(RGBA(28,30,34,192)) + nanovg.pathFill() + + nanovg.setFontSize(30.0) + nanovg.setFont("sans") + nanovg.textAlign("center middle") + + nanovg.setFontBlur(2) + nanovg.setFillColor(RGBA(0,0,0,128)) + nanovg.text(x+w/2, y+16+1, title) + + nanovg.setFontBlur(0) + nanovg.setFillColor(RGBA(220,220,220,160)) + nanovg.text(x+w/2,y+16, title) + +proc isBlack(color: Color): bool = + result = true + + for n, v in color.fieldPairs: + if v != 0: + return false + +proc cpToUtf8*(code: int): string = + var n = 0 + var cp = code + + if cp < 0x80: n = 1 + elif cp < 0x800: n = 2 + elif cp < 0x10000: n = 3 + elif cp < 0x200000: n = 4 + elif cp < 0x4000000: n = 5 + elif cp <= 0x7fffffff: n = 6 + + var res = newStringOfCap(n) + res.setLen(n) + + if n >= 6: + res[5] = char(0x80 or (cp and 0x3f)) + cp = cp shr 6 + cp = cp or 0x4000000 + if n >= 5: + res[4] = char(0x80 or (cp and 0x3f)) + cp = cp shr 6 + cp = cp or 0x200000 + if n >= 4: + res[3] = char(0x80 or (cp and 0x3f)) + cp = cp shr 6 + cp = cp or 0x10000 + if n >= 3: + res[2] = char(0x80 or (cp and 0x3f)) + cp = cp shr 6 + cp = cp or 0x800 + if n >= 2: + res[1] = char(0x80 or (cp and 0x3f)) + cp = cp shr 6 + cp = cp or 0xc0 + if n >= 1: + res[0] = char(cp) + + return res + +proc drawButton*(text: string, x, y, width, height: float) = + let bg = linearGradient( + x, y, x, y+height, + RGBA(255, 255, 255, 16), + RGBA(100, 100, 100, 16) + ) + + let color = RGBA(29, 100, 210, 255) + let shadowColor = RGBA(0, 0, 0, 90) + let highlightColor = RGBA(255, 255, 255, 100) + let radius = 3.0 + let lightWidth = 0.5 + let shadowOffset = 3.0 + let drawShadow = true + + if drawShadow: + nanovg.beginPath() + nanovg.pathRoundedRect(x+1+shadowOffset, y+1+shadowOffset, width-2, height-2, radius) + nanovg.setFillColor(shadowColor) + nanovg.pathFill() + + nanovg.beginPath() + nanovg.pathRoundedRect(x+1, y+1, width-2, height-2, radius) + nanovg.setFillColor(color) + nanovg.pathFill() + + nanovg.setFillPaint(bg) + nanovg.pathFill() + + nanovg.beginPath() + nanovg.pathMoveTo(x+radius, y+lightWidth+1) + nanovg.setStrokeWidth(lightWidth) + nanovg.setStrokeColor(highlightColor) + nanovg.pathLineTo(x+width-(radius), y+lightWidth+1) + nanovg.pathStroke() + + +proc drawButton*(preicon: string, text: string, x, y, w, h: float, color: Color) = + + var + bg: Paint + cornerRadius = 4.0 + tb: TextBounds + ib: TextBounds + tw = 0.0 + iw = 0.0 + + bg = nanovg.linearGradient( + x,y,x,y+h, + RGBA(255,255,255, if isBlack(color): 16 else:32), + RGBA(0,0,0, if isBlack(color): 16 else:32) + ) + + nanovg.beginPath() + nanovg.pathRoundedRect(x+1, y+1, w-2, h-2, cornerRadius-1) + + if not isBlack(color): + nanovg.setFillColor(color) + nanovg.pathFill() + + nanovg.setFillPaint(bg) + nanovg.pathFill() + + nanovg.beginPath() + nanovg.pathRoundedRect(x+0.5, y+0.5, w-1, h-1, cornerRadius-0.5) + nanovg.setStrokeColor(RGBA(0,0,0,48)) + nanovg.pathStroke() + + nanovg.setFontSize(20.0) + nanovg.setFont("sans-bold") + tb = nanovg.textBounds(0.0, 0.0, text) + tw = tb.horizontalAdvance + + nanovg.setFontSize(h*0.5) + nanovg.setFont("fa") + ib = nanovg.textBounds(0,0, preicon) + iw = ib.horizontalAdvance + iw += h*0.15 + + nanovg.setFontSize(h*0.5) + nanovg.setFont("fa") + nanovg.setFillColor(RGBA(255,255,255,96)) + nanovg.textAlign("left middle") + nanovg.text(x+w*0.5-tw*0.5-iw*0.75, y+h*0.5, preicon) + + nanovg.setFontSize(20.0) + nanovg.setFont("sans-bold") + nanovg.textAlign("left middle") + nanovg.setFillColor(RGBA(0,0,0,160)) + nanovg.text(x+w*0.5-tw*0.5+iw*0.25, y+h*0.5-1, text) + nanovg.setFillColor(RGBA(255,255,255,160)) + nanovg.text(x+w*0.5-tw*0.5+iw*0.25, y+h*0.5, text) + +proc main = + glfw.initialize() + + var c = DefaultOpenglWindowConfig + c.version = glv32 + c.title = "Minimal Nim-GLFW example" + c.forwardCompat = true + c.profile = opCoreProfile + c.debugContext = false + + let + fps = newGraph(RenderStyle.FPS, "Frame Time") + cpuGraph = newGraph(RenderStyle.MS, "CPU Time") + + + var w = newWindow(c) + echo currentSourcePath + nanovg.init() + nanovg.loadFont(currentSourceDir()/"resources/Roboto-Regular.ttf", "sans") + nanovg.loadFont(currentSourceDir()/"resources/Roboto-Bold.ttf", "sans-bold") + nanovg.loadFont(currentSourceDir()/"resources/fa.ttf", "fa") + nanovg.loadFont(currentSourceDir()/"resources/entypo.ttf", "icons") + swapInterval(0) + setTime(0) + + var prevt = getTime() + + while not w.shouldClose(): + let t = getTime() + let dt = t - prevt + prevt = t + + #let pos = w.cursorPos() + let fbSize = w.frameBufferSize() + + glViewPort(0, 0, fbSize.w, fbSize.h) + glCullFace(GL_BACK) + glFrontFace(GL_CCW) + glClearColor(0.3, 0.3, 0.32, 1.0) + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT) + + withFrame(w): + let x = glyphPositions("Some仮名thing is up", 0, 0) + drawWindow("Title", 50, 50, 300, 400) + drawLabel("Hello!", 10, 10, 280, 20) + drawButton(ICON_TRASH, "Delete", 100, 200, 160, 28, RGBA(128, 16, 8, 255)) + drawButton(ICON_TRASH, "Deleter", 100, 250, 160, 28, RGBA(12, 130, 80, 255)) + drawButton("Testing", 100, 300, 160, 28) + + fps.render(5, 5) + cpuGraph.render(210, 5) + + w.swapBuffers() + pollEvents() + + let cpuTime = glfw.getTime() - t + + fps.update(dt) + cpuGraph.update(cpuTime) + waitEvents() + + w.destroy() + glfw.terminate() + +main() diff --git a/examples/nim.cfg b/examples/nim.cfg new file mode 100644 index 0000000..85bf6c4 --- /dev/null +++ b/examples/nim.cfg @@ -0,0 +1 @@ +--path:"../src/" diff --git a/examples/perf.nim b/examples/perf.nim new file mode 100644 index 0000000..7c5a7ca --- /dev/null +++ b/examples/perf.nim @@ -0,0 +1,123 @@ +import nanovg +import strformat + +const GRAPH_HISTORY_COUNT = 100 + +type + RenderStyle* {.pure.} = enum + FPS, + MS, + PERCENT + + PerfGraph* = ref object + style: RenderStyle + name: string + values: array[GRAPH_HISTORY_COUNT, float] + head: int + + +proc newGraph*(style: RenderStyle, name: string): PerfGraph = + new(result) + result.style = style + result.name = name + +proc update*(graph: PerfGraph, frameTime: float) = + graph.head = (graph.head + 1) mod GRAPH_HISTORY_COUNT + graph.values[graph.head] = frameTime + +proc getGraphAverage(graph: PerfGraph): float = + var avg: float = 0.0 + for i in 0 ..< GRAPH_HISTORY_COUNT: + avg += graph.values[i] + + return avg / GRAPH_HISTORY_COUNT.float + +proc render*(graph: PerfGraph, x, y: float) = + let + avg = getGraphAverage(graph) + width: float = 200 + height: float = 35 + + nanovg.beginPath() + nanovg.pathRect(x, y, width, height) + nanovg.setFillColor(0, 0, 0, 128) + nanovg.pathFill() + + nanovg.beginPath() + nanovg.pathMoveTo(x, y+height) + + case graph.style: + of RenderStyle.FPS: + for i in 0 ..< GRAPH_HISTORY_COUNT: + var v: float = 1.0 / (0.00001 + graph.values[(graph.head+i) mod GRAPH_HISTORY_COUNT]) + var vx, vy: float + + if v > 80: + v = 80 + + vx = x + (i/(GRAPH_HISTORY_COUNT-1)) * width + vy = y + height - ((v / 80) * height) + + nanovg.pathLineTo(vx, vy) + + of RenderStyle.PERCENT: + for i in 0 ..< GRAPH_HISTORY_COUNT: + var v: float = graph.values[(graph.head+i) mod GRAPH_HISTORY_COUNT] + var vx, vy: float + + if v > 100: + v = 100 + + vx = x + (i/(GRAPH_HISTORY_COUNT-1)) * width + vy = y + height - ((v / 100) * height) + + nanovg.pathLineTo(vx, vy) + + of RenderStyle.MS: + for i in 0 ..< GRAPH_HISTORY_COUNT: + var v: float = graph.values[(graph.head+i) mod GRAPH_HISTORY_COUNT] * 1000 + var vx, vy: float + + if v > 20: + v = 20 + + vx = x + (i/(GRAPH_HISTORY_COUNT-1)) * width + vy = y + height - ((v / 20) * height) + + nanovg.pathLineTo(vx, vy) + + nanovg.pathLineTo(x+width, y+height) + nanovg.setFillColor(255, 192, 0, 128) + nanovg.pathFill() + + nanovg.setFont("sans") + + if graph.name.len() > 0: + nanovg.setFontSize(14) + nanovg.textAlign("top left") + nanovg.setFillColor(240, 240, 240, 192) + nanovg.text(x+3, y+1, graph.name) + + nanovg.setFontSize(18) + nanovg.textAlign("top right") + nanovg.setFillColor(240, 240, 240, 255) + + case graph.style: + of RenderStyle.FPS: + var str = fmt"{1.0/avg:.2f} FPS" + + nanovg.text(x+width-3, y+1, str) + nanovg.setFontSize(15) + nanovg.textAlign("bottom right") + nanovg.setFillColor(240, 240, 240, 160) + + str = fmt"{avg*1000:.2f} ms" + nanovg.text(x+width-3, y+height-1, str) + + of RenderStyle.PERCENT: + let str = fmt"{avg:.1f} %" + nanovg.text(x+width-3, y+1, str) + + of RenderStyle.MS: + let str = fmt"{avg*1000:.2f} ms" + nanovg.text(x+width-3, y+1, str) diff --git a/examples/resources/NotoEmoji-Regular.ttf b/examples/resources/NotoEmoji-Regular.ttf new file mode 100755 index 0000000..19b7bad Binary files /dev/null and b/examples/resources/NotoEmoji-Regular.ttf differ diff --git a/examples/resources/Roboto-Bold.ttf b/examples/resources/Roboto-Bold.ttf new file mode 100755 index 0000000..aaf374d Binary files /dev/null and b/examples/resources/Roboto-Bold.ttf differ diff --git a/examples/resources/Roboto-Light.ttf b/examples/resources/Roboto-Light.ttf new file mode 100755 index 0000000..664e1b2 Binary files /dev/null and b/examples/resources/Roboto-Light.ttf differ diff --git a/examples/resources/Roboto-Regular.ttf b/examples/resources/Roboto-Regular.ttf new file mode 100755 index 0000000..3e6e2e7 Binary files /dev/null and b/examples/resources/Roboto-Regular.ttf differ diff --git a/examples/resources/entypo.ttf b/examples/resources/entypo.ttf new file mode 100755 index 0000000..fc305d2 Binary files /dev/null and b/examples/resources/entypo.ttf differ diff --git a/examples/resources/fa.ttf b/examples/resources/fa.ttf new file mode 100755 index 0000000..c6c3dd4 Binary files /dev/null and b/examples/resources/fa.ttf differ diff --git a/nanovg.nimble b/nanovg.nimble new file mode 100644 index 0000000..0ec2d06 --- /dev/null +++ b/nanovg.nimble @@ -0,0 +1,17 @@ +# Package + +version = "0.1.0" +author = "Joey Yakimowich-Payne" +description = "A wrapper around nanovg" +license = "MIT" +srcDir = "src" + + + +# Dependencies + +requires "nim >= 1.0.0", + "nimterop >= 0.2.1", + "regex >= 0.12.0", + "opengl >= 1.2.2", + "https://github.com/jyapayne/nim-glfw#d4f30db" diff --git a/nim.cfg b/nim.cfg new file mode 100644 index 0000000..71629b9 --- /dev/null +++ b/nim.cfg @@ -0,0 +1,2 @@ +-d:glfwStaticLib +-d:useGlew diff --git a/src/nanovg.nim b/src/nanovg.nim new file mode 100644 index 0000000..006d8cc --- /dev/null +++ b/src/nanovg.nim @@ -0,0 +1,546 @@ +import macros +import sequtils +import typetraits +import strutils +import strformat +import nanovg/wrapper + +converter intToCuchar*(source: uint8 | int): cuchar = + return source.cuchar + +export HSL +export HSLA +export RGBA +export RGBAf +export RGB +export RGBf +export LerpRGBA +export TransRGBA +export TransRGBAf + +#{.experimental: "dynamicBindSym".} + +type + FontLoadError* = object of Exception + ImageLoadError* = object of Exception + ContextInitError* = object of Exception + Context = ptr NVGContext + + Alignment* {.size: sizeof(cint), pure.} = enum + NONE = 0 + # Horizontal + LEFT = NVG_ALIGN_LEFT + CENTER = NVG_ALIGN_CENTER + RIGHT = NVG_ALIGN_RIGHT + + # Vertical + TOP = NVG_ALIGN_TOP + MIDDLE = NVG_ALIGN_MIDDLE + BOTTOM = NVG_ALIGN_BOTTOM + BASELINE = NVG_ALIGN_BASELINE # Default + + LineCap* {.size: sizeof(cint), pure.} = enum + BUTT = NVG_BUTT + ROUND = NVG_ROUND + SQUARE = NVG_SQUARE + BEVEL = NVG_BEVEL + MITER = NVG_MITER + + LineJoin* {.size: sizeof(cint), pure.} = enum + ROUND = NVG_ROUND + BEVEL = NVG_BEVEL + MITER = NVG_MITER + + CompositeOperation* {.size: sizeof(cint), pure.} = enum + SOURCE_OVER, SOURCE_IN, SOURCE_OUT, ATOP, DESTINATION_OVER, + DESTINATION_IN, DESTINATION_OUT, DESTINATION_ATOP, LIGHTER, + COPY, XOR + + BlendFactor* {.size: sizeof(cint), pure.} = enum + ZERO = NVG_ZERO, ONE = NVG_ONE, SRC_COLOR = NVG_SRC_COLOR, + ONE_MINUS_SRC_COLOR = NVG_ONE_MINUS_SRC_COLOR, DST_COLOR = NVG_DST_COLOR, + ONE_MINUS_DST_COLOR = NVG_ONE_MINUS_DST_COLOR, SRC_ALPHA = NVG_SRC_ALPHA, + ONE_MINUS_SRC_ALPHA = NVG_ONE_MINUS_SRC_ALPHA, DST_ALPHA = NVG_DST_ALPHA, + ONE_MINUS_DST_ALPHA = NVG_ONE_MINUS_DST_ALPHA, SRC_ALPHA_SATURATE = NVG_SRC_ALPHA_SATURATE + + Bounds* = tuple[xmin, ymin, xmax, ymax: float] + + TextBounds* = tuple[horizontalAdvance: float, bounds: Bounds] + + Size* = tuple[width, height: int] + + GlyphPosition* = object + glyph: string + x, y: float + minX, maxX: float + height: float + + Paint* = NVGPaint + Color* = NVGColor + Image* = cint + Font* = cint + + Winding* {.size: sizeof(cint), pure.} = enum + CCW = NVG_CCW + CW = NVG_CW + + Solidity* {.size: sizeof(cint), pure.} = enum + SOLID = NVG_SOLID + HOLE = NVG_HOLE + + TextMetrics* = tuple[ascender, descender, lineHeight: float] + + TextRow* = tuple[x, y, minX, maxX, height: float] + + ImageFlags* {.size: sizeof(cint).} = enum + NONE = 0, + GENERATE_MIPMAPS = NVG_IMAGE_GENERATE_MIPMAPS, ## Generate mipmaps during creation of the image. + REPEATX = NVG_IMAGE_REPEATX, ## Repeat image in X direction. + REPEATY = NVG_IMAGE_REPEATY, ## Repeat image in Y direction. + FLIPY = NVG_IMAGE_FLIPY, ## Flips (inverses) image in Y direction when rendered. + PREMULTIPLIED = NVG_IMAGE_PREMULTIPLIED, ## Image data has premultiplied alpha. + NEAREST = NVG_IMAGE_NEAREST ## Image interpolation is Nearest instead Linear + + View* = concept v + v.size() is tuple[w, h: int32] + v.frameBufferSize() is tuple[w, h: int32] + +proc width*(pos: GlyphPosition): float = + return pos.maxX - pos.minX + +proc createExpr*(ty, name: string, descriptor: NimNode, args: varargs[NimNode]): NimNode = + let tokens = ($descriptor).toUpper().split(" ").map( + proc(s: string): string = + return ty & "." & s + ) + + let argTokens = args.map( + proc(arg: NimNode): string = + $arg.toStrLit() + ) + + let allTokens = argTokens.concat(tokens) + + let newExpr = name & "(" & allTokens.join(",") & ")" + + result = parseStmt(newExpr) + + +template reduce[T](elements: openArray[T], op: untyped): untyped = + var res = T.NONE + + for element in elements: + res = op(res, element) + + res + +proc createContext(antialias = true, stencilStrokes = true, debugChecks = false): Context = + var flags: cint + + if antialias: + flags = flags or NVG_ANTIALIAS.cint + if stencilStrokes: + flags = flags or NVG_STENCIL_STROKES.cint + if debugChecks: + flags = flags or NVG_DEBUG.cint + + result = CreateGL3(flags) + + if result.isNil: + raise newException(ContextInitError, "Could not initialize graphics context") + +var context: Context + +proc init*() = + context = createContext() + +proc loadFont*(path, name: string): Font {.discardable.} = + ## Load the font from `path` and give it a `name` that can be used to reference it. + result = context.CreateFont(name, path) + + if result == -1: + raise newException(FontLoadError, fmt"Could not load font {name}.") + +proc loadFontMem*(data: openArray[uint8], name: string, freeDataAutomatically = true): Font {.discardable.} = + ## Load the font from `path` and give it a `name` that can be used to reference it. + result = context.CreateFontMem(name, cast[ptr cuchar](data[0].unsafeAddr), data.len.cint, freeDataAutomatically.cint) + + if result == -1: + raise newException(FontLoadError, fmt"Could not load font {name}.") + +proc findFont*(name: string): Font = + return context.FindFont(name) + +proc setFallbackFont*(baseFont, fallbackFont: string): Font = + return context.AddFallbackFont(baseFont, fallbackFont) + +proc setFallbackFont*(baseFont, fallbackFont: Font): Font = + return context.AddFallbackFontId(baseFont, fallbackFont) + +proc setFont*(font: Font) = + context.FontFaceId(font) + +proc setFont*(name: string) = + context.FontFace(name) + +proc setFontSize*(size: float) = + context.FontSize(size) + +proc setFontBlur*(blur: float) = + context.FontBlur(blur) + +proc setTextLetterSpacing*(spacing: float) = + context.TextLetterSpacing(spacing) + +proc setTextLineHeight*(lineHeight: float) = + context.TextLineHeight(lineHeight) + +proc `or`(align1: Alignment, align2: Alignment): Alignment = + return (align1.cint or align2.cint).Alignment + +proc textAlign*(alignments: varargs[Alignment]) = + var alignment = reduce(alignments, `or`) + + context.TextAlign(alignment.cint) + +macro textAlign*(descriptor: string) = + result = createExpr("Alignment", "textAlign", descriptor) + +proc textBounds*(x, y: float, text: string): TextBounds = + var res: array[4, cfloat] + let horizonalAdvance = context.TextBounds(x, y, text, nil, res[0].addr) + + let bounds: Bounds = (res[0].float, res[1].float, res[2].float, res[3].float) + return (horizonalAdvance.float, bounds) + +proc text*(x, y: float, content: string) = + discard context.Text(x, y, content, nil) + +proc textBoxBounds*(x, y, breakRowWidth: float, text: string): Bounds = + var res: array[4, cfloat] + context.TextBoxBounds(x, y, breakRowWidth, text, nil, res[0].addr) + + return (res[0].float, res[1].float, res[2].float, res[3].float) + +proc textBox*(x, y, breakRowWidth: float, content: string) = + context.TextBox(x, y, breakRowWidth, content, nil) + +proc textMetrics*(): TextMetrics = + var + ascender, descender, lineHeight: cfloat + + context.TextMetrics(ascender.addr, descender.addr, lineHeight.addr) + + return (ascender.float, descender.float, lineHeight.float) + +# TODO Continue with TextGlyphPos +proc glyphPositions*(text: string, x, y: float): seq[GlyphPosition] = + const maxPositions = 100 + var + positions: array[maxPositions, NVGglyphPosition] + numGlyphs = 0 + bytesProcessed = 0 + lastX = x + strIndex = 0 + lineHeight = textMetrics().lineHeight + + result = newSeqOfCap[GlyphPosition](maxPositions) + + while (strIndex < text.len): + numGlyphs = context.TextGlyphPositions( + lastX, y, cast[cstring](text[strIndex].unsafeAddr), nil, + positions[0].addr, maxPositions + ) + + for i in 0.. +#include "nanovg.h" +""") + writeFile(srcDir/"src/nanovg_gl.h", newContents) + +# Manually wrap any symbols since nimterop cannot or incorrectly wraps them +cOverride: + # Standard Nim code to wrap types, consts, procs, etc. + type + NVGcolor* {.importc: "struct NVGcolor", bycopy.} = object + r* {.importc: "r".}: cfloat + g* {.importc: "g".}: cfloat + b* {.importc: "b".}: cfloat + a* {.importc: "a".}: cfloat + +# Specify include directories for gcc and Nim +cIncludeDir(srcDir/"src") + +# Define global symbols +cDefine("NANOVG_GL3_IMPLEMENTATION", "1") + +# Any global compiler options +when defined(macosx): + # cDefine("GLFW_INCLUDE_GLCOREARB", "1") + {.passC: "-DNANOVG_GL3_IMPLEMENTATION -DNANOVG_GLEW -D_GLFW_USE_RETINA -D_GLFW_COCOA -D_GLFW_USE_CHDir -D_GLFW_USE_MENUBAR".} + {.passL: "-m64 -framework GLUT -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo -framework Carbon -lm".} + +elif defined(unix): + {.passC: "-DNANOVG_GL3_IMPLEMENTATION -DNANOVG_GLEW".} + {.passL: "-lGL -lGLU -lGLEW -lm -lglfw".} + + +# Compile in any common source code +cCompile(srcDir/"src/*.c") + +# Use cPlugin() to make any symbol changes +cPlugin: + import strutils + + # Symbol renaming examples + proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} = + # Get rid of leading and trailing underscores + # sym.name = sym.name.strip(chars = {'_'}) + + # Remove prefixes or suffixes from procs + if sym.kind == nskProc: + sym.name = sym.name.replace("glnvg__", "") + sym.name = sym.name.replace("nvg__", "") + sym.name = sym.name.replace("nvglu", "") + sym.name = sym.name.replace("nvgl", "") + sym.name = sym.name.replace("nvg", "") + +# Finally import wrapped header file. Recurse if #include files should also +# be wrapped. Set dynlib if binding to dynamic library. +cImport(srcDir/"src/nanovg.h") +cImport(srcDir/"src/nanovg_gl.h") +cImport(srcDir/"src/nanovg_gl_utils.h")