Repository navigation
CGpMatrix
Home › All Categories › sys/win › sys/win/gdiplus › CGpMatrix
Moves, scales, rotates and shears points with a GDI+ affine transformation matrix.
A CGpMatrix wraps one GDI+ Matrix object, which it creates in its constructor and deletes in
its destructor. You pass it by address to the calls that take a transformation:
CGpGraphics SetTransform and MultiplyTransform,
CGpGraphicsPath TransForm, CGpRegion Transform, and the
transform methods of pens and brushes.
The six numbers. A matrix holds m11, m12, m21, m22, dx and dy. A point
(x, y) becomes
x' = x * m11 + y * m21 + dx
y' = x * m12 + y * m22 + dy
so m11 … m22 scale, rotate and shear, and dx, dy move. A new matrix is the identity
(1, 0, 0, 1, 0, 0), which leaves every point where it is.
Order. Translate, Scale, Rotate, RotateAt,
Shear and Multiply combine a new operation with the matrix. With
MatrixOrderPrepend (the default) the new operation is applied to a point before the ones
already in the matrix; with MatrixOrderAppend it is applied after them. So a matrix built
with Scale( 2, 2 ) and then Translate( 10, 0 ) (both prepended) moves a point first and
scales it second. Angles are in degrees, clockwise on the screen, because y grows downwards.
Lifetime. Never copy a CGpMatrix by value (dim b as CGpMatrix = a, or a byval
parameter): the copy holds the same GDI+ object and deletes it when it goes, which leaves the
original unusable. To make an independent copy pass the address, dim b as CGpMatrix = @a, or
use Clone.
Status. The methods that change the matrix return a GpStatus: Ok (0) on success,
otherwise the reason, such as InvalidParameter (2). The status is also stored, and
GetLastStatus(), which every CGp* class inherits, returns it; getters that return a value
store theirs too. GDI+ itself is started and stopped by the CGp* objects as they come and go;
see CGpGraphics and GDI+ procedures.
#import "sys/win"
#import "sys/win/gdiplus"
using win, gdiplusA window that draws one rectangle six times, each copy turned 30 degrees further about the same centre. The matrix scales 96-DPI units to pixels last, after the rotation:
#import "sys/win"
#import "sys/win/gui"
#import "sys/win/gdiplus"
using win, gui, gdiplus
declare function WndProc( byval hwnd as HWND, byval uMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM ) as LRESULT
function main() as long
SetProcessDpiAwareness( PROCESS_SYSTEM_DPI_AWARE )
dim token as ULONG_PTR = gdiplus.Init()
dim pWindow as CWindow = "MatrixDemo"
pWindow.Create( NULL, "CGpMatrix", @WndProc )
pWindow.SetClientSize( 360, 240 )
pWindow.Center()
dim nResult as long = pWindow.DoEvents( SW_NORMAL )
gdiplus.Uninit( token )
return nResult
end function
function WndProc( byval hwnd as HWND, byval uMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM ) as LRESULT
select case uMsg
case WM_PAINT
dim ps as PAINTSTRUCT
dim hdc as HDC = BeginPaint( hwnd, @ps )
scope
dim graphics as CGpGraphics = hdc
graphics.SetSmoothingMode( SmoothingModeAntiAlias )
graphics.Clear( ARGB_WHITE )
dim ratio as single = graphics.GetDpiX() / 96
dim pen as CGpPen = CGpPen( ARGB_DARKSLATEBLUE, 2 )
dim centre as GpPointF = type<GpPointF>( 180, 120 )
for i as long = 0 to 5
dim matrix as CGpMatrix
matrix.Scale( ratio, ratio ) ' applied last
matrix.RotateAt( i * 30, @centre ) ' prepended: applied first
graphics.SetTransform( @matrix )
graphics.DrawRectangle( @pen, 100, 100, 160, 40 )
next
graphics.ResetTransform()
end scope
EndPaint( hwnd, @ps )
return 0
case WM_DESTROY
PostQuitMessage( 0 )
return 0
end select
return DefWindowProcW( hwnd, uMsg, wParam, lParam )
end function
end main()| Member | Does |
|---|---|
| Constructor | Creates an identity matrix, a copy, or a matrix from six numbers or a parallelogram. |
| Destructor | Deletes the GDI+ matrix. |
| Clone | Copies this matrix into another CGpMatrix. |
| GetElements | Reads the six numbers into an array. |
| SetElements | Replaces the six numbers. |
| OffsetX | Returns the horizontal translation, dx. |
| OffsetY | Returns the vertical translation, dy. |
| Reset | Makes the matrix the identity again. |
| Multiply | Combines the matrix with another one. |
| Translate | Adds a move. |
| Scale | Adds a scaling. |
| Rotate | Adds a rotation about the origin. |
| RotateAt | Adds a rotation about a given point. |
| Shear | Adds a shear. |
| Invert | Replaces the matrix with its inverse. |
| TransformPoints | Applies the matrix to an array of points. |
| TransformVectors | Applies the matrix to an array of vectors, without the translation. |
| IsInvertible | Tells whether the matrix has an inverse. |
| IsIdentity | Tells whether the matrix is the identity. |
| Equals | Tells whether two matrices hold the same numbers. |
constructor
constructor( byval pMatrix as CGpMatrix ptr )
constructor( byval m11 as single, byval m12 as single, byval m21 as single, byval m22 as single, byval dx as single, byval dy as single )
constructor( byval rcf as GpRectF ptr, byval dstplg as GpPointF ptr )
constructor( byval rc as GpRect ptr, byval dstplg as GpPoint ptr )Creates the GDI+ matrix.
- With no argument it is the identity matrix.
- With a pointer to another
CGpMatrixit is an independent copy of that matrix. The pointer must not beNULL. - With six numbers it holds exactly those, in the order shown in the introduction.
- With a rectangle and three points it maps the rectangle onto a parallelogram:
dstplgpoints to an array of three points, where the rectangle's top-left, top-right and bottom-left corners go. The bottom-right corner follows from the other three.
GetLastStatus() tells whether the matrix was created.
| Parameter | Meaning |
|---|---|
pMatrix |
The matrix to copy. |
m11, m12, m21, m22
|
The scaling, rotation and shearing part. |
dx, dy
|
The translation. |
rcf, rc
|
The source rectangle. |
dstplg |
An array of three destination points. |
Example
dim rc as GpRectF = type<GpRectF>( 0, 0, 10, 10 )
dim plg(0 to 2) as GpPointF = { (100, 100), (120, 100), (100, 130) }
dim m as CGpMatrix = CGpMatrix( @rc, @plg(0) )
dim pt as GpPointF = type<GpPointF>( 10, 10 )
m.TransformPoints( @pt )
print pt.x; pt.y ' 120 130Microsoft Learn: Matrix::Matrix
destructorDeletes the GDI+ matrix. Objects that were given the matrix (a graphics transform, a path that was transformed) keep their own copy of the numbers and are not affected.
Example
dim pM as CGpMatrix ptr = new CGpMatrix( 2, 0, 0, 2, 0, 0 )
print pM->IsIdentity() ' false
delete pMfunction Clone( byval pMatrix as CGpMatrix ptr ) as GpStatusCopies this matrix into the existing CGpMatrix that pMatrix points to. The GDI+ matrix the
target held is deleted first.
| Parameter | Meaning |
|---|---|
pMatrix |
The object that receives the copy. |
Returns Ok on success; InvalidParameter when pMatrix is NULL.
Example
dim m as CGpMatrix
m.Rotate( 45 )
dim copy as CGpMatrix
if m.Clone( @copy ) = Ok then print copy.Equals( @m ) ' trueMicrosoft Learn: Matrix::Clone
function GetElements( byval m as single ptr ) as GpStatusCopies the six numbers into an array of six single values that m points to, in the order
m11, m12, m21, m22, dx, dy.
| Parameter | Meaning |
|---|---|
m |
The first of six single values. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix = CGpMatrix( 1, 2, 3, 4, 5, 6 )
dim e(0 to 5) as single
m.GetElements( @e(0) )
print e(0); e(1); e(2); e(3); e(4); e(5) ' 1 2 3 4 5 6Microsoft Learn: Matrix::GetElements
function SetElements( byval m11 as single, byval m12 as single, byval m21 as single, byval m22 as single, byval dx as single, byval dy as single ) as GpStatusReplaces all six numbers of the matrix.
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.SetElements( 1, 0, 0, 1, 7, 8 )
print m.OffsetX(); m.OffsetY() ' 7 8Microsoft Learn: Matrix::SetElements
function OffsetX() as singleReturns dx, the horizontal translation.
Returns the value, or 0 when the elements could not be read.
Example
dim m as CGpMatrix
m.Translate( 10, 20 )
print m.OffsetX() ' 10Microsoft Learn: Matrix::OffsetX
function OffsetY() as singleReturns dy, the vertical translation.
Returns the value, or 0 when the elements could not be read.
Example
dim m as CGpMatrix
m.Translate( 10, 20 )
print m.OffsetY() ' 20Microsoft Learn: Matrix::OffsetY
function Reset() as GpStatusSets the matrix back to the identity (1, 0, 0, 1, 0, 0).
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix = CGpMatrix( 2, 0, 0, 2, 5, 5 )
m.Reset()
print m.IsIdentity() ' trueMicrosoft Learn: Matrix::Reset
function Multiply( byval pMatrix as CGpMatrix ptr, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines this matrix with another one and keeps the product. With MatrixOrderPrepend the
other matrix is applied to points first, with MatrixOrderAppend last. pMatrix must not be
NULL.
| Parameter | Meaning |
|---|---|
pMatrix |
The matrix to combine with. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim t as CGpMatrix
t.Translate( 10, 0 )
dim s as CGpMatrix
s.Scale( 2, 2 )
t.Multiply( @s ) ' scale first, then move
dim pt as GpPointF = type<GpPointF>( 1, 1 )
t.TransformPoints( @pt )
print pt.x; pt.y ' 12 2Microsoft Learn: Matrix::Multiply
function Translate( byval nOffsetX as single, byval nOffsetY as single, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines the matrix with a move by nOffsetX, nOffsetY.
| Parameter | Meaning |
|---|---|
nOffsetX, nOffsetY
|
The distances to move. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Scale( 2, 3 )
m.Translate( 5, 5 ) ' prepended: moved, then scaled
dim pt as GpPointF = type<GpPointF>( 0, 0 )
m.TransformPoints( @pt )
print pt.x; pt.y ' 10 15Microsoft Learn: Matrix::Translate
function Scale( byval scaleX as single, byval scaleY as single, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines the matrix with a scaling by scaleX horizontally and scaleY vertically, about the
origin. A negative factor mirrors.
| Parameter | Meaning |
|---|---|
scaleX, scaleY
|
The factors. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Scale( 2, 2 )
m.Rotate( 90, MatrixOrderAppend ) ' scaled, then rotated
dim pt as GpPointF = type<GpPointF>( 1, 0 )
m.TransformPoints( @pt ) ' (0, 2) give or take roundingMicrosoft Learn: Matrix::Scale
function Rotate( byval angle as single, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines the matrix with a rotation by angle degrees about the origin, clockwise on the
screen.
| Parameter | Meaning |
|---|---|
angle |
The angle in degrees. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Translate( 10, 20 )
m.Rotate( 90 ) ' rotated, then moved
dim pt as GpPointF = type<GpPointF>( 1, 0 )
m.TransformPoints( @pt )
print pt.x; pt.y ' 10 21Microsoft Learn: Matrix::Rotate
function RotateAt( byval angle as single, byval center as GpPointF ptr, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines the matrix with a rotation by angle degrees about the point center. It is made of
three steps (a move of center to the origin, the rotation, and the move back), combined in the
order that order asks for; only the status of the last step is returned.
| Parameter | Meaning |
|---|---|
angle |
The angle in degrees, clockwise. |
center |
The point to rotate about. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
dim centre as GpPointF = type<GpPointF>( 10, 10 )
m.RotateAt( 90, @centre )
dim pt as GpPointF = type<GpPointF>( 20, 10 )
m.TransformPoints( @pt ) ' (10, 20) give or take roundingMicrosoft Learn: Matrix::RotateAt
function Shear( byval shearX as single, byval shearY as single, byval order as MatrixOrder = MatrixOrderPrepend ) as GpStatusCombines the matrix with a shear: shearX moves each point sideways by shearX times its y
coordinate, and shearY moves it vertically by shearY times its x coordinate.
| Parameter | Meaning |
|---|---|
shearX, shearY
|
The shear factors. |
order |
MatrixOrderPrepend (the default) or MatrixOrderAppend. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Shear( 1, 0 )
dim pt as GpPointF = type<GpPointF>( 0, 10 )
m.TransformPoints( @pt )
print pt.x; pt.y ' 10 10Microsoft Learn: Matrix::Shear
function Invert() as GpStatusReplaces the matrix with its inverse, the matrix that undoes it. A matrix that has no inverse (see IsInvertible) is left unchanged.
Returns Ok on success; InvalidParameter when the matrix has no inverse.
Example
dim m as CGpMatrix
m.Rotate( 30 )
dim undo as CGpMatrix = @m
if undo.Invert() = Ok then print "inverse ready"Microsoft Learn: Matrix::Invert
function TransformPoints( byval pts as GpPointF ptr, byval nCount as INT_ = 1 ) as GpStatus
function TransformPoints( byval pts as GpPoint ptr, byval nCount as INT_ = 1 ) as GpStatusApplies the matrix to nCount points in place, translation included. With GpPoint the
results are rounded to whole numbers.
| Parameter | Meaning |
|---|---|
pts |
The first point of the array; the points are overwritten. |
nCount |
How many points; 1 by default. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Translate( 5, 5 )
dim pts(0 to 1) as GpPoint = { (0, 0), (10, 10) }
m.TransformPoints( @pts(0), 2 ) ' (5, 5) and (15, 15)Microsoft Learn: Matrix::TransformPoints
function TransformVectors( byval pts as GpPointF ptr, byval nCount as INT_ = 1 ) as GpStatus
function TransformVectors( byval pts as GpPoint ptr, byval nCount as INT_ = 1 ) as GpStatusApplies the matrix to nCount vectors in place, leaving out dx and dy: a direction or a
distance is scaled, rotated and sheared but not moved.
| Parameter | Meaning |
|---|---|
pts |
The first vector of the array; the vectors are overwritten. |
nCount |
How many vectors; 1 by default. |
Returns Ok on success, otherwise the error.
Example
dim m as CGpMatrix
m.Translate( 10, 20 )
m.Rotate( 90 )
dim v as GpPointF = type<GpPointF>( 1, 0 )
m.TransformVectors( @v ) ' (0, 1): turned, not movedMicrosoft Learn: Matrix::TransformVectors
function IsInvertible() as booleanTells whether the matrix has an inverse. A matrix that squashes the plane onto a line, such as (1, 2, 2, 4, 0, 0), has none.
Returns true if it is invertible.
Example
dim m as CGpMatrix = CGpMatrix( 1, 2, 2, 4, 0, 0 )
print m.IsInvertible() ' falseMicrosoft Learn: Matrix::IsInvertible
function IsIdentity() as booleanTells whether the matrix is the identity. The test is on the stored numbers, so a matrix that was rotated and rotated back may differ from the identity by rounding.
Returns true if it is the identity.
Example
dim m as CGpMatrix
print m.IsIdentity() ' trueMicrosoft Learn: Matrix::IsIdentity
function Equals( byval pMatrix as CGpMatrix ptr ) as booleanTells whether this matrix and the one pMatrix points to hold the same six numbers.
| Parameter | Meaning |
|---|---|
pMatrix |
The matrix to compare with. |
Returns true if they are equal; false when they differ or pMatrix is NULL.
Example
dim a as CGpMatrix = CGpMatrix( 2, 0, 0, 2, 0, 0 )
dim b as CGpMatrix
b.Scale( 2, 2 )
print a.Equals( @b ) ' trueMicrosoft Learn: Matrix::Equals
- CGpGraphics for the world transformation a matrix is set as
- CGpGraphicsPath and CGpRegion, which a matrix transforms
- sys/win/gdiplus
tiko-lang · Home · Feature Index · Keyword Index · License
FreeBASIC manual pages reproduced under the GNU FDL 1.3.
- Generics
- Interfaces
- For Each
- Iterators
- Tuples
- Array Results
- Defer
- Lambdas
- Block Strings
- Partial Types
- String Slices
- Embed
- Typed Variadics
- C Header Import
- Foreign Library Linking
- UString
- Fixed-Width Types
- Nullptr
- String Library
- Format
- Array
- Map
- Set
- LinkedList
- OrderedMap
- OrderedSet
- Sorting
- Optional
- Result
- Smart Pointers
- Date and Time (Chrono)
- Filesystem
- File Streams
- Config (INI and TOML)
- Codec
- Hash
- UUID
- OS
- Process
- Net
- HTTP and TLS
- Math Library
- Finance
- Logging
- Terminal TUI Library
- PsControls
- tkControls
- sys/win
- Goroutines and Channels
- LLVM Backend
- tiko build
- TIKO_COMPILER
- Variable Declarations
- Standard Data Types
- User Defined Types
- Procedures
- Operators
- Control Flow Statements
- Converting Data Types
- Array Functions
- String Functions
- Mathematical Functions
- Bit Manipulation
- Date and Time Functions
- File I/O Functions
- Console Functions
- User Input (Runtime Library)
- User Input Functions (Graphics Library)
- Screen Functions
- 2D Drawing Functions
- Graphics Library Reference
- Graphics Keyword List
- Memory Functions
- Threading Support Functions
- Error Handling Functions
- Operating System Functions
- Preprocessor
- Intrinsic Defines
- Miscellaneous Keywords
- Modularizing