- 1. idtransform
- 1.1. Syntax
- 1.2. Stack Effects
- 1.3. Description
- 1.4. PostScript Level
- 1.5. Examples
- 1.6. Common Use Cases
- 1.7. Common Pitfalls
- 1.8. Error Conditions
- 1.9. Implementation Notes
- 1.10. Transformation Formula
- 1.11. Delta Transform Pairs
- 1.12. Computing Device Pixel Size
- 1.13. Relationship to Graphics Parameters
- 1.14. Performance Considerations
- 1.15. See Also
1. idtransform
Transforms a distance vector from device space to user space (inverse delta transform).
1.2. Stack Effects
| Level | Object |
|---|---|
1 |
|
0 |
|
| Level | Object |
|---|---|
1 |
|
0 |
|
1.3. Description
With no matrix operand, idtransform (inverse delta transform) transforms the device space distance vector (dx', dy') by the inverse of the CTM to produce the corresponding distance vector (dx, dy) in user space.
If the matrix operand is supplied, idtransform transforms the distance vector by the inverse of matrix rather than by the inverse of CTM.
A delta transformation is similar to a normal transformation, but the translation components (tx and ty) of the transformation matrix are not used, making the distance vectors position-independent in both user space and device space.
idtransform is the inverse of dtransform. It is useful for determining how distances map from device space to user space.
1.5. Examples
2 2 scale
100 200 dtransform
% → 200.0 400.0
200 400 idtransform
% → 100.0 200.0 (back to original)
100 100 translate
2 2 scale
% Distance transformation ignores translation
100 100 idtransform
% → 50.0 50.0 (only scaling reversed)
72 72 scale % 72 points per inch
1 1 idtransform
% → 0.0138... 0.0138... (1 pixel ≈ 1/72 inch)
1.6. Common Use Cases
1.6.1. Converting Device Units to User Units
% How much is 1 device pixel in user space?
2 2 scale
1 0 idtransform pop
% → 0.5 (1 device pixel = 0.5 user units)
1.6.2. Computing User Space Line Width
% What line width in user space gives 1 device pixel?
/deviceLineWidth 1 def
deviceLineWidth 0 idtransform abs exch abs max
setlinewidth
% Now line appears as 1 device pixel regardless of scale
1.7. Common Pitfalls
For Distances Only - idtransform is for distance vectors, not positions.
|
100 100 translate
2 2 scale
% Wrong - for point coordinates:
300 400 idtransform % → 150 200 (incorrect)
300 400 itransform % → 100 150 (correct)
% Right - for distances:
200 400 idtransform % → 100 200 (correct distance)
Singular Matrices - If CTM or matrix is singular, idtransform fails.
|
0 0 scale % Singular matrix (determinant = 0)
100 100 idtransform % Error: undefinedresult
| Different from itransform - These are not the same! |
100 100 translate
100 100 itransform % → 0 0 (point transformation)
100 100 idtransform % → 100 100 (distance transformation)
| Use for Scale-Independent Sizing - Compute sizes that remain constant in device space: |
% Draw circle with fixed device radius
/drawDeviceCircle { % deviceRadius
0 exch idtransform % Convert to user space
/radiusY exch def
/radiusX exch def
% Draw ellipse if non-uniform scaling
0 0 radiusX radiusY scale
0 0 1 0 360 arc
} def
5 drawDeviceCircle % Always 5 device pixels radius
| Round-Trip Testing - Verify inverse relationship: |
/testDelta { % dx dy
2 copy dtransform idtransform
3 -1 roll sub abs 0.001 lt
3 1 roll exch sub abs 0.001 lt and
} def
100 200 testDelta % Should return true
1.8. Error Conditions
| Error | Condition |
|---|---|
[ |
Matrix operand does not have exactly 6 elements |
[ |
Fewer than 2 operands on stack (first form) or fewer than 3 (second form) |
[ |
Operands are not numbers, or matrix operand is not an array |
[ |
CTM or matrix is singular (determinant = 0) and cannot be inverted |
1.9. Implementation Notes
-
More expensive than
dtransform(requires inverse computation) -
Translation components are explicitly ignored
-
The inverse uses only [a b c d] components
-
Precision depends on matrix condition number
-
No caching of inverse matrix
1.10. Transformation Formula
For CTM = [a b c d tx ty], the inverse delta transformation is:
det = a×d - b×c dx = (d×dx' - c×dy') / det dy = (a×dy' - b×dx') / det
Note: tx and ty are not used.
Example with CTM = [2 0 0 3 100 100]:
det = 2×3 - 0×0 = 6 (20, 60) inverse delta transforms to: dx = (3×20 - 0×60) / 6 = 60/6 = 10 dy = (2×60 - 0×20) / 6 = 120/6 = 20 → (10, 20)
1.11. Delta Transform Pairs
| Operation | Direction | Translation |
|---|---|---|
User → Device |
Ignored |
|
Device → User |
Ignored |
|
User → Device |
Included |
|
Device → User |
Included |
1.12. Computing Device Pixel Size
% Determine size of device pixel in current user space
/getPixelSize {
% Returns width and height of device pixel
1 0 idtransform abs exch abs % X direction
0 1 idtransform abs exch abs % Y direction
} def
2 3 scale
getPixelSize
% → 0.5 0.333... (pixel is 0.5×0.333 user units)
1.13. Relationship to Graphics Parameters
Many graphics parameters are affected by transformations:
% Line width:
% User space width → dtransform → device width
% Device width → idtransform → user space width
% Dash pattern:
% User space lengths → dtransform → device lengths
% Device lengths → idtransform → user space lengths
% Character widths:
% Font space → dtransform → device pixels
% Device pixels → idtransform → font space
1.14. Performance Considerations
-
Requires matrix inversion computation
-
More expensive than
dtransform -
Still very fast for occasional use
-
Consider caching inverse matrix for repeated use:
% Inefficient:
{
deviceDX deviceDY idtransform
% ... process ...
} repeat
% Efficient:
matrix currentmatrix matrix invertmatrix
/inverseMatrix exch def
{
deviceDX deviceDY inverseMatrix dtransform
% ... process ...
} repeat
1.15. See Also
-
dtransform- Transform distance vector (forward) -
transform- Transform coordinates (includes translation) -
itransform- Inverse coordinate transformation -
invertmatrix- Invert transformation matrix -
currentmatrix- Get current CTM -
setlinewidth- Set line width