Cairo__GraphicsContext.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 12 Feb 2016 16:36:39 +0000
changeset 35 395689a88b32
parent 34 97705b5a9411
child 36 9b680e54aa94
permissions -rw-r--r--
Make Cairo::GraphicsContext to inherit from DeviceGraphicsContext This allows using Cairo's GraphicsContext in views as *the* graphics context so the whole view is then rendered by Cairo.

"{ Package: 'stx:goodies/libcairo' }"

"{ NameSpace: Cairo }"

DeviceGraphicsContext subclass:#GraphicsContext
	instanceVariableNames:'surface crId saved savedPos'
	classVariableNames:'Lobby'
	poolDictionaries:'Cairo::FontSlant Cairo::FontWeight Cairo::Format'
	category:'Cairo-Objects'
!


!GraphicsContext class methodsFor:'initialization'!

initialize
    "Invoked at system start or when the class is dynamically loaded."

    "/ please change as required (and remove this comment)

    Lobby := Registry new.

    "Modified: / 09-01-2015 / 15:08:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext class methodsFor:'instance creation'!

onSurface: surface
    | handle |

    self
        assert: (surface isKindOf: Cairo::Surface)
        message: 'surface is not valid Cairo surface'.

    handle := CPrimitives cairo_create: surface.
    ^ self new initializeWithHandle: handle surface: surface

    "Created: / 28-12-2014 / 23:45:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 12-02-2016 / 16:19:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext class methodsFor:'accessing'!

dllPath

    OperatingSystem isMSWINDOWSlike ifTrue:[
        ^ #( 'C:\Windows' 'C:\Windows\System32' "Wild guess, should not harm" )
    ].

    OperatingSystem isUNIXlike ifTrue:[
        OperatingSystem getSystemType == #linux ifTrue:[
            | path |

            path := #( '/lib' '/usr/lib' '/usr/local/lib' ).
            (OperatingSystem getSystemInfo at:#machine) = 'x86_64' ifTrue:[
                "If the machine is 64bit, prepend standard path for 32bit libs.
                 Leave standard paths at the end, as the system might be completely
                 32bit but running on 64bit-capable CPU.

                CAVEAT: This is bit dangerous, as on 64bit OS, if ia32 libs are
                not installed byt 64bit sqlite libs are, then 64bit libs are found
                and when a function is called, segfault will occur!!

                Q: Is there a way how to figure out if the OS itself is 32bit,
                regardles on CPU?"
                path := #( '/lib32' '/usr/lib32' '/usr/local/lib32' ) , path.
            ].
            ^path

        ].
    ].

    self error:'Unsupported operating system'

    "
        SqliteLibrary dllPath
    "

    "Created: / 31-08-2011 / 18:02:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

libraryName

    OperatingSystem isUNIXlike ifTrue:[^'libcairo.so.2'].

    OperatingSystem isMSWINDOWSlike ifTrue:[^'cairo.dll'].

    self error:'Library name for host OS is not known'
!

sizeof
    "Returns size of undelaying structure in bytes"

    ^0
! !

!GraphicsContext class methodsFor:'examples'!

rectangleOnTranscript

    "
        Cairo::GraphicsContext rectangleOnTranscript
    "


    | gc |
    gc := Transcript cairo.
    gc paint: Color black.
    gc moveToX: 30 y: 50.
    gc paint: (Color red alpha: 0.5).
    gc rectangleX: 10 y: 15 width: 150 height: 60.
    gc fill.
    gc paint: (Color red alpha: 0.75).
    gc rectangleX: 10 y: 15 width: 150 height: 60.
    gc stroke.

    "Created: / 23-04-2009 / 17:33:57 / Jan Vrany <vranyj1@fel.cvut.cz>"
! !

!GraphicsContext methodsFor:'accessing'!

cairo
    gcId isNil ifTrue:[ 
        self initGC.
        self assert: crId notNil
    ] ifFalse:[ 
        crId notNil ifTrue:[ 
"/            CPrimitives cairo_destroy: crId. 
"/            crId := CPrimitives cairo_create: surface.
        ].
    ].

    ^ self

    "Created: / 12-02-2016 / 16:03:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-02-2016 / 17:10:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

device
    ^ device

    "Created: / 29-12-2014 / 18:44:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

deviceClippingBoundsOrNil
    ^ clipRect

    "Created: / 02-01-2015 / 12:36:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

font:aFont
    | dfont family slant psize weight |

    dfont := aFont onDevice: device.

    family := dfont family.
    slant := SymbolicFontSlantToCairoFontSlantMap at: (dfont style ? 'roman'). 
    weight := SymbolicFontFaceToCairoFontWeightMap at: (dfont face ? 'regular').

    self font: family slant: slant weight: weight.

    psize := dfont pixelSize.
    psize isNil ifTrue:[ 
        psize := (self device verticalPixelPerInch / 72) * dfont size.
    ].
    self fontSize: psize .

    font := ScaledFont family: dfont family face: dfont face style: dfont style size: dfont size.
    font handle: (CPrimitives cairo_get_scaled_font: crId).

    "Modified: / 09-01-2015 / 15:43:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

function:aFunctionSymbol
    "set the drawing function"

    ^ self shouldImplement
!

lineWidth: w
    lineWidth ~~ w ifTrue:[  
        super lineWidth: w. 
        CPrimitives cairo_set_line_width: crId _:w asFloat
    ].

    "Created: / 17-06-2012 / 21:55:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 02-01-2015 / 00:18:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

mask:aForm
    "set the drawing mask"

    ^ self shouldImplement
!

paint: aColor

"/    paint ~= aColor ifTrue:[  
        paint := aColor ? Black.
        CPrimitives cairo_set_source_rgba: crId _: (paint red / 100) asDouble _: (paint green / 100) asDouble _: (paint blue / 100) asDouble _: paint alpha asDouble
"/    ].

    "Created: / 10-07-2008 / 11:18:13 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 23-04-2009 / 17:31:33 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 02-01-2015 / 00:51:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

referenceCount
    "Return value or reference counter"

    ^ CPrimitives cairo_get_reference_count: crId

    "Created: / 28-12-2014 / 22:11:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

surface
    ^surface

    "Created: / 10-07-2008 / 10:33:59 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 10-09-2008 / 20:53:00 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 28-12-2014 / 23:59:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'accessing-path properties'!

lineCap: lc

    ^ CPrimitives cairo_set_line_cap: crId _: lc

    "Created: / 17-06-2012 / 22:09:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 28-12-2014 / 21:58:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'accessing-transformation'!

transformation:aTransformation 
    "set the transformation"

    super transformation: aTransformation.
    CPrimitives cairo_identity_matrix: crId.
    transformation notNil ifTrue:[
        CPrimitives cairo_translate: crId _: transformation translationX asFloat _: transformation translationY asFloat.
        CPrimitives cairo_scale: crId _: transformation scaleX asFloat _: transformation scaleY asFloat.        
    ] ifFalse:[ 
        CPrimitives cairo_translate: crId _: 0.0 _: 0.0.
        CPrimitives cairo_scale: crId _: 1.0 _: 1.0.        
    ].

    "Created: / 01-01-2015 / 12:07:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-01-2015 / 16:15:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'basic drawing'!

displayArcX:x y:y width:w height:h from:start angle:angle

    | angle1 angle2 |

    self save.    
    w ~~ h ifTrue:[
        self notYetImplemented
    ].

    angle1 := (360 - start) .
    angle2 := (360 - (start + angle)) \\ 360.

    (angle2 < angle1) ifTrue:[
        self arcNegativeX: (x + (w / 2)) y: (y + (h / 2)) radius: w / 2 from: angle1 * (Float pi / 180) to: angle2 * (Float pi / 180).
    ] ifFalse:[ 
        self arcNegativeX: (x + (w / 2)) y: (y + (h / 2)) radius: w / 2 from: angle2 * (Float pi / 180) to: angle1 * (Float pi / 180).
    ].
    self stroke.

    w ~~ h ifTrue:[
        self notYetImplemented
    ].
    self restore.

    "Modified: / 07-01-2015 / 11:58:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

displayLineFromX:x0 y:y0 toX:x1 y:y1
    "draw a line from x0/y0 to x1/y1"

    self moveToX: x0 y: y0.
    self lineToX: x1 y: y1.
    self stroke.

    "Modified: / 29-12-2014 / 01:18:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

displayOpaqueString:aString from:index1 to:index2 x:x y:y maxWitdh:maxWidth
    "draw part of a string with both fg and bg at x/y in current font"

    ^ self shouldImplement
!

displayPolygon:points
    "draw a polygon
     - this could be recoded to draw using displayLine"

    self moveToX: points first x asFloat y: points first y asFloat.
    2 to: points size do:[:i |  
        self lineToX: (points at: i) x asFloat  y: (points at: i) y asFloat
    ].
    self closePath.
    self stroke.

    "Modified: / 02-01-2015 / 01:46:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

displayRectangleX:x y:y width:w height:h
    "draw a rectangle
     - this could be recoded to draw using displayLine"

    self rectangleX: x y: y width: w height: h.
    self stroke.

    "Modified: / 29-12-2014 / 01:18:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

displayString:aString from:index1 to:index2 x:x y:y
    "draw part of a string with fg at x/y in current font"

    self save.
    self moveToX: x y: y.
    (index1 == 1 and:[ index2 == aString size ]) ifTrue:[ 
        self showText: aString
    ] ifFalse:[ 
        self showText: (aString copyFrom: index1 to: index2).
    ].
    self restore.

    "Modified: / 09-01-2015 / 15:21:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'basic filling'!

