--- a/CairoGraphicsContext.st Tue Feb 16 07:46:52 2016 +0000
+++ b/CairoGraphicsContext.st Wed Feb 17 06:43:31 2016 +0000
@@ -3,9 +3,9 @@
"{ NameSpace: Smalltalk }"
DeviceGraphicsContext subclass:#CairoGraphicsContext
- instanceVariableNames:'cr crId'
- classVariableNames:'Lobby'
- poolDictionaries:'Cairo::FontSlant Cairo::FontWeight Cairo::Format'
+ instanceVariableNames:'cr'
+ classVariableNames:'Lobby SkippedSlotIndexes'
+ poolDictionaries:'Cairo::FontSlant Cairo::FontWeight Cairo::Format Cairo::Status'
category:'Cairo-Compatibility'
!
@@ -19,7 +19,13 @@
Lobby := Registry new.
- "Modified: / 09-01-2015 / 15:08:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ SkippedSlotIndexes := {
+ DeviceGraphicsContext instVarIndexFor: #font.
+ DeviceGraphicsContext instVarIndexFor: #deviceFont.
+ DeviceGraphicsContext instVarIndexFor: #lineWidth.
+ }
+
+ "Modified: / 17-02-2016 / 21:43:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CairoGraphicsContext class methodsFor:'instance creation'!
@@ -27,19 +33,21 @@
onDeviceGraphicsContext: dGC
| cGC |
- cGC := self onDevice: dGC device.
- 1 to: DeviceGraphicsContext instSize do:[:i |
- cGC instVarAt: i put: (dGC instVarAt: i).
+ cGC := self basicNew.
+ 1 to: DeviceGraphicsContext instSize do:[:i |
+ (SkippedSlotIndexes includes:i) ifFalse:[
+ cGC instVarAt: i put: (dGC instVarAt: i).
+ ].
].
dGC gcId notNil ifTrue:[
cGC createCR.
].
cGC lineWidth: dGC lineWidth.
- cGC font: dGC font.
+ cGC basicFont: dGC basicFont.
^ cGC
"Created: / 15-02-2016 / 21:20:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 16-02-2016 / 10:44:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 17-02-2016 / 22:46:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CairoGraphicsContext class methodsFor:'accessing'!
@@ -122,6 +130,22 @@
!CairoGraphicsContext methodsFor:'accessing'!
+basicFont:aFont
+ (aFont ~~ font) ifTrue:[
+ super basicFont: aFont.
+ font notNil ifTrue:[
+ font := CairoScaledFont fromFontDescription: font onDevice: device.
+ cr notNil ifTrue:[
+ cr font: font scaledFont.
+ cr fontSize: (Screen current verticalPixelPerInch / 72) * font size.
+ ].
+ ].
+ ].
+
+ "Created: / 16-02-2016 / 15:37:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 18-02-2016 / 00:38:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
clippingBounds:aRectangleOrNil
"set the clipping rectangle for drawing (in logical coordinates);
a nil argument turn off clipping (i.e. whole view is drawable)"
@@ -131,25 +155,6 @@
"Created: / 15-02-2016 / 21:38:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-font:aFont
- | family slant psize weight |
-
- super font: aFont.
-
- family := font family.
- slant := SymbolicFontSlantToCairoFontSlantMap at: (font style ? 'roman').
- weight := SymbolicFontFaceToCairoFontWeightMap at: (font face ? 'regular').
- psize := font pixelSize.
- psize isNil ifTrue:[
- psize := (self device verticalPixelPerInch / 72) * font size.
- ].
-
- cr font: family slant: slant weight: weight.
- cr fontSize: psize .
-
- "Modified: / 16-02-2016 / 10:55:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
function:aFunctionSymbol
"set the drawing function"
@@ -256,11 +261,12 @@
displayRectangleX:x y:y width:w height:h
"draw a rectangle
- this could be recoded to draw using displayLine"
+ (w > 0 and:[h > 0]) ifTrue:[
+ cr rectangleX: x y: y width: w height: h.
+ cr stroke.
+ ]
- cr rectangleX: x y: y width: w height: h.
- cr stroke.
-
- "Modified: / 13-02-2016 / 20:04:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 18-02-2016 / 22:21:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
displayString:aStringArg from:index1Arg to:index2Arg x:x y:y opaque:opaqueArg maxWidth:maxWidth
@@ -271,19 +277,63 @@
the case where paint and/or bgPaint are dithered colors.
maxWidth is the maximum width of the string in pixels or nil if unknown."
+ | opaque string |
+ "
+ if backgroundPaint color is nil, we assume
+ this is a non-opaque draw
+ "
+ opaque := opaqueArg ? false.
+ bgPaint isNil ifTrue:[
+ opaque := false.
+ ].
+
+ gcId isNil ifTrue:[
+ self initGC
+ ].
+
+ (aStringArg isString not or:[aStringArg isText]) ifTrue:[
+ "
+ hook for non-strings (i.e. attributed text)
+ that 'thing' should know how to display itself ...
+ "
+ aStringArg displayOn:self x:x y:y from:index1Arg to:index2Arg opaque:opaque.
+ ^ self
+ ].
+
+ (index1Arg == 1 and:[ index2Arg == aStringArg size ]) ifTrue:[
+ string := aStringArg
+ ] ifFalse:[
+ string := aStringArg copyFrom: index1Arg to: index2Arg
+ ].
+
cr save.
[
+ | extents |
+
+ extents := cr textExtents: string.
+ cr rectangleX: x + extents xBearing ceiling y: y - font ascent ceiling width: extents xAdvance ceiling height: font height ceiling.
+ cr lineWidth: 0.
+
+ opaque ifTrue:[
+ cr source: bgPaint.
+ cr fill.
+ ] ifFalse:[
+ "/ I'm not sure why this is required but if not done,
+ "/ selected text is not rendered correcrtly...
+ cr stroke.
+ ].
+
+ self assert: cr status == CAIRO_STATUS_SUCCESS.
+ cr source: paint.
cr moveToX: x y: y.
- (index1Arg == 1 and:[ index2Arg == aStringArg size ]) ifTrue:[
- cr showText: aStringArg
- ] ifFalse:[
- cr showText: (aStringArg copyFrom: index1Arg to: index2Arg).
- ].
+ cr showText: string.
+ self assert: cr status == CAIRO_STATUS_SUCCESS.
] ensure:[
cr restore.
]
"Created: / 16-02-2016 / 10:51:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 18-02-2016 / 21:12:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CairoGraphicsContext methodsFor:'basic filling'!
@@ -341,18 +391,70 @@
fillRectangleX:x y:y width:w height:h
"fill a rectangle with current paint color"
- cr rectangleX: x y: y width: w height: h.
- cr strokeAndPreserve.
- cr fill.
+ (w > 0 and:[h > 0]) ifTrue:[
+ cr lineWidth: 0.
+ cr rectangleX: x y: y width: w height: h.
+ cr fill.
+ cr lineWidth: (lineWidth == 0 ifTrue:[1] ifFalse:[lineWidth])
+ ].
"/ cr save.
"/ cr rectangleX: x y: y width: w height: h.
"/ cr sourceR: 1 G: 0 B: 0.
-"/ cr lineWidth: 3.
+"/ cr lineWidth: 1.
"/ cr stroke.
"/ cr restore.
- "Modified: / 16-02-2016 / 07:58:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 18-02-2016 / 22:20:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!CairoGraphicsContext methodsFor:'bit blitting'!
+
+copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth padding:pad width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+ "copy bits from a smalltalk byteArray.
+ The bits found there are supposed to be in the devices native format (i.e.
+ translated to allocated color indices on pseudoColor devices and padded as required.
+ The byteOrder is MSB and will be converted as appropriate by the underlying devices
+ method to whatever the device needs."
+
+ cr notNil ifTrue:[
+ cr surface flush
+ ].
+ ^ super copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth padding:pad width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+
+ "Created: / 18-02-2016 / 20:16:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+copyFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h async:async
+ "copy from aDrawable into the receiver;
+ the source may be the receiver as well - in this case its a scroll.
+ All coordinates are in device coordinates.
+ If the receiver is a view AND async is true, the call returns immediately
+ - otherwise, it returns when the scroll operation is finished.
+ (not all devices care for this).
+ If the receiver is a pixmap, the call always returns immediately."
+
+ cr notNil ifTrue:[
+ cr surface flush
+ ].
+ ^ super copyFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h async:async
+
+ "Created: / 18-02-2016 / 20:17:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+copyPlaneFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h
+ "copy one plane from aDrawable into the receiver. 0's are drawn in
+ background, while 1's are drawn with foreground color.
+ The depth of aDrawable must (should) be 1.
+ The drawable must have been allocated on the same device.
+ All coordinates are in device coordinates."
+
+ cr notNil ifTrue:[
+ cr surface flush
+ ].
+ ^ super copyPlaneFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h
+
+ "Created: / 18-02-2016 / 20:17:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!CairoGraphicsContext methodsFor:'drawing'!
@@ -375,15 +477,36 @@
[
image bitsARGB32Into: data stride: stride fg: self paint bg: self backgroundPaint.
image_surface := Cairo::CPrimitives cairo_image_surface_create_for_data: data _: CAIRO_FORMAT_ARGB32 _: width _: height _: stride.
- Cairo::CPrimitives cairo_set_source_surface: crId _: image_surface _: x asFloat _: y asFloat.
- Cairo::CPrimitives cairo_paint: crId.
+ Cairo::CPrimitives cairo_set_source_surface: cr _: image_surface _: x asFloat _: y asFloat.
+ Cairo::CPrimitives cairo_paint: cr.
] ensure:[
data finalize.
image_surface release.
].
"Created: / 31-12-2014 / 12:08:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 15-02-2016 / 21:32:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 17-02-2016 / 20:58:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+displayLineFrom:p0 to:p1
+ "draw a line (with current paint-color); apply transformation if nonNil"
+
+ ^ self displayLineFromX: p0 x y: p0 y toX: p1 x y: p1 y
+
+ "Created: / 18-02-2016 / 20:27:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+displayLineFromX:xStart y:yStart toX:xEnd y:yEnd brush:aForm
+ "draw a line using a brush.
+ Here, a slow fallback is used, drawing into a
+ temporary bitmap first, which is then displayed"
+
+ cr notNil ifTrue:[
+ cr surface flush
+ ].
+ ^ super displayLineFromX:xStart y:yStart toX:xEnd y:yEnd brush:aForm
+
+ "Created: / 18-02-2016 / 20:28:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
displayRoundRectangleX:x y:y width:w height:h wCorner:wCorn hCorner:hCorn
@@ -485,9 +608,12 @@
"Physically create a Cairo graphics context"
cr := self cairo.
+ font notNil ifTrue:[
+ cr font: font scaledFont.
+ ].
"Created: / 12-02-2016 / 16:59:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 13-02-2016 / 19:56:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 17-02-2016 / 22:42:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
createGC