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: Gustavo J. A. M.
Subject: RE: [Devel] pixel size, hinting and scaling
Date: 12 Feb 2003 13:15:18 +0000

On Fri, 2003-01-24 at 19:20, Graham Asher wrote:
> <<<<<<
> On Fri, 2003-01-24 at 18:45, Graham Asher wrote:
> > <<<<<<
> > Regarding the subject of decomposing a transformation matrix into
> > (scale x rest), libart_lgpl has this function that is probably what you
> > want:
> > >>>>>>
> >
> > Unfortunately not. What we need is something that gives the two separate x
> > and y scale factors.
> 
>  You can always call FT_Set_Char_Size(face, s, s). Then, you can get the
> rest of the transformation with:
>                T = R x S
>       INV(R) x T = S
> 
>       where S = | s  0 |
>                 | 0  s |
>       and
>             s = art_affine_expansion(T);
> 
>   This should produce similar results... more or less :)

  I screwed up. I meant something, and wrote another thing :)
  However, the principle stands. What I meant is this:

        T - total (global) transformation matrix
        R - "the Rest" of the transformation (leftover, if you will)
            after scaling is removed.
        S - the scaling part of the transformation
                S = |s 0|
                    |0 s|
                s = art_affine_expansion(T)
  Equations:
        T          = R x S
        T x INV(S) = R

  You call:
        FT_Set_Char_Size(face, s, s)

  Then use the affine R:
        FT_Glyph_Transform(glyph, R, NULL)

  It's pure algebra. The advantage of this approach is simplicity,
accuracy, and generality, since I get the impression you are assuming
that R is rotation only.
  
  In fact, this weekend I have put my theory to work with great results!
I could even activate hinting, so that all glyphs actually load and the
rendering looks much better! Here's the code I used. If I made yet
another mistake above, the code is copy-paste and it works:

/* Initialize font->char_width, font->char_height, font->ft_transf */
static void nxplot_artft_font_init_transf(NxplotArtftFont *font)
{
    double s;
    double scale_inv[6], rest[6];

    /*          T = R x S */
    /* T x INV(S) = R     */
    s = art_affine_expansion(font->transf);
    font->char_height = s*64;
    font->char_width  = font->char_height;
    s = font->char_height / 64.0;
    art_affine_scale(scale_inv, 1/s, 1/s);
    art_affine_multiply(rest, font->transf, scale_inv);
    
    /* (x1,  y1,  x2,  y2,  x3,  y3)  */
    /* (xx,  yx,  xy,  yy )           */
    /* ([0], [1], [2], [3], [4], [5]) */
    font->ft_transf.xx = rest[0]*0x10000;
    font->ft_transf.xy = rest[2]*0x10000;
    font->ft_transf.yx = rest[1]*0x10000;
    font->ft_transf.yy = rest[3]*0x10000;
}

Notes:
  o font->transf is double[6], a libart affine transformation matrix
  o font->ft_trans is an FT_Matrix


> >>>>>>
> 
> Er... no - I think there is a misunderstanding. Your explanation seems to
> state that R (by which I suppose you to mean rotation) and S (scale) are
> already known. The function needed should decompose an affine transformation
> into two pieces:
> 
> 1. A transformation that performs scaling only and no shearing or rotation
> (your S).
> 
> 2. A transformation that performs the shearing and rotation only ( your R).
> 
> Concatenating the two transformations (i.e., multiplying the matrices) gives
> the original transformation. But this problem has already been solved (at
> least, to my satisfaction); I append my posting of 4 days ago. BUT - if you
> have a better way - by which I mean faster or more accurate - I would be
> interested in seeing it.
> 
> <<<<<<
> 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);
>               }
>       }
> >>>>>>
> 
> Graham Asher
> 
> 
> _______________________________________________
> Devel mailing list
> address@hidden
> http://www.freetype.org/mailman/listinfo/devel
-- 
Gustavo João Alves Marques Carneiro
<address@hidden> <address@hidden>





reply via email to

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