fixes for builder get() procs and cairo
This commit is contained in:
parent
e84cb1dba9
commit
4c93a26d04
7 changed files with 3212 additions and 267 deletions
219
README.adoc
219
README.adoc
|
|
@ -843,7 +843,10 @@ main()
|
||||||
The following code is a plain Nim version of a drawing demo which I wrote some years ago in Ruby (http://ssalewski.de/PetEd-Demo.html.en).
|
The following code is a plain Nim version of a drawing demo which I wrote some years ago in Ruby (http://ssalewski.de/PetEd-Demo.html.en).
|
||||||
With the latest fix to Nim GTK3 bindings it seems to work fine, but some rewriting for optimized performance
|
With the latest fix to Nim GTK3 bindings it seems to work fine, but some rewriting for optimized performance
|
||||||
may be needed, I have to investigate that. Cairo surface is currently manually freed, because GC may have a too large delay.
|
may be needed, I have to investigate that. Cairo surface is currently manually freed, because GC may have a too large delay.
|
||||||
Later we may use Destructors for that.
|
|
||||||
|
You can resize the window and zoom in with the mouse wheel. When zoomed in scroll bars appear. You
|
||||||
|
can hold the middle mouse button pressed while moving the mouse for panning, and you can press left mouse button
|
||||||
|
and move the mouse to first draw a selection rectangle and zoom into it when releasing the mouse button.
|
||||||
|
|
||||||
[[drawingarea.nim]]
|
[[drawingarea.nim]]
|
||||||
[source,nim]
|
[source,nim]
|
||||||
|
|
@ -851,46 +854,26 @@ Later we may use Destructors for that.
|
||||||
----
|
----
|
||||||
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
|
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
|
||||||
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
|
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
|
||||||
# Nim version April 2019 -- well first draft :-)
|
# Nim version April 2019
|
||||||
# License MIT
|
# License MIT
|
||||||
|
|
||||||
|
# This version of the demo program uses a separate proc paint()
|
||||||
|
# which allocates a custom surface for buffered drawing.
|
||||||
|
# That may be not really necessary, for simple drawings doing all
|
||||||
|
# the drawing in the "draw" call back is easier and faster. But for
|
||||||
|
# more complicated drawing operations, for example when using a
|
||||||
|
# background grid, which is a bit larger than the window size and
|
||||||
|
# is reused when scrolling, a custom surface may be useful.
|
||||||
|
# And finally that custom surface and custom cairo context is an
|
||||||
|
# important test for the language bindings.
|
||||||
|
|
||||||
import gintro/[gtk, gdk, glib, gobject, gio, cairo]
|
import gintro/[gtk, gdk, glib, gobject, gio, cairo]
|
||||||
|
|
||||||
const
|
const
|
||||||
DataX = 150.0
|
ZoomFactorMouseWheel = 1.1
|
||||||
DataY = 250.0
|
ZoomFactorSelectMax = 10 # ignore zooming in tiny selection
|
||||||
DataWidth = 200.0
|
ZoomNearMousepointer = true # mouse wheel zooming -- to mouse-pointer or center
|
||||||
DataHeight = 120.0
|
SelectRectCol = [0.0, 0, 1, 0.5] # blue with transparency
|
||||||
|
|
||||||
# The following two functions are intended to be user defined -- we have still
|
|
||||||
# to investigate how to do that best.
|
|
||||||
|
|
||||||
# bounding box of user data -- x, y, w, h -- top left corner, width, height
|
|
||||||
proc getWorldExtends(): (float, float, float, float) =
|
|
||||||
(DataX, DataY, DataWidth, DataHeight) # current extents of our user world
|
|
||||||
|
|
||||||
# draw to cairo context
|
|
||||||
proc drawWorld(cr: cairo.Context) =
|
|
||||||
cr.setSource(1, 1, 1)
|
|
||||||
cr.paint
|
|
||||||
cr.setSource(0, 0, 0)
|
|
||||||
cr.setLineWidth(2)
|
|
||||||
cr.rectangle(DataX, DataY, DataWidth, DataHeight)
|
|
||||||
var i = 10.0
|
|
||||||
while true:
|
|
||||||
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
|
|
||||||
break
|
|
||||||
cr.rectangle(DataX + i, DataY + i, DataWidth - 2.0 * i,
|
|
||||||
DataHeight - 2.0 * i)
|
|
||||||
i += 10.0
|
|
||||||
cr.stroke
|
|
||||||
|
|
||||||
const
|
|
||||||
|
|
||||||
ZOOM_FACTOR_MOUSE_WHEEL = 1.1
|
|
||||||
ZOOM_FACTOR_SELECT_MAX = 10 # ignore zooming in tiny selection
|
|
||||||
ZOOM_NEAR_MOUSEPOINTER = true # mouse wheel zooming -- to mousepointer or center
|
|
||||||
SELECT_RECT_COL = [0.0, 0, 1, 0.5] # blue with transparency
|
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
Zooming, scrolling, panning...
|
Zooming, scrolling, panning...
|
||||||
|
|
@ -931,6 +914,12 @@ type
|
||||||
proc newPosAdj: PosAdj =
|
proc newPosAdj: PosAdj =
|
||||||
initAdjustment(result, 0, 0, 1, 1, 10, 1)
|
initAdjustment(result, 0, 0, 1, 1, 10, 1)
|
||||||
|
|
||||||
|
type
|
||||||
|
PDA_Data* = object
|
||||||
|
draw*: proc (cr: Context)
|
||||||
|
extents*: proc (): tuple[x, y, w, h: float]
|
||||||
|
windowSize*: tuple[w, h: int]
|
||||||
|
|
||||||
type
|
type
|
||||||
PDA = ref object of Grid
|
PDA = ref object of Grid
|
||||||
zoomNearMousepointer: bool
|
zoomNearMousepointer: bool
|
||||||
|
|
@ -953,6 +942,8 @@ type
|
||||||
lastMousePosY: float
|
lastMousePosY: float
|
||||||
zoomRectX1: float
|
zoomRectX1: float
|
||||||
zoomRectY1: float
|
zoomRectY1: float
|
||||||
|
drawWorld: proc (cr: Context)
|
||||||
|
extents: proc (): tuple[x, y, w, h: float]
|
||||||
|
|
||||||
proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
||||||
if this.surf.isNil: return
|
if this.surf.isNil: return
|
||||||
|
|
@ -967,7 +958,8 @@ proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
||||||
cr.setSource(0, 0, 0)
|
cr.setSource(0, 0, 0)
|
||||||
cr.setLineWidth(2)
|
cr.setLineWidth(2)
|
||||||
cr.stroke
|
cr.stroke
|
||||||
return true # TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
|
return SignalEventStopPropagation
|
||||||
|
#return true # TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
|
||||||
|
|
||||||
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
|
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
|
||||||
proc updateVal(adj: PosAdj; d: float) =
|
proc updateVal(adj: PosAdj; d: float) =
|
||||||
|
|
@ -977,35 +969,30 @@ proc updateVal(adj: PosAdj; d: float) =
|
||||||
|
|
||||||
proc updateAdjustments(this: PDA; dx, dy: float) =
|
proc updateAdjustments(this: PDA; dx, dy: float) =
|
||||||
this.hadjustment.setUpper(this.darea.allocatedWidth.float * this.userZoom)
|
this.hadjustment.setUpper(this.darea.allocatedWidth.float * this.userZoom)
|
||||||
this.vadjustment.setUpper(this.darea.allocatedHeight.float *
|
this.vadjustment.setUpper(this.darea.allocatedHeight.float * this.userZoom)
|
||||||
this.userZoom)
|
|
||||||
this.hadjustment.setPageSize(this.darea.allocatedWidth.float)
|
this.hadjustment.setPageSize(this.darea.allocatedWidth.float)
|
||||||
this.vadjustment.setPageSize(this.darea.allocatedHeight.float)
|
this.vadjustment.setPageSize(this.darea.allocatedHeight.float)
|
||||||
updateVal(this.hadjustment, dx)
|
updateVal(this.hadjustment, dx)
|
||||||
updateVal(this.vadjustment, dy)
|
updateVal(this.vadjustment, dy)
|
||||||
|
|
||||||
# Maybe we should fix this for latest GTK3, see
|
# maybe for optimization we should only allocate a new surface when its size has changed.
|
||||||
# https://developer.gnome.org/gdk3/stable/gdk3-Cairo-Interaction.html
|
|
||||||
# so use gdk_drawing_context_get_cairo_context ()
|
|
||||||
# or maybe even better do all drwing from within "draw" callback?
|
|
||||||
proc paint(this: PDA) =
|
proc paint(this: PDA) =
|
||||||
if this.surf != nil:
|
if this.surf != nil:
|
||||||
cairosurfaceDestroy(this.surf.impl) # we may have to fix that later for automatically destroy
|
destroy(this.surf) # manually destroy surface -- GC would do it for us, but GC is slow...
|
||||||
this.surf = this.darea.window.createSimilarSurface(Content.color,
|
this.surf = this.darea.window.createSimilarSurface(Content.color,
|
||||||
this.darea.allocatedWidth, this.darea.allocatedHeight)
|
this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
let cr = newContext(this.surf)
|
let cr = newContext(this.surf)
|
||||||
cr.translate(this.hadjustment.upper * 0.5 - this.hadjustment.value, # our origin is the center
|
cr.translate(this.hadjustment.upper * 0.5 - this.hadjustment.value, # our origin is the center
|
||||||
this.vadjustment.upper * 0.5 - this.vadjustment.value)
|
this.vadjustment.upper * 0.5 - this.vadjustment.value)
|
||||||
cr.scale(this.fullScale * this.userZoom, this.fullScale * this.userZoom)
|
cr.scale(this.fullScale * this.userZoom, this.fullScale * this.userZoom)
|
||||||
cr.translate(-this.dataX - this.dataWidth * 0.5,
|
cr.translate(-this.dataX - this.dataWidth * 0.5, -this.dataY - this.dataHeight * 0.5)
|
||||||
-this.dataY - this.dataHeight * 0.5)
|
this.drawWorld(cr) # call the user provided drawing function
|
||||||
drawWorld(cr) # call the user provided drawing fonction
|
destroy(cr) # we can also manually destroy the context here, but GC would do it for us
|
||||||
|
|
||||||
proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
|
proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
this.updateAdjustments(0, 0)
|
this.updateAdjustments(0, 0)
|
||||||
(this.dataX, this.dataY, this.dataWidth,
|
(this.dataX, this.dataY, this.dataWidth,
|
||||||
this.dataHeight) = getWorldExtends() # query user defined size
|
this.dataHeight) = this.extents() # query user defined size
|
||||||
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
|
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
|
||||||
this.darea.allocatedHeight.float / this.dataHeight)
|
this.darea.allocatedHeight.float / this.dataHeight)
|
||||||
this.paint
|
this.paint
|
||||||
|
|
@ -1013,8 +1000,7 @@ proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
|
||||||
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
|
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
|
||||||
this.updateAdjustments(dx, dy)
|
this.updateAdjustments(dx, dy)
|
||||||
this.paint
|
this.paint
|
||||||
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
|
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
this.darea.allocatedHeight)
|
|
||||||
|
|
||||||
# event coordinates to user space
|
# event coordinates to user space
|
||||||
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
||||||
|
|
@ -1026,16 +1012,13 @@ proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
||||||
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
|
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
|
||||||
let state = getState(event)
|
let state = getState(event)
|
||||||
let (x, y) = event.getCoords
|
let (x, y) = event.getCoords
|
||||||
#(x, y) = this.getUserCoordinates(x, y)
|
|
||||||
if (state.contains(button1)): # selecting
|
if (state.contains(button1)): # selecting
|
||||||
this.selecting = true
|
this.selecting = true
|
||||||
this.zoomRectX1 = x
|
this.zoomRectX1 = x
|
||||||
this.zoomRectY1 = y
|
this.zoomRectY1 = y
|
||||||
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
|
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
this.darea.allocatedHeight)
|
|
||||||
elif button2 in state: # panning
|
elif button2 in state: # panning
|
||||||
this.updateAdjustmentsAndPaint(this.lastMousePosX - x,
|
this.updateAdjustmentsAndPaint(this.lastMousePosX - x, this.lastMousePosY - y)
|
||||||
this.lastMousePosY - y)
|
|
||||||
this.lastMousePosX = x
|
this.lastMousePosX = x
|
||||||
this.lastMousePosY = y
|
this.lastMousePosY = y
|
||||||
#event.request # request more motion events ?
|
#event.request # request more motion events ?
|
||||||
|
|
@ -1048,25 +1031,20 @@ proc scrollEvent(darea: DrawingArea; event: EventScroll; this: PDA): bool =
|
||||||
var d = getScrollDirection(event)
|
var d = getScrollDirection(event)
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
if d == ScrollDirection.up:
|
if d == ScrollDirection.up:
|
||||||
this.userZoom *= ZOOM_FACTOR_MOUSE_WHEEL
|
this.userZoom *= ZoomFactorMouseWheel
|
||||||
elif d == ScrollDirection.down:
|
elif d == ScrollDirection.down:
|
||||||
this.userZoom /= ZOOM_FACTOR_MOUSE_WHEEL
|
this.userZoom /= ZoomFactorMouseWheel
|
||||||
if (this.userZoom < 1):
|
if (this.userZoom < 1):
|
||||||
this.userZoom = 1
|
this.userZoom = 1
|
||||||
if this.zoomNearMousepointer:
|
if this.zoomNearMousepointer:
|
||||||
this.updateAdjustmentsAndPaint((this.hadjustment.value + x) * (
|
this.updateAdjustmentsAndPaint((this.hadjustment.value + x) * (this.userZoom / z0 - 1),
|
||||||
this.userZoom / z0 - 1),
|
(this.vadjustment.value + y) * (this.userZoom / z0 - 1))
|
||||||
(this.vadjustment.value + y) * (
|
|
||||||
this.userZoom / z0 - 1))
|
|
||||||
else: # zoom to center
|
else: # zoom to center
|
||||||
this.updateAdjustmentsAndPaint((this.hadjustment.value +
|
this.updateAdjustmentsAndPaint((this.hadjustment.value +
|
||||||
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
|
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
|
||||||
(this.vadjustment.value +
|
(this.vadjustment.value + this.darea.allocatedHeight.float * 0.5) * (this.userZoom / z0 - 1))
|
||||||
this.darea.allocatedHeight.float * 0.5) * (
|
|
||||||
this.userZoom / z0 - 1))
|
|
||||||
|
|
||||||
proc buttonPressEvent(darea: DrawingArea; event: EventButton;
|
proc buttonPressEvent(darea: DrawingArea; event: EventButton; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
this.lastMousePosX = x
|
this.lastMousePosX = x
|
||||||
this.lastMousePosY = y
|
this.lastMousePosY = y
|
||||||
|
|
@ -1077,8 +1055,7 @@ proc buttonPressEvent(darea: DrawingArea; event: EventButton;
|
||||||
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
|
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
|
||||||
|
|
||||||
# zoom into selected rectangle and center it
|
# zoom into selected rectangle and center it
|
||||||
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
var b = getButton(event)
|
var b = getButton(event)
|
||||||
if b == 1:
|
if b == 1:
|
||||||
|
|
@ -1086,7 +1063,7 @@ proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
||||||
let z1 = min(this.darea.allocatedWidth.float / (
|
let z1 = min(this.darea.allocatedWidth.float / (
|
||||||
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
|
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
|
||||||
this.lastButtonDownPosY - y).abs)
|
this.lastButtonDownPosY - y).abs)
|
||||||
if z1 < ZOOM_FACTOR_SELECT_MAX: # else selection rectangle will persist, we may output a message...
|
if z1 < ZoomFactorSelectMax: # else selection rectangle will persist, we may output a message...
|
||||||
this.userZoom *= z1
|
this.userZoom *= z1
|
||||||
this.updateAdjustmentsAndPaint(
|
this.updateAdjustmentsAndPaint(
|
||||||
((2 * this.hadjustment.value + x + this.lastButtonDownPosX) * z1 -
|
((2 * this.hadjustment.value + x + this.lastButtonDownPosX) * z1 -
|
||||||
|
|
@ -1096,24 +1073,19 @@ proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
||||||
|
|
||||||
proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
|
proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
|
||||||
pda.paint
|
pda.paint
|
||||||
pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth,
|
pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth, pda.darea.allocatedHeight)
|
||||||
pda.darea.allocatedHeight)
|
|
||||||
|
|
||||||
proc newPDA: PDA =
|
proc newPDA: PDA =
|
||||||
initGrid(result)
|
initGrid(result)
|
||||||
result.zoomNearMousepointer = ZOOM_NEAR_MOUSEPOINTER # mouse wheel zooming
|
result.zoomNearMousepointer = ZoomNearMousepointer # mouse wheel zooming
|
||||||
result.selecting = false
|
|
||||||
result.userZoom = 1.0
|
result.userZoom = 1.0
|
||||||
result.surf = nil
|
|
||||||
result.darea = newDrawingArea()
|
result.darea = newDrawingArea()
|
||||||
result.darea.setHExpand#(true)
|
result.darea.setHExpand
|
||||||
result.darea.setVExpand#(true)
|
result.darea.setVExpand
|
||||||
result.darea.connect("draw", drawingAreaDrawCb, result)
|
result.darea.connect("draw", drawingAreaDrawCb, result)
|
||||||
result.darea.connect("configure-event", dareaConfigureCallback, result)
|
result.darea.connect("configure-event", dareaConfigureCallback, result)
|
||||||
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
|
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
|
||||||
EventFlag.scroll,
|
EventFlag.scroll, button1Motion, button2Motion, pointerMotionHint})
|
||||||
EventFlag.button1Motion, EventFlag.button2Motion,
|
|
||||||
EventFlag.pointerMotionHint})
|
|
||||||
result.darea.connect("motion-notify-event", onMotion, result)
|
result.darea.connect("motion-notify-event", onMotion, result)
|
||||||
result.darea.connect("scroll_event", scrollEvent, result)
|
result.darea.connect("scroll_event", scrollEvent, result)
|
||||||
result.darea.connect("button_press_event", buttonPressEvent, result)
|
result.darea.connect("button_press_event", buttonPressEvent, result)
|
||||||
|
|
@ -1126,25 +1098,98 @@ proc newPDA: PDA =
|
||||||
onAdjustmentEvent, result)
|
onAdjustmentEvent, result)
|
||||||
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
|
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
|
||||||
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
|
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
|
||||||
result.hscrollbar.setHExpand#(true)
|
result.hscrollbar.setHExpand
|
||||||
result.vscrollbar.setVExpand#(true)
|
result.vscrollbar.setVExpand
|
||||||
result.attach(result.darea, 0, 0, 1, 1)
|
result.attach(result.darea, 0, 0, 1, 1)
|
||||||
result.attach(result.vscrollbar, 1, 0, 1, 1)
|
result.attach(result.vscrollbar, 1, 0, 1, 1)
|
||||||
result.attach(result.hscrollbar, 0, 1, 1, 1)
|
result.attach(result.hscrollbar, 0, 1, 1, 1)
|
||||||
|
|
||||||
proc appActivate(app: Application) =
|
proc appActivate(app: Application; initData: ref PDA_Data) =
|
||||||
let window = newApplicationWindow(app)
|
let window = newApplicationWindow(app)
|
||||||
window.title = "Drawing example"
|
window.title = "Drawing example"
|
||||||
window.defaultSize = (400, 400)
|
window.defaultSize = (initData.windowSize[0], initData.windowSize[1])
|
||||||
let pda = newPDA()
|
let pda = newPDA()
|
||||||
|
pda.drawWorld = initData.draw
|
||||||
|
pda.extents = initData.extents
|
||||||
window.add(pda)
|
window.add(pda)
|
||||||
showAll(window)
|
showAll(window)
|
||||||
|
|
||||||
proc main =
|
proc newDisplay*(initData: PDA_Data) =
|
||||||
let app = newApplication("org.gtk.example")
|
let app = newApplication("org.gtk.example")
|
||||||
connect(app, "activate", appActivate)
|
var d = new (ref PDA_Data)
|
||||||
|
d[] = initData
|
||||||
|
connect(app, "activate", appActivate, d)
|
||||||
discard run(app)
|
discard run(app)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
|
||||||
|
const # arbitrary locations for our data
|
||||||
|
DataX = 150.0
|
||||||
|
DataY = 250.0
|
||||||
|
DataWidth = 200.0
|
||||||
|
DataHeight = 120.0
|
||||||
|
|
||||||
|
# we need two user defined functions -- one gives the extent of the graphics,
|
||||||
|
# and the other does the cairo drawing using a cairo context.
|
||||||
|
|
||||||
|
# bounding box of user data -- x, y, w, h -- top left corner, width, height
|
||||||
|
proc worldExtents(): (float, float, float, float) =
|
||||||
|
(DataX, DataY, DataWidth, DataHeight) # current extents of our user world
|
||||||
|
|
||||||
|
# draw to cairo context
|
||||||
|
proc drawWorld(cr: cairo.Context) =
|
||||||
|
cr.setSource(1, 1, 1)
|
||||||
|
cr.paint
|
||||||
|
cr.setSource(0, 0, 0)
|
||||||
|
cr.setLineWidth(2)
|
||||||
|
var i = 0.0
|
||||||
|
while true:
|
||||||
|
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
|
||||||
|
break
|
||||||
|
cr.rectangle(DataX + i, DataY + i, DataWidth - 2 * i, DataHeight - 2 * i)
|
||||||
|
i += 10.0
|
||||||
|
cr.stroke
|
||||||
|
|
||||||
|
proc test =
|
||||||
|
var data: PDA_Data
|
||||||
|
data.draw = drawWorld
|
||||||
|
data.extents = worldExtents
|
||||||
|
data.windowSize = (800, 600)
|
||||||
|
newDisplay(data)
|
||||||
|
|
||||||
|
test()
|
||||||
|
----
|
||||||
|
|
||||||
|
We can use this module as a library easily and get this simple drawing tool with full zoom and scroll support:
|
||||||
|
|
||||||
|
[[darea_test.nim]]
|
||||||
|
[source,nim]
|
||||||
|
.darea_test.nim
|
||||||
|
----
|
||||||
|
import gintro/cairo
|
||||||
|
import drawingarea
|
||||||
|
from math import PI
|
||||||
|
|
||||||
|
proc extents(): (float, float, float, float) =
|
||||||
|
(0.0, 0.0, 100.0, 100.0) # ugly float literals
|
||||||
|
|
||||||
|
# draw to cairo context
|
||||||
|
proc draw(cr: cairo.Context) =
|
||||||
|
cr.setSource(1, 1, 1) # set background color and paint
|
||||||
|
cr.paint
|
||||||
|
cr.setSource(0, 0, 0) # forground color
|
||||||
|
cr.arc(20, 30, 10, 0, 5) # nearly a circle
|
||||||
|
cr.newSubPath # do not join the two arcs
|
||||||
|
cr.arc(70, 60, 20, 0, math.PI)
|
||||||
|
cr.stroke # finally do it
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var data: PDA_Data
|
||||||
|
data.draw = draw
|
||||||
|
data.extents = extents
|
||||||
|
data.windowSize = (800, 600)
|
||||||
|
newDisplay(data)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
||||||
25
examples/darea_test.nim
Normal file
25
examples/darea_test.nim
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import gintro/cairo
|
||||||
|
import drawingarea
|
||||||
|
from math import PI
|
||||||
|
|
||||||
|
proc extents(): (float, float, float, float) =
|
||||||
|
(0.0, 0.0, 100.0, 100.0) # ugly float literals
|
||||||
|
|
||||||
|
# draw to cairo context
|
||||||
|
proc draw(cr: cairo.Context) =
|
||||||
|
cr.setSource(1, 1, 1) # set background color and paint
|
||||||
|
cr.paint
|
||||||
|
cr.setSource(0, 0, 0) # forground color
|
||||||
|
cr.arc(20, 30, 10, 0, 5) # nearly a circle
|
||||||
|
cr.newSubPath # do not join the two arcs
|
||||||
|
cr.arc(70, 60, 20, 0, math.PI)
|
||||||
|
cr.stroke # finally do it
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var data: PDA_Data
|
||||||
|
data.draw = draw
|
||||||
|
data.extents = extents
|
||||||
|
data.windowSize = (800, 600)
|
||||||
|
newDisplay(data)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
@ -1,45 +1,25 @@
|
||||||
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
|
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
|
||||||
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
|
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
|
||||||
# Nim version April 2019 -- well first draft :-)
|
# Nim version April 2019
|
||||||
# License MIT
|
# License MIT
|
||||||
|
|
||||||
|
# This version of the demo program uses a separate proc paint()
|
||||||
|
# which allocates a custom surface for buffered drawing.
|
||||||
|
# That may be not really necessary, for simple drawings doing all
|
||||||
|
# the drawing in the "draw" call back is easier and faster. But for
|
||||||
|
# more complicated drawing operations, for example when using a
|
||||||
|
# background grid, which is a bit larger than the window size and
|
||||||
|
# is reused when scrolling, a custom surface may be useful.
|
||||||
|
# And finally that custom surface and custom cairo context is an
|
||||||
|
# important test for the language bindings.
|
||||||
|
|
||||||
import gintro/[gtk, gdk, glib, gobject, gio, cairo]
|
import gintro/[gtk, gdk, glib, gobject, gio, cairo]
|
||||||
|
|
||||||
const
|
const
|
||||||
DataX = 150.0
|
ZoomFactorMouseWheel = 1.1
|
||||||
DataY = 250.0
|
ZoomFactorSelectMax = 10 # ignore zooming in tiny selection
|
||||||
DataWidth = 200.0
|
ZoomNearMousepointer = true # mouse wheel zooming -- to mouse-pointer or center
|
||||||
DataHeight = 120.0
|
SelectRectCol = [0.0, 0, 1, 0.5] # blue with transparency
|
||||||
|
|
||||||
# The following two functions are intended to be user defined -- we have still
|
|
||||||
# to investigate how to do that best.
|
|
||||||
|
|
||||||
# bounding box of user data -- x, y, w, h -- top left corner, width, height
|
|
||||||
proc getWorldExtends(): (float, float, float, float) =
|
|
||||||
(DataX, DataY, DataWidth, DataHeight) # current extents of our user world
|
|
||||||
|
|
||||||
# draw to cairo context
|
|
||||||
proc drawWorld(cr: cairo.Context) =
|
|
||||||
cr.setSource(1, 1, 1)
|
|
||||||
cr.paint
|
|
||||||
cr.setSource(0, 0, 0)
|
|
||||||
cr.setLineWidth(2)
|
|
||||||
cr.rectangle(DataX, DataY, DataWidth, DataHeight)
|
|
||||||
var i = 10.0
|
|
||||||
while true:
|
|
||||||
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
|
|
||||||
break
|
|
||||||
cr.rectangle(DataX + i, DataY + i, DataWidth - 2.0 * i,
|
|
||||||
DataHeight - 2.0 * i)
|
|
||||||
i += 10.0
|
|
||||||
cr.stroke
|
|
||||||
|
|
||||||
const
|
|
||||||
|
|
||||||
ZOOM_FACTOR_MOUSE_WHEEL = 1.1
|
|
||||||
ZOOM_FACTOR_SELECT_MAX = 10 # ignore zooming in tiny selection
|
|
||||||
ZOOM_NEAR_MOUSEPOINTER = true # mouse wheel zooming -- to mousepointer or center
|
|
||||||
SELECT_RECT_COL = [0.0, 0, 1, 0.5] # blue with transparency
|
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
Zooming, scrolling, panning...
|
Zooming, scrolling, panning...
|
||||||
|
|
@ -80,6 +60,12 @@ type
|
||||||
proc newPosAdj: PosAdj =
|
proc newPosAdj: PosAdj =
|
||||||
initAdjustment(result, 0, 0, 1, 1, 10, 1)
|
initAdjustment(result, 0, 0, 1, 1, 10, 1)
|
||||||
|
|
||||||
|
type
|
||||||
|
PDA_Data* = object
|
||||||
|
draw*: proc (cr: Context)
|
||||||
|
extents*: proc (): tuple[x, y, w, h: float]
|
||||||
|
windowSize*: tuple[w, h: int]
|
||||||
|
|
||||||
type
|
type
|
||||||
PDA = ref object of Grid
|
PDA = ref object of Grid
|
||||||
zoomNearMousepointer: bool
|
zoomNearMousepointer: bool
|
||||||
|
|
@ -102,6 +88,8 @@ type
|
||||||
lastMousePosY: float
|
lastMousePosY: float
|
||||||
zoomRectX1: float
|
zoomRectX1: float
|
||||||
zoomRectY1: float
|
zoomRectY1: float
|
||||||
|
drawWorld: proc (cr: Context)
|
||||||
|
extents: proc (): tuple[x, y, w, h: float]
|
||||||
|
|
||||||
proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
||||||
if this.surf.isNil: return
|
if this.surf.isNil: return
|
||||||
|
|
@ -116,7 +104,8 @@ proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
|
||||||
cr.setSource(0, 0, 0)
|
cr.setSource(0, 0, 0)
|
||||||
cr.setLineWidth(2)
|
cr.setLineWidth(2)
|
||||||
cr.stroke
|
cr.stroke
|
||||||
return true # TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
|
return SignalEventStopPropagation
|
||||||
|
#return true # TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
|
||||||
|
|
||||||
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
|
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
|
||||||
proc updateVal(adj: PosAdj; d: float) =
|
proc updateVal(adj: PosAdj; d: float) =
|
||||||
|
|
@ -126,35 +115,30 @@ proc updateVal(adj: PosAdj; d: float) =
|
||||||
|
|
||||||
proc updateAdjustments(this: PDA; dx, dy: float) =
|
proc updateAdjustments(this: PDA; dx, dy: float) =
|
||||||
this.hadjustment.setUpper(this.darea.allocatedWidth.float * this.userZoom)
|
this.hadjustment.setUpper(this.darea.allocatedWidth.float * this.userZoom)
|
||||||
this.vadjustment.setUpper(this.darea.allocatedHeight.float *
|
this.vadjustment.setUpper(this.darea.allocatedHeight.float * this.userZoom)
|
||||||
this.userZoom)
|
|
||||||
this.hadjustment.setPageSize(this.darea.allocatedWidth.float)
|
this.hadjustment.setPageSize(this.darea.allocatedWidth.float)
|
||||||
this.vadjustment.setPageSize(this.darea.allocatedHeight.float)
|
this.vadjustment.setPageSize(this.darea.allocatedHeight.float)
|
||||||
updateVal(this.hadjustment, dx)
|
updateVal(this.hadjustment, dx)
|
||||||
updateVal(this.vadjustment, dy)
|
updateVal(this.vadjustment, dy)
|
||||||
|
|
||||||
# Maybe we should fix this for latest GTK3, see
|
# maybe for optimization we should only allocate a new surface when its size has changed.
|
||||||
# https://developer.gnome.org/gdk3/stable/gdk3-Cairo-Interaction.html
|
|
||||||
# so use gdk_drawing_context_get_cairo_context ()
|
|
||||||
# or maybe even better do all drwing from within "draw" callback?
|
|
||||||
proc paint(this: PDA) =
|
proc paint(this: PDA) =
|
||||||
if this.surf != nil:
|
if this.surf != nil:
|
||||||
cairosurfaceDestroy(this.surf.impl) # we may have to fix that later for automatically destroy
|
destroy(this.surf) # manually destroy surface -- GC would do it for us, but GC is slow...
|
||||||
this.surf = this.darea.window.createSimilarSurface(Content.color,
|
this.surf = this.darea.window.createSimilarSurface(Content.color,
|
||||||
this.darea.allocatedWidth, this.darea.allocatedHeight)
|
this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
let cr = newContext(this.surf)
|
let cr = newContext(this.surf)
|
||||||
cr.translate(this.hadjustment.upper * 0.5 - this.hadjustment.value, # our origin is the center
|
cr.translate(this.hadjustment.upper * 0.5 - this.hadjustment.value, # our origin is the center
|
||||||
this.vadjustment.upper * 0.5 - this.vadjustment.value)
|
this.vadjustment.upper * 0.5 - this.vadjustment.value)
|
||||||
cr.scale(this.fullScale * this.userZoom, this.fullScale * this.userZoom)
|
cr.scale(this.fullScale * this.userZoom, this.fullScale * this.userZoom)
|
||||||
cr.translate(-this.dataX - this.dataWidth * 0.5,
|
cr.translate(-this.dataX - this.dataWidth * 0.5, -this.dataY - this.dataHeight * 0.5)
|
||||||
-this.dataY - this.dataHeight * 0.5)
|
this.drawWorld(cr) # call the user provided drawing function
|
||||||
drawWorld(cr) # call the user provided drawing fonction
|
destroy(cr) # we can also manually destroy the context here, but GC would do it for us
|
||||||
|
|
||||||
proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
|
proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
this.updateAdjustments(0, 0)
|
this.updateAdjustments(0, 0)
|
||||||
(this.dataX, this.dataY, this.dataWidth,
|
(this.dataX, this.dataY, this.dataWidth,
|
||||||
this.dataHeight) = getWorldExtends() # query user defined size
|
this.dataHeight) = this.extents() # query user defined size
|
||||||
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
|
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
|
||||||
this.darea.allocatedHeight.float / this.dataHeight)
|
this.darea.allocatedHeight.float / this.dataHeight)
|
||||||
this.paint
|
this.paint
|
||||||
|
|
@ -162,8 +146,7 @@ proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
|
||||||
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
|
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
|
||||||
this.updateAdjustments(dx, dy)
|
this.updateAdjustments(dx, dy)
|
||||||
this.paint
|
this.paint
|
||||||
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
|
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
this.darea.allocatedHeight)
|
|
||||||
|
|
||||||
# event coordinates to user space
|
# event coordinates to user space
|
||||||
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
||||||
|
|
@ -175,16 +158,13 @@ proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
|
||||||
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
|
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
|
||||||
let state = getState(event)
|
let state = getState(event)
|
||||||
let (x, y) = event.getCoords
|
let (x, y) = event.getCoords
|
||||||
#(x, y) = this.getUserCoordinates(x, y)
|
|
||||||
if (state.contains(button1)): # selecting
|
if (state.contains(button1)): # selecting
|
||||||
this.selecting = true
|
this.selecting = true
|
||||||
this.zoomRectX1 = x
|
this.zoomRectX1 = x
|
||||||
this.zoomRectY1 = y
|
this.zoomRectY1 = y
|
||||||
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
|
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth, this.darea.allocatedHeight)
|
||||||
this.darea.allocatedHeight)
|
|
||||||
elif button2 in state: # panning
|
elif button2 in state: # panning
|
||||||
this.updateAdjustmentsAndPaint(this.lastMousePosX - x,
|
this.updateAdjustmentsAndPaint(this.lastMousePosX - x, this.lastMousePosY - y)
|
||||||
this.lastMousePosY - y)
|
|
||||||
this.lastMousePosX = x
|
this.lastMousePosX = x
|
||||||
this.lastMousePosY = y
|
this.lastMousePosY = y
|
||||||
#event.request # request more motion events ?
|
#event.request # request more motion events ?
|
||||||
|
|
@ -197,25 +177,20 @@ proc scrollEvent(darea: DrawingArea; event: EventScroll; this: PDA): bool =
|
||||||
var d = getScrollDirection(event)
|
var d = getScrollDirection(event)
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
if d == ScrollDirection.up:
|
if d == ScrollDirection.up:
|
||||||
this.userZoom *= ZOOM_FACTOR_MOUSE_WHEEL
|
this.userZoom *= ZoomFactorMouseWheel
|
||||||
elif d == ScrollDirection.down:
|
elif d == ScrollDirection.down:
|
||||||
this.userZoom /= ZOOM_FACTOR_MOUSE_WHEEL
|
this.userZoom /= ZoomFactorMouseWheel
|
||||||
if (this.userZoom < 1):
|
if (this.userZoom < 1):
|
||||||
this.userZoom = 1
|
this.userZoom = 1
|
||||||
if this.zoomNearMousepointer:
|
if this.zoomNearMousepointer:
|
||||||
this.updateAdjustmentsAndPaint((this.hadjustment.value + x) * (
|
this.updateAdjustmentsAndPaint((this.hadjustment.value + x) * (this.userZoom / z0 - 1),
|
||||||
this.userZoom / z0 - 1),
|
(this.vadjustment.value + y) * (this.userZoom / z0 - 1))
|
||||||
(this.vadjustment.value + y) * (
|
|
||||||
this.userZoom / z0 - 1))
|
|
||||||
else: # zoom to center
|
else: # zoom to center
|
||||||
this.updateAdjustmentsAndPaint((this.hadjustment.value +
|
this.updateAdjustmentsAndPaint((this.hadjustment.value +
|
||||||
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
|
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
|
||||||
(this.vadjustment.value +
|
(this.vadjustment.value + this.darea.allocatedHeight.float * 0.5) * (this.userZoom / z0 - 1))
|
||||||
this.darea.allocatedHeight.float * 0.5) * (
|
|
||||||
this.userZoom / z0 - 1))
|
|
||||||
|
|
||||||
proc buttonPressEvent(darea: DrawingArea; event: EventButton;
|
proc buttonPressEvent(darea: DrawingArea; event: EventButton; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
this.lastMousePosX = x
|
this.lastMousePosX = x
|
||||||
this.lastMousePosY = y
|
this.lastMousePosY = y
|
||||||
|
|
@ -226,8 +201,7 @@ proc buttonPressEvent(darea: DrawingArea; event: EventButton;
|
||||||
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
|
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
|
||||||
|
|
||||||
# zoom into selected rectangle and center it
|
# zoom into selected rectangle and center it
|
||||||
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton; this: PDA): bool =
|
||||||
this: PDA): bool =
|
|
||||||
var (x, y) = event.getCoords
|
var (x, y) = event.getCoords
|
||||||
var b = getButton(event)
|
var b = getButton(event)
|
||||||
if b == 1:
|
if b == 1:
|
||||||
|
|
@ -235,7 +209,7 @@ proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
||||||
let z1 = min(this.darea.allocatedWidth.float / (
|
let z1 = min(this.darea.allocatedWidth.float / (
|
||||||
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
|
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
|
||||||
this.lastButtonDownPosY - y).abs)
|
this.lastButtonDownPosY - y).abs)
|
||||||
if z1 < ZOOM_FACTOR_SELECT_MAX: # else selection rectangle will persist, we may output a message...
|
if z1 < ZoomFactorSelectMax: # else selection rectangle will persist, we may output a message...
|
||||||
this.userZoom *= z1
|
this.userZoom *= z1
|
||||||
this.updateAdjustmentsAndPaint(
|
this.updateAdjustmentsAndPaint(
|
||||||
((2 * this.hadjustment.value + x + this.lastButtonDownPosX) * z1 -
|
((2 * this.hadjustment.value + x + this.lastButtonDownPosX) * z1 -
|
||||||
|
|
@ -245,24 +219,19 @@ proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
|
||||||
|
|
||||||
proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
|
proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
|
||||||
pda.paint
|
pda.paint
|
||||||
pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth,
|
pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth, pda.darea.allocatedHeight)
|
||||||
pda.darea.allocatedHeight)
|
|
||||||
|
|
||||||
proc newPDA: PDA =
|
proc newPDA: PDA =
|
||||||
initGrid(result)
|
initGrid(result)
|
||||||
result.zoomNearMousepointer = ZOOM_NEAR_MOUSEPOINTER # mouse wheel zooming
|
result.zoomNearMousepointer = ZoomNearMousepointer # mouse wheel zooming
|
||||||
result.selecting = false
|
|
||||||
result.userZoom = 1.0
|
result.userZoom = 1.0
|
||||||
result.surf = nil
|
|
||||||
result.darea = newDrawingArea()
|
result.darea = newDrawingArea()
|
||||||
result.darea.setHExpand#(true)
|
result.darea.setHExpand
|
||||||
result.darea.setVExpand#(true)
|
result.darea.setVExpand
|
||||||
result.darea.connect("draw", drawingAreaDrawCb, result)
|
result.darea.connect("draw", drawingAreaDrawCb, result)
|
||||||
result.darea.connect("configure-event", dareaConfigureCallback, result)
|
result.darea.connect("configure-event", dareaConfigureCallback, result)
|
||||||
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
|
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
|
||||||
EventFlag.scroll,
|
EventFlag.scroll, button1Motion, button2Motion, pointerMotionHint})
|
||||||
EventFlag.button1Motion, EventFlag.button2Motion,
|
|
||||||
EventFlag.pointerMotionHint})
|
|
||||||
result.darea.connect("motion-notify-event", onMotion, result)
|
result.darea.connect("motion-notify-event", onMotion, result)
|
||||||
result.darea.connect("scroll_event", scrollEvent, result)
|
result.darea.connect("scroll_event", scrollEvent, result)
|
||||||
result.darea.connect("button_press_event", buttonPressEvent, result)
|
result.darea.connect("button_press_event", buttonPressEvent, result)
|
||||||
|
|
@ -275,23 +244,63 @@ proc newPDA: PDA =
|
||||||
onAdjustmentEvent, result)
|
onAdjustmentEvent, result)
|
||||||
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
|
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
|
||||||
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
|
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
|
||||||
result.hscrollbar.setHExpand#(true)
|
result.hscrollbar.setHExpand
|
||||||
result.vscrollbar.setVExpand#(true)
|
result.vscrollbar.setVExpand
|
||||||
result.attach(result.darea, 0, 0, 1, 1)
|
result.attach(result.darea, 0, 0, 1, 1)
|
||||||
result.attach(result.vscrollbar, 1, 0, 1, 1)
|
result.attach(result.vscrollbar, 1, 0, 1, 1)
|
||||||
result.attach(result.hscrollbar, 0, 1, 1, 1)
|
result.attach(result.hscrollbar, 0, 1, 1, 1)
|
||||||
|
|
||||||
proc appActivate(app: Application) =
|
proc appActivate(app: Application; initData: ref PDA_Data) =
|
||||||
let window = newApplicationWindow(app)
|
let window = newApplicationWindow(app)
|
||||||
window.title = "Drawing example"
|
window.title = "Drawing example"
|
||||||
window.defaultSize = (400, 400)
|
window.defaultSize = (initData.windowSize[0], initData.windowSize[1])
|
||||||
let pda = newPDA()
|
let pda = newPDA()
|
||||||
|
pda.drawWorld = initData.draw
|
||||||
|
pda.extents = initData.extents
|
||||||
window.add(pda)
|
window.add(pda)
|
||||||
showAll(window)
|
showAll(window)
|
||||||
|
|
||||||
proc main =
|
proc newDisplay*(initData: PDA_Data) =
|
||||||
let app = newApplication("org.gtk.example")
|
let app = newApplication("org.gtk.example")
|
||||||
connect(app, "activate", appActivate)
|
var d = new (ref PDA_Data)
|
||||||
|
d[] = initData
|
||||||
|
connect(app, "activate", appActivate, d)
|
||||||
discard run(app)
|
discard run(app)
|
||||||
|
|
||||||
main()
|
when isMainModule:
|
||||||
|
|
||||||
|
const # arbitrary locations for our data
|
||||||
|
DataX = 150.0
|
||||||
|
DataY = 250.0
|
||||||
|
DataWidth = 200.0
|
||||||
|
DataHeight = 120.0
|
||||||
|
|
||||||
|
# we need two user defined functions -- one gives the extent of the graphics,
|
||||||
|
# and the other does the cairo drawing using a cairo context.
|
||||||
|
|
||||||
|
# bounding box of user data -- x, y, w, h -- top left corner, width, height
|
||||||
|
proc worldExtents(): (float, float, float, float) =
|
||||||
|
(DataX, DataY, DataWidth, DataHeight) # current extents of our user world
|
||||||
|
|
||||||
|
# draw to cairo context
|
||||||
|
proc drawWorld(cr: cairo.Context) =
|
||||||
|
cr.setSource(1, 1, 1)
|
||||||
|
cr.paint
|
||||||
|
cr.setSource(0, 0, 0)
|
||||||
|
cr.setLineWidth(2)
|
||||||
|
var i = 0.0
|
||||||
|
while true:
|
||||||
|
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
|
||||||
|
break
|
||||||
|
cr.rectangle(DataX + i, DataY + i, DataWidth - 2 * i, DataHeight - 2 * i)
|
||||||
|
i += 10.0
|
||||||
|
cr.stroke
|
||||||
|
|
||||||
|
proc test =
|
||||||
|
var data: PDA_Data
|
||||||
|
data.draw = drawWorld
|
||||||
|
data.extents = worldExtents
|
||||||
|
data.windowSize = (800, 600)
|
||||||
|
newDisplay(data)
|
||||||
|
|
||||||
|
test()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.4.17"
|
version = "0.4.18"
|
||||||
author = "Stefan Salewski"
|
author = "Stefan Salewski"
|
||||||
description = "High level GObject-Introspection based GTK3 bindings"
|
description = "High level GObject-Introspection based GTK3 bindings"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
||||||
207
gintro/cairo.nim
207
gintro/cairo.nim
|
|
@ -1,10 +1,12 @@
|
||||||
# this is the high level cairo module for Nim -- based on the low level ngtk3 module, manually tuned.
|
# This is the high level cairo module for Nim -- based on the low level ngtk3 module, manually tuned.
|
||||||
# S. Salewski 2017, cairo 1.15.6
|
# (c) S. Salewski 2017, cairo 1.15.6
|
||||||
|
# v0.4.18
|
||||||
|
# 24-APR-2019
|
||||||
|
|
||||||
# cairo does not really support gobject introspection and gobject's toggle references.
|
# Cairo does not really support gobject introspection and gobject's toggle references.
|
||||||
# so code for memory management is a bit different compared to other gtk modules.
|
# So code for memory management is a bit different compared to other gtk modules.
|
||||||
|
|
||||||
# This is the template for creation of new objects:
|
# This was the initial template for creation of new objects :
|
||||||
|
|
||||||
# proc newImageSurface*(format: Format; width, height: int): Surface =
|
# proc newImageSurface*(format: Format; width, height: int): Surface =
|
||||||
# new(result, surfaceDestroy)
|
# new(result, surfaceDestroy)
|
||||||
|
|
@ -12,7 +14,6 @@
|
||||||
# discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
# discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
# with
|
# with
|
||||||
|
|
||||||
# proc gcuref(o: pointer) {.cdecl.} = GC_unref(cast[RootRef](o))
|
# proc gcuref(o: pointer) {.cdecl.} = GC_unref(cast[RootRef](o))
|
||||||
# proc surfaceDestroy*(surface: Surface) = cairo_surface_destroy(surface.impl)
|
# proc surfaceDestroy*(surface: Surface) = cairo_surface_destroy(surface.impl)
|
||||||
|
|
||||||
|
|
@ -24,17 +25,44 @@
|
||||||
# result.impl = cairo_create(target.impl)
|
# result.impl = cairo_create(target.impl)
|
||||||
# discard cairo_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
# discard cairo_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
# we have to call GC_ref() because we store no direct reference to the proxy object.
|
# We have to call GC_ref() because we store no direct reference to the proxy object.
|
||||||
# for this example cairo_create() references the surface.
|
# For this example cairo_create() references the surface.
|
||||||
# when ref count of surface is decreased, maybe because context is destroyed, then gcuref is called
|
# When ref count of surface is decreased, maybe because context is destroyed, then gcuref is called
|
||||||
# which calls GC_unref() on proxy. When there is no other ref to proxy GC can free proxy and surface
|
# which calls GC_unref() on proxy. When there is no other ref to proxy GC can free proxy and surface
|
||||||
# by calling surfaceDestroy(). This works also when surface is newer used for something.
|
# by calling surfaceDestroy(). This works also when surface is newer used for something.
|
||||||
|
|
||||||
# currently this is still nearly untested!
|
# But there is at least one design flaw:
|
||||||
# one problem may be procs like cairo_surface_create_similar() when called frequently, maybe
|
# When we create for example a surface and GC releases it, then gcunref() is called on it while
|
||||||
|
# gc_ref() was newer called. When we consider that the cairo context is the only element which
|
||||||
|
# stores references to other objects, then we can simplify the code to
|
||||||
|
|
||||||
|
# proc newImageSurface*(format: Format; width, height: int): Surface =
|
||||||
|
# new(result, surfaceDestroy)
|
||||||
|
# result.impl = cairo_image_surface_create(format, width.cint, height.cint)
|
||||||
|
|
||||||
|
# with
|
||||||
|
|
||||||
|
# proc surfaceDestroy*(surface: Surface) = cairo_surface_destroy(surface.impl)
|
||||||
|
|
||||||
|
# and this is the template for refering such an object:
|
||||||
|
|
||||||
|
# proc newContext*(target: Surface): Context =
|
||||||
|
# new(result, destroy)
|
||||||
|
# GC_ref(target)
|
||||||
|
# result.impl = cairo_create(target.impl)
|
||||||
|
# discard cairo_surface_set_user_data(target.impl, NUDK, cast[pointer](target), gcuref)
|
||||||
|
|
||||||
|
# with
|
||||||
|
# proc gcuref(o: pointer) {.cdecl.} = GC_unref(cast[RootRef](o))
|
||||||
|
|
||||||
|
# Currently this is all not really tested.
|
||||||
|
# One problem may be procs like cairo_surface_create_similar() when called frequently, maybe
|
||||||
# for each frame in animations. GC may be too slow in freeing the memory.
|
# for each frame in animations. GC may be too slow in freeing the memory.
|
||||||
# We should try to avoid such usage, or we may add a way to manually free memory.
|
# We should try to avoid such usage, or we may add a way to manually free memory.
|
||||||
# Maybe later destructors can be used?
|
# Maybe later destructors can be used, or newruntime with owned refs?
|
||||||
|
|
||||||
|
# Maybe currently the best fix is to allow manually calling destroy() procs, which then ignore
|
||||||
|
# the later call from GC because impl field is already nil.
|
||||||
|
|
||||||
# Some procs are marked with label TODO -- because I have no real idea what to do with them
|
# Some procs are marked with label TODO -- because I have no real idea what to do with them
|
||||||
|
|
||||||
|
|
@ -238,7 +266,9 @@ proc setUserData*(cr: Context; key: ptr UserDataKey; userData: pointer; destroy:
|
||||||
proc cairo_destroy*(cr: ptr Context00) {.importc, libcairo.}
|
proc cairo_destroy*(cr: ptr Context00) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc destroy*(cr: Context) =
|
proc destroy*(cr: Context) =
|
||||||
cairo_destroy(cr.impl)
|
if cr != nil and cr.impl != nil:
|
||||||
|
cairo_destroy(cr.impl)
|
||||||
|
cr.impl = nil
|
||||||
|
|
||||||
proc cairo_surface_reference*(surface: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
proc cairo_surface_reference*(surface: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -246,13 +276,22 @@ proc surfaceReference*(surface: Surface): Surface =
|
||||||
discard cairo_surface_reference(surface.impl)
|
discard cairo_surface_reference(surface.impl)
|
||||||
return surface
|
return surface
|
||||||
|
|
||||||
|
proc cairo_surface_set_user_data*(surface: ptr Surface00;
|
||||||
|
key: ptr UserDataKey; userData: pointer; destroy: DestroyFunc00): Status {.importc, libcairo.}
|
||||||
|
#
|
||||||
|
proc setUserData*(surface: Surface; key: ptr UserDataKey; userData: pointer; destroy: DestroyFunc00): Status =
|
||||||
|
cairo_surface_set_user_data(surface.impl, key, userData, destroy)
|
||||||
|
|
||||||
proc cairo_create*(target: ptr Surface00): ptr Context00 {.importc, libcairo.}
|
proc cairo_create*(target: ptr Surface00): ptr Context00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc newContext*(target: Surface): Context =
|
proc newContext*(target: Surface): Context =
|
||||||
new(result, destroy)
|
new(result, destroy)
|
||||||
GC_ref(target)
|
GC_ref(target)
|
||||||
result.impl = cairo_create(target.impl)
|
result.impl = cairo_create(target.impl)
|
||||||
discard cairo_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
discard cairo_surface_set_user_data(target.impl, NUDK, cast[pointer](target), gcuref)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc cairo_reference*(cr: ptr Context00): ptr Context00 {.importc, libcairo.}
|
proc cairo_reference*(cr: ptr Context00): ptr Context00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -1002,6 +1041,7 @@ proc getFontFace*(cr: Context): FontFace =
|
||||||
#assert false # may this happen?
|
#assert false # may this happen?
|
||||||
new(result, fontFaceDestroy)
|
new(result, fontFaceDestroy)
|
||||||
result.impl = h
|
result.impl = h
|
||||||
|
# TODO check
|
||||||
discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
discard cairo_font_face_reference(result.impl)
|
discard cairo_font_face_reference(result.impl)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1234,7 +1274,7 @@ proc cairo_toy_font_face_create*(family: cstring; slant: FontSlant;
|
||||||
proc toyFontFaceCreate*(family: string; slant: FontSlant; weight: FontWeight): FontFace =
|
proc toyFontFaceCreate*(family: string; slant: FontSlant; weight: FontWeight): FontFace =
|
||||||
new(result, fontFaceDestroy)
|
new(result, fontFaceDestroy)
|
||||||
result.impl = cairo_toy_font_face_create(family, slant, weight)
|
result.impl = cairo_toy_font_face_create(family, slant, weight)
|
||||||
discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
# returns: The family name. This string is owned by the font face and remains valid as long as the font face is alive (referenced).
|
# returns: The family name. This string is owned by the font face and remains valid as long as the font face is alive (referenced).
|
||||||
proc cairo_toy_font_face_get_family*(fontFace: ptr Font_face00): cstring {.importc, libcairo.}
|
proc cairo_toy_font_face_get_family*(fontFace: ptr Font_face00): cstring {.importc, libcairo.}
|
||||||
|
|
@ -1258,7 +1298,7 @@ proc userFontFaceCreate*(): FontFace =
|
||||||
new(result, fontFaceDestroy)
|
new(result, fontFaceDestroy)
|
||||||
result.impl = cairo_user_font_face_create()
|
result.impl = cairo_user_font_face_create()
|
||||||
# there is no cairo_user_font_face_set_user_data()
|
# there is no cairo_user_font_face_set_user_data()
|
||||||
discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
# discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
type
|
type
|
||||||
UserScaledFontInitFunc00* = proc (scaledFont: ptr ScaledFont00;
|
UserScaledFontInitFunc00* = proc (scaledFont: ptr ScaledFont00;
|
||||||
|
|
@ -1434,19 +1474,17 @@ proc getMatrix*(cr: Context; matrix: var Matrix) =
|
||||||
|
|
||||||
proc cairo_surface_destroy*(surface: ptr Surface00) {.importc, libcairo.}
|
proc cairo_surface_destroy*(surface: ptr Surface00) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc surfaceDestroy(surface: Surface) =
|
proc destroy*(surface: Surface) =
|
||||||
cairo_surface_destroy(surface.impl)
|
if surface != nil and surface.impl != nil:
|
||||||
|
cairo_surface_destroy(surface.impl)
|
||||||
|
surface.impl = nil
|
||||||
|
|
||||||
proc cairo_surface_get_user_data*(surface: ptr Surface00; key: ptr UserDataKey): pointer {.importc, libcairo.}
|
proc cairo_surface_get_user_data*(surface: ptr Surface00; key: ptr UserDataKey): pointer {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc getUserData*(surface: Surface; key: ptr UserDataKey): pointer =
|
proc getUserData*(surface: Surface; key: ptr UserDataKey): pointer =
|
||||||
cairo_surface_get_user_data(surface.impl, key)
|
cairo_surface_get_user_data(surface.impl, key)
|
||||||
|
|
||||||
proc cairo_surface_set_user_data*(surface: ptr Surface00;
|
|
||||||
key: ptr UserDataKey; userData: pointer; destroy: DestroyFunc00): Status {.importc, libcairo.}
|
|
||||||
#
|
|
||||||
proc setUserData*(surface: Surface; key: ptr UserDataKey; userData: pointer; destroy: DestroyFunc00): Status =
|
|
||||||
cairo_surface_set_user_data(surface.impl, key, userData, destroy)
|
|
||||||
|
|
||||||
proc cairo_get_target*(cr: ptr Context00): ptr Surface00 {.importc, libcairo.}
|
proc cairo_get_target*(cr: ptr Context00): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -1456,7 +1494,7 @@ proc getTarget*(cr: Context): Surface =
|
||||||
let d = cairo_surface_get_user_data(h, NUDK)
|
let d = cairo_surface_get_user_data(h, NUDK)
|
||||||
if d.isNil:
|
if d.isNil:
|
||||||
assert false # may this happen?
|
assert false # may this happen?
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = h
|
result.impl = h
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
discard cairo_surface_reference(result.impl)
|
discard cairo_surface_reference(result.impl)
|
||||||
|
|
@ -1473,10 +1511,10 @@ proc getGroupTarget*(cr: Context): Surface =
|
||||||
let d = cairo_surface_get_user_data(h, NUDK)
|
let d = cairo_surface_get_user_data(h, NUDK)
|
||||||
if d.isNil:
|
if d.isNil:
|
||||||
#assert false # may this happen?
|
#assert false # may this happen?
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = h
|
result.impl = h
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
discard cairo_surface_reference(result.impl)
|
### discard cairo_surface_reference(result.impl)
|
||||||
else:
|
else:
|
||||||
result = cast[Surface](d)
|
result = cast[Surface](d)
|
||||||
assert(result.impl == h)
|
assert(result.impl == h)
|
||||||
|
|
@ -1586,17 +1624,17 @@ proc cairo_surface_create_similar*(other: ptr Surface00; content: Content; width
|
||||||
ptr Surface00 {.importc, libcairo.}
|
ptr Surface00 {.importc, libcairo.}
|
||||||
|
|
||||||
proc createSimilar*(other: Surface; content: Content; width, height: int): Surface =
|
proc createSimilar*(other: Surface; content: Content; width, height: int): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_surface_create_similar(other.impl, content, width.cint, height.cint)
|
result.impl = cairo_surface_create_similar(other.impl, content, width.cint, height.cint)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_surface_create_similar_image*(other: ptr Surface00; format: Format; width, height: cint):
|
proc cairo_surface_create_similar_image*(other: ptr Surface00; format: Format; width, height: cint):
|
||||||
ptr Surface00 {.importc, libcairo.}
|
ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc createSimilarImage*(other: Surface; format: Format; width, height: int): Surface =
|
proc createSimilarImage*(other: Surface; format: Format; width, height: int): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_surface_create_similar_image(other.impl, format, width.cint, height.cint)
|
result.impl = cairo_surface_create_similar_image(other.impl, format, width.cint, height.cint)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_surface_unmap_image*(surface: ptr Surface00; image: ptr Surface00) {.importc, libcairo.}
|
proc cairo_surface_unmap_image*(surface: ptr Surface00; image: ptr Surface00) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -1606,7 +1644,7 @@ proc unmapImage*(surface: Surface; image: Surface) =
|
||||||
proc cairo_surface_map_to_image*(surface: ptr Surface00; extents: RectangleInt): ptr Surface00 {.importc, libcairo.}
|
proc cairo_surface_map_to_image*(surface: ptr Surface00; extents: RectangleInt): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc mapToImage*(surface: Surface; extents: RectangleInt): Surface =
|
proc mapToImage*(surface: Surface; extents: RectangleInt): Surface =
|
||||||
#new(result, surfaceDestroy) # no idea currently
|
#new(result, destroy) # no idea currently
|
||||||
new(result)
|
new(result)
|
||||||
result.impl = cairo_surface_map_to_image(surface.impl, extents)
|
result.impl = cairo_surface_map_to_image(surface.impl, extents)
|
||||||
|
|
||||||
|
|
@ -1614,9 +1652,9 @@ proc cairo_surface_create_for_rectangle*(target: ptr Surface00; x, y, width, hei
|
||||||
ptr Surface00 {.importc, libcairo.}
|
ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc surfaceCreateForRectangle*(target: Surface; x, y, width, height: float): Surface =
|
proc surfaceCreateForRectangle*(target: Surface; x, y, width, height: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_surface_create_for_rectangle(target.impl, x.cdouble, y.cdouble, width.cdouble, height.cdouble)
|
result.impl = cairo_surface_create_for_rectangle(target.impl, x.cdouble, y.cdouble, width.cdouble, height.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
type
|
type
|
||||||
SurfaceObserverMode* {.size: sizeof(cint), pure.} = enum
|
SurfaceObserverMode* {.size: sizeof(cint), pure.} = enum
|
||||||
|
|
@ -1627,9 +1665,9 @@ proc cairo_surface_create_observer*(target: ptr Surface00;
|
||||||
mode: SurfaceObserverMode): ptr Surface00 {.importc, libcairo.}
|
mode: SurfaceObserverMode): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc createObserver*(target: Surface; mode: SurfaceObserverMode): Surface =
|
proc createObserver*(target: Surface; mode: SurfaceObserverMode): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_surface_create_observer(target.impl, mode)
|
result.impl = cairo_surface_create_observer(target.impl, mode)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
type
|
type
|
||||||
SurfaceObserverCallback00* = proc (observer: ptr Surface00;
|
SurfaceObserverCallback00* = proc (observer: ptr Surface00;
|
||||||
|
|
@ -1841,9 +1879,9 @@ proc hasShowTextGlyphs*(surface: Surface): bool =
|
||||||
proc cairo_image_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
|
proc cairo_image_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc imageSurfaceCreate*(format: Format; width, height: int): Surface =
|
proc imageSurfaceCreate*(format: Format; width, height: int): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_image_surface_create(format, width.cint, height.cint)
|
result.impl = cairo_image_surface_create(format, width.cint, height.cint)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_format_stride_for_width*(format: Format; width: cint): cint {.importc, libcairo.}
|
proc cairo_format_stride_for_width*(format: Format; width: cint): cint {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -1880,24 +1918,24 @@ when CAIRO_HAS_PNG_FUNCTIONS:
|
||||||
proc cairo_image_surface_create_from_png*(filename: cstring): ptr Surface00 {.importc, libcairo.}
|
proc cairo_image_surface_create_from_png*(filename: cstring): ptr Surface00 {.importc, libcairo.}
|
||||||
|
|
||||||
proc imageSurfaceCreateFromPng*(filename: string): Surface =
|
proc imageSurfaceCreateFromPng*(filename: string): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_image_surface_create_from_png(filename)
|
result.impl = cairo_image_surface_create_from_png(filename)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_image_surface_create_from_png_stream*(read_func: Read_func00;
|
proc cairo_image_surface_create_from_png_stream*(read_func: Read_func00;
|
||||||
closure: pointer): ptr Surface00 {.importc, libcairo.}
|
closure: pointer): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc imageSurfaceCreateFromPngStream*(readFunc: ReadFunc00; closure: pointer): Surface =
|
proc imageSurfaceCreateFromPngStream*(readFunc: ReadFunc00; closure: pointer): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_image_surface_create_from_png_stream(readFunc, closure)
|
result.impl = cairo_image_surface_create_from_png_stream(readFunc, closure)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_recording_surface_create*(content: Content; extents: Rectangle00): ptr Surface00 {.importc, libcairo.}
|
proc cairo_recording_surface_create*(content: Content; extents: Rectangle00): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc recordingSurfaceCreate*(content: Content; extents: Rectangle00): Surface =
|
proc recordingSurfaceCreate*(content: Content; extents: Rectangle00): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_recording_surface_create(content, extents)
|
result.impl = cairo_recording_surface_create(content, extents)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_recording_surface_ink_extents*(surface: ptr Surface00; x0, y0, width, height: var cdouble) {.importc, libcairo.}
|
proc cairo_recording_surface_ink_extents*(surface: ptr Surface00; x0, y0, width, height: var cdouble) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -1943,7 +1981,7 @@ proc cairo_pattern_create_raster_source*(userData: pointer; content: Content; wi
|
||||||
proc patternCreateRasterSource*(userData: pointer; content: Content; width, height: int): Pattern =
|
proc patternCreateRasterSource*(userData: pointer; content: Content; width, height: int): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_raster_source(userData, content, width.cint, height.cint)
|
result.impl = cairo_pattern_create_raster_source(userData, content, width.cint, height.cint)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_raster_source_pattern_set_callback_data*(pattern: ptr Pattern00; data: pointer) {.importc,libcairo.}
|
proc cairo_raster_source_pattern_set_callback_data*(pattern: ptr Pattern00; data: pointer) {.importc,libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2002,42 +2040,42 @@ proc cairo_pattern_create_rgb*(red, green, blue: cdouble): ptr Pattern00 {.impor
|
||||||
proc patternCreateRgb*(red, green, blue: float): Pattern =
|
proc patternCreateRgb*(red, green, blue: float): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_rgb(red.cdouble, green.cdouble, blue.cdouble)
|
result.impl = cairo_pattern_create_rgb(red.cdouble, green.cdouble, blue.cdouble)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_create_rgba*(red, green, blue, alpha: cdouble): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_create_rgba*(red, green, blue, alpha: cdouble): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc patternCreateRgba*(red, green, blue, alpha: float): Pattern =
|
proc patternCreateRgba*(red, green, blue, alpha: float): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_rgba(red.cdouble, green.cdouble, blue.cdouble, alpha.cdouble)
|
result.impl = cairo_pattern_create_rgba(red.cdouble, green.cdouble, blue.cdouble, alpha.cdouble)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_create_for_surface*(surface: ptr Surface00): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_create_for_surface*(surface: ptr Surface00): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc patternCreateForSurface*(surface: Surface): Pattern =
|
proc patternCreateForSurface*(surface: Surface): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_for_surface(surface.impl)
|
result.impl = cairo_pattern_create_for_surface(surface.impl)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_create_linear*(x0, y0, x1, y1: cdouble): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_create_linear*(x0, y0, x1, y1: cdouble): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc patternCreateLinear*(x0, y0, x1, y1: float): Pattern =
|
proc patternCreateLinear*(x0, y0, x1, y1: float): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_linear(x0.cdouble, y0.cdouble, x1.cdouble, y1.cdouble)
|
result.impl = cairo_pattern_create_linear(x0.cdouble, y0.cdouble, x1.cdouble, y1.cdouble)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: cdouble): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: cdouble): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc patternCreateRadial*(cx0, cy0, radius0, cx1, cy1, radius1: float): Pattern =
|
proc patternCreateRadial*(cx0, cy0, radius0, cx1, cy1, radius1: float): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_radial(cx0.cdouble, cy0.cdouble, radius0.cdouble, cx1.cdouble, cy1.cdouble, radius1.cdouble)
|
result.impl = cairo_pattern_create_radial(cx0.cdouble, cy0.cdouble, radius0.cdouble, cx1.cdouble, cy1.cdouble, radius1.cdouble)
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_create_mesh*(): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_create_mesh*(): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc patternCreateMesh*(): Pattern =
|
proc patternCreateMesh*(): Pattern =
|
||||||
new(result, patternDestroy)
|
new(result, patternDestroy)
|
||||||
result.impl = cairo_pattern_create_mesh()
|
result.impl = cairo_pattern_create_mesh()
|
||||||
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pattern_reference*(pattern: ptr Pattern00): ptr Pattern00 {.importc, libcairo.}
|
proc cairo_pattern_reference*(pattern: ptr Pattern00): ptr Pattern00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2166,6 +2204,7 @@ proc getRgba*(pattern: Pattern; red, green, blue, alpha: var float): Status =
|
||||||
blue = blue0.float
|
blue = blue0.float
|
||||||
alpha = alpha0.float
|
alpha = alpha0.float
|
||||||
|
|
||||||
|
# TODO this seems to be wrong
|
||||||
proc cairo_pattern_get_surface*(pattern: ptr Pattern00; surface: var ptr Surface00): Status {.importc, libcairo.}
|
proc cairo_pattern_get_surface*(pattern: ptr Pattern00; surface: var ptr Surface00): Status {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc getSurface*(pattern: Pattern; surface: var Surface): Status =
|
proc getSurface*(pattern: Pattern; surface: var Surface): Status =
|
||||||
|
|
@ -2175,7 +2214,7 @@ proc getSurface*(pattern: Pattern; surface: var Surface): Status =
|
||||||
let d = cairo_surface_get_user_data(h, NUDK)
|
let d = cairo_surface_get_user_data(h, NUDK)
|
||||||
if d.isNil:
|
if d.isNil:
|
||||||
assert false # may this happen?
|
assert false # may this happen?
|
||||||
new(surface, surfaceDestroy)
|
new(surface, destroy)
|
||||||
surface.impl = h
|
surface.impl = h
|
||||||
discard cairo_surface_set_user_data(surface.impl, NUDK, cast[pointer](surface), gcuref)
|
discard cairo_surface_set_user_data(surface.impl, NUDK, cast[pointer](surface), gcuref)
|
||||||
discard cairo_surface_reference(surface.impl)
|
discard cairo_surface_reference(surface.impl)
|
||||||
|
|
@ -2324,21 +2363,21 @@ type
|
||||||
|
|
||||||
proc cairo_region_destroy*(region: ptr Region00) {.importc, libcairo.}
|
proc cairo_region_destroy*(region: ptr Region00) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc regionDestroy*(region: Region) =
|
proc destroy*(region: Region) =
|
||||||
cairo_region_destroy(region.impl)
|
cairo_region_destroy(region.impl)
|
||||||
|
|
||||||
# there is no cairo_region_set_user_data()
|
# there is no cairo_region_set_user_data()
|
||||||
proc cairo_region_create*(): ptr Region00 {.importc, libcairo.}
|
proc cairo_region_create*(): ptr Region00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc regionCreate*(): Region =
|
proc regionCreate*(): Region =
|
||||||
new(result, regionDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_region_create()
|
result.impl = cairo_region_create()
|
||||||
#discard cairo_region_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_region_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_region_create_rectangle*(rectangle: RectangleInt): ptr Region00 {.importc, libcairo.}
|
proc cairo_region_create_rectangle*(rectangle: RectangleInt): ptr Region00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc regionCreateRectangle*(rectangle: RectangleInt): Region =
|
proc regionCreateRectangle*(rectangle: RectangleInt): Region =
|
||||||
new(result, regionDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_region_create_rectangle(rectangle)
|
result.impl = cairo_region_create_rectangle(rectangle)
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
@ -2348,7 +2387,7 @@ proc cairo_region_create_rectangles*(rects: RectangleInt; count: cint): ptr Regi
|
||||||
proc cairo_region_copy*(original: ptr Region00): ptr Region00 {.importc, libcairo.}
|
proc cairo_region_copy*(original: ptr Region00): ptr Region00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc regionCopy*(original: Region): Region =
|
proc regionCopy*(original: Region): Region =
|
||||||
new(result, regionDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_region_copy(original.impl)
|
result.impl = cairo_region_copy(original.impl)
|
||||||
|
|
||||||
proc cairo_region_reference*(region: ptr Region00): ptr Region00 {.importc, libcairo.}
|
proc cairo_region_reference*(region: ptr Region00): ptr Region00 {.importc, libcairo.}
|
||||||
|
|
@ -2456,17 +2495,17 @@ when CAIRO_HAS_PDF_SURFACE:
|
||||||
importc, libcairo.}
|
importc, libcairo.}
|
||||||
#pong
|
#pong
|
||||||
proc pdfSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
proc pdfSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_pdf_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_pdf_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pdf_surface_create_for_stream*(writeFunc: WriteFunc00;
|
proc cairo_pdf_surface_create_for_stream*(writeFunc: WriteFunc00;
|
||||||
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc pdfSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
proc pdfSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_pdf_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_pdf_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_pdf_surface_restrict_to_version*(surface: ptr Surface00;
|
proc cairo_pdf_surface_restrict_to_version*(surface: ptr Surface00;
|
||||||
version: PdfVersion) {.importc, libcairo.}
|
version: PdfVersion) {.importc, libcairo.}
|
||||||
|
|
@ -2537,17 +2576,17 @@ when CAIRO_HAS_PS_SURFACE:
|
||||||
importc, libcairo.}
|
importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc psSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
proc psSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_ps_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_ps_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_ps_surface_create_for_stream*(writeFunc: WriteFunc00; closure: pointer;
|
proc cairo_ps_surface_create_for_stream*(writeFunc: WriteFunc00; closure: pointer;
|
||||||
widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc psSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
proc psSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_ps_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_ps_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_ps_surface_restrict_to_level*(surface: ptr Surface00; level: PsLevel) {.importc, libcairo.}
|
proc cairo_ps_surface_restrict_to_level*(surface: ptr Surface00; level: PsLevel) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2604,17 +2643,17 @@ when CAIRO_HAS_SVG_SURFACE:
|
||||||
importc, libcairo.}
|
importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc svgSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
proc svgSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_svg_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_svg_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_svg_surface_create_for_stream*(write_func: Write_func00;
|
proc cairo_svg_surface_create_for_stream*(write_func: Write_func00;
|
||||||
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc svgSurfaceCreateForstream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
proc svgSurfaceCreateForstream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_svg_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
result.impl = cairo_svg_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_svg_surface_restrict_to_version*(surface: ptr Surface00; version: SvgVersion) {.importc, libcairo.}
|
proc cairo_svg_surface_restrict_to_version*(surface: ptr Surface00; version: SvgVersion) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2638,22 +2677,22 @@ when CAIRO_HAS_XML_SURFACE:
|
||||||
proc xml_create*(filename: string): Device =
|
proc xml_create*(filename: string): Device =
|
||||||
new(result, deviceDestroy)
|
new(result, deviceDestroy)
|
||||||
result.impl = cairo_xml_create(filename)
|
result.impl = cairo_xml_create(filename)
|
||||||
discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_xml_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
|
proc cairo_xml_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc xmlCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
|
proc xmlCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
|
||||||
new(result, deviceDestroy)
|
new(result, deviceDestroy)
|
||||||
result.impl = cairo_xml_create_for_stream(writeFunc, closure)
|
result.impl = cairo_xml_create_for_stream(writeFunc, closure)
|
||||||
discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_xml_surface_create*(xml: ptr Device00; content: Content; width, height: cdouble): ptr Surface00 {.
|
proc cairo_xml_surface_create*(xml: ptr Device00; content: Content; width, height: cdouble): ptr Surface00 {.
|
||||||
importc, libcairo.}
|
importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc xmlSurfaceCreate*(xml: Device; content: Content; width, height: float): Surface =
|
proc xmlSurfaceCreate*(xml: Device; content: Content; width, height: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_xml_surface_create(xml.impl, content, width.cdouble, height.cdouble)
|
result.impl = cairo_xml_surface_create(xml.impl, content, width.cdouble, height.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_xml_for_recording_surface*(xml: ptr Device00; surface: ptr Surface00): Status {.importc, libcairo.}
|
proc cairo_xml_for_recording_surface*(xml: ptr Device00; surface: ptr Surface00): Status {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2670,14 +2709,14 @@ when CAIRO_HAS_SCRIPT_SURFACE:
|
||||||
proc scriptCreate*(filename: string): Device =
|
proc scriptCreate*(filename: string): Device =
|
||||||
new(result, deviceDestroy)
|
new(result, deviceDestroy)
|
||||||
result.impl = cairo_script_create(filename)
|
result.impl = cairo_script_create(filename)
|
||||||
discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_script_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
|
proc cairo_script_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc scriptCcreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
|
proc scriptCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
|
||||||
new(result, deviceDestroy)
|
new(result, deviceDestroy)
|
||||||
result.impl = cairo_script_create_for_stream(writeFunc, closure)
|
result.impl = cairo_script_create_for_stream(writeFunc, closure)
|
||||||
discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_script_write_comment*(script: ptr Device00; comment: cstring; len: cint) {.importc, libcairo.}
|
proc cairo_script_write_comment*(script: ptr Device00; comment: cstring; len: cint) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
@ -2698,17 +2737,17 @@ when CAIRO_HAS_SCRIPT_SURFACE:
|
||||||
importc, libcairo.}
|
importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc scriptSurfaceCreate*(script: Device; content: Content; width, height: float): Surface =
|
proc scriptSurfaceCreate*(script: Device; content: Content; width, height: float): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_script_surface_create(script.impl, content, width.cdouble, height.cdouble)
|
result.impl = cairo_script_surface_create(script.impl, content, width.cdouble, height.cdouble)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_script_surface_create_for_target*(script: ptr Device00;
|
proc cairo_script_surface_create_for_target*(script: ptr Device00;
|
||||||
target: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
target: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc scriptSurfaceCreateForTarget*(script: Device; target: Surface): Surface =
|
proc scriptSurfaceCreateForTarget*(script: Device; target: Surface): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_script_surface_create_for_target(script.impl, target.impl)
|
result.impl = cairo_script_surface_create_for_target(script.impl, target.impl)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_script_from_recording_surface*(script: ptr Device00;
|
proc cairo_script_from_recording_surface*(script: ptr Device00;
|
||||||
recordingSurface: ptr Surface00): Status {.importc, libcairo.}
|
recordingSurface: ptr Surface00): Status {.importc, libcairo.}
|
||||||
|
|
@ -2720,9 +2759,9 @@ when CAIRO_HAS_SKIA_SURFACE:
|
||||||
proc cairo_skia_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
|
proc cairo_skia_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc skiaSurfaceCreate*(format: Format; width, height: int): Surface =
|
proc skiaSurfaceCreate*(format: Format; width, height: int): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_skia_surface_create(format, width.cint, height.cint)
|
result.impl = cairo_skia_surface_create(format, width.cint, height.cint)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
#TODO
|
#TODO
|
||||||
proc cairo_skia_surface_create_for_data*(data: ptr cuchar; format: Format; width, height, stride: cint):
|
proc cairo_skia_surface_create_for_data*(data: ptr cuchar; format: Format; width, height, stride: cint):
|
||||||
|
|
@ -2762,9 +2801,9 @@ when CAIRO_HAS_TEE_SURFACE:
|
||||||
proc cairo_tee_surface_create*(master: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
proc cairo_tee_surface_create*(master: ptr Surface00): ptr Surface00 {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
proc teeSurfaceCreate*(master: Surface): Surface =
|
proc teeSurfaceCreate*(master: Surface): Surface =
|
||||||
new(result, surfaceDestroy)
|
new(result, destroy)
|
||||||
result.impl = cairo_tee_surface_create(master.impl)
|
result.impl = cairo_tee_surface_create(master.impl)
|
||||||
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
|
||||||
|
|
||||||
proc cairo_tee_surface_add*(surface: ptr Surface00; target: ptr Surface00) {.importc, libcairo.}
|
proc cairo_tee_surface_add*(surface: ptr Surface00; target: ptr Surface00) {.importc, libcairo.}
|
||||||
#
|
#
|
||||||
|
|
|
||||||
2785
gintro/oldcairo.nim
Normal file
2785
gintro/oldcairo.nim
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
# High level gobject-introspection based GTK3 bindings for the Nim programming language
|
# High level gobject-introspection based GTK3 bindings for the Nim programming language
|
||||||
# v 0.4.17 2019-APR-16
|
# v 0.4.18 2019-APR-27
|
||||||
# (c) S. Salewski 2018
|
# (c) S. Salewski 2018
|
||||||
|
|
||||||
# https://wiki.gnome.org/Projects/GObjectIntrospection
|
# https://wiki.gnome.org/Projects/GObjectIntrospection
|
||||||
|
|
@ -106,6 +106,7 @@ proc renumber(s: var string; i: int) =
|
||||||
|
|
||||||
var defaultParameters = newTable[string, string]()
|
var defaultParameters = newTable[string, string]()
|
||||||
var fixedProcNames = newTable[string, string]()
|
var fixedProcNames = newTable[string, string]()
|
||||||
|
var fixedDestroyNames = newTable[string, string]()
|
||||||
var mangledNames = newTable[string, string]()
|
var mangledNames = newTable[string, string]()
|
||||||
var gdkKeys = newTable[string, seq[string]]()
|
var gdkKeys = newTable[string, seq[string]]()
|
||||||
var allSyms: HashSet[string]
|
var allSyms: HashSet[string]
|
||||||
|
|
@ -124,6 +125,11 @@ var delayedMethods: seq[(GIBaseInfo, GIFunctionInfo)]
|
||||||
var classList: seq[GIBaseInfo]
|
var classList: seq[GIBaseInfo]
|
||||||
var ct: CountTable[string]
|
var ct: CountTable[string]
|
||||||
|
|
||||||
|
fixedDestroyNames.add("gdk_window_create_similar_surface", "cairo.destroy")
|
||||||
|
fixedDestroyNames.add("gdk_window_create_similar_image_surface", "cairo.destroy")
|
||||||
|
fixedDestroyNames.add("gdk_cairo_region_create_from_surface", "cairo.destroy")
|
||||||
|
fixedDestroyNames.add("gdk_cairo_surface_create_from_pixbuf", "cairo.destroy")
|
||||||
|
|
||||||
fixedProcNames.add("gtk_button_new_with_label", "newButton")
|
fixedProcNames.add("gtk_button_new_with_label", "newButton")
|
||||||
fixedProcNames.add("pango_font_description_from_string", "newFontDescription")
|
fixedProcNames.add("pango_font_description_from_string", "newFontDescription")
|
||||||
fixedProcNames.add("pango_language_from_string", "languageFromString")
|
fixedProcNames.add("pango_language_from_string", "languageFromString")
|
||||||
|
|
@ -722,8 +728,12 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
|
||||||
freeMe = gStructInfoFindMethod(info, "unref")
|
freeMe = gStructInfoFindMethod(info, "unref")
|
||||||
var freeMeName: string
|
var freeMeName: string
|
||||||
if freeMe == nil:
|
if freeMe == nil:
|
||||||
echo "Caution: No free/unref found for ", ' ', " (", sym, ')' # Mostly missing cairo functions...
|
if fixedDestroyNames.contains(sym):
|
||||||
|
freeMeName = fixedDestroyNames[sym]
|
||||||
|
else:
|
||||||
|
echo "Caution: No free/unref found for ", ' ', " (", sym, ')' # Mostly missing cairo functions...
|
||||||
else:
|
else:
|
||||||
|
assert not fixedDestroyNames.contains(sym)
|
||||||
freeMeName = $gBaseInfoGetName(freeMe)
|
freeMeName = $gBaseInfoGetName(freeMe)
|
||||||
if sym == "g_closure_new_simple" or sym == "g_closure_new_object": freeMeName = "unref" # TODO GI bug?
|
if sym == "g_closure_new_simple" or sym == "g_closure_new_object": freeMeName = "unref" # TODO GI bug?
|
||||||
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
|
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
|
||||||
|
|
@ -797,8 +807,16 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
|
||||||
elif h.endsWith("unref"):
|
elif h.endsWith("unref"):
|
||||||
freeMeName = "unref"
|
freeMeName = "unref"
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if fixedDestroyNames.contains(sym):
|
||||||
|
freeMeName = fixedDestroyNames[sym]
|
||||||
|
#else:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if freeMeName == "":
|
if freeMeName == "":
|
||||||
# assert false # TODO we have to fix this case manually
|
# assert false # TODO we have to fix this case manually
|
||||||
|
|
||||||
echo "Caution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')'
|
echo "Caution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')'
|
||||||
methodBuffer.writeLine(" new(result)")
|
methodBuffer.writeLine(" new(result)")
|
||||||
else:
|
else:
|
||||||
|
|
@ -847,8 +865,17 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
|
||||||
freeMe = gStructInfoFindMethod(info, "free")
|
freeMe = gStructInfoFindMethod(info, "free")
|
||||||
if freeMe.isNil:
|
if freeMe.isNil:
|
||||||
freeMe = gStructInfoFindMethod(info, "unref")
|
freeMe = gStructInfoFindMethod(info, "unref")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if freeMe == nil:
|
if freeMe == nil:
|
||||||
echo "Caution: No free/unref found for ", ' ', " (", sym, ')' # Mostly missing cairo functions...
|
if fixedDestroyNames.contains(sym):
|
||||||
|
freeMeName = fixedDestroyNames[sym]
|
||||||
|
else:
|
||||||
|
|
||||||
|
|
||||||
|
echo "Caution: No free/unref found for ", ' ', " (", sym, ')' # Mostly missing cairo functions...
|
||||||
else:
|
else:
|
||||||
freeMeName = $gBaseInfoGetName(freeMe)
|
freeMeName = $gBaseInfoGetName(freeMe)
|
||||||
let h2 = mangleName(gBaseInfoGetName(arg))
|
let h2 = mangleName(gBaseInfoGetName(arg))
|
||||||
|
|
@ -1907,6 +1934,10 @@ proc main(namespace: string) =
|
||||||
output.writeLine("type\n ColorArray* = pointer")
|
output.writeLine("type\n ColorArray* = pointer")
|
||||||
output.writeLine("type\n Point00Array* = pointer")
|
output.writeLine("type\n Point00Array* = pointer")
|
||||||
elif namespace == "Gtk":
|
elif namespace == "Gtk":
|
||||||
|
output.writeLine("# https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-draw")
|
||||||
|
output.writeLine("# TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.")
|
||||||
|
output.writeLine("const\n SignalEventStopPropagation* = true")
|
||||||
|
output.writeLine("const\n SignalEventContinuePropagation* = false")
|
||||||
output.writeLine("type\n TargetEntry00Array* = pointer")
|
output.writeLine("type\n TargetEntry00Array* = pointer")
|
||||||
output.writeLine("type\n AccelGroupEntry00Array* = pointer")
|
output.writeLine("type\n AccelGroupEntry00Array* = pointer")
|
||||||
output.writeLine("type\n BindingArg00Array* = pointer")
|
output.writeLine("type\n BindingArg00Array* = pointer")
|
||||||
|
|
@ -2115,10 +2146,21 @@ proc main(namespace: string) =
|
||||||
if i == "": continue
|
if i == "": continue
|
||||||
output.write("""
|
output.write("""
|
||||||
proc get$1*(builder: Builder; name: string): $1 =
|
proc get$1*(builder: Builder; name: string): $1 =
|
||||||
new result
|
|
||||||
let gt = g_type_from_name("Gtk$1")
|
let gt = g_type_from_name("Gtk$1")
|
||||||
assert(gt != 0)
|
assert(gt != 0)
|
||||||
result.impl = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
|
let gobj = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
|
||||||
|
if g_object_get_qdata(gobj, Quark) != nil:
|
||||||
|
result = cast[type(result)](g_object_get_qdata(gobj, Quark))
|
||||||
|
assert(result.impl == gobj)
|
||||||
|
else:
|
||||||
|
new(result, finalizeGObject)
|
||||||
|
result.impl = gobj
|
||||||
|
#GC_ref(result) # we should not need this for builder, as returned objects are not floating
|
||||||
|
#discard g_object_ref_sink(result.impl)
|
||||||
|
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
|
||||||
|
#g_object_unref(result.impl)
|
||||||
|
assert(g_object_get_qdata(result.impl, Quark) == nil)
|
||||||
|
g_object_set_qdata(result.impl, Quark, addr(result[]))
|
||||||
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
|
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
|
||||||
|
|
||||||
""" % [i])
|
""" % [i])
|
||||||
|
|
@ -2176,4 +2218,4 @@ o.close()
|
||||||
supmod.close
|
supmod.close
|
||||||
|
|
||||||
#for i in callerAllocCollector: echo i
|
#for i in callerAllocCollector: echo i
|
||||||
# 1743 lines
|
# 2233 lines
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue