freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [Devel] pixel size, hinting and scaling


From: Graham Asher
Subject: RE: [Devel] pixel size, hinting and scaling
Date: Mon, 20 Jan 2003 16:06:52 -0000

Here's some working code that decomposes a FreeType matrix into scale and
the rest. I'd be grateful for comments. It converts the matrix's effect on a
vector pointing rightward into a new matrix representing the inverse of the
rotation. It then removes the rotation, stores the scale factors, removes
the scales, and adds the rotation back. The scales are forced positive so
that they can be used to set pixel sizes without further manipulation (apart
from converting to 1/64 pixels).

I developed this code as part of my work for Artifex on the
GhostScript-to-FreeType bridge.

Graham Asher

code follows:


static void transform_concat(FT_Matrix* a_A,const FT_Matrix* a_B)
        {
        FT_Matrix result = *a_B;
        FT_Matrix_Multiply(a_A,&result);
        *a_A = result;
        }

/** Create a transform representing an angle defined as a vector. */
static void make_rotation(FT_Matrix* a_transform,const FT_Vector* a_vector)
        {
        FT_Fixed length, cos, sin;
        if (a_vector->x >= 0 && a_vector->y == 0)
                {
                a_transform->xx = a_transform->yy = 65536;
                a_transform->xy = a_transform->yx = 0;
                return;
                }

        length = FT_Vector_Length((FT_Vector*)a_vector);
        cos = FT_DivFix(a_vector->x,length);
        sin = FT_DivFix(a_vector->y,length);
        a_transform->xx = a_transform->yy = cos;
        a_transform->xy = -sin;
        a_transform->yx = sin;
        }

/**
Divide a transformation into a scaling part and a rotation-and-shear part.
The scaling part is used for setting the pixel size for hinting.
*/
static void transform_decompose(FT_Matrix* a_transform,FT_Fixed*
a_x_scale,FT_Fixed* a_y_scale)
        {
        FT_Matrix rotation;
        bool have_rotation = false;
        FT_Vector v;

        /*
        Set v to the result of applying the matrix to the (1,0) vector
        and reverse the direction of rotation by negating the y coordinate.
        */
        v.x = a_transform->xx;
        v.y = -a_transform->yx;
        if (v.y || v.x < 0)
                {
                have_rotation = true;

                /* Get the inverse of the rotation. */
                make_rotation(&rotation,&v);

                /* Remove the rotation. */
                transform_concat(a_transform,&rotation);
                }

        /* Get the scales. */
        *a_x_scale = a_transform->xx;
        if (*a_x_scale < 0)
                *a_x_scale = -*a_x_scale;
        *a_y_scale = a_transform->yy;
        if (*a_y_scale < 0)
                *a_y_scale = -*a_y_scale;

        /* Remove the scales. */
        a_transform->xx = 65536;
        a_transform->yx = FT_DivFix(a_transform->yx,*a_x_scale);
        a_transform->xy = FT_DivFix(a_transform->xy,*a_y_scale);
        a_transform->yy = 65536;

        if (have_rotation)
                {
                /* Add back the rotation. */
                rotation.xy = -rotation.xy;
                rotation.yx = -rotation.yx;
                transform_concat(a_transform,&rotation);
                }
        }







reply via email to

[Prev in Thread] Current Thread [Next in Thread]