> > How can I get FreeType2 to draw only the outline of my FT_Outline
> > object with a fixed pixel stroke width?
> 
> Have a look at the function `Render_Stroke' in the `ftview' demo
> program.  It uses the FreeType stroker API.

I have successfully adapted the code from the FT_Glyph_Stroke() API
used in the example mentioned above to work without FT_Glyphs as I'm
not working with glyphs but with paths stored in FT_Stroker objects.

There is only one remaining problem now: I want to apply a transformation
matrix before letting FreeType draw the unfilled shape. This is of
course possible using FT_Outline_Transform() but the problem is that
FT_Outline_Transform() will also apply the transformation matrix to
the outline stroke size and I don't want that. For example, I set
an outline stroke size of 8 pixels like this:

    FT_Stroker_Set(stroker, (int) ((double) 8.0 * 32.0), 
FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);                       

Now when applying the following transformation matrix, the outline
stroke size is reduced to 4 pixels on the y-axis:

    m.xx = Float2Fixed(1.0);
    m.xy = Float2Fixed(0.0);
    m.yx = Float2Fixed(0.0);
    m.yy = Float2Fixed(0.5);

But I don't want this! I want FreeType to use a constant outline stroke
size. The outline stroke size should always be the value that has been
set with FT_Stroker_Set(). Transformations shouldn't change the outline
stroke size. It should always be of size 8 pixels or whatever has been
set using FT_Stroker_Set().

Unfortunately, it is not possible to apply a transformation matrix to
an FT_Stroker AFAICS. If that was possible, I could first apply the
transformation matrix to the stroker and then export it into an FT_Outline.
This would probably leave the outline stroke size intact. But as of
now, I first have to export the path from the FT_Stroker object into
an FT_Outline, and then apply the matrix. This leads to the matrix
getting applied to the outline stroke size as well which I don't
want.

Is there any way around this?

I attach a small example source that shows the problem.

Marco
#include <stdio.h>
#include <math.h>

#include <ft2build.h> 
#include FT_FREETYPE_H 
#include FT_GLYPH_H 
#include FT_OUTLINE_H 
#include FT_SYNTHESIS_H 
#include FT_STROKER_H

static FT_Library freetype_library = NULL;
 
#define WIDTH 320
#define HEIGHT 240

// desired stroke thickness in pixels
#define STROKE_THICKNESS 8

#define setvector(pv, px, py) (pv).x = ((int) (px)) << 6; (pv).y = ((int) (py)) 
<< 6;
#define Float2Fixed(fl) ((FT_Fixed)((fl)*65536.0f))

int main(int argc, char *argv[])
{
        FT_Stroker stroker;
        FT_UInt points, contours;
        FT_Outline outline;
        FT_BBox bbox;
        FT_Bitmap bm;   
        FT_Vector v;
        FT_Matrix m;
        int x, y, xmin, ymin, xmax, ymax, pixelwidth, pixelheight;
        unsigned char *buf;
                        
        FT_Init_FreeType(&freetype_library);
        
        FT_Stroker_New(freetype_library, &stroker);

        FT_Stroker_Set(stroker, (int) ((double) STROKE_THICKNESS * 32.0), 
FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);                      

        setvector(v, 0, 0);
        FT_Stroker_BeginSubPath(stroker, &v, 1);
        FT_Stroker_LineTo(stroker, &v);
                
        setvector(v, 0, 0);
        FT_Stroker_LineTo(stroker, &v);

        setvector(v, 0, HEIGHT);
        FT_Stroker_LineTo(stroker, &v);

        setvector(v, WIDTH, HEIGHT);
        FT_Stroker_LineTo(stroker, &v);                 

        setvector(v, WIDTH, 0);
        FT_Stroker_LineTo(stroker, &v);                 

        setvector(v, 0, 0);
        FT_Stroker_LineTo(stroker, &v);
                                        
        FT_Stroker_EndSubPath(stroker);
        
        FT_Stroker_GetBorderCounts(stroker, FT_STROKER_BORDER_LEFT, &points, 
&contours);
                
        memset(&outline, 0, sizeof(FT_Outline));
        FT_Outline_New(freetype_library, 1024, 512, &outline);

        outline.n_points = 0;
        outline.n_contours = 0;
        FT_Stroker_Export(stroker, &outline);   
        
        FT_Stroker_ParseOutline(stroker, &outline, 0); 
        FT_Stroker_GetCounts(stroker, &points, &contours);
                        
        FT_Stroker_Done(stroker);
        
        // this transformation will reduce STROKE_THICKNESS on the y-axis to 
STROKE_THICKNESS*0.5
        // but I don't want this! STROKE_THICKNESS should always be the 
constant value that has
        // been set in FT_Stroker_Set() --- no matter which transformation 
matrix has been applied!
        m.xx = Float2Fixed(1.0);
        m.xy = Float2Fixed(0.0);
        m.yx = Float2Fixed(0.0);
        m.yy = Float2Fixed(0.5);
                
        FT_Outline_Transform(&outline, &m);     
        
        FT_Outline_Get_BBox(&outline, &bbox);
        FT_Outline_Translate(&outline, -bbox.xMin, -bbox.yMin);
        FT_Outline_Get_BBox(&outline, &bbox);                           

        xmin = bbox.xMin >> 6;
        ymin = bbox.yMin >> 6;
        xmax = bbox.xMax >> 6;
        ymax = bbox.yMax >> 6;
                
        if(bbox.xMax & 0x3f) xmax++;
        if(bbox.yMax & 0x3f) ymax++;

        pixelwidth = xmax - xmin;
        pixelheight = ymax - ymin;
        
        buf = calloc(pixelwidth * pixelheight, 1);
                                        
        memset(&bm, 0, sizeof(FT_Bitmap));
        bm.rows = pixelheight;
        bm.width = pixelwidth;
        bm.pitch = pixelwidth;
        bm.buffer = buf;
        bm.num_grays = 256;
        bm.pixel_mode = FT_PIXEL_MODE_GRAY;

        FT_Outline_Get_Bitmap(freetype_library, &outline, &bm);
        
        free(buf);
        
        FT_Outline_Done(freetype_library, &outline);    
        FT_Done_FreeType(freetype_library);
                        
        return 0;
}
        
_______________________________________________
Freetype mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype

Reply via email to