Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AeCairoMatrix: add API to scale and rotate around a center #76

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/Alexandrie-Cairo-Tests/AeCairoExamplesRenderTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,41 @@ AeCairoExamplesRenderTest >> surfaceWithPixelatedIcon [
^ aSurface
]

{ #category : #tests }
AeCairoExamplesRenderTest >> surfaceWithRotationAboutCenter [
"Draw an asterisk with multiple lines rotated and scaled about the surface center."

| extent pivot mainSurface mainContext aMatrix numberOfLines |
extent := 40 @ 30.
pivot := extent / 2.
numberOfLines := 5.

mainSurface :=
AeCairoImageSurface
extent: extent
format: AeCairoSurfaceFormat argb32.
mainContext := mainSurface newContext.

aMatrix := AeCairoMatrix newIdentity.
(Color wheel: numberOfLines) do: [ :eachColor |
"Each iteration, rotate and scale a bit more"
aMatrix
rotateByRadians: Float twoPi / numberOfLines
center: pivot.
aMatrix
scaleBy: 1.2 @ 1.2
center: pivot.

mainContext
matrix: aMatrix;
sourceColor: (eachColor alpha: 0.75);
moveTo: pivot - 5;
lineTo: pivot + 5;
stroke ].

^ mainSurface
]

{ #category : #tests }
AeCairoExamplesRenderTest >> surfaceWithRotationByQuadrantsOnContext [

Expand Down
32 changes: 32 additions & 0 deletions src/Alexandrie-Cairo-Tests/AeCairoMatrixTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,22 @@ AeCairoMatrixTest >> testRotateByRadians [
self assert: matrix shy equals: radians sin
]

{ #category : #tests }
AeCairoMatrixTest >> testRotateByRadiansCenter [

| radians |
matrix := AeCairoMatrix newIdentity.
radians := 180 degreesToRadians.
matrix rotateByRadians: radians center: 20@10.

self assert: matrix x equals: 40.0.
self assert: matrix y equals: 20.0.
self assert: matrix sx equals: radians cos.
self assert: matrix sy equals: radians cos.
self assert: matrix shx equals: radians sin negated.
self assert: matrix shy equals: radians sin
]

{ #category : #tests }
AeCairoMatrixTest >> testRotateTwice [

Expand Down Expand Up @@ -335,6 +351,22 @@ AeCairoMatrixTest >> testScaleBy [
self assert: matrix scaleFactors equals: 2 @ 3
]

{ #category : #tests }
AeCairoMatrixTest >> testScaleByCenter [

matrix := AeCairoMatrix newIdentity.
matrix scaleBy: 2 @ 3 center: 20 @ 10.

self assert: matrix x equals: -20.0.
self assert: matrix y equals: -20.0.
self assert: matrix sx equals: 2.0.
self assert: matrix sy equals: 3.0.
self assert: matrix shx equals: 0.0.
self assert: matrix shy equals: 0.0.

self assert: matrix scaleFactors equals: 2 @ 3
]

{ #category : #tests }
AeCairoMatrixTest >> testScaleTwice [

Expand Down
47 changes: 47 additions & 0 deletions src/Alexandrie-Cairo/AeCairoMatrix.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -486,12 +486,47 @@ AeCairoMatrix >> rotateByRadians: angle [
double angle ) )
]

{ #category : #'API - transformations' }
AeCairoMatrix >> rotateByRadians: angle center: aPoint [
"Rotate about a center.

See: https://www.cairographics.org/cookbook/transform_about_point/"

self rotateByRadians: angle centerX: aPoint x y: aPoint y
]

{ #category : #'API - transformations' }
AeCairoMatrix >> rotateByRadians: angle centerX: cx y: cy [
"Rotate about a center.

See: https://www.cairographics.org/cookbook/transform_about_point/"

self
translateByX: cx y: cy;
rotateByRadians: angle;
translateByX: cx negated y: cy negated
]

{ #category : #'API - transformations' }
AeCairoMatrix >> scaleBy: aPoint [
"Scale about origin (0@0)."

self scaleByX: aPoint x y: aPoint y
]

{ #category : #'API - transformations' }
AeCairoMatrix >> scaleBy: aPoint center: anotherPoint [
"Scale about a center.

See: https://www.cairographics.org/cookbook/transform_about_point/"

self
scaleByX: aPoint x
y: aPoint y
centerX: anotherPoint x
y: anotherPoint y
]

{ #category : #'API - transformations' }
AeCairoMatrix >> scaleByX: sx y: sy [
"Applies scaling by (sx @ sy) to the transformation in this matrix. The effect of the new transformation is to first scale the coordinates by sx and sy, then apply the original transformation to the coordinates.
Expand All @@ -506,6 +541,18 @@ AeCairoMatrix >> scaleByX: sx y: sy [
double sy ) )
]

{ #category : #'API - transformations' }
AeCairoMatrix >> scaleByX: sx y: sy centerX: cx y: cy [
"Scale about a center.

See: https://www.cairographics.org/cookbook/transform_about_point/"

self
translateByX: cx y: cy;
scaleByX: sx y: sy;
translateByX: cx negated y: cy negated
]

{ #category : #'accessing - structure variables' }
AeCairoMatrix >> scaleFactors [

Expand Down
Binary file added tests/cairo/surfaceWithRotationAboutCenter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.