Take a step back: separate Cairo's GraphicsContext (cairo_t) and Smalltalk/X's graphics context
...into two separate classes for cleaner responsibilities. Also, API of Smalltalk/X graphics
contexts does not play well with Cairo's save/restore semantics.
"{ Package: 'stx:goodies/libcairo' }"
"{ NameSpace: Cairo }"
CObject subclass:#GraphicsContext
instanceVariableNames:'surface'
classVariableNames:''
poolDictionaries:''
category:'Cairo-Objects'
!
!GraphicsContext class methodsFor:'instance creation'!
onSurface: surface
| instance |
self
assert: (surface isKindOf: Cairo::Surface)
message: 'surface is not valid Cairo surface'.
instance := CPrimitives cairo_create: surface.
^ instance initializeWithSurface: surface
"Created: / 28-12-2014 / 23:45:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 13-02-2016 / 16:07:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'accessing'!
referenceCount
"Return value or reference counter"
^ CPrimitives cairo_get_reference_count: self.
"Modified: / 13-02-2016 / 16:13:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
surface
^ surface
! !
!GraphicsContext methodsFor:'cairo api - paths'!
arcNegativeX:x y:y radius:r from:startAngle to:stopAngle
^ CPrimitives
cairo_arc_negative:self
_:x asDouble
_:y asDouble
_:r asDouble
_:startAngle asDouble
_:stopAngle asDouble
"Created: / 07-01-2015 / 02:35:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
arcX:x y:y radius:r from:startAngle to:stopAngle
^ CPrimitives
cairo_arc:self
_:x asDouble
_:y asDouble
_:r asDouble
_:startAngle asDouble
_:stopAngle asDouble
"Created: / 17-06-2012 / 21:50:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:00:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
closePath
^ CPrimitives cairo_close_path:self.
"Created: / 01-01-2015 / 22:42:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lineCap: lc
^ CPrimitives cairo_set_line_cap: self _: lc
"Created: / 17-06-2012 / 22:09:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 13-02-2016 / 16:42:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lineToX:x y:y
^ CPrimitives
cairo_line_to:self
_:x asDouble
_:y asDouble
"Created: / 17-06-2012 / 22:15:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:00:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lineWidth: aNumber
CPrimitives cairo_set_line_width: self _:aNumber asFloat
.
"Created: / 13-02-2016 / 16:45:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
moveToX:x y:y
^ CPrimitives
cairo_move_to:self
_:x asDouble
_:y asDouble
"Created: / 23-04-2009 / 17:21:00 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 28-12-2014 / 22:00:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
rectangleX:x y:y width:w height:h
| rx ry rw rh |
rx := x.
ry := y.
rw := w.
rh := h.
rw < 0 ifTrue:[
rx := rx + rw.
rw := rw abs.
].
rh < 0 ifTrue:[
ry := ry + rh.
rh := rh abs.
].
^ CPrimitives
cairo_rectangle:self
_:rx asDouble
_:ry asDouble
_:rw asDouble
_:rh asDouble
"Created: / 10-07-2008 / 09:41:50 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 02-01-2015 / 01:21:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - patterns'!
setSourceSurface: aSurface
^ self setSourceSurface: aSurface x: 0.0 y: 0.0
"Created: / 24-12-2014 / 23:12:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setSourceSurface:aSyrface x:x y:y
"raise an error: this method should be implemented (TODO)"
^ CPrimitives
cairo_set_source_surface:self
_:aSyrface
_:x
_:y
"Created: / 24-12-2014 / 23:12:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 21:59:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - save & restore'!
restore
^ CPrimitives cairo_restore:self
"Created: / 17-06-2012 / 21:51:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 13-02-2016 / 16:14:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
save
^ CPrimitives cairo_save:self
"Created: / 17-06-2012 / 21:51:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 13-02-2016 / 16:15:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - source'!
source: aCairoPatternOrColor
aCairoPatternOrColor isColor ifTrue:[
self sourceR: (aCairoPatternOrColor red / 100)
G: (aCairoPatternOrColor green / 100)
B: (aCairoPatternOrColor blue / 100)
A: aCairoPatternOrColor alpha.
^ self.
].
self notYetImplemented
"Created: / 13-02-2016 / 16:52:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
sourceR:r G:g B:b
CPrimitives cairo_set_source_rgb: self
_: r asDouble
_: g asDouble
_: b asDouble
"Created: / 13-02-2016 / 16:55:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
sourceR:r G:g B:b A:a
CPrimitives cairo_set_source_rgba: self
_: r asDouble
_: g asDouble
_: b asDouble
_: a asDouble.
"Created: / 13-02-2016 / 16:54:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - stroke & fill'!
fill
^ CPrimitives cairo_fill:self
"Created: / 10-07-2008 / 09:42:50 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 28-12-2014 / 22:01:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
fillAndPreserve
^ CPrimitives cairo_fill_preserve:self
"Created: / 17-06-2012 / 21:52:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:01:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
paint
"A drawing operator that paints the current source everywhere within
the current clip region."
^ CPrimitives cairo_paint:self.
"Created: / 13-02-2016 / 16:59:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showPage
"Makes sense only for PDF surfaces"
^ CPrimitives cairo_show_page:self.
"Created: / 17-06-2012 / 08:44:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:02:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
stroke
^ CPrimitives cairo_stroke:self
"Created: / 10-07-2008 / 09:42:43 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 28-12-2014 / 22:02:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
strokeAndPreserve
^ CPrimitives cairo_stroke_preserve:self
"Created: / 17-06-2012 / 21:52:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:15:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - text'!
font:family slant:slant weight:weight
^ CPrimitives
cairo_select_font_face:self
_:family asString
_:slant asInteger
_:weight asInteger
"Created: / 29-12-2014 / 01:08:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
fontSize:sz
^ CPrimitives cairo_set_font_size:self _:sz asFloat
"Created: / 23-04-2009 / 17:24:33 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 02-01-2015 / 01:39:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showText:aString
^ CPrimitives cairo_show_text:self _:aString utf8Encoded
"Created: / 23-04-2009 / 17:25:20 / Jan Vrany <vranyj1@fel.cvut.cz>"
"Modified: / 28-12-2014 / 22:02:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'cairo api - transformations & clipping'!
clip
^ CPrimitives cairo_clip:self.
"Created: / 17-06-2012 / 21:56:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2014 / 22:02:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matrix: aCairoMatrix
self notYetImplemented
"Created: / 13-02-2016 / 19:51:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matrixReset
"Resets the current transformation matrix (CTM) by setting it equal to the
identity matrix. That is, the user-space and device-space axes will be
aligned and one user-space unit will transform to one device-space unit."
CPrimitives cairo_identity_matrix: self.
"Created: / 13-02-2016 / 19:54:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
scale: aNumberOrPoint
| sx sy |
aNumberOrPoint isPoint ifTrue:[
sx := aNumberOrPoint x asFloat.
sy := aNumberOrPoint y asFloat.
] ifFalse:[
sx := sy := aNumberOrPoint asFloat.
].
CPrimitives cairo_scale: self _: sx _: sy.
"Created: / 13-02-2016 / 16:40:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
translate: aNumberOrPoint
| tx ty |
aNumberOrPoint isPoint ifTrue:[
tx := aNumberOrPoint x asFloat.
ty := aNumberOrPoint y asFloat.
] ifFalse:[
tx := ty := aNumberOrPoint asFloat.
].
CPrimitives cairo_translate: self _: tx _: ty.
"Created: / 13-02-2016 / 16:40:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'initialization & release'!
initializeWithSurface: aSurface
surface := aSurface.
self registerForFinalization
"Created: / 13-02-2016 / 16:08:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GraphicsContext methodsFor:'private'!
destroy
"Tell Cairo library to destroy the corresponding C object.
Remember that object is physically destroyed only if internal
refcounter goes to zero. However, after calling destroy,
this instance should be treated as invalid."
surface := nil.
CPrimitives cairo_destroy: self.
self setAddress: nil.
"Modified: / 13-02-2016 / 16:13:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !