How to convert line width to device space using CTM?
The line width is essentially the size of the line perpendicular to its direction. Thus, in order to calculate the width after conversion using CTM, you select a plane vector perpendicular to the original line whose length is the width of the line from the current graphic state, apply CTM (without translating, i.e. setting e and f to 0) so that this vector (embedded in three-dimensional space, setting the third coordinate to 1) and calculating the length of the resulting 2D vector (projecting the first two coordinates).
eg. you have a line from (0,0) to (1,4) in the current coordinates of the user space with a width of 1. You need to find a vector perpendicular to it, for example. (-4,1) by rotating 90 Β° counterclockwise and scaling it to a length of 1, i.e. (-4 / sqrt (17), 1 / sqrt (17)) in this case.
If CTM is that of @Tikitu's answers
CTM has a horizontal scaling factor of 2 and a vertical scaling factor of 1
it will be
2 0 0 0 1 0 0 0 1
This matrix will cause the line from the above example to go from (0,0) to (2,4), and the "width vector" (-4 / sqrt (17), 1 / sqrt (17)) will be converted to (-8 / sqrt (17), 1 / sqrt (17)) (CTM no longer has a translation part) with a length of sqrt (65/17), which is about 1.955. That is, the width of the resulting line (its size perpendicular to its direction) is almost 2.
If the original row were (0,0) - (4,1) with a width of 1, the choice of the width vector would be (-1 / sqrt (17), 4 / sqrt (17)). In this case, the converted line will go from (0,0) to (8,1), and the width vector will be converted to (-2 / sqrt (17), 4 / sqrt (17)) with a length of sqrt (20/17) which is about 1,085. That is, the width of the resulting line (perpendicular to its direction) is slightly greater than 1.
It seems to you that you are interested in the "corners" of the line. To do this, you need to take the beginning and end of the converted line and add or subtract half the vector of the transformed width. In the above samples:
(source string from (0,0) to (1,4)): (-4 / sqrt (17), 1 / (2 * sqrt (17))), (4 / sqrt (17), (2-4 sqrt (17))), -1 / (2 * sqrt (17)));
(source string from (0,0) to (4,1)): (-1 / sqrt (17), 2 / sqrt (17)), (1 / sqrt (17), -2 / sqrt (17)) , (8-1 / sqrt (17), 1 + 2 / sqrt (17)), (8 + 1 / sqrt (17), 1-2 / sqrt (17)).
Remember, however, that PDF lines are often not trimmed at the end, but instead have some kind of cap. And besides that, remember the special value of line width 0.