Skip to content

Instantly share code, notes, and snippets.

@planetis-m
Last active January 3, 2020 21:22
Show Gist options
  • Save planetis-m/3e1adf194ad22246f5354a6c1fe891a0 to your computer and use it in GitHub Desktop.
Save planetis-m/3e1adf194ad22246f5354a6c1fe891a0 to your computer and use it in GitHub Desktop.
when declared(use_pkg_config) or declared(use_pkg_config_static):
{.pragma: libcairo, cdecl.}
when defined(use_pkg_config_static):
{.passl: gorge("pkg-config cairo --libs --static").}
else:
{.passl: gorge("pkg-config cairo --libs").}
else:
when defined(windows):
const LibCairo* = "libcairo-2.dll"
elif defined(macosx):
const LibCairo* = "libcairo(|.2).dylib"
else:
const LibCairo* = "libcairo.so(|.2)"
{.pragma: libcairo, cdecl, dynlib: LibCairo.}
type
Status* = enum
StatusSuccess,
StatusNoMemory,
StatusInvalidRestore,
StatusInvalidPopGroup,
StatusNoCurrentPoint,
StatusInvalidMatrix,
StatusInvalidStatus,
StatusNullPointer,
StatusInvalidString,
StatusInvalidPathData,
StatusReadError,
StatusWriteError,
StatusSurfaceFinished,
StatusSurfaceTypeMismatch,
StatusPatternTypeMismatch,
StatusInvalidContent,
StatusInvalidFormat,
StatusInvalidVisual,
StatusFileNotFound,
StatusInvalidDash,
StatusInvalidDscComment,
StatusInvalidIndex,
StatusClipNotRepresentable,
StatusTempFileError,
StatusInvalidStride,
StatusFontTypeMismatch,
StatusUserFontImmutable,
StatusUserFontError,
StatusNegativeCount,
StatusInvalidClusters,
StatusInvalidSlant,
StatusInvalidWeight
Format* = enum
FormatArgb32, FormatRgb24, FormatA8, FormatA1
TContext*{.final.} = object
TSurface*{.final.} = object
PContext* = ptr TContext
PSurface* = ptr TSurface
{.push dynlib: LibCairo, importc, cdecl.}
proc cairo_create(target: PSurface): PContext
proc cairo_destroy(cr: PContext)
proc cairo_get_reference_count(cr: PContext): int32
proc cairo_set_source_rgba(cr: PContext, red, green, blue, alpha: float64)
proc cairo_set_line_width(cr: PContext, width: float64)
proc cairo_line_to(cr: PContext, x, y: float64)
proc cairo_arc(cr: PContext, xc, yc, radius, angle1, angle2: float64)
proc cairo_stroke(cr: PContext)
proc cairo_fill(cr: PContext)
proc cairo_status_to_string(status: Status): cstring
proc cairo_surface_destroy(surface: PSurface)
proc cairo_surface_get_reference_count(surface: PSurface): int32
proc cairo_image_surface_create(format: Format, width, height: int32): PSurface
{.pop.}
proc statusToString*(status: Status): string =
$cairo_status_to_string(status)
proc checkStatus*(s: Status) {.noinline.} =
## if ``s != StatusSuccess`` the error is turned into an appropirate Nim
## exception and raised.
case s
of StatusSuccess: discard
of StatusNoMemory:
raise newException(OutOfMemError, statusToString(s))
of StatusReadError, StatusWriteError, StatusFileNotFound,
StatusTempFileError:
raise newException(IOError, statusToString(s))
else:
raise newException(AssertionError, statusToString(s))
type
Context* = object
impl: PContext
Surface* = object
impl: PSurface
proc `=`(cr: var Context, original: Context) {.error.}
proc `=destroy`(cr: var Context) =
if cr.impl != nil:
cairo_destroy(cr.impl)
assert cairo_get_reference_count(cr.impl) == 0, "dangling pointers exist!"
cr.impl = nil
proc `=sink`(cr: var Context; original: Context) =
`=destroy`(cr)
cr.impl = original.impl
proc `=`(surface: var Surface, original: Surface) {.error.}
proc `=destroy`(surface: var Surface) =
if surface.impl != nil:
cairo_surface_destroy(surface.impl)
assert cairo_surface_get_reference_count(surface.impl) == 0, "dangling pointers exist!"
surface.impl = nil
proc `=sink`(surface: var Surface; original: Surface) =
`=destroy`(surface)
surface.impl = original.impl
proc create*(target: Surface): Context =
result = Context(impl: cairo_create(target.impl))
proc setSourceRgba*(cr: Context, red, green, blue, alpha: float64) =
cairo_set_source_rgba(cr.impl, red, green, blue, alpha)
proc setLineWidth*(cr: Context, width: float64) =
cairo_set_line_width(cr.impl, width)
proc lineTo*(cr: Context, x, y: float64) =
cairo_line_to(cr.impl, x, y)
proc arc*(cr: Context, xc, yc, radius, angle1, angle2: float64) =
cairo_arc(cr.impl, xc, yc, radius, angle1, angle2)
proc stroke*(cr: Context) =
cairo_stroke(cr.impl)
proc fill*(cr: Context) =
cairo_fill(cr.impl)
proc imageSurfaceCreate*(format: Format, width, height: int32): Surface =
result = Surface(impl: cairo_image_surface_create(format, width, height))
import cairo2, math
var
surface = imageSurfaceCreate(FormatArgb32, 512, 512)
ctx = surface.create()
var
xc = 256.0
yc = 256.0
radius = 100.0
angle1 = 45.0 * PI / 180.0 # angles are specified in radians
angle2 = 180.0 * PI / 180.0
ctx.setLineWidth(10.0)
ctx.arc(xc, yc, radius, angle1, angle2)
ctx.stroke()
# draw helping lines
ctx.setSourceRGBA(1.0, 0.2, 0.2, 0.6)
ctx.setLineWidth(6.0)
ctx.arc(xc, yc, 10.0, 0, 2.0 * PI)
ctx.fill()
ctx.arc(xc, yc, radius, angle1, angle1)
ctx.lineTo(xc, yc)
ctx.arc(xc, yc, radius, angle2, angle2)
ctx.lineTo(xc, yc)
ctx.stroke()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment