Transforms

The fz_matrix structure is used to represent 2 dimensional matrices used for transforming points, shapes and other geometry.

The six fields of the fz_matrix structure correspond to a matrix of the form:


\begin{displaymath}\left(
\begin{array}{ccc}
a & b & 0 \\
c & d & 0 \\
e & f & 1
\end{array}\right) \end{displaymath}

Such transformation matrices can be used to represent a wide range of different operations, including translations, rotations, scales, sheers, and any combination thereof.

Typically, a matrix will be created for a specific purpose, such as a scale, or a translation. For this reason, we have dedicated construction calls.


\begin{lstlisting}
/*
fz_scale: Create a scaling matrix.
\par
The returned matr...
....
*/
fz_matrix *fz_translate(fz_matrix *m, float tx, float ty);
\end{lstlisting}

Mathematically, points are transformed by multiplying them (extended to 3 elements long). For example (x',y'), the point given by mapping (x,y) through such a matrix is calculated as follows:


\begin{displaymath}
\left(
\begin{array}{ccc}
x' & y' & 1
\end{array}\right)
=
\...
...{ccc}
a & b & 0 \\
c & d & 0 \\
e & f & 1
\end{array}\right)
\end{displaymath}

There are various functions in MuPDF to perform such transformations:


\begin{lstlisting}
/*
fz_transform_point: Apply a transformation to a point.
\p...
... point, const fz_matrix *restrict transform, float x, float y);
\end{lstlisting}

Rectangles can be transformed using the following function, which allows for the fact that the image of a rectangle may `flip' the rectangle (i.e. that a minimum coordinate may end up as a maximum one after translation, and vice versa):


\begin{lstlisting}
/*
fz_transform_rect: Apply a transform to a rectangle.
\par...
...t(fz_rect *restrict rect, const fz_matrix *restrict transform);
\end{lstlisting}

Also, it can be useful to transform a point, ignoring the translation components of a transformation, so we have a convenience function for this:


\begin{lstlisting}
/*
fz_transform_vector: Apply a transformation to a vector.
...
...z_point *restrict vector, const fz_matrix *restrict transform);
\end{lstlisting}

Transformations can be combined by multiplying their representative matrices together. Transforming a point by applying matrix A then matrix B, will give identical results to transforming the point by AB.

MuPDF provides an API for combining matrices in this way:


\begin{lstlisting}
/*
fz_concat: Multiply two matrices.
\par
The order of the t...
...matrix *result, const fz_matrix *left, const fz_matrix *right);
\end{lstlisting}

Alternatively, operations can be specifically applied to existing matrices. Because of the non-commutative nature of matrix operations, it matters whether the new operation is applied before or after the existing matrix.

For example, if you have a matrix that performs a rotation, and you wish to combine that with a translation, you must decide whether you want the translation to occur before the rotation (`pre') or afterwards (`post').

MuPDF has various API functions for such operations:


\begin{lstlisting}
/*
fz_pre_scale: Scale a matrix by premultiplication.
\par
m...
...
fz_matrix *fz_pre_translate(fz_matrix *m, float tx, float ty);
\end{lstlisting}

Finally, sometimes it is useful to find the matrix that would represent the reverse of a given transformation. This can be achieved by `inverting' the matrix. This is not possible in all cases, but can be achieved for most `well-behaved' transformations.


\begin{lstlisting}
/*
fz_invert_matrix: Create an inverse matrix.
\par
inverse:...
...try_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
\end{lstlisting}