[Top][All Lists]
[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>
- RE: [Devel] pixel size, hinting and scaling,
Gustavo J. A. M. <=