fillArcX:x y:y width:w height:h from:start angle:angle

    | angle1 angle2 |

    self save.    
    w ~~ h ifTrue:[
        self notYetImplemented
    ].


    angle1 := (360 - start) .
    angle2 := (360 - (start + angle)) \\ 360.

    self moveToX: (x + (w / 2)) y: (y + (h / 2)).

    (angle2 < angle1) ifTrue:[
        self arcNegativeX: (x + (w / 2)) y: (y + (h / 2)) radius: w / 2 from: angle1 * (Float pi / 180) to: angle2 * (Float pi / 180).
    ] ifFalse:[ 
        self arcNegativeX: (x + (w / 2)) y: (y + (h / 2)) radius: w / 2 from: angle2 * (Float pi / 180) to: angle1 * (Float pi / 180).
    ].
    self closePath.

    self strokeAndPreserve.
    self fill.

    w ~~ h ifTrue:[

    ].
    self restore.

    "Modified: / 07-01-2015 / 04:25:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

fillPolygon:points
    "fill a polygon with current paint color"

    self moveToX: points first x asFloat y: points first y asFloat.
    2 to: points size do:[:i |  
        self lineToX: (points at: i) x asFloat  y: (points at: i) y asFloat
    ].
    self closePath.
    self strokeAndPreserve.
    self fill.

    "Modified: / 02-01-2015 / 01:45:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

fillRectangleX:x y:y width:w height:h
    "fill a rectangle with current paint color"

    self rectangleX: x y: y width: w height: h. 
    self strokeAndPreserve.
    self fill.

    "Modified: / 02-01-2015 / 00:32:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'bit blitting'!

copyFrom:aGC x:srcX y:srcY toX:dstX y:dstY width:w height:h
    "copy from a drawable - maybe self"

    ^ self shouldImplement
! !

!GraphicsContext methodsFor:'cairo api - paths'!

arcNegativeX: x y: y radius: r from: startAngle to: stopAngle

    ^CPrimitives cairo_arc_negative: crId _: 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: crId _: 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: crId.

    "Created: / 01-01-2015 / 22:42:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

lineToX: x y: y

    ^CPrimitives cairo_line_to: crId _: 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>"
!

moveToX: x y: y

    ^CPrimitives cairo_move_to: crId _: 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: crId
        _: 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: crId _: 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
    | savedData |
    (saved isNil or:[ savedPos == 0 ]) ifTrue:[ 
        self error: 'Cannot restore, no save called!!'.
    ].
    savedData := saved at: savedPos.
    saved at: savedPos put: nil.
    savedPos := savedPos - 1.

    transformation := savedData at: 1.

    ^CPrimitives cairo_restore: crId

    "Created: / 17-06-2012 / 21:51:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-02-2016 / 21:16:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

save
    | savedData |
    saved isNil ifTrue:[ 
        saved := Array new: 10.
        savedPos := 0.
    ].
    savedPos == saved size ifTrue:[ 
        | newSaved |

        newSaved := Array new: savedPos + 10.
        newSaved replaceFrom: 1 to: savedPos with: saved startingAt: 1.
        saved := newSaved.
    ].
    savedPos := savedPos + 1.
    savedData := Array new: 1.
    saved at: savedPos put: savedData.
    savedData at: 1 put: transformation.

    ^CPrimitives cairo_save: crId

    "Created: / 17-06-2012 / 21:51:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 12-02-2016 / 21:14:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'cairo api - stroke & fill'!

draw
    "Fills whole surface. 

     This method calls  cairo_paint(), however, #paint is defined in 
     GraphicsContext as method returning current foreground color/pattern."
    
    ^ CPrimitives cairo_paint:crId.

    "Created: / 29-12-2014 / 11:28:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

fill

    ^CPrimitives cairo_fill: crId

    "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: crId

    "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>"
!

showPage
    "Makes sense only for PDF surfaces"

    ^CPrimitives cairo_show_page: crId.

    "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: crId

    "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: crId

    "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: crId
        _: 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: crId _: 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: crId _: 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: crId.

    "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>"
! !

!GraphicsContext methodsFor:'drawing'!

displayForm:aFormOrImage x:x y:y
    "draw a form (or image) at x/y; 
     if the form has depth 1, 1's in the form are
     drawn in current paint color, 0's are ignored.
     If the form has depth ~~ 1, the current fg color setting is ignored."

    | image width height stride data image_surface |

    image := aFormOrImage asImage.
    width := image width.
    height := image height.
    stride := CPrimitives cairo_format_stride_for_width: CAIRO_FORMAT_ARGB32 _: width.
    data := ExternalBytes basicNew allocateBytes: stride * height clear: false.
    [
        image bitsARGB32Into: data stride: stride fg: self paint bg:  self backgroundPaint. 
        image_surface := CPrimitives cairo_image_surface_create_for_data: data _: CAIRO_FORMAT_ARGB32 _: width _: height _: stride.
        CPrimitives cairo_set_source_surface: crId _: image_surface _: x asFloat _: y asFloat.
        CPrimitives cairo_paint: crId.
    ] ensure:[ 
        data finalize.
        image_surface release.
    ].

    "Created: / 31-12-2014 / 12:08:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 01-01-2015 / 02:48:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

