1. concatmatrix

Multiplies two transformation matrices.

1.1. Syntax

matrix1 matrix2 matrix3 concatmatrix → matrix3

1.2. Stack Effects

Table 1. Before
Level Object

2

matrix1 (6-element array)

1

matrix2 (6-element array)

0

matrix3 (6-element array)

Table 2. After
Level Object

0

matrix3 (modified array)

1.3. Description

concatmatrix replaces the value of matrix3 with the result of multiplying matrix1 × matrix2, and pushes the modified matrix3 back on the operand stack.

This operator performs matrix multiplication without affecting the current transformation matrix (CTM). It is useful for building complex transformations from simpler ones.

The multiplication order is: matrix1 × matrix2, which means transformations in matrix2 are applied first, followed by transformations in matrix1.

All three matrix operands must be 6-element arrays. matrix3 can be the same array as matrix1 or matrix2.

1.4. PostScript Level

Level 1 and later

1.5. Examples

Basic matrix multiplication
/m1 [2 0 0 2 0 0] def      % Scale by 2
/m2 [1 0 0 1 100 100] def  % Translate
/m3 matrix def
m1 m2 m3 concatmatrix
% m3 = [2 0 0 2 100 100]
% Scale, then translate (in that order)
Building complex transformations
% Translation matrix
/trans matrix 50 100 translate def

% Rotation matrix
/rot matrix 45 rotate def

% Combined transformation
/combined matrix def
trans rot combined concatmatrix
% combined = translation followed by rotation
In-place multiplication
/m1 [2 0 0 2 0 0] def
/m2 [1 0 0 1 50 50] def
m1 m2 m1 concatmatrix  % Store result in m1
% m1 now contains product

1.6. Common Use Cases

1.6.1. Precomputing Transformations

% Build transformation once, use many times
/baseTransform matrix 100 100 translate def
/scaleTransform matrix 2 2 scale def
/finalTransform matrix def

baseTransform scaleTransform finalTransform concatmatrix

% Use multiple times
finalTransform concat
% ... draw content ...

1.6.2. Composing Transformations

% Create library of transformations
/rotLeft matrix 90 rotate def
/rotRight matrix -90 rotate def
/scale2x matrix 2 2 scale def

% Combine as needed
matrix
rotLeft scale2x matrix concatmatrix concat
% Rotates left then scales by 2

1.6.3. Inverting Transformations

% Forward transformation
/forward matrix 100 100 translate 2 2 scale def

% Inverse transformation
/inverse matrix def
forward inverse invertmatrix

% Apply forward then inverse
forward concat
% ... draw ...
inverse concat
% Back to original transformation

1.7. Common Pitfalls

Multiplication Order - Matrix multiplication is not commutative. Order matters!
/m1 [2 0 0 2 0 0] def      % Scale
/m2 [1 0 0 1 100 0] def    % Translate

/r1 matrix def
/r2 matrix def

m1 m2 r1 concatmatrix  % → [2 0 0 2 100 0]
m2 m1 r2 concatmatrix  % → [2 0 0 2 200 0]
% Different results!
Output Array Can Be Input - Storing result in input array can be confusing.
/m1 [2 0 0 2 0 0] def
/m2 [1 0 0 1 50 50] def
m1 m2 m1 concatmatrix  % Overwrites m1
% m1 no longer contains original value
Use Separate Result Array - For clarity, use a separate result array:
/m1 matrix 2 2 scale def
/m2 matrix 100 100 translate def
/result matrix def
m1 m2 result concatmatrix
% m1 and m2 unchanged, result has product
Chain Multiplications - Build complex transformations step by step:
/result matrix def
matrix 100 100 translate
matrix 2 2 scale
result concatmatrix
matrix 45 rotate
result concatmatrix
% result now has all three transformations

1.8. Error Conditions

Error Condition

[rangecheck]

Any array has fewer than 6 elements

[stackunderflow]

Fewer than 3 operands on stack

[typecheck]

Any operand is not an array, or array elements are not all numbers

1.9. Implementation Notes

  • The result matrix is completely independent of the CTM

  • All three arrays must have at least 6 elements

  • Only the first 6 elements are used/modified

  • The operation is purely computational

  • Input matrices are not modified (unless one is also the output)

1.10. Matrix Mathematics

Given matrices M₁ and M₂:

M₁ = [a₁  b₁  c₁  d₁  tx₁  ty₁]
M₂ = [a₂  b₂  c₂  d₂  tx₂  ty₂]

concatmatrix computes M₃ = M₁ × M₂:

M₃ = [a₁×a₂ + b₁×c₂              a₁×b₂ + b₁×d₂
      c₁×a₂ + d₁×c₂              c₁×b₂ + d₁×d₂
      tx₁×a₂ + ty₁×c₂ + tx₂      tx₁×b₂ + ty₁×d₂ + ty₂]

1.11. Transformation Composition

When M₃ = M₁ × M₂, applying M₃ to a point is equivalent to:

  1. First applying M₂ to the point

  2. Then applying M₁ to the result

% These are equivalent:
m1 m2 m3 concatmatrix
m3 concat

% And:
m2 concat
m1 concat

1.12. Example: Building Rotation Around Point

% Rotate 45° around point (100, 100)
/cx 100 def
/cy 100 def
/angle 45 def

% T1: Translate to origin
/t1 matrix cx neg cy neg translate def

% R: Rotate
/r matrix angle rotate def

% T2: Translate back
/t2 matrix cx cy translate def

% Combine: T2 × R × T1
/result matrix def
r t1 result concatmatrix
t2 exch result concatmatrix

% Apply transformation
result concat

1.13. Performance Considerations

  • Pure matrix multiplication is very fast

  • No interaction with graphics state

  • Can be used freely for precomputing transformations

  • More efficient to compute once and reuse than to compute repeatedly

1.14. Associativity

Matrix multiplication is associative:

% (M₁ × M₂) × M₃ = M₁ × (M₂ × M₃)
/temp1 matrix def
/temp2 matrix def
/result matrix def

m1 m2 temp1 concatmatrix
temp1 m3 result concatmatrix

% Same as:
m2 m3 temp2 concatmatrix
m1 temp2 result concatmatrix

1.15. See Also


Back to top

Copyright © 2025 Ribose. PostScript is a trademark of Adobe. Distributed under the MIT License.