displayRoundRectangleX:x y:y width:w height:h wCorner:wCorn hCorner:hCorn
    | r pi |
    wCorn ~~ hCorn ifTrue:[ 
        self notYetImplemented.
    ].
    r := wCorn / 2.
    pi := Float pi.

    "/ top-left arc
    self arcX: x + r     y: y + r     radius: r from:         pi to: (3/2) * pi.
    "/ top-right atc
    self arcX: x + w - r y: y + r     radius: r from: (3/2) * pi to: 0.0.
    "/ bottom-right atc
    self arcX: x + w - r y: y + h - r radius: r from: 0.0        to: (1/2) * pi.
    "/ bottom-left atc
    self arcX: x + r     y: y + h - r radius: r from: (1/2) * pi to:         pi.
    self closePath.
    self stroke.
    
    "
     |v|

     (v := View new) extent:200@200; openAndWait.
     v cairo 
            lineWidth: 5;
            displayRoundRectangleX:10 y:10 width:100 height:100 wCorner:20 hCorner:20;
            release
    "

    "Created: / 07-01-2015 / 20:41:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'filling'!

fillRoundRectangleX:x y:y width:w height:h wCorner:wCorn hCorner:hCorn
    | r pi |
    wCorn ~~ hCorn ifTrue:[ 
        self notYetImplemented.
    ].
    r := wCorn / 2.
    pi := Float pi.

    "/ top-left arc
    self arcX: x + r     y: y + r     radius: r from:         pi to: (3/2) * pi.
    "/ top-right atc
    self arcX: x + w - r y: y + r     radius: r from: (3/2) * pi to: 0.0.
    "/ bottom-right atc
    self arcX: x + w - r y: y + h - r radius: r from: 0.0        to: (1/2) * pi.
    "/ bottom-left atc
    self arcX: x + r     y: y + h - r radius: r from: (1/2) * pi to:         pi.
    self closePath.
    self fill.
    
    "
     |v|

     (v := View new) extent:200@200; openAndWait.
     v cairo 
            lineWidth: 5;
            displayRoundRectangleX:10 y:10 width:100 height:100 wCorner:20 hCorner:20;
            release
    "

    "Created: / 07-01-2015 / 21:33:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'finalization'!

executor
    ^ super executor
    "/^ self shallowCopy

    "Created: / 12-02-2016 / 17:04:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

finalization
    self destroy

    "Created: / 09-01-2015 / 10:20:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

finalizationLobby
    "answer a Registry used for finalization.
     Use a generic Registry for any object.
     Subclasses using their own Registry should redefine this"

    ^ Lobby

    "Created: / 09-01-2015 / 10:20:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext methodsFor:'initialization & release'!

createCR
    "Physically create a Cairo graphics context"

    surface := device cairoSurfaceFor: (device viewFromId: drawableId).
    crId := CPrimitives cairo_create: surface.

    "Created: / 12-02-2016 / 16:59:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

createGC
    "physically create a device GC.
     Since we do not need a gc-object for the drawable until something is
     really drawn, none is created up to the first draw.
     This method is sent, when the first drawing happens"      
    super createGC.
    self createCR

    "Created: / 12-02-2016 / 16:58:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

destroyCR
    "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."

    crId notNil ifTrue:[
        CPrimitives cairo_destroy: crId.
        crId := nil.
        surface destroy.
        surface := nil.
    ].

    "Created: / 12-02-2016 / 16:59:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

destroyGC
    self destroyCR.
    super destroyGC

    "Created: / 12-02-2016 / 17:01:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

initializeWithHandle:anExternalAddress surface: aSurface
    crId := anExternalAddress.
    surface := aSurface.
    device := aSurface device.
    self lineWidth: 1.
    self initialize.
    self font: font.
    self registerForFinalization

    "Created: / 28-12-2014 / 23:52:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-01-2015 / 10:20:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

releaseCR
    self destroyCR

    "Created: / 12-02-2016 / 17:02:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

releaseGC
    "destroy the associated device GC resource - can be done to be nice to the
     display if you know that you are done with a drawable."

    self releaseCR.
    super releaseGC.

    "Created: / 12-02-2016 / 17:03:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GraphicsContext class methodsFor:'documentation'!

version
    ^'$Id$'
!

version_HG
    ^ '$Changeset: <not expanded> $'
! !


GraphicsContext initialize!