Example #1
0
  static FT_Error
  tt_size_request( FT_Size          size,
                   FT_Size_Request  req )
  {
    TT_Size   ttsize = (TT_Size)size;
    FT_Error  error  = TT_Err_Ok;


#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS

    if ( FT_HAS_FIXED_SIZES( size->face ) )
    {
      TT_Face       ttface = (TT_Face)size->face;
      SFNT_Service  sfnt   = (SFNT_Service) ttface->sfnt;
      FT_ULong      strike_index;


      error = sfnt->set_sbit_strike( ttface, req, &strike_index );

      if ( error )
        ttsize->strike_index = 0xFFFFFFFFUL;
      else
        return tt_size_select( size, strike_index );
    }

#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */

    FT_Request_Metrics( size->face, req );

    if ( FT_IS_SCALABLE( size->face ) )
    {
      error = tt_size_reset( ttsize );
      ttsize->root.metrics = ttsize->metrics;
    }

    return error;
  }
Example #2
0
	bool initFaceSize(Font font, const unsigned int size, const unsigned int res = 72)
	{
		FT_Face fontFace = font->ftFace;
		FT_Size fontSize;

		if (FT_Select_Charmap(fontFace, FT_ENCODING_UNICODE) || FT_Set_Char_Size(fontFace, 0L, size * 64, res, res))
			return false;

		font->charSize = size;
		fontSize = font->ftSize = fontFace->size;
	
		if(FT_IS_SCALABLE((fontFace)))
		{
			font->glyphWidth = (fontFace->bbox.xMax-fontFace->bbox.xMin) * ((float)(fontSize->metrics.x_ppem)/(float)(fontFace->units_per_EM));
			font->glyphHeight = (fontFace->bbox.yMax-fontFace->bbox.yMin) * ((float)fontSize->metrics.y_ppem/(float)fontFace->units_per_EM);
		}
		else
		{
			font->glyphWidth = static_cast<float>(fontSize->metrics.max_advance)/64.0f;
			font->glyphHeight = static_cast<float>(fontSize->metrics.height)/64.0f;
		}

		return true;
	}
Example #3
0
void font_instance::LoadGlyph(int glyph_id)
{
    if ( pFont == NULL ) {
        return;
    }
    InitTheFace();
#ifndef USE_PANGO_WIN32
    if ( !FT_IS_SCALABLE(theFace) ) {
        return; // bitmap font
    }
#endif

    if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
        Geom::PathBuilder path_builder;

        if ( nbGlyph >= maxGlyph ) {
            maxGlyph=2*nbGlyph+1;
            glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
        }
        font_glyph  n_g;
        n_g.pathvector=NULL;
        n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
        n_g.h_advance = 0;
        n_g.v_advance = 0;
        n_g.h_width = 0;
        n_g.v_width = 0;
        bool   doAdd=false;

#ifdef USE_PANGO_WIN32

#ifndef GGO_UNHINTED         // For compatibility with old SDKs.
#define GGO_UNHINTED 0x0100
#endif

        MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
        OUTLINETEXTMETRIC otm;
        GetOutlineTextMetrics(daddy->hScreenDC, sizeof(otm), &otm);
        GLYPHMETRICS metrics;
        DWORD bufferSize=GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
        double scale=1.0/daddy->fontSize;
        n_g.h_advance=metrics.gmCellIncX*scale;
        n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
        n_g.h_width=metrics.gmBlackBoxX*scale;
        n_g.v_width=metrics.gmBlackBoxY*scale;
        if ( bufferSize == GDI_ERROR) {
            // shit happened
        } else if ( bufferSize == 0) {
            // character has no visual representation, but is valid (eg whitespace)
            doAdd=true;
        } else {
            char *buffer = new char[bufferSize];
            if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
                // shit happened
            } else {
                // Platform SDK is rubbish, read KB87115 instead
                DWORD polyOffset=0;
                while ( polyOffset < bufferSize ) {
                    TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
                    if (polyOffset+polyHeader->cb > bufferSize) break;

                    if (polyHeader->dwType == TT_POLYGON_TYPE) {
                        path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
                        DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);

                        while ( curveOffset < polyOffset+polyHeader->cb ) {
                            TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
                            POINTFX const *p=polyCurve->apfx;
                            POINTFX const *endp=p+polyCurve->cpfx;

                            switch (polyCurve->wType) {
                            case TT_PRIM_LINE:
                                while ( p != endp )
                                    path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
                                break;

                            case TT_PRIM_QSPLINE:
                                {
                                    g_assert(polyCurve->cpfx >= 2);

                                    // The list of points specifies one or more control points and ends with the end point.
                                    // The intermediate points (on the curve) are the points between the control points.
                                    Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
                                    while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
                                        Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
                                        path_builder.quadTo(this_control, (new_control+this_control)/2);
                                        this_control = new_control;
                                    }
                                    Geom::Point end = pointfx_to_nrpoint(*p++, scale);
                                    path_builder.quadTo(this_control, end);
                                }
                                break;

                            case 3:  // TT_PRIM_CSPLINE
                                g_assert(polyCurve->cpfx % 3 == 0);
                                while ( p != endp ) {
                                    path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
                                                         pointfx_to_nrpoint(p[1], scale),
                                                         pointfx_to_nrpoint(p[2], scale));
                                    p += 3;
                                }
                                break;
                            }
                            curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
                        }
                    }
                    polyOffset += polyHeader->cb;
                }
                doAdd=true;
            }
            delete [] buffer;
        }
#else
        if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
            // shit happened
        } else {
            if ( FT_HAS_HORIZONTAL(theFace) ) {
                n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
                n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
            } else {
                n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
            }
            if ( FT_HAS_VERTICAL(theFace) ) {
                n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
                n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
            } else {
                n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
            }
            if ( theFace->glyph->format == ft_glyph_format_outline ) {
                FT_Outline_Funcs ft2_outline_funcs = {
                    ft2_move_to,
                    ft2_line_to,
                    ft2_conic_to,
                    ft2_cubic_to,
                    0, 0
                };
                FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
                FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
            }
            doAdd=true;
        }
#endif
        path_builder.finish();

        if ( doAdd ) {
            Geom::PathVector pv = path_builder.peek();
            // close all paths
            for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
                i->close();
            }
            if ( !pv.empty() ) {
                n_g.pathvector = new Geom::PathVector(pv);
                Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
                if (bounds) {
                    n_g.bbox[0] = bounds->left();
                    n_g.bbox[1] = bounds->top();
                    n_g.bbox[2] = bounds->right();
                    n_g.bbox[3] = bounds->bottom();
                }
            }
            glyphs[nbGlyph]=n_g;
            id_to_no[glyph_id]=nbGlyph;
            nbGlyph++;
        }
    } else {
    }
}
Example #4
0
sfnt_load_face(FT_Stream stream,
               TT_Face face,
               FT_Int face_index,
               FT_Int num_params,
               FT_Parameter * params)
{
    FT_Error error;

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    FT_Error psnames_error;
#endif
    FT_Bool has_outline;
    FT_Bool is_apple_sbit;
    FT_Bool ignore_preferred_family    = FALSE;
    FT_Bool ignore_preferred_subfamily = FALSE;

    SFNT_Service sfnt = (SFNT_Service)face->sfnt;

    FT_UNUSED(face_index);

    /* Check parameters */

    {
        FT_Int i;


        for (i = 0; i < num_params; i++)
        {
            if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY)
                ignore_preferred_family = TRUE;
            else if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY)
                ignore_preferred_subfamily = TRUE;
        }
    }

    /* Load tables */

    /* We now support two SFNT-based bitmapped font formats.  They */
    /* are recognized easily as they do not include a `glyf'       */
    /* table.                                                      */
    /*                                                             */
    /* The first format comes from Apple, and uses a table named   */
    /* `bhed' instead of `head' to store the font header (using    */
    /* the same format).  It also doesn't include horizontal and   */
    /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
    /* missing).                                                   */
    /*                                                             */
    /* The other format comes from Microsoft, and is used with     */
    /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
    /* it doesn't contain outlines.                                */
    /*                                                             */

    FT_TRACE2(("sfnt_load_face: %08p\n\n", face));

    /* do we have outlines in there? */
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    has_outline = FT_BOOL(face->root.internal->incremental_interface != 0 ||
                          tt_face_lookup_table(face, TTAG_glyf) != 0 ||
                          tt_face_lookup_table(face, TTAG_CFF) != 0);
#else
    has_outline = FT_BOOL(tt_face_lookup_table(face, TTAG_glyf) != 0 ||
                          tt_face_lookup_table(face, TTAG_CFF) != 0);
#endif

    is_apple_sbit = 0;

    /* if this font doesn't contain outlines, we try to load */
    /* a `bhed' table                                        */
    if (!has_outline && sfnt->load_bhed)
    {
        LOAD_(bhed);
        is_apple_sbit = FT_BOOL(!error);
    }

    /* load the font header (`head' table) if this isn't an Apple */
    /* sbit font file                                             */
    if (!is_apple_sbit)
    {
        LOAD_(head);
        if (error)
            goto Exit;
    }

    if (face->header.Units_Per_EM == 0)
    {
        error = SFNT_Err_Invalid_Table;

        goto Exit;
    }

    /* the following tables are often not present in embedded TrueType */
    /* fonts within PDF documents, so don't check for them.            */
    LOAD_(maxp);
    LOAD_(cmap);

    /* the following tables are optional in PCL fonts -- */
    /* don't check for errors                            */
    LOAD_(name);
    LOAD_(post);

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    psnames_error = error;
#endif

    /* do not load the metrics headers and tables if this is an Apple */
    /* sbit font file                                                 */
    if (!is_apple_sbit)
    {
        /* load the `hhea' and `hmtx' tables */
        LOADM_(hhea, 0);
        if (!error)
        {
            LOADM_(hmtx, 0);
            if (error == SFNT_Err_Table_Missing)
            {
                error = SFNT_Err_Hmtx_Table_Missing;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
                /* If this is an incrementally loaded font and there are */
                /* overriding metrics, tolerate a missing `hmtx' table.  */
                if (face->root.internal->incremental_interface &&
                    face->root.internal->incremental_interface->funcs->
                    get_glyph_metrics)
                {
                    face->horizontal.number_Of_HMetrics = 0;
                    error                               = SFNT_Err_Ok;
                }
#endif
            }
        }
        else if (error == SFNT_Err_Table_Missing)
        {
            /* No `hhea' table necessary for SFNT Mac fonts. */
            if (face->format_tag == TTAG_true)
            {
                FT_TRACE2(("This is an SFNT Mac font.\n"));
                has_outline = 0;
                error       = SFNT_Err_Ok;
            }
            else
            {
                error = SFNT_Err_Horiz_Header_Missing;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
                /* If this is an incrementally loaded font and there are */
                /* overriding metrics, tolerate a missing `hhea' table.  */
                if (face->root.internal->incremental_interface &&
                    face->root.internal->incremental_interface->funcs->
                    get_glyph_metrics)
                {
                    face->horizontal.number_Of_HMetrics = 0;
                    error                               = SFNT_Err_Ok;
                }
#endif
            }
        }

        if (error)
            goto Exit;

        /* try to load the `vhea' and `vmtx' tables */
        LOADM_(hhea, 1);
        if (!error)
        {
            LOADM_(hmtx, 1);
            if (!error)
                face->vertical_info = 1;
        }

        if (error && error != SFNT_Err_Table_Missing)
            goto Exit;

        LOAD_(os2);
        if (error)
        {
            if (error != SFNT_Err_Table_Missing)
                goto Exit;

            face->os2.version = 0xFFFFU;
        }
    }

    /* the optional tables */

    /* embedded bitmap support */
    if (sfnt->load_eblc)
    {
        LOAD_(eblc);
        if (error)
        {
            /* a font which contains neither bitmaps nor outlines is */
            /* still valid (although rather useless in most cases);  */
            /* however, you can find such stripped fonts in PDFs     */
            if (error == SFNT_Err_Table_Missing)
                error = SFNT_Err_Ok;
            else
                goto Exit;
        }
    }

    LOAD_(pclt);
    if (error)
    {
        if (error != SFNT_Err_Table_Missing)
            goto Exit;

        face->pclt.Version = 0;
    }

    /* consider the kerning and gasp tables as optional */
    LOAD_(gasp);
    LOAD_(kern);

    face->root.num_glyphs = face->max_profile.numGlyphs;

    /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
    /* a WWS-only font face.  `WWS' stands for `weight', width', and */
    /* `slope', a term used by Microsoft's Windows Presentation      */
    /* Foundation (WPF).  This flag has been introduced in version   */
    /* 1.5 of the OpenType specification (May 2008).                 */

    face->root.family_name = NULL;
    face->root.style_name  = NULL;
    if (face->os2.version != 0xFFFFU && face->os2.fsSelection & 256)
    {
        if (!ignore_preferred_family)
            GET_NAME(PREFERRED_FAMILY, &face->root.family_name);

        if (!face->root.family_name)
            GET_NAME(FONT_FAMILY, &face->root.family_name);

        if (!ignore_preferred_subfamily)
            GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name);

        if (!face->root.style_name)
            GET_NAME(FONT_SUBFAMILY, &face->root.style_name);
    }
    else
    {
        GET_NAME(WWS_FAMILY, &face->root.family_name);
        if (!face->root.family_name && !ignore_preferred_family)
            GET_NAME(PREFERRED_FAMILY, &face->root.family_name);

        if (!face->root.family_name)
            GET_NAME(FONT_FAMILY, &face->root.family_name);

        GET_NAME(WWS_SUBFAMILY, &face->root.style_name);
        if (!face->root.style_name && !ignore_preferred_subfamily)
            GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name);

        if (!face->root.style_name)
            GET_NAME(FONT_SUBFAMILY, &face->root.style_name);
    }

    /* now set up root fields */
    {
        FT_Face root  = &face->root;
        FT_Long flags = root->face_flags;


        /*********************************************************************/
        /*                                                                   */
        /* Compute face flags.                                               */
        /*                                                                   */
        if (has_outline == TRUE)
            flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */

        /* The sfnt driver only supports bitmap fonts natively, thus we */
        /* don't set FT_FACE_FLAG_HINTER.                               */
        flags |= FT_FACE_FLAG_SFNT |      /* SFNT file format  */
                 FT_FACE_FLAG_HORIZONTAL; /* horizontal data   */

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
        if (psnames_error == SFNT_Err_Ok &&
            face->postscript.FormatType != 0x00030000L)
            flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif

        /* fixed width font? */
        if (face->postscript.isFixedPitch)
            flags |= FT_FACE_FLAG_FIXED_WIDTH;

        /* vertical information? */
        if (face->vertical_info)
            flags |= FT_FACE_FLAG_VERTICAL;

        /* kerning available ? */
        if (TT_FACE_HAS_KERNING(face))
            flags |= FT_FACE_FLAG_KERNING;

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
        /* Don't bother to load the tables unless somebody asks for them. */
        /* No need to do work which will (probably) not be used.          */
        if (tt_face_lookup_table(face, TTAG_glyf) != 0 &&
            tt_face_lookup_table(face, TTAG_fvar) != 0 &&
            tt_face_lookup_table(face, TTAG_gvar) != 0)
            flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
#endif

        root->face_flags = flags;

        /*********************************************************************/
        /*                                                                   */
        /* Compute style flags.                                              */
        /*                                                                   */

        flags = 0;
        if (has_outline == TRUE && face->os2.version != 0xFFFFU)
        {
            /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
            /* indicates an oblique font face.  This flag has been        */
            /* introduced in version 1.5 of the OpenType specification.   */

            if (face->os2.fsSelection & 512)     /* bit 9 */
                flags |= FT_STYLE_FLAG_ITALIC;
            else if (face->os2.fsSelection & 1)  /* bit 0 */
                flags |= FT_STYLE_FLAG_ITALIC;

            if (face->os2.fsSelection & 32)      /* bit 5 */
                flags |= FT_STYLE_FLAG_BOLD;
        }
        else
        {
            /* this is an old Mac font, use the header field */

            if (face->header.Mac_Style & 1)
                flags |= FT_STYLE_FLAG_BOLD;

            if (face->header.Mac_Style & 2)
                flags |= FT_STYLE_FLAG_ITALIC;
        }

        root->style_flags = flags;

        /*********************************************************************/
        /*                                                                   */
        /* Polish the charmaps.                                              */
        /*                                                                   */
        /*   Try to set the charmap encoding according to the platform &     */
        /*   encoding ID of each charmap.                                    */
        /*                                                                   */

        tt_face_build_cmaps(face);  /* ignore errors */


        /* set the encoding fields */
        {
            FT_Int m;


            for (m = 0; m < root->num_charmaps; m++)
            {
                FT_CharMap charmap = root->charmaps[m];


                charmap->encoding = sfnt_find_encoding(charmap->platform_id,
                                                       charmap->encoding_id);

#if 0
                if (root->charmap == NULL &&
                    charmap->encoding == FT_ENCODING_UNICODE)
                {
                    /* set 'root->charmap' to the first Unicode encoding we find */
                    root->charmap = charmap;
                }
#endif
            }
        }

#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
        /*
         *  Now allocate the root array of FT_Bitmap_Size records and
         *  populate them.  Unfortunately, it isn't possible to indicate bit
         *  depths in the FT_Bitmap_Size record.  This is a design error.
         */
        {
            FT_UInt i, count;


#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
            count = face->sbit_num_strikes;
#else
            count = (FT_UInt)face->num_sbit_strikes;
#endif

            if (count > 0)
            {
                FT_Memory       memory   = face->root.stream->memory;
                FT_UShort       em_size  = face->header.Units_Per_EM;
                FT_Short        avgwidth = face->os2.xAvgCharWidth;
                FT_Size_Metrics metrics;


                if (em_size == 0 || face->os2.version == 0xFFFFU)
                {
                    avgwidth = 0;
                    em_size  = 1;
                }

                if (FT_NEW_ARRAY(root->available_sizes, count))
                    goto Exit;

                for (i = 0; i < count; i++)
                {
                    FT_Bitmap_Size *bsize = root->available_sizes + i;


                    error = sfnt->load_strike_metrics(face, i, &metrics);
                    if (error)
                        goto Exit;

                    bsize->height = (FT_Short)(metrics.height >> 6);
                    bsize->width  = (FT_Short)(
                        (avgwidth * metrics.x_ppem + em_size / 2) / em_size);

                    bsize->x_ppem = metrics.x_ppem << 6;
                    bsize->y_ppem = metrics.y_ppem << 6;

                    /* assume 72dpi */
                    bsize->size = metrics.y_ppem << 6;
                }

                root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
                root->num_fixed_sizes = (FT_Int)count;
            }
        }
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */

        /* a font with no bitmaps and no outlines is scalable; */
        /* it has only empty glyphs then                       */
        if (!FT_HAS_FIXED_SIZES(root) && !FT_IS_SCALABLE(root))
            root->face_flags |= FT_FACE_FLAG_SCALABLE;


        /*********************************************************************/
        /*                                                                   */
        /*  Set up metrics.                                                  */
        /*                                                                   */
        if (FT_IS_SCALABLE(root))
        {
            /* XXX What about if outline header is missing */
            /*     (e.g. sfnt wrapped bitmap)?             */
            root->bbox.xMin    = face->header.xMin;
            root->bbox.yMin    = face->header.yMin;
            root->bbox.xMax    = face->header.xMax;
            root->bbox.yMax    = face->header.yMax;
            root->units_per_EM = face->header.Units_Per_EM;


            /* XXX: Computing the ascender/descender/height is very different */
            /*      from what the specification tells you.  Apparently, we    */
            /*      must be careful because                                   */
            /*                                                                */
            /*      - not all fonts have an OS/2 table; in this case, we take */
            /*        the values in the horizontal header.  However, these    */
            /*        values very often are not reliable.                     */
            /*                                                                */
            /*      - otherwise, the correct typographic values are in the    */
            /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
            /*                                                                */
            /*        However, certain fonts have these fields set to 0.      */
            /*        Rather, they have usWinAscent & usWinDescent correctly  */
            /*        set (but with different values).                        */
            /*                                                                */
            /*      As an example, Arial Narrow is implemented through four   */
            /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
            /*                                                                */
            /*      Strangely, all fonts have the same values in their        */
            /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
            /*                                                                */
            /*      On the other hand, they all have different                */
            /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
            /*      table cannot be used to compute the text height reliably! */
            /*                                                                */

            /* The ascender/descender/height are computed from the OS/2 table */
            /* when found.  Otherwise, they're taken from the horizontal      */
            /* header.                                                        */
            /*                                                                */

            root->ascender  = face->horizontal.Ascender;
            root->descender = face->horizontal.Descender;

            root->height = (FT_Short)(root->ascender - root->descender +
                                      face->horizontal.Line_Gap);

#if 0
            /* if the line_gap is 0, we add an extra 15% to the text height --  */
            /* this computation is based on various versions of Times New Roman */
            if (face->horizontal.Line_Gap == 0)
                root->height = (FT_Short)((root->height * 115 + 50) / 100);
#endif /* 0 */

#if 0
            /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
            /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
            if (face->os2.version != 0xFFFFU && root->ascender)
            {
                FT_Int height;


                root->ascender  = face->os2.sTypoAscender;
                root->descender = -face->os2.sTypoDescender;

                height = root->ascender + root->descender + face->os2.sTypoLineGap;
                if (height > root->height)
                    root->height = height;
            }
#endif /* 0 */

            root->max_advance_width  = face->horizontal.advance_Width_Max;
            root->max_advance_height = (FT_Short)(face->vertical_info
                                                  ? face->vertical.advance_Height_Max
                                                  : root->height);

            /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
            /* Adjust underline position from top edge to centre of     */
            /* stroke to convert TrueType meaning to FreeType meaning.  */
            root->underline_position = face->postscript.underlinePosition -
                                       face->postscript.underlineThickness / 2;
            root->underline_thickness = face->postscript.underlineThickness;
        }
    }
EFontFT2::EFontFT2(const EEntry *entry, eint32 faceIndex)
	: EFontEngine(), fFilename(NULL), fFaceIndex(-1), nFaces(-1), fFace(NULL), fScalable(false), fForceFontAliasing(false)
{
	EPath aPath;
	if(entry == NULL || entry->Exists() == false || entry->GetPath(&aPath) != E_OK) return;
	EString filename = aPath.Path();
#ifdef _WIN32
	filename.ReplaceAll("/", "\\");
#endif

	SetRenderMode(E_FONT_RENDER_PIXMAP);

	EAutolock <ELocker> autolock(&etk_ft2_font_locker);
	if(!_etk_ft2_initialized_) return;

	FT_Error error = FT_New_Face(_etk_ft2_library_, filename.String(), faceIndex, &fFace);
	if(error || !fFace)
	{
		ETK_DEBUG("[FONT]: %s --- CAN NOT load face[%s:%d].", __PRETTY_FUNCTION__, aPath.Path(), faceIndex);
		return;
	}

	if(FT_Select_Charmap(fFace, FT_ENCODING_UNICODE))
	{
//		ETK_DEBUG("[FONT]: %s --- font[%s] don't support ENCODING_UNICODE.", __PRETTY_FUNCTION__, aPath.Path());

		if(FT_Select_Charmap(fFace, FT_ENCODING_NONE))
		{
//			ETK_WARNING("[FONT]: %s --- font[%s] don't support unicode at all.", __PRETTY_FUNCTION__, aPath.Path());
			FT_Done_Face(fFace);
			fFace = NULL;
			return;
		}
	}

	fFilename = EStrdup(filename.String());
	fFaceIndex = faceIndex;
	nFaces = fFace->num_faces;

	EString family = fFace->family_name;
	if(family.Length() <= 0)
	{
		family = aPath.Leaf();
		eint32 cFound;
		if((cFound = family.FindFirst('.')) >= 0) family.Remove(cFound, -1);
		if(family.Length() < 0) family = "Unknown";
	}
	SetFamily(family.String());

	EString style = fFace->style_name;
	if(style.Length() <= 0)
	{
		if((fFace->style_flags & FT_STYLE_FLAG_BOLD) && (fFace->style_flags & FT_STYLE_FLAG_ITALIC))
			style = "Bold Italic";
		else if(fFace->style_flags & FT_STYLE_FLAG_BOLD)
			style = "Bold";
		else if(fFace->style_flags & FT_STYLE_FLAG_ITALIC)
			style = "Italic";
		else
			style = "Regular";
	}
	SetStyle(style.String());

	if(FT_IS_SCALABLE(fFace)) fScalable = true;

	if(fFace->num_fixed_sizes > 0)
	{
		float *sizes = new float[(int)fFace->num_fixed_sizes];
		for(int i = 0; i < fFace->num_fixed_sizes; i++) sizes[i] = (float)(fFace->available_sizes[i].height);
		SetFixedSize(sizes, (eint32)fFace->num_fixed_sizes);
		delete[] sizes;
	}

	FT_Done_Face(fFace);
	fFace = NULL;
}
Example #6
0
static FT_Error
Load_Glyph(TTF_Font * font, Uint16 ch, c_glyph * cached, int want)
{
    FT_Face face;
    FT_Error error;
    FT_GlyphSlot glyph;
    FT_Glyph_Metrics *metrics;
    FT_Outline *outline;

    if(!font || !font->face)
    {
        return FT_Err_Invalid_Handle;
    }

    face = font->face;

    /* Load the glyph */
    if(!cached->index)
    {
        cached->index = FT_Get_Char_Index(face, ch);
    }
    error = FT_Load_Glyph(face, cached->index, FT_LOAD_DEFAULT);
    if(error)
    {
        return error;
    }

    /* Get our glyph shortcuts */
    glyph = face->glyph;
    metrics = &glyph->metrics;
    outline = &glyph->outline;

    /* Get the glyph metrics if desired */
    if((want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS))
    {
        if(FT_IS_SCALABLE(face))
        {
            /* Get the bounding box */
            cached->minx = FT_FLOOR(metrics->horiBearingX);
            cached->maxx = cached->minx + FT_CEIL(metrics->width);
            cached->maxy = FT_FLOOR(metrics->horiBearingY);
            cached->miny = cached->maxy - FT_CEIL(metrics->height);
            cached->yoffset = font->ascent - cached->maxy;
            cached->advance = FT_CEIL(metrics->horiAdvance);
        }
        else
        {
            /* Get the bounding box for non-scalable format.
             * Again, freetype2 fills in many of the font metrics
             * with the value of 0, so some of the values we
             * need must be calculated differently with certain
             * assumptions about non-scalable formats.
             * */
            cached->minx = FT_FLOOR(metrics->horiBearingX);
            cached->maxx = cached->minx + FT_CEIL(metrics->horiAdvance);
            cached->maxy = FT_FLOOR(metrics->horiBearingY);
            cached->miny =
                cached->maxy -
                FT_CEIL(face->available_sizes[font->font_size_family].height);
            cached->yoffset = 0;
            cached->advance = FT_CEIL(metrics->horiAdvance);
        }

        /* Adjust for bold and italic text */
        if(font->style & TTF_STYLE_BOLD)
        {
            cached->maxx += font->glyph_overhang;
        }
        if(font->style & TTF_STYLE_ITALIC)
        {
            cached->maxx += (int) ceil(font->glyph_italics);
        }
        cached->stored |= CACHED_METRICS;
    }

    if(((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
            ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)))
    {
        int mono = (want & CACHED_BITMAP);
        int i;
        FT_Bitmap *src;
        FT_Bitmap *dst;

        /* Handle the italic style */
        if(font->style & TTF_STYLE_ITALIC)
        {
            FT_Matrix shear;

            shear.xx = 1 << 16;
            shear.xy = (int) (font->glyph_italics * (1 << 16)) / font->height;
            shear.yx = 0;
            shear.yy = 1 << 16;

            FT_Outline_Transform(outline, &shear);
        }

        /* Render the glyph */
        if(mono)
        {
            error = FT_Render_Glyph(glyph, ft_render_mode_mono);
        }
        else
        {
            error = FT_Render_Glyph(glyph, ft_render_mode_normal);
        }
        if(error)
        {
            return error;
        }

        /* Copy over information to cache */
        src = &glyph->bitmap;
        if(mono)
        {
            dst = &cached->bitmap;
        }
        else
        {
            dst = &cached->pixmap;
        }
        memcpy(dst, src, sizeof(*dst));

        /* FT_Render_Glyph() and .fon fonts always generate a
         * two-color (black and white) glyphslot surface, even
         * when rendered in ft_render_mode_normal.  This is probably
         * a freetype2 bug because it is inconsistent with the
         * freetype2 documentation under FT_Render_Mode section.
         * */
        if(mono || !FT_IS_SCALABLE(face))
        {
            dst->pitch *= 8;
        }

        /* Adjust for bold and italic text */
        if(font->style & TTF_STYLE_BOLD)
        {
            int bump = font->glyph_overhang;

            dst->pitch += bump;
            dst->width += bump;
        }
        if(font->style & TTF_STYLE_ITALIC)
        {
            int bump = (int) ceil(font->glyph_italics);

            dst->pitch += bump;
            dst->width += bump;
        }

        if(dst->rows != 0)
        {
            dst->buffer = (unsigned char *) malloc(dst->pitch * dst->rows);
            if(!dst->buffer)
            {
                return FT_Err_Out_Of_Memory;
            }
            memset(dst->buffer, 0, dst->pitch * dst->rows);

            for(i = 0; i < src->rows; i++)
            {
                int soffset = i * src->pitch;
                int doffset = i * dst->pitch;

                if(mono)
                {
                    unsigned char *srcp = src->buffer + soffset;
                    unsigned char *dstp = dst->buffer + doffset;
                    int j;

                    for(j = 0; j < src->width; j += 8)
                    {
                        unsigned char ch = *srcp++;

                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                        ch <<= 1;
                        *dstp++ = (ch & 0x80) >> 7;
                    }
                }
                else if(!FT_IS_SCALABLE(face))
                {
                    /* This special case wouldn't
                     * be here if the FT_Render_Glyph()
                     * function wasn't buggy when it tried
                     * to render a .fon font with 256
                     * shades of gray.  Instead, it
                     * returns a black and white surface
                     * and we have to translate it back
                     * to a 256 gray shaded surface.
                     * */
                    unsigned char *srcp = src->buffer + soffset;
                    unsigned char *dstp = dst->buffer + doffset;
                    unsigned char ch;
                    int j, k;

                    for(j = 0; j < src->width; j += 8)
                    {
                        ch = *srcp++;
                        for(k = 0; k < 8; ++k)
                        {
                            if((ch & 0x80) >> 7)
                            {
                                *dstp++ = NUM_GRAYS - 1;
                            }
                            else
                            {
                                *dstp++ = 0x00;
                            }
                            ch <<= 1;
                        }
                    }
Example #7
0
bool TTFFont::load(Common::SeekableReadStream &stream, int size, bool monochrome, const uint32 *mapping) {
	if (!g_ttf.isInitialized())
		return false;

	_size = stream.size();
	if (!_size)
		return false;

	_ttfFile = new uint8[_size];
	assert(_ttfFile);

	if (stream.read(_ttfFile, _size) != _size) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	if (!g_ttf.loadFont(_ttfFile, _size, _face)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	// We only support scalable fonts.
	if (!FT_IS_SCALABLE(_face)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		g_ttf.closeFont(_face);

		return false;
	}

	// Check whether we have kerning support
	_hasKerning = (FT_HAS_KERNING(_face) != 0);

	if (FT_Set_Char_Size(_face, 0, size * 64, 0, 0)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	_monochrome = monochrome;

	FT_Fixed yScale = _face->size->metrics.y_scale;
	_ascent = ftCeil26_6(FT_MulFix(_face->ascender, yScale));
	_descent = ftCeil26_6(FT_MulFix(_face->descender, yScale));

	_width = ftCeil26_6(FT_MulFix(_face->max_advance_width, _face->size->metrics.x_scale));
	_height = _ascent - _descent + 1;

	if (!mapping) {
		// Load all ISO-8859-1 characters.
		for (uint i = 0; i < 256; ++i) {
			if (!cacheGlyph(_glyphs[i], _glyphSlots[i], i))
				_glyphSlots[i] = 0;
		}
	} else {
		for (uint i = 0; i < 256; ++i) {
			const uint32 unicode = mapping[i] & 0x7FFFFFFF;
			const bool isRequired = (mapping[i] & 0x80000000) != 0;
			// Check whether loading an important glyph fails and error out if
			// that is the case.
			if (!cacheGlyph(_glyphs[i], _glyphSlots[i], unicode)) {
				_glyphSlots[i] = 0;
				if (isRequired)
					return false;
			}
		}
	}

	_initialized = (_glyphs.size() != 0);
	return _initialized;
}
Example #8
0
    //------------------------------------------------------------------------
    bool font_engine_freetype_base::load_font(const char* font_name, 
                                              unsigned face_index,
                                              glyph_rendering ren_type,
                                              const char* font_mem, 
                                              const long font_mem_size)
    {
        bool ret = false;

        if(m_library_initialized)
        {
            m_last_error = 0;

            int idx = find_face(font_name);
            if(idx >= 0)
            {
                m_cur_face = m_faces[idx];
                m_name     = m_face_names[idx];
            }
            else
            {
                if(m_num_faces >= m_max_faces)
                {
                    delete [] m_face_names[0];
                    FT_Done_Face(m_faces[0]);
                    memcpy(m_faces, 
                           m_faces + 1, 
                           (m_max_faces - 1) * sizeof(FT_Face));
                    memcpy(m_face_names, 
                           m_face_names + 1, 
                           (m_max_faces - 1) * sizeof(char*));
                    m_num_faces = m_max_faces - 1;
                }

                if (font_mem && font_mem_size)
                {
                    m_last_error = FT_New_Memory_Face(m_library, 
                                                      (const FT_Byte*)font_mem, 
                                                      font_mem_size, 
                                                      face_index, 
                                                      &m_faces[m_num_faces]);
                }
                else
                {
                    m_last_error = FT_New_Face(m_library,
                                               font_name,
                                               face_index,
                                               &m_faces[m_num_faces]);
                }

                if(m_last_error == 0)
                {
                    m_face_names[m_num_faces] = new char [strlen(font_name) + 1];
                    strcpy(m_face_names[m_num_faces], font_name);
                    m_cur_face = m_faces[m_num_faces];
                    m_name     = m_face_names[m_num_faces];
                    ++m_num_faces;
                }
                else
                {
                    m_face_names[m_num_faces] = 0;
                    m_cur_face = 0;
                    m_name = 0;
                }
            }


            if(m_last_error == 0)
            {
                ret = true;
                
                switch(ren_type)
                {
                case glyph_ren_native_mono:
                    m_glyph_rendering = glyph_ren_native_mono;
                    break;

                case glyph_ren_native_gray8:
                    m_glyph_rendering = glyph_ren_native_gray8;
                    break;

                case glyph_ren_outline:
                    if(FT_IS_SCALABLE(m_cur_face))
                    {
                        m_glyph_rendering = glyph_ren_outline;
                    }
                    else
                    {
                        m_glyph_rendering = glyph_ren_native_gray8;
                    }
                    break;

                case glyph_ren_agg_mono:
                    if(FT_IS_SCALABLE(m_cur_face))
                    {
                        m_glyph_rendering = glyph_ren_agg_mono;
                    }
                    else
                    {
                        m_glyph_rendering = glyph_ren_native_mono;
                    }
                    break;

                case glyph_ren_agg_gray8:
                    if(FT_IS_SCALABLE(m_cur_face))
                    {
                        m_glyph_rendering = glyph_ren_agg_gray8;
                    }
                    else
                    {
                        m_glyph_rendering = glyph_ren_native_gray8;
                    }
                    break;
                }
                update_signature();
            }
        }

        return ret;
    }
Example #9
0
font::font( FT_Face face, std::string fam, std::string style, double pixsize )
		: script::font( std::move( fam ), std::move( style ), pixsize ),
		  _face( face )
{
	auto err = FT_Select_Charmap( _face, FT_ENCODING_UNICODE );
	if ( err )
	{
		std::cerr << "ERROR selecting UNICODE charmap: [" << FT_Errors[err].code << "] " << FT_Errors[err].message << std::endl;
		if ( _face->charmaps )
		{
			err = FT_Set_Charmap( _face, _face->charmaps[0] );
			if ( err )
				throw std::runtime_error( errorstr( err ) );
		}
		else
			throw std::runtime_error( "Unable to select any character map" );
	}

	std::cout << "Need to add global DPI accessor somehow (multiple screens?)" << std::endl;
	static const int theDPI = 95;

	if ( FT_IS_SCALABLE( _face ) )
	{
		err = FT_Set_Char_Size( _face, static_cast<int>( pixsize * 64.0 ), 0,
								theDPI, theDPI );
		if ( err )
			throw std::runtime_error( "Unable to set character size" );
	}
	else if ( _face->num_fixed_sizes > 1 )
	{
		int targsize = static_cast<int>( pixsize );
		int bestSize[2];
		bestSize[0] = bestSize[1] = targsize;
		int i;
		for ( i = 0; i != _face->num_fixed_sizes; ++i )
		{
			if ( _face->available_sizes[i].width == targsize )
			{
				bestSize[1] = _face->available_sizes[i].height;
				break;
			}
			else if ( _face->available_sizes[i].width > targsize &&
					  bestSize[0] > _face->available_sizes[i].width )
			{
				bestSize[0] = _face->available_sizes[i].width;
				bestSize[1] = _face->available_sizes[i].height;
			}
		}

		if ( i == _face->num_fixed_sizes )
			_size = bestSize[0];

		// otherwise we have to use FT_Set_Pixel_Sizes
		err = FT_Set_Pixel_Sizes( _face, static_cast<FT_UInt>( bestSize[0] ), static_cast<FT_UInt>( bestSize[1] ) );
		if ( err )
			throw std::runtime_error( "Unable to set fixed character size" );
	}

	_extents.ascent = static_cast<double>( _face->size->metrics.ascender ) / 64.0;
	_extents.descent = static_cast<double>( _face->size->metrics.descender ) / 64.0;

	if ( FT_IS_SCALABLE( _face ) )
	{
		double scaleX = ( static_cast<double>( _face->size->metrics.x_ppem ) /
						  static_cast<double>( _face->units_per_EM ) );
		double scaleY = ( static_cast<double>( _face->size->metrics.y_ppem ) /
						  static_cast<double>( _face->units_per_EM ) );
		_extents.width = std::ceil( static_cast<double>( _face->bbox.xMax - _face->bbox.xMin ) * scaleX );
		_extents.height = static_cast<double>( _face->size->metrics.height ) / 64.0;
			// was: std::ceil( static_cast<double>( _face->bbox.yMax - _face->bbox.yMin ) * scaleY );

		_extents.max_x_advance = static_cast<double>( _face->max_advance_width ) * scaleX;
		_extents.max_y_advance = static_cast<double>( _face->max_advance_height ) * scaleY;
	}
	else
	{
		_extents.width = static_cast<double>( _face->size->metrics.max_advance ) / 64.0;
		_extents.height = static_cast<double>( _face->size->metrics.height ) / 64.0;

		_extents.max_x_advance = static_cast<double>( _face->size->metrics.max_advance ) / 64.0;
		_extents.max_y_advance = 0.0;
	}

}
Example #10
0
TTF_Font* TTF_OpenFontIndexRW( FILE* src, int freesrc, int ptsize, long index )
{
	TTF_Font* font;
	FT_Error error;
	FT_Face face;
	FT_Fixed scale;
	FT_Stream stream;
	FT_CharMap found;
	int position, i;

	if ( ! TTF_initialized ) {
		TTF_SetError( "Library not initialized" );
		return NULL;
	}

	/* Check to make sure we can seek in this stream */
	position = ftell(src);
	if ( position < 0 ) {
		TTF_SetError( "Can't seek in stream" );
		return NULL;
	}

	font = (TTF_Font*) malloc(sizeof *font);
	if ( font == NULL ) {
		TTF_SetError( "Out of memory" );
		return NULL;
	}
	memset(font, 0, sizeof(*font));

	font->src = src;
	font->freesrc = freesrc;

	stream = (FT_Stream)malloc(sizeof(*stream));
	if ( stream == NULL ) {
		TTF_SetError( "Out of memory" );
		TTF_CloseFont( font );
		return NULL;
	}
	memset(stream, 0, sizeof(*stream));

	stream->read = ft_read;
	stream->descriptor.pointer = src;
	stream->pos = (unsigned long)position;
	fseek(src, 0, SEEK_END);
	stream->size = (unsigned long)(ftell(src) - position);
	fseek(src, position, SEEK_SET);

	font->args.flags = FT_OPEN_STREAM;
	font->args.stream = stream;

	error = FT_Open_Face( library, &font->args, index, &font->face );
	if( error ) {
		TTF_SetFTError( "Couldn't load font file", error );
		TTF_CloseFont( font );
		return NULL;
	}
	face = font->face;

	/* Set charmap for loaded font */
	found = 0;
	for (i = 0; i < face->num_charmaps; i++) {
		FT_CharMap charmap = face->charmaps[i];
/* Windows Unicode */
		if ((charmap->platform_id == 3 && charmap->encoding_id == 1) 
/* Windows Symbol */
		 || (charmap->platform_id == 3 && charmap->encoding_id == 0)
/* ISO Unicode */
		 || (charmap->platform_id == 2 && charmap->encoding_id == 1)
/* Apple Unicode */
		 || (charmap->platform_id == 0)) { 
			found = charmap;
			break;
		}
	}
	if ( found ) {
		/* If this fails, continue using the default charmap */
		FT_Set_Charmap(face, found);
	}

	/* Make sure that our font face is scalable (global metrics) */
	if ( FT_IS_SCALABLE(face) ) {

	  	/* Set the character size and use default DPI (72) */
	  	error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 );
			if( error ) {
	    	TTF_SetFTError( "Couldn't set font size", error );
	    	TTF_CloseFont( font );
	    	return NULL;
	  }

	  /* Get the scalable font metrics for this font */
	  scale = face->size->metrics.y_scale;
	  font->ascent  = FT_CEIL(FT_MulFix(face->ascender, scale));
	  font->descent = FT_CEIL(FT_MulFix(face->descender, scale));
	  font->height  = font->ascent - font->descent + /* baseline */ 1;
	  font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
	  font->underline_offset = FT_FLOOR(
			FT_MulFix(face->underline_position, scale));
	  font->underline_height = FT_FLOOR(
			FT_MulFix(face->underline_thickness, scale));

	} else {
		/* Non-scalable font case.  ptsize determines which family
		 * or series of fonts to grab from the non-scalable format.
		 * It is not the point size of the font.
		 * */
		if ( ptsize >= font->face->num_fixed_sizes )
			ptsize = font->face->num_fixed_sizes - 1;
		font->font_size_family = ptsize;
		error = FT_Set_Pixel_Sizes( face,
				face->available_sizes[ptsize].height,
				face->available_sizes[ptsize].width );
	  	/* With non-scalale fonts, Freetype2 likes to fill many of the
		 * font metrics with the value of 0.  The size of the
		 * non-scalable fonts must be determined differently
		 * or sometimes cannot be determined.
		 * */
	  	font->ascent = face->available_sizes[ptsize].height;
	  	font->descent = 0;
	  	font->height = face->available_sizes[ptsize].height;
	  	font->lineskip = FT_CEIL(font->ascent);
	  	font->underline_offset = FT_FLOOR(face->underline_position);
	  	font->underline_height = FT_FLOOR(face->underline_thickness);
	}

	if ( font->underline_height < 1 ) {
		font->underline_height = 1;
	}

#ifdef DEBUG_FONTS
	printf("Font metrics:\n");
	printf("\tascent = %d, descent = %d\n",
		font->ascent, font->descent);
	printf("\theight = %d, lineskip = %d\n",
		font->height, font->lineskip);
	printf("\tunderline_offset = %d, underline_height = %d\n",
		font->underline_offset, font->underline_height);
	printf("\tunderline_top_row = %d, strikethrough_top_row = %d\n",
		TTF_underline_top_row(font), TTF_strikethrough_top_row(font));
#endif

	/* Initialize the font face style */
	font->face_style = TTF_STYLE_NORMAL;
	if ( font->face->style_flags & FT_STYLE_FLAG_BOLD ) {
		font->face_style |= TTF_STYLE_BOLD;
	}
	if ( font->face->style_flags & FT_STYLE_FLAG_ITALIC ) {
		font->face_style |= TTF_STYLE_ITALIC;
	}
	/* Set the default font style */
	font->style = font->face_style;
	font->outline = 0;
	font->kerning = 1;
	font->glyph_overhang = face->size->metrics.y_ppem / 10;
	/* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
	font->glyph_italics = 0.207f;
	font->glyph_italics *= font->height;

	return font;
}
Example #11
0
BOOL KG3DFontTexture::Initialize(LPCSTR szName, float fPixel, DWORD dwStyle)
{
	static FT_Long const DEFAULT_FACE_INDEX = 0;

	int nRetCode = false;
    int nResult = false;
	KG3DFTFontLibrary* pFontLibrary = NULL;
	FT_Face pFontFace = NULL;
	FT_Error nError = 0;
    FT_F26Dot6 FontSize = 0;
	BOOL bUnicode = FALSE;
	UINT uEncoding = FT_ENCODING_UNICODE;

	if (dwStyle & KG3DUI_TEXT_STYLE_MONO)
	{
		m_InitParams.dwRenderMode = FT_RENDER_MODE_MONO;
		m_InitParams.dwLoadFlag = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_HINTING;
	}
	else
	{
		m_InitParams.dwRenderMode = FT_RENDER_MODE_LIGHT;
		m_InitParams.dwLoadFlag = FT_LOAD_TARGET_LIGHT | FT_LOAD_MONOCHROME;
	}

    _tcsncpy(m_InitParams.szName, szName, _countof(m_InitParams.szName));
    m_InitParams.szName[_countof(m_InitParams.szName) - 1] = _T('\0');

	m_InitParams.fPixel = fPixel;
    m_InitParams.dwStyle = dwStyle;

	pFontLibrary = KG3DFTFontLibrary::Instance();
	KGLOG_PROCESS_ERROR(pFontLibrary);

    nRetCode = s_FontFacePool.Load(pFontLibrary->m_library, m_InitParams.szName, DEFAULT_FACE_INDEX, &pFontFace);
    KGLOG_PROCESS_ERROR(nRetCode);

	ASSERT(pFontFace);

	nRetCode = FT_IS_SCALABLE(pFontFace);
	KGLOG_PROCESS_ERROR(nRetCode);

	KGLOG_PROCESS_ERROR(pFontFace->charmap);

	for (int i = 0; i < pFontFace->num_charmaps; ++i)
	{
		if (FT_Encoding(FT_ENCODING_UNICODE) == pFontFace->charmaps[i]->encoding)
		{
			bUnicode = TRUE;
			break;
		}
	}

	if (!bUnicode)
	{
		uEncoding = pFontFace->charmaps[0]->encoding;
		bUnicode = uEncoding == FT_ENCODING_UNICODE;
	}

	nError = FT_Select_Charmap(pFontFace, FT_Encoding(uEncoding));
	KGLOG_PROCESS_ERROR(nError == 0);

    FontSize = FontFixMul(fPixel);
    nError = FT_Set_Char_Size(pFontFace, FontSize, 0, 0, 0);
    KGLOG_PROCESS_ERROR(nError == 0);

	LoadAlphaAdjustTable(szName, (INT)fPixel);

	m_pFontFace	= pFontFace;
    pFontFace = NULL;

	m_dwEffect = dwStyle & ~KG3DUI_TEXT_STYLE_VERTICAL;
	m_bVertical = dwStyle & KG3DUI_TEXT_STYLE_VERTICAL;
	if (m_bVertical)
		m_InitParams.dwLoadFlag |= FT_LOAD_VERTICAL_LAYOUT;

    m_uMipmapLevel = (dwStyle & KG3DUI_TEXT_STYLE_MIPMAP) ? 8 : 1;

	if (FT_IS_SCALABLE(m_pFontFace))
	{
		m_fontWidth = (m_pFontFace->bbox.xMax - m_pFontFace->bbox.xMin)
			* ((FLOAT)(m_pFontFace->size->metrics.x_ppem) / (FLOAT)(m_pFontFace->units_per_EM));
		m_fontHeight = (m_pFontFace->bbox.yMax - m_pFontFace->bbox.yMin)
			* ((FLOAT)m_pFontFace->size->metrics.y_ppem / (FLOAT)m_pFontFace->units_per_EM);
	}
	else
	{
		m_fontWidth = FontFixDiv(m_pFontFace->size->metrics.max_advance);
		m_fontHeight = FontFixDiv(m_pFontFace->size->metrics.height);
	}
	
	m_fontWidth = ceil(m_fontWidth);
	m_fontHeight = ceil(m_fontHeight);

	m_fontAscender = FontFixDiv(m_pFontFace->size->metrics.ascender);
	m_fontDescender = FontFixDiv(m_pFontFace->size->metrics.descender);

	m_fontAscender = ceil(m_fontAscender);
	m_fontDescender = ceil(m_fontDescender);

	nResult = true;
Exit0:
    if (!nResult)
    {
        if (pFontFace)
        {
            nRetCode = s_FontFacePool.Unload(pFontFace);
            KGLOG_CHECK_ERROR(nRetCode);

            pFontFace = NULL;
        }

        CleanUp();
    }
	return nResult;
}
Example #12
0
bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
{
    // Compute a shape matrix compatible with Cairo's _compute_transform.
    // Finds major/minor scales and uses them to normalize the transform.
    double scaleX = m.getScaleX();
    double skewX = m.getSkewX();
    double skewY = m.getSkewY();
    double scaleY = m.getScaleY();
    double det = scaleX * scaleY - skewY * skewX;
    if (!std::isfinite(det)) {
        fScaleX = fRec.fTextSize * fRec.fPreScaleX;
        fScaleY = fRec.fTextSize;
        fHaveShape = false;
        return false;
    }
    double major = det != 0.0 ? hypot(scaleX, skewY) : 0.0;
    double minor = major != 0.0 ? fabs(det) / major : 0.0;
    // Limit scales to be above 1pt.
    major = SkTMax(major, 1.0);
    minor = SkTMax(minor, 1.0);

    // If the font is not scalable, then choose the best available size.
    CairoLockedFTFace faceLock(fScaledFont);
    FT_Face face = faceLock.getFace();
    if (face && !FT_IS_SCALABLE(face)) {
        double bestDist = DBL_MAX;
        FT_Int bestSize = -1;
        for (FT_Int i = 0; i < face->num_fixed_sizes; i++) {
            // Distance is positive if strike is larger than desired size,
            // or negative if smaller. If previously a found smaller strike,
            // then prefer a larger strike. Otherwise, minimize distance.
            double dist = face->available_sizes[i].y_ppem / 64.0 - minor;
            if (bestDist < 0 ? dist >= bestDist : fabs(dist) <= bestDist) {
                bestDist = dist;
                bestSize = i;
            }
        }
        if (bestSize < 0) {
            fScaleX = fRec.fTextSize * fRec.fPreScaleX;
            fScaleY = fRec.fTextSize;
            fHaveShape = false;
            return false;
        }
        major = face->available_sizes[bestSize].x_ppem / 64.0;
        minor = face->available_sizes[bestSize].y_ppem / 64.0;
        fHaveShape = true;
    } else {
        fHaveShape = !m.isScaleTranslate();
    }

    fScaleX = SkDoubleToScalar(major);
    fScaleY = SkDoubleToScalar(minor);

    if (fHaveShape) {
        // Normalize the transform and convert to fixed-point.
        double invScaleX = 65536.0 / major;
        double invScaleY = 65536.0 / minor;
        fShapeMatrix.xx = (FT_Fixed)(scaleX * invScaleX);
        fShapeMatrix.yx = -(FT_Fixed)(skewY * invScaleX);
        fShapeMatrix.xy = -(FT_Fixed)(skewX * invScaleY);
        fShapeMatrix.yy = (FT_Fixed)(scaleY * invScaleY);
    }
    return true;
}
Example #13
0
int
main(int argc,
     char** argv)
{
  FT_Face     face;
  long        max_bytes = CACHE_SIZE * 1024;
  char*       test_string = NULL;
  int         size = FACE_SIZE;
  int         max_iter = 0;
  double      max_time = BENCH_TIME;
  int         compare_cached = 0;
  int         i;

  while ( 1 )
  {
    int  opt;


    opt = getopt( argc, argv, "Cc:f:m:pr:s:t:b:" );

    if ( opt == -1 )
      break;

    switch ( opt )
    {
    case 'C':
      compare_cached = 1;
      break;
    case 'c':
      max_iter = atoi( optarg );
      break;
    case 'f':
      load_flags = strtol( optarg, NULL, 16 );
      break;
    case 'm':
      max_bytes = atoi( optarg );
      max_bytes *= 1024;
      break;
    case 'p':
      preload = 1;
      break;
    case 'r':
      render_mode = (FT_Render_Mode)atoi( optarg );
      if ( render_mode >= FT_RENDER_MODE_MAX )
        render_mode = FT_RENDER_MODE_NORMAL;
      break;
    case 's':
      size = atoi( optarg );
      if ( size <= 0 )
        size = 1;
      else if ( size > 500 )
        size = 500;
      break;
    case 't':
      max_time = atof( optarg );
      break;
    case 'b':
      test_string = optarg;
      break;
    default:
      usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

  if ( argc != 1 )
    usage();

  if ( FT_Init_FreeType( &lib ) )
  {
    fprintf( stderr, "could not initialize font library\n" );

    return 1;
  }

  filename = *argv;

  if ( get_face( &face ) )
    goto Exit;

  if ( FT_IS_SCALABLE( face ) )
  {

    if ( FT_Set_Pixel_Sizes( face, size, size ) )
    {
      fprintf( stderr, "failed to set pixel size to %d\n", size );

      return 1;
    }
  }
  else
    size = face->available_sizes[0].width;

  FTC_Manager_New( lib, 0, 0, max_bytes, face_requester, face, &cache_man );

  font_type.face_id = (FTC_FaceID) 1;
  font_type.width   = (short) size;
  font_type.height  = (short) size;
  font_type.flags   = load_flags;

  for ( i = 0; i < N_FT_BENCH; i++ )
  {
    btest_t   test;
    FT_ULong  flags;


    if ( !TEST( 'a' + i ) )
      continue;

    test.title       = NULL;
    test.bench       = NULL;
    test.cache_first = 0;
    test.user_data   = NULL;

    switch ( i )
    {
    case FT_BENCH_LOAD_GLYPH:
      test.title = "Load";
      test.bench = test_load;
      benchmark( face, &test, max_iter, max_time );

      if ( compare_cached )
      {
        test.cache_first = 1;

        test.title = "Load (image cached)";
        test.bench = test_image_cache;
        benchmark( face, &test, max_iter, max_time );

        test.title = "Load (sbit cached)";
        test.bench = test_sbit_cache;
        benchmark( face, &test, max_iter, max_time );
      }
      break;
    case FT_BENCH_LOAD_ADVANCES:
      test.user_data = &flags;

      test.title = "Load_Advances (Normal)";
      test.bench = test_load_advances;
      flags      = FT_LOAD_DEFAULT;
      benchmark( face, &test, max_iter, max_time );

      test.title  = "Load_Advances (Fast)";
      test.bench  = test_load_advances;
      flags       = FT_LOAD_TARGET_LIGHT;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_RENDER:
      test.title = "Render";
      test.bench = test_render;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_GET_GLYPH:
      test.title = "Get_Glyph";
      test.bench = test_get_glyph;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_GET_CBOX:
      test.title = "Get_CBox";
      test.bench = test_get_cbox;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_CMAP:
      {
        bcharset_t  charset;


        get_charset( face, &charset );
        if ( charset.code )
        {
          test.user_data = (void*)&charset;


          test.title = "Get_Char_Index";
          test.bench = test_get_char_index;

          benchmark( face, &test, max_iter, max_time );

          if ( compare_cached )
          {
            test.cache_first = 1;

            test.title = "Get_Char_Index (cached)";
            test.bench = test_cmap_cache;
            benchmark( face, &test, max_iter, max_time );
          }

          free( charset.code );
        }
      }
      break;
    case FT_BENCH_CMAP_ITER:
      test.title = "Iterate CMap";
      test.bench = test_cmap_iter;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_NEW_FACE:
      test.title = "New_Face";
      test.bench = test_new_face;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_EMBOLDEN:
      test.title = "Embolden";
      test.bench = test_embolden;
      benchmark( face, &test, max_iter, max_time );
      break;
    }
  }

Exit:
  /* The following is a bit subtle: When we call FTC_Manager_Done, this
   * normally destroys all FT_Face objects that the cache might have created
   * by calling the face requester.
   *
   * However, this little benchmark uses a tricky face requester that
   * doesn't create a new FT_Face through FT_New_Face but simply pass a
   * pointer to the one that was previously created.
   *
   * If the cache manager has been used before, the call to FTC_Manager_Done
   * discards our single FT_Face.
   *
   * In the case where no cache manager is in place, or if no test was run,
   * the call to FT_Done_FreeType releases any remaining FT_Face object
   * anyway.
   */
  if ( cache_man )
    FTC_Manager_Done( cache_man );

  FT_Done_FreeType( lib );

  return 0;
}
    QGlyph render(QChar ch)
    {
	selectThisSize();

	int index = ch.unicode();
	if ( !unicode(index) )
	    index = 0;
	QGlyph result;

	FT_Error err;

	err=FT_Load_Glyph(myface,index,FT_LOAD_DEFAULT);
	if(err)
	    qFatal("Load glyph error %x",err);

	int width,height,pitch,size = 0;
	FT_Glyph glyph;
	err=FT_Get_Glyph( myface->glyph, &glyph );
	if(err)
	    qFatal("Get glyph error %x",err);

	FT_BBox bbox;
	FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_gridfit, &bbox);

	FT_Vector origin;
	origin.x = -bbox.xMin;
	origin.y = -bbox.yMin;

	if ( FT_IS_SCALABLE(myface) ) {
	    err=FT_Glyph_To_Bitmap(&glyph,
		smooth ? ft_render_mode_normal : ft_render_mode_mono,
		&origin, 1); // destroy original glyph
	    if(err)
		qWarning("Get bitmap error %d",err);
	}

	if ( !err ) {
	    FT_Bitmap bm = ((FT_BitmapGlyph)glyph)->bitmap;
	    pitch = bm.pitch;
	    size=pitch*bm.rows;
	    result.data = new uchar[size]; // XXX memory manage me
	    width=bm.width;
	    height=bm.rows;
	    if ( size ) {
		memcpy( result.data, bm.buffer, size );
	    } else {
		result.data = new uchar[0]; // XXX memory manage me
	    }
	} else {
	    result.data = new uchar[0]; // XXX memory manage me
	}

	result.metrics = new QGlyphMetrics;
	memset((char*)result.metrics, 0, sizeof(QGlyphMetrics));
	result.metrics->bearingx=myface->glyph->metrics.horiBearingX/64;
	result.metrics->advance=myface->glyph->metrics.horiAdvance/64;
	result.metrics->bearingy=myface->glyph->metrics.horiBearingY/64;

	result.metrics->linestep=pitch;
	result.metrics->width=width;
	result.metrics->height=height;

	FT_Done_Glyph( glyph );

	return result;
    }
Example #15
0
				bool IsScalable() const override
				{
					return FT_IS_SCALABLE(m_face) != 0;
				}
Example #16
0
void
XeTeXFontInst::initialize(const char* pathname, int index, int &status)
{
    TT_Postscript *postTable;
    TT_OS2* os2Table;
    FT_Error error;
    hb_face_t *hbFace;

    if (!gFreeTypeLibrary) {
        error = FT_Init_FreeType(&gFreeTypeLibrary);
        if (error) {
            fprintf(stderr, "FreeType initialization failed! (%d)\n", error);
            exit(1);
        }
    }

    error = FT_New_Face(gFreeTypeLibrary, pathname, index, &m_ftFace);
    if (error) {
        status = 1;
        return;
    }

    if (!FT_IS_SCALABLE(m_ftFace)) {
        status = 1;
        return;
    }

    /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */
    if (index == 0 && !FT_IS_SFNT(m_ftFace)) {
        char* afm = xstrdup (xbasename (pathname));
        char* p = strrchr (afm, '.');
        if (p != NULL && strlen(p) == 4 && tolower(*(p+1)) == 'p' &&
            tolower(*(p+2)) == 'f')
            strcpy(p, ".afm");
        char *fullafm = kpse_find_file (afm, kpse_afm_format, 0);
        free (afm);
        if (fullafm) {
            FT_Attach_File(m_ftFace, fullafm);
            free (fullafm);
        }
    }

    m_filename = xstrdup(pathname);
    m_index = index;
    m_unitsPerEM = m_ftFace->units_per_EM;
    m_ascent = unitsToPoints(m_ftFace->ascender);
    m_descent = unitsToPoints(m_ftFace->descender);

    postTable = (TT_Postscript *) getFontTable(ft_sfnt_post);
    if (postTable != NULL) {
        m_italicAngle = Fix2D(postTable->italicAngle);
    }

    os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2);
    if (os2Table) {
        m_capHeight = unitsToPoints(os2Table->sCapHeight);
        m_xHeight = unitsToPoints(os2Table->sxHeight);
    }

    // Set up HarfBuzz font
    hbFace = hb_face_create_for_tables(_get_table, m_ftFace, NULL);
    hb_face_set_index(hbFace, index);
    hb_face_set_upem(hbFace, m_unitsPerEM);
    m_hbFont = hb_font_create(hbFace);
    hb_face_destroy(hbFace);

    if (hbFontFuncs == NULL)
        hbFontFuncs = _get_font_funcs();

    hb_font_set_funcs(m_hbFont, hbFontFuncs, m_ftFace, NULL);
    hb_font_set_scale(m_hbFont, m_unitsPerEM, m_unitsPerEM);
    // We don’t want device tables adjustments
    hb_font_set_ppem(m_hbFont, 0, 0);

    return;
}
Example #17
0
bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, TTFRenderMode renderMode, const uint32 *mapping) {
	if (!g_ttf.isInitialized())
		return false;

	_size = stream.size();
	if (!_size)
		return false;

	_ttfFile = new uint8[_size];
	assert(_ttfFile);

	if (stream.read(_ttfFile, _size) != _size) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	if (!g_ttf.loadFont(_ttfFile, _size, _face)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	// We only support scalable fonts.
	if (!FT_IS_SCALABLE(_face)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		g_ttf.closeFont(_face);

		return false;
	}

	// Check whether we have kerning support
	_hasKerning = (FT_HAS_KERNING(_face) != 0);

	if (FT_Set_Char_Size(_face, 0, size * 64, dpi, dpi)) {
		delete[] _ttfFile;
		_ttfFile = 0;

		return false;
	}

	switch (renderMode) {
	case kTTFRenderModeNormal:
		_loadFlags = FT_LOAD_TARGET_NORMAL;
		_renderMode = FT_RENDER_MODE_NORMAL;
		break;

	case kTTFRenderModeLight:
		_loadFlags = FT_LOAD_TARGET_LIGHT;
		_renderMode = FT_RENDER_MODE_LIGHT;
		break;

	case kTTFRenderModeMonochrome:
		_loadFlags = FT_LOAD_TARGET_MONO;
		_renderMode = FT_RENDER_MODE_MONO;
		break;
	}

	FT_Fixed yScale = _face->size->metrics.y_scale;
	_ascent = ftCeil26_6(FT_MulFix(_face->ascender, yScale));
	_descent = ftCeil26_6(FT_MulFix(_face->descender, yScale));

	_width = ftCeil26_6(FT_MulFix(_face->max_advance_width, _face->size->metrics.x_scale));
	_height = _ascent - _descent + 1;

	if (!mapping) {
		// Allow loading of all unicode characters.
		_allowLateCaching = true;

		// Load all ISO-8859-1 characters.
		for (uint i = 0; i < 256; ++i) {
			if (!cacheGlyph(_glyphs[i], i)) {
				_glyphs.erase(i);
			}
		}
	} else {
		// We have a fixed map of characters do not load more later.
		_allowLateCaching = false;

		for (uint i = 0; i < 256; ++i) {
			const uint32 unicode = mapping[i] & 0x7FFFFFFF;
			const bool isRequired = (mapping[i] & 0x80000000) != 0;
			// Check whether loading an important glyph fails and error out if
			// that is the case.
			if (!cacheGlyph(_glyphs[i], unicode)) {
				_glyphs.erase(i);
				if (isRequired)
					return false;
			}
		}
	}

	_initialized = (_glyphs.size() != 0);
	return _initialized;
}
Example #18
0
static GdkPixmap *
create_text_pixmap(GtkWidget *drawing_area, FT_Face face)
{
    gint i, pixmap_width, pixmap_height, pos_y, textlen;
    GdkPixmap *pixmap = NULL;
    const gchar *text;
    Display *xdisplay;
    Drawable xdrawable;
    Visual *xvisual;
    Colormap xcolormap;
    XftDraw *draw;
    XftColor colour;
    XGlyphInfo extents;
    XftFont *font;
    gint *sizes = NULL, n_sizes, alpha_size;
    FcCharSet *charset = NULL;
    cairo_t *cr;
    GdkWindow *window = gtk_widget_get_window (drawing_area);

    text = pango_language_get_sample_string(NULL);
    if (! check_font_contain_text (face, text))
	{
	    pango_language_get_sample_string (pango_language_from_string ("en_US"));
	}

    textlen = strlen(text);

    /* create the XftDraw */
    xdisplay = GDK_PIXMAP_XDISPLAY(window);

	#if GTK_CHECK_VERSION(3, 0, 0)
		xvisual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(window));
	#else
		xvisual = GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(window));
	#endif

    xcolormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(window));
    XftColorAllocName(xdisplay, xvisual, xcolormap, "black", &colour);

    /* work out what sizes to render */
    if (FT_IS_SCALABLE(face)) {
	n_sizes = 8;
	sizes = g_new(gint, n_sizes);
	sizes[0] = 8;
	sizes[1] = 10;
	sizes[2] = 12;
	sizes[3] = 18;
	sizes[4] = 24;
	sizes[5] = 36;
	sizes[6] = 48;
	sizes[7] = 72;
	alpha_size = 24;
    } else {
	/* use fixed sizes */
	n_sizes = face->num_fixed_sizes;
	sizes = g_new(gint, n_sizes);
	alpha_size = 0;
	for (i = 0; i < face->num_fixed_sizes; i++) {
	    sizes[i] = face->available_sizes[i].height;

	    /* work out which font size to render */
	    if (face->available_sizes[i].height <= 24)
		alpha_size = face->available_sizes[i].height;
	}
    }

    /* calculate size of pixmap to use (with 4 pixels padding) ... */
    pixmap_width = 8;
    pixmap_height = 8;

    font = get_font(xdisplay, face, alpha_size, charset);
    charset = FcCharSetCopy (font->charset);
    XftTextExtentsUtf8(xdisplay, font,
		       (guchar *)lowercase_text, strlen(lowercase_text), &extents);
    pixmap_height += extents.height + 4;
    pixmap_width = MAX(pixmap_width, 8 + extents.width);
    XftTextExtentsUtf8(xdisplay, font,
		       (guchar *)uppercase_text, strlen(uppercase_text), &extents);
    pixmap_height += extents.height + 4;
    pixmap_width = MAX(pixmap_width, 8 + extents.width);
    XftTextExtentsUtf8(xdisplay, font,
		       (guchar *)punctuation_text, strlen(punctuation_text), &extents);
    pixmap_height += extents.height + 4;
    pixmap_width = MAX(pixmap_width, 8 + extents.width);
    XftFontClose(xdisplay, font);

    pixmap_height += 8;

    for (i = 0; i < n_sizes; i++) {
	font = get_font(xdisplay, face, sizes[i], charset);
	if (!font) continue;
	XftTextExtentsUtf8(xdisplay, font, (guchar *)text, textlen, &extents);
	pixmap_height += extents.height + 4;
	pixmap_width = MAX(pixmap_width, 8 + extents.width);
	XftFontClose(xdisplay, font);
    }

    /* create pixmap */
    gtk_widget_set_size_request(drawing_area, pixmap_width, pixmap_height);
    pixmap = gdk_pixmap_new(window,
			    pixmap_width, pixmap_height, -1);
    if (!pixmap)
	goto end;
    cr = gdk_cairo_create (pixmap);
    cairo_set_source_rgb (cr, 1, 1, 1);
    cairo_paint (cr);
    cairo_destroy (cr);

    xdrawable = GDK_DRAWABLE_XID(pixmap);
    draw = XftDrawCreate(xdisplay, xdrawable, xvisual, xcolormap);

    /* draw text */
    pos_y = 4;
    font = get_font(xdisplay, face, alpha_size, charset);
    draw_string(xdisplay, draw, font, &colour, lowercase_text, &pos_y);
    draw_string(xdisplay, draw, font, &colour, uppercase_text, &pos_y);
    draw_string(xdisplay, draw, font, &colour, punctuation_text, &pos_y);
    XftFontClose(xdisplay, font);

    pos_y += 8;
    for (i = 0; i < n_sizes; i++) {
	font = get_font(xdisplay, face, sizes[i], charset);
	if (!font) continue;
	draw_string(xdisplay, draw, font, &colour, text, &pos_y);
	XftFontClose(xdisplay, font);
    }

    g_signal_connect(drawing_area, "expose-event", G_CALLBACK(expose_event),
                     pixmap);

 end:
    g_free(sizes);
    FcCharSetDestroy (charset);
    return pixmap;
}
bool gfx_font_adapter::prepare_glyph(unsigned int code)
{
    if (m_impl->font) {
        m_impl->cur_glyph_index = FT_Get_Char_Index(m_impl->font, code);

        int error = FT_Load_Glyph(m_impl->font, m_impl->cur_glyph_index,
                                 m_impl->hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING);

        bool is_sys_bitmap = false;
        if (m_impl->font->glyph->format == FT_GLYPH_FORMAT_BITMAP)
            is_sys_bitmap = true;

        if (error == 0) {
            if (m_impl->antialias && !is_sys_bitmap) {
                if (m_impl->weight == 500) {
                    int strength = 1 << 5;
                    FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                } else if (m_impl->weight == 700) {
                    int strength = 1 << 6;
                    FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                } else if (m_impl->weight == 900) {
                    int strength = 1 << 7;
                    FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                }
                // outline text
                m_impl->cur_data_type = glyph_type_outline;
                m_impl->cur_font_path.remove_all();

                if (decompose_ft_outline(m_impl->font->glyph->outline,
                            m_impl->flip_y, m_impl->matrix, m_impl->cur_font_path))
                {
                    m_impl->cur_bound_rect = get_bounding_rect(m_impl->cur_font_path);
                    m_impl->cur_data_size = m_impl->cur_font_path.total_byte_size()+sizeof(unsigned int);//count data
                    m_impl->cur_advance_x = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.x));
                    m_impl->cur_advance_y = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.y));
                    m_impl->matrix.transform(&m_impl->cur_advance_x, &m_impl->cur_advance_y);
                    return true;
                }
            } else {
                m_impl->cur_data_type = glyph_type_mono;
                if (is_sys_bitmap || !FT_IS_SCALABLE(m_impl->font) || m_impl->matrix.is_identity()) {
                    gfx_scanline_bin sl;
                    error = FT_Render_Glyph(m_impl->font->glyph, FT_RENDER_MODE_MONO);
                    if (error == 0) {
                        decompose_ft_bitmap_mono(m_impl->font->glyph->bitmap,
                           m_impl->font->glyph->bitmap_left, m_impl->flip_y ? -m_impl->font->glyph->bitmap_top :
                           m_impl->font->glyph->bitmap_top, m_impl->flip_y, sl, m_impl->cur_font_scanlines_bin);

                        m_impl->cur_bound_rect = rect(m_impl->cur_font_scanlines_bin.min_x(),
                                m_impl->cur_font_scanlines_bin.min_y(),
                                m_impl->cur_font_scanlines_bin.max_x() + 1,
                                m_impl->cur_font_scanlines_bin.max_y() + 1);
                        m_impl->cur_data_size = m_impl->cur_font_scanlines_bin.byte_size();
                        m_impl->cur_advance_x = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.x));
                        m_impl->cur_advance_y = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.y));
                        return true;
                    }
                } else {
                    if (m_impl->weight == 500) {
                        int strength = 1 << 5;
                        FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                    } else if (m_impl->weight == 700) {
                        int strength = 1 << 6;
                        FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                    } else if (m_impl->weight == 900) {
                        int strength = 1 << 7;
                        FT_Outline_Embolden(&(m_impl->font->glyph->outline), strength);
                    }

                    m_impl->cur_font_path.remove_all();
                    if (decompose_ft_outline(m_impl->font->glyph->outline,
                                m_impl->flip_y, m_impl->matrix, m_impl->cur_font_path))
                    {
                        gfx_rasterizer_scanline_aa<> rasterizer;
                        picasso::conv_curve curves(m_impl->cur_font_path);
                        curves.approximation_scale(4.0);
                        rasterizer.add_path(curves);

                        gfx_scanline_bin sl;
                        m_impl->cur_font_scanlines_bin.prepare(); // Remove all
                        gfx_render_scanlines(rasterizer, sl, m_impl->cur_font_scanlines_bin);
                        m_impl->cur_bound_rect = rect(m_impl->cur_font_scanlines_bin.min_x(),
                                m_impl->cur_font_scanlines_bin.min_y(),
                                m_impl->cur_font_scanlines_bin.max_x() + 1,
                                m_impl->cur_font_scanlines_bin.max_y() + 1);
                        m_impl->cur_data_size = m_impl->cur_font_scanlines_bin.byte_size();
                        m_impl->cur_advance_x = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.x));
                        m_impl->cur_advance_y = FLT_TO_SCALAR(int26p6_to_flt(m_impl->font->glyph->advance.y));
                        m_impl->matrix.transform(&m_impl->cur_advance_x, &m_impl->cur_advance_y);
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want )
{
	FT_Face face;
	FT_Error error;
	FT_GlyphSlot glyph;
	FT_Glyph_Metrics* metrics;
	FT_Outline* outline;

	if ( !font || !font->face ) {
		return FT_Err_Invalid_Handle;
	}

	face = font->face;

	/* Load the glyph */
	if ( ! cached->index ) {
		cached->index = FT_Get_Char_Index( face, ch );
	}
	error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT );
	if( error ) {
		return error;
	}

	/* Get our glyph shortcuts */
	glyph = face->glyph;
	metrics = &glyph->metrics;
	outline = &glyph->outline;

	/* Get the glyph metrics if desired */
	if ( (want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS) ) {
		if ( FT_IS_SCALABLE( face ) ) {
			/* Get the bounding box */
			cached->minx = FT_FLOOR(metrics->horiBearingX);
			cached->maxx = cached->minx + FT_CEIL(metrics->width);
			cached->maxy = FT_FLOOR(metrics->horiBearingY);
			cached->miny = cached->maxy - FT_CEIL(metrics->height);
			cached->yoffset = font->ascent - cached->maxy;
			cached->advance = FT_CEIL(metrics->horiAdvance);
		} else {
			/* Get the bounding box for non-scalable format.
			 * Again, freetype2 fills in many of the font metrics
			 * with the value of 0, so some of the values we
			 * need must be calculated differently with certain
			 * assumptions about non-scalable formats.
			 * */
			cached->minx = FT_FLOOR(metrics->horiBearingX);
			cached->maxx = cached->minx + FT_CEIL(metrics->horiAdvance);
			cached->maxy = FT_FLOOR(metrics->horiBearingY);
			cached->miny = cached->maxy - FT_CEIL(face->available_sizes[font->font_size_family].height);
			cached->yoffset = 0;
			cached->advance = FT_CEIL(metrics->horiAdvance);
		}
		
		/* Adjust for bold and italic text */
		if( font->style & TTF_STYLE_BOLD ) {
			cached->maxx += font->glyph_overhang;
		}
		if( font->style & TTF_STYLE_ITALIC ) {
			cached->maxx += (int)ceil(font->glyph_italics);
		}
		cached->stored |= CACHED_METRICS;
	}

	if ( ((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
	     ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ) {
		int mono = (want & CACHED_BITMAP);
		int i;
		FT_Bitmap* src;
		FT_Bitmap* dst;

		/* Handle the italic style */
		if( font->style & TTF_STYLE_ITALIC ) {
			FT_Matrix shear;

			shear.xx = 1 << 16;
			shear.xy = (int) ( font->glyph_italics * ( 1 << 16 ) ) / font->height;
			shear.yx = 0;
			shear.yy = 1 << 16;

			FT_Outline_Transform( outline, &shear );
		}

		/* Render the glyph */
		if ( mono ) {
			error = FT_Render_Glyph( glyph, ft_render_mode_mono );
		} else {
			error = FT_Render_Glyph( glyph, ft_render_mode_normal );
		}
		if( error ) {
			return error;
		}

		/* Copy over information to cache */
		src = &glyph->bitmap;
		if ( mono ) {
			dst = &cached->bitmap;
		} else {
			dst = &cached->pixmap;
		}
		memcpy( dst, src, sizeof( *dst ) );

		/* FT_Render_Glyph() and .fon fonts always generate a
		 * two-color (black and white) glyphslot surface, even
		 * when rendered in ft_render_mode_normal. */
		/* FT_IS_SCALABLE() means that the font is in outline format,
		 * but does not imply that outline is rendered as 8-bit
		 * grayscale, because embedded bitmap/graymap is preferred
		 * (see FT_LOAD_DEFAULT section of FreeType2 API Reference).
		 * FT_Render_Glyph() canreturn two-color bitmap or 4/16/256-
		 * color graymap according to the format of embedded bitmap/
		 * graymap. */
		if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) {
			dst->pitch *= 8;
		} else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY2 ) {
			dst->pitch *= 4;
		} else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY4 ) {
			dst->pitch *= 2;
		}

		/* Adjust for bold and italic text */
		if( font->style & TTF_STYLE_BOLD ) {
			int bump = font->glyph_overhang;
			dst->pitch += bump;
			dst->width += bump;
		}
		if( font->style & TTF_STYLE_ITALIC ) {
			int bump = (int)ceil(font->glyph_italics);
			dst->pitch += bump;
			dst->width += bump;
		}

		if (dst->rows != 0) {
			dst->buffer = (unsigned char *)malloc( dst->pitch * dst->rows );
			if( !dst->buffer ) {
				return FT_Err_Out_Of_Memory;
			}
			memset( dst->buffer, 0, dst->pitch * dst->rows );

			for( i = 0; i < src->rows; i++ ) {
				int soffset = i * src->pitch;
				int doffset = i * dst->pitch;
				if ( mono ) {
					unsigned char *srcp = src->buffer + soffset;
					unsigned char *dstp = dst->buffer + doffset;
					int j;
					if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) {
						for ( j = 0; j < src->width; j += 8 ) {
							unsigned char ch = *srcp++;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
							ch <<= 1;
							*dstp++ = (ch&0x80) >> 7;
						}
					}  else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY2 ) {
						for ( j = 0; j < src->width; j += 4 ) {
							unsigned char ch = *srcp++;
							*dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0;
							ch <<= 2;
							*dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0;
							ch <<= 2;
							*dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0;
							ch <<= 2;
							*dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0;
						}
					} else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY4 ) {
						for ( j = 0; j < src->width; j += 2 ) {
							unsigned char ch = *srcp++;
							*dstp++ = (((ch&0xF0) >> 4) >= 0x8) ? 1 : 0;
							ch <<= 4;
							*dstp++ = (((ch&0xF0) >> 4) >= 0x8) ? 1 : 0;
						}
					} else {
						for ( j = 0; j < src->width; j++ ) {
Example #21
0
void FontRenderer::rasterize() {
    clear_bitmaps();
    if (!m_ft_face) {
        return;
    }


    qDebug() << " begin rasterize_font ";



    if (m_config->italic()!=0) {
        FT_Matrix matrix;
        const float angle = (-M_PI*m_config->italic()) / 180.0f;
        matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
        matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
        matrix.yx = (FT_Fixed)( 0/*sin( angle )*/ * 0x10000L );
        matrix.yy = (FT_Fixed)( 1/*cos( angle )*/ * 0x10000L );
        FT_Set_Transform(m_ft_face,&matrix,0);
    } else {
        FT_Set_Transform(m_ft_face,0,0);
    }


    /// fill metrics
    if (FT_IS_SCALABLE(m_ft_face)) {
        m_rendered.metrics.ascender = m_ft_face->size->metrics.ascender / 64;
        m_rendered.metrics.descender = m_ft_face->size->metrics.descender/ 64;
        m_rendered.metrics.height = m_ft_face->size->metrics.height/ 64;
    } else {
        m_rendered.metrics.ascender = m_ft_face->ascender;
        m_rendered.metrics.descender = m_ft_face->descender;
        m_rendered.metrics.height = m_ft_face->height;
    }


    bool use_kerning = FT_HAS_KERNING( m_ft_face );

    const ushort* chars = m_config->characters().utf16();
    size_t amount = 0;
    while (chars[amount]!=0) amount++;
    int error = 0;
    for (size_t i=0;i<amount;i++) {
        int glyph_index = FT_Get_Char_Index( m_ft_face, chars[i] );
        if (glyph_index==0 && !m_config->renderMissing())
            continue;

        FT_Int32 flags = FT_LOAD_DEFAULT;
        if (!m_config->antialiased()) {
            flags = flags | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO;
        } else {
            flags = flags | FT_LOAD_TARGET_NORMAL;
        }
        switch (m_config->hinting()) {
        case  FontConfig::HintingDisable:
            flags = flags | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
            break;
        case  FontConfig::HintingForceFreetypeAuto:
            flags = flags | FT_LOAD_FORCE_AUTOHINT;
            break;
        case  FontConfig::HintingDisableFreetypeAuto:
            flags = flags | FT_LOAD_NO_AUTOHINT;
            break;
        default:
            break;
        }

        error = FT_Load_Glyph( m_ft_face, glyph_index, flags );
        if ( error )
           continue;
        if (m_config->bold()!=0) {
            FT_Pos strength = m_config->size()*m_config->bold();
            if ( m_ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
                FT_Outline_Embolden( &m_ft_face->glyph->outline, strength );
        }
        if (m_ft_face->glyph->format!=FT_GLYPH_FORMAT_BITMAP) {
            error = FT_Render_Glyph( m_ft_face->glyph,
               m_config->antialiased() ? FT_RENDER_MODE_NORMAL:FT_RENDER_MODE_MONO );
        }
        if ( error )
           continue;
        if (append_bitmap(chars[i])) {
            if (use_kerning)
                append_kerning(chars[i],chars,amount);
        }
    }
    imagesChanged(m_chars);
    imagesChanged();
}
Example #22
0
TTF_Font *
TTF_OpenFontIndexRW(SDL_RWops * src, int freesrc, int ptsize, long index)
{
    TTF_Font *font;
    FT_Error error;
    FT_Face face;
    FT_Fixed scale;
    FT_Stream stream;
    int position;

    if(!TTF_initialized)
    {
        TTF_SetError("Library not initialized");
        return NULL;
    }

    /* Check to make sure we can seek in this stream */
    position = SDL_RWtell(src);
    if(position < 0)
    {
        TTF_SetError("Can't seek in stream");
        return NULL;
    }

    font = (TTF_Font *) malloc(sizeof *font);
    if(font == NULL)
    {
        TTF_SetError("Out of memory");
        return NULL;
    }
    memset(font, 0, sizeof(*font));

    font->src = src;
    font->freesrc = freesrc;

    stream = (FT_Stream) malloc(sizeof(*stream));
    if(stream == NULL)
    {
        TTF_SetError("Out of memory");
        TTF_CloseFont(font);
        return NULL;
    }
    memset(stream, 0, sizeof(*stream));

    /* 090303 Chase - Newer FT2 version sets this internally so we don't
    				have to. (Can't anyway, Don't have a definition for FT_Library)
    */
    // stream->memory = library->memory;

    stream->read = RWread;
    stream->descriptor.pointer = src;
    stream->pos = (unsigned long) position;
    SDL_RWseek(src, 0, SEEK_END);
    stream->size = (unsigned long) (SDL_RWtell(src) - position);
    SDL_RWseek(src, position, SEEK_SET);

    font->args.flags = FT_OPEN_STREAM;
    font->args.stream = stream;

    error = FT_Open_Face(library, &font->args, index, &font->face);
    if(error)
    {
        TTF_SetFTError("Couldn't load font file", error);
        TTF_CloseFont(font);
        return NULL;
    }
    face = font->face;

    /* Make sure that our font face is scalable (global metrics) */
    if(FT_IS_SCALABLE(face))
    {

        /* Set the character size and use default DPI (72) */
        error = FT_Set_Char_Size(font->face, 0, ptsize * 64, 0, 0);
        if(error)
        {
            TTF_SetFTError("Couldn't set font size", error);
            TTF_CloseFont(font);
            return NULL;
        }

        /* Get the scalable font metrics for this font */
        scale = face->size->metrics.y_scale;
        font->ascent = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
        font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
        font->height = font->ascent - font->descent + /* baseline */ 1;
        font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
        font->underline_offset =
            FT_FLOOR(FT_MulFix(face->underline_position, scale));
        font->underline_height =
            FT_FLOOR(FT_MulFix(face->underline_thickness, scale));

    }
    else
    {
        /* Non-scalable font case.  ptsize determines which family
         * or series of fonts to grab from the non-scalable format.
         * It is not the point size of the font.
         * */
        if(ptsize >= font->face->num_fixed_sizes)
            ptsize = font->face->num_fixed_sizes - 1;
        font->font_size_family = ptsize;
        error = FT_Set_Pixel_Sizes(face,
                                   face->available_sizes[ptsize].height,
                                   face->available_sizes[ptsize].width);
        /* With non-scalale fonts, Freetype2 likes to fill many of the
         * font metrics with the value of 0.  The size of the
         * non-scalable fonts must be determined differently
         * or sometimes cannot be determined.
         * */
        font->ascent = face->available_sizes[ptsize].height;
        font->descent = 0;
        font->height = face->available_sizes[ptsize].height;
        font->lineskip = FT_CEIL(font->ascent);
        font->underline_offset = FT_FLOOR(face->underline_position);
        font->underline_height = FT_FLOOR(face->underline_thickness);
    }

    if(font->underline_height < 1)
    {
        font->underline_height = 1;
    }

#ifdef DEBUG_FONTS
    printf("Font metrics:\n");
    printf("\tascent = %d, descent = %d\n", font->ascent, font->descent);
    printf("\theight = %d, lineskip = %d\n", font->height, font->lineskip);
    printf("\tunderline_offset = %d, underline_height = %d\n",
           font->underline_offset, font->underline_height);
#endif

    /* Set the default font style */
    font->style = TTF_STYLE_NORMAL;
    font->glyph_overhang = face->size->metrics.y_ppem / 10;
    /* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
    font->glyph_italics = 0.207f;
    font->glyph_italics *= font->height;

    return font;
}
Example #23
0
//
// _checkLicenses();
//
void FontFace::_checkLicenses(void){
	
	//
	// Assign the default:
	//
	_licenseData = UnknownLicense::pData;
	
	std::string licenseString;
	
	///////////////////////////////////////
	//
	// Handle both (1) TrueType/OpenType
	//         and (2) Type1 fonts
	//
	///////////////////////////////////////
	if(FT_IS_SFNT(_face)){
		
		///////////////////////////////
		//
		// TrueType / OpenType CASE:
		//
		///////////////////////////////
		
		FT_UInt count=FT_Get_Sfnt_Name_Count(_face);
		
		FT_SfntName fontName;
		
		//
		// Check both the COPYRIGHT (TTF) and LICENSE (OPENTYPE) fields:
		//
		for(unsigned j=0;j<count;j++){
			
			FT_Get_Sfnt_Name(_face,j,&fontName);
			if(fontName.name_id==NID_LICENSE || fontName.name_id==NID_COPYRIGHT){
				
				licenseString = _getStringFromTrueTypeFont(fontName);
				
				if(fontName.name_id==NID_COPYRIGHT){
					_storeCopyrightSummary(licenseString);
				}
				
				if(_checkAllKnownLicenses(licenseString)){
					
					return;
					
				}
			}
			
			if(fontName.name_id==NID_URL_LICENSE){
				
				_licenseURL = _getStringFromTrueTypeFont(fontName);
				
			}
		}
		
		//
		// Get here if not a known license string:
		//
		
	}else if(FT_IS_SCALABLE(_face)){
		
		///////////////////////////////
		//
		// Could be Type 1, Type 42, 
		// CID, or PFR CASES:
		//
		///////////////////////////////
		
		PS_FontInfoRec fi;
		FT_Get_PS_Font_Info(_face,&fi);
		
		if(fi.notice){
			licenseString = fi.notice;
			_checkAllKnownLicenses(licenseString);
			_storeCopyrightSummary(licenseString);
		}
		
	}
	
	
}
Example #24
0
FT2Font::FT2Font(std::string facefile) 
{
  _VERBOSE("FT2Font::FT2Font");
  clear(Py::Tuple(0));
  
  int error = FT_New_Face( _ft2Library, facefile.c_str(), 0, &face );
  
  if (error == FT_Err_Unknown_File_Format ) {
    std::ostringstream s;
    s << "Could not load facefile " << facefile << "; Unknown_File_Format" << std::endl;
    throw Py::RuntimeError(s.str());
  }
  else if (error == FT_Err_Cannot_Open_Resource) {
    std::ostringstream s;
    s << "Could not open facefile " << facefile << "; Cannot_Open_Resource" << std::endl;
    throw Py::RuntimeError(s.str());
  }
  else if (error == FT_Err_Invalid_File_Format) {
    std::ostringstream s;
    s << "Could not open facefile " << facefile << "; Invalid_File_Format" << std::endl;
    throw Py::RuntimeError(s.str());
  }
  else if (error) {
    std::ostringstream s;
    s << "Could not open facefile " << facefile << "; freetype error code " << error<< std::endl;
    throw Py::RuntimeError(s.str());
  }
  
  // set a default fontsize 12 pt at 72dpi
  error = FT_Set_Char_Size( face, 12 * 64, 0, 72, 72 );
  //error = FT_Set_Char_Size( face, 20 * 64, 0, 80, 80 );
  if (error) {
    std::ostringstream s;
    s << "Could not set the fontsize for facefile  " << facefile << std::endl;
    throw Py::RuntimeError(s.str());
  }
  
  // set some face props as attributes
  //small memory leak fixed after 2.1.8 
  const char* ps_name = FT_Get_Postscript_Name( face );
  //const char* ps_name = "jdh";
  if ( ps_name == NULL )
    ps_name = "UNAVAILABLE";
  
  setattr("postscript_name", Py::String(ps_name));
  setattr("num_faces",       Py::Int(face->num_faces));
  setattr("family_name",     Py::String(face->family_name));
  setattr("style_name",      Py::String(face->style_name));
  setattr("face_flags",      Py::Int(face->face_flags));
  setattr("style_flags",     Py::Int(face->style_flags));
  setattr("num_glyphs",      Py::Int(face->num_glyphs));
  setattr("num_fixed_sizes", Py::Int(face->num_fixed_sizes));
  setattr("num_charmaps",    Py::Int(face->num_charmaps));
   
  int scalable = FT_IS_SCALABLE( face );

  setattr("scalable", Py::Int(scalable));
  
  if (scalable) {
    setattr("units_per_EM", Py::Int(face->units_per_EM));
    
    Py::Tuple bbox(4);
    bbox[0] = Py::Int(face->bbox.xMin);
    bbox[1] = Py::Int(face->bbox.yMin);
    bbox[2] = Py::Int(face->bbox.xMax);
    bbox[3] = Py::Int(face->bbox.yMax);
    setattr("bbox",  bbox);
    setattr("ascender",            Py::Int(face->ascender));
    setattr("descender",           Py::Int(face->descender));
    setattr("height",              Py::Int(face->height));
    setattr("max_advance_width",   Py::Int(face->max_advance_width));
    setattr("max_advance_height",  Py::Int(face->max_advance_height));
    setattr("underline_position",  Py::Int(face->underline_position));
    setattr("underline_thickness", Py::Int(face->underline_thickness));
  }
}
Example #25
0
TTF_Font* TTF_OpenFontIndex( const char *file, int ptsize, long index )
{
        TTF_Font* font;
        FT_Error error;
        FT_Face face;
        FT_Fixed scale;

	extern int strict_font;

        font = (TTF_Font*) malloc(sizeof *font);
        if ( font == NULL ) {
                fprintf(stderr, "Out of memory\n" );
                return NULL;
        }
        memset( font, 0, sizeof( *font ) );

        /* Open the font and create ancillary data */
        error = FT_New_Face( library, file, 0, &font->face );

	if( error && !strict_font )
		error=FT_New_Memory_Face(library, (const FT_Byte*)DroidSans_ttf, DROIDSANS_SIZE, 0, &font->face );

        if( error ) {
                printf( "Couldn't load font file\n");
                free( font );
                return NULL;
        }

        if ( index != 0 ) {
                if ( font->face->num_faces > index ) {
                        FT_Done_Face( font->face );
                        error = FT_New_Face( library, file, index, &font->face
);
                        if( error ) {
                                printf( "Couldn't get font face\n");
                                free( font );
                                return NULL;
                        }
                } else {
                        fprintf(stderr, "No such font face\n");
                        free( font );
                        return NULL;
                }
        }
        face = font->face;

        /* Make sure that our font face is scalable (global metrics) */
        if ( ! FT_IS_SCALABLE(face) ) {
                fprintf(stderr,"Font face is not scalable\n");
                TTF_CloseFont( font );
                return NULL;
        }
       /* Set the character size and use default DPI (72) */
        error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 );
        if( error ) {
                fprintf(stderr, "Couldn't set font size\n");
                TTF_CloseFont( font );
                return NULL;
        }
        
        /* Get the scalable font metrics for this font */
        scale = face->size->metrics.y_scale;
        font->ascent  = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
        font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
        font->height  = font->ascent - font->descent + /* baseline */ 1;
        font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
        font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
        font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
        if ( font->underline_height < 1 ) {
                font->underline_height = 1;
        }
#ifdef DEBUG_FONTS
        printf("Font metrics:\n");
        printf("\tascent = %d, descent = %d\n",
                font->ascent, font->descent);
        printf("\theight = %d, lineskip = %d\n",
                font->height, font->lineskip);
        printf("\tunderline_offset = %d, underline_height = %d\n",
                font->underline_offset, font->underline_height);
#endif

        /* Set the default font style */
        font->style = TTF_STYLE_NORMAL;
        font->glyph_overhang = face->size->metrics.y_ppem / 10;
        /* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */

        /*font->glyph_italics = 0.207f;
        font->glyph_italics *= font->height;*/

        return font;
}
Example #26
0
tt_face_init( FT_Stream      stream,
              FT_Face        ttface,      /* TT_Face */
              FT_Int         face_index,
              FT_Int         num_params,
              FT_Parameter*  params )
{
    FT_Error      error;
    FT_Library    library;
    SFNT_Service  sfnt;
    TT_Face       face = (TT_Face)ttface;


    FT_TRACE2(( "TTF driver\n" ));

    library = ttface->driver->root.library;

    sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
    if ( !sfnt )
    {
        FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
        error = FT_THROW( Missing_Module );
        goto Exit;
    }

    /* create input stream from resource */
    if ( FT_STREAM_SEEK( 0 ) )
        goto Exit;

    /* check that we have a valid TrueType file */
    error = sfnt->init_face( stream, face, face_index, num_params, params );

    /* Stream may have changed. */
    stream = face->root.stream;

    if ( error )
        goto Exit;

    /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
    /* The 0x00020000 tag is completely undocumented; some fonts from   */
    /* Arphic made for Chinese Windows 3.1 have this.                   */
    if ( face->format_tag != 0x00010000L &&    /* MS fonts  */
            face->format_tag != 0x00020000L &&    /* CJK fonts for Win 3.1 */
            face->format_tag != TTAG_true   )     /* Mac fonts */
    {
        FT_TRACE2(( "  not a TTF font\n" ));
        goto Bad_Format;
    }

#ifdef TT_USE_BYTECODE_INTERPRETER
    ttface->face_flags |= FT_FACE_FLAG_HINTER;
#endif

    /* If we are performing a simple font format check, exit immediately. */
    if ( face_index < 0 )
        return FT_Err_Ok;

    /* Load font directory */
    error = sfnt->load_face( stream, face, face_index, num_params, params );
    if ( error )
        goto Exit;

    if ( tt_check_trickyness( ttface ) )
        ttface->face_flags |= FT_FACE_FLAG_TRICKY;

    error = tt_face_load_hdmx( face, stream );
    if ( error )
        goto Exit;

    if ( FT_IS_SCALABLE( ttface ) )
    {

#ifdef FT_CONFIG_OPTION_INCREMENTAL

        if ( !ttface->internal->incremental_interface )
            error = tt_face_load_loca( face, stream );
        if ( !error )
            error = tt_face_load_cvt( face, stream );
        if ( !error )
            error = tt_face_load_fpgm( face, stream );
        if ( !error )
            error = tt_face_load_prep( face, stream );

        /* Check the scalable flag based on `loca'. */
        if ( !ttface->internal->incremental_interface &&
                ttface->num_fixed_sizes                  &&
                face->glyph_locations                    &&
                tt_check_single_notdef( ttface )         )
        {
            FT_TRACE5(( "tt_face_init:"
                        " Only the `.notdef' glyph has an outline.\n"
                        "             "
                        " Resetting scalable flag to FALSE.\n" ));

            ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
        }

#else /* !FT_CONFIG_OPTION_INCREMENTAL */

        if ( !error )
            error = tt_face_load_loca( face, stream );
        if ( !error )
            error = tt_face_load_cvt( face, stream );
        if ( !error )
            error = tt_face_load_fpgm( face, stream );
        if ( !error )
            error = tt_face_load_prep( face, stream );

        /* Check the scalable flag based on `loca'. */
        if ( ttface->num_fixed_sizes          &&
                face->glyph_locations            &&
                tt_check_single_notdef( ttface ) )
        {
            FT_TRACE5(( "tt_face_init:"
                        " Only the `.notdef' glyph has an outline.\n"
                        "             "
                        " Resetting scalable flag to FALSE.\n" ));

            ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
        }

#endif /* !FT_CONFIG_OPTION_INCREMENTAL */

    }

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT

    {
        FT_Int  instance_index = face_index >> 16;


        if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
                instance_index > 0                )
        {
            error = TT_Get_MM_Var( face, NULL );
            if ( error )
                goto Exit;

            if ( face->blend->mmvar->namedstyle )
            {
                FT_Memory  memory = ttface->memory;

                FT_Var_Named_Style*  named_style;
                FT_String*           style_name;


                /* in `face_index', the instance index starts with value 1 */
                named_style = face->blend->mmvar->namedstyle + instance_index - 1;
                error = sfnt->get_name( face,
                                        (FT_UShort)named_style->strid,
                                        &style_name );
                if ( error )
                    goto Exit;

                /* set style name; if already set, replace it */
                if ( face->root.style_name )
                    FT_FREE( face->root.style_name );
                face->root.style_name = style_name;

                /* finally, select the named instance */
                error = TT_Set_Var_Design( face,
                                           face->blend->mmvar->num_axis,
                                           named_style->coords );
                if ( error )
                    goto Exit;
            }
        }
    }

#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */

    /* initialize standard glyph loading routines */
    TT_Init_Glyph_Loading( face );

Exit:
    return error;

Bad_Format:
    error = FT_THROW( Unknown_File_Format );
    goto Exit;
}
Example #27
0
File: font.cpp Project: viticm/pap2
BOOL Font::Initialize(LPCTSTR fontName, INT fontSize, UINT fontStyle, UINT fontDpi)
{
	if (KG3DFTFontLibrary::Instance() == NULL)
		return false;

	FT_Long const DEFAULT_FACE_INDEX = 0;
	FT_Face pFontFace = NULL;
	FT_Error err = 0;

	err = FT_New_Face(KG3DFTFontLibrary::Instance()->m_library, fontName, DEFAULT_FACE_INDEX, &pFontFace);
	if (err != 0)
	{
		if (err == FT_Err_Unknown_File_Format)
			_ASSERT(0 && "FT_Err_Unknown_File_Format == err");

		m_fontFace = NULL;
		return FALSE;
	}
	else
	{
		m_fontGlyphs = pFontFace->num_glyphs;
		m_fontUploads = pFontFace->num_glyphs;
		m_fontKerningTable = FT_HAS_KERNING(pFontFace);
	}


	// get face caps
	//if (!FT_HAS_VERTICAL(pFontFace))
	if (!FT_IS_SCALABLE(pFontFace))
	{
		_ASSERT(0 && "Sorry, font is not scalable.");
		return FALSE;
	}


	// get face encoding
	//m_fontFlagDraw = !fontAntialias ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL;
	m_fontEncoding = FT_ENCODING_UNICODE;
	m_fontUnicode  = FALSE;


	if (NULL != pFontFace->charmap)
	{
		for (int i = 0; i < pFontFace->num_charmaps; ++ i)
		{
			if (FT_Encoding(m_fontEncoding) == pFontFace->charmaps[i]->encoding)
			{
				m_fontUnicode = TRUE;
				break ;
			}

		}

		if (!m_fontUnicode)
		{
			 m_fontEncoding = pFontFace->charmaps[0]->encoding;
			 m_fontUnicode  = (m_fontEncoding == FT_ENCODING_UNICODE);
		}

		err = FT_Select_Charmap(pFontFace, FT_Encoding(m_fontEncoding));
		if (0 != err)
		{
			_ASSERT(0 && "FT_Select_Charmap");
			CleanUp();
			return FALSE;
		}
	}
	else
	{
		m_fontEncoding = pFontFace->charmap->encoding;
		m_fontUnicode  = (m_fontEncoding == FT_ENCODING_UNICODE);
	}
		

	// set char size
	err = FT_Set_Char_Size(pFontFace, 0L, FONT_FIXMULT(fontSize), fontDpi, fontDpi);
	if (0 != err)
	{
		// tmd;
		_ASSERT(0 && "FT_Set_Char_Size");
		CleanUp();
		return FALSE;
	}

	m_fontFace = pFontFace;
	m_fontPoint = fontSize;
	m_fontDPI = fontDpi;

	m_fontEffect = (fontStyle & (~KG3DFONT_STYLE_VERTICAL));
	m_fontVertical = fontStyle & KG3DFONT_STYLE_VERTICAL;
	m_fontFlagLoader = m_fontVertical ? m_fontFlagLoader | FT_LOAD_VERTICAL_LAYOUT : m_fontFlagLoader;

	return TRUE;
}
Example #28
0
void
gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics,
                             PRUint32* aSpaceGlyph)
{
    NS_PRECONDITION(aMetrics != NULL, "aMetrics must not be NULL");
    NS_PRECONDITION(aSpaceGlyph != NULL, "aSpaceGlyph must not be NULL");

    if (NS_UNLIKELY(!mFace)) {
        // No face.  This unfortunate situation might happen if the font
        // file is (re)moved at the wrong time.
        aMetrics->emHeight = mGfxFont->GetStyle()->size;
        aMetrics->emAscent = 0.8 * aMetrics->emHeight;
        aMetrics->emDescent = 0.2 * aMetrics->emHeight;
        aMetrics->maxAscent = aMetrics->emAscent;
        aMetrics->maxDescent = aMetrics->maxDescent;
        aMetrics->maxHeight = aMetrics->emHeight;
        aMetrics->internalLeading = 0.0;
        aMetrics->externalLeading = 0.2 * aMetrics->emHeight;
        aSpaceGlyph = 0;
        aMetrics->spaceWidth = 0.5 * aMetrics->emHeight;
        aMetrics->maxAdvance = aMetrics->spaceWidth;
        aMetrics->aveCharWidth = aMetrics->spaceWidth;
        aMetrics->zeroOrAveCharWidth = aMetrics->spaceWidth;
        aMetrics->xHeight = 0.5 * aMetrics->emHeight;
        aMetrics->underlineSize = aMetrics->emHeight / 14.0;
        aMetrics->underlineOffset = -aMetrics->underlineSize;
        aMetrics->strikeoutOffset = 0.25 * aMetrics->emHeight;
        aMetrics->strikeoutSize = aMetrics->underlineSize;
        aMetrics->superscriptOffset = aMetrics->xHeight;
        aMetrics->subscriptOffset = aMetrics->xHeight;

        return;
    }

    const FT_Size_Metrics& ftMetrics = mFace->size->metrics;

    gfxFloat emHeight;
    // Scale for vertical design metric conversion: pixels per design unit.
    gfxFloat yScale;
    if (FT_IS_SCALABLE(mFace)) {
        // Prefer FT_Size_Metrics::x_scale to x_ppem as x_ppem does not
        // have subpixel accuracy.
        //
        // FT_Size_Metrics::y_scale is in 16.16 fixed point format.  Its
        // (fractional) value is a factor that converts vertical metrics from
        // design units to units of 1/64 pixels, so that the result may be
        // interpreted as pixels in 26.6 fixed point format.
        yScale = FLOAT_FROM_26_6(FLOAT_FROM_16_16(ftMetrics.y_scale));
        emHeight = mFace->units_per_EM * yScale;
    } else { // Not scalable.
        // FT_Size_Metrics doc says x_scale is "only relevant for scalable
        // font formats".
        gfxFloat emUnit = mFace->units_per_EM;
        emHeight = ftMetrics.y_ppem;
        yScale = emHeight / emUnit;
    }

    TT_OS2 *os2 =
        static_cast<TT_OS2*>(FT_Get_Sfnt_Table(mFace, ft_sfnt_os2));

    aMetrics->maxAscent = FLOAT_FROM_26_6(ftMetrics.ascender);
    aMetrics->maxDescent = -FLOAT_FROM_26_6(ftMetrics.descender);
    aMetrics->maxAdvance = FLOAT_FROM_26_6(ftMetrics.max_advance);

    gfxFloat lineHeight;
    if (os2 && os2->sTypoAscender) {
        aMetrics->emAscent = os2->sTypoAscender * yScale;
        aMetrics->emDescent = -os2->sTypoDescender * yScale;
        FT_Short typoHeight =
            os2->sTypoAscender - os2->sTypoDescender + os2->sTypoLineGap;
        lineHeight = typoHeight * yScale;

        // maxAscent/maxDescent get used for frame heights, and some fonts
        // don't have the HHEA table ascent/descent set (bug 279032).
        if (aMetrics->emAscent > aMetrics->maxAscent)
            aMetrics->maxAscent = aMetrics->emAscent;
        if (aMetrics->emDescent > aMetrics->maxDescent)
            aMetrics->maxDescent = aMetrics->emDescent;
    } else {
        aMetrics->emAscent = aMetrics->maxAscent;
        aMetrics->emDescent = aMetrics->maxDescent;
        lineHeight = FLOAT_FROM_26_6(ftMetrics.height);
    }

    cairo_text_extents_t extents;
    *aSpaceGlyph = GetCharExtents(' ', &extents);
    if (*aSpaceGlyph) {
        aMetrics->spaceWidth = extents.x_advance;
    } else {
        aMetrics->spaceWidth = aMetrics->maxAdvance; // guess
    }

    aMetrics->zeroOrAveCharWidth = 0.0;
    if (GetCharExtents('0', &extents)) {
        aMetrics->zeroOrAveCharWidth = extents.x_advance;
    }

    // Prefering a measured x over sxHeight because sxHeight doesn't consider
    // hinting, but maybe the x extents are not quite right in some fancy
    // script fonts.  CSS 2.1 suggests possibly using the height of an "o",
    // which would have a more consistent glyph across fonts.
    if (GetCharExtents('x', &extents) && extents.y_bearing < 0.0) {
        aMetrics->xHeight = -extents.y_bearing;
        aMetrics->aveCharWidth = extents.x_advance;
    } else {
        if (os2 && os2->sxHeight) {
            aMetrics->xHeight = os2->sxHeight * yScale;
        } else {
            // CSS 2.1, section 4.3.2 Lengths: "In the cases where it is
            // impossible or impractical to determine the x-height, a value of
            // 0.5em should be used."
            aMetrics->xHeight = 0.5 * emHeight;
        }
        aMetrics->aveCharWidth = 0.0; // updated below
    }
    // aveCharWidth is used for the width of text input elements so be
    // liberal rather than conservative in the estimate.
    if (os2 && os2->xAvgCharWidth) {
        // Round to pixels as this is compared with maxAdvance to guess
        // whether this is a fixed width font.
        gfxFloat avgCharWidth =
            ScaleRoundDesignUnits(os2->xAvgCharWidth, ftMetrics.x_scale);
        aMetrics->aveCharWidth =
            NS_MAX(aMetrics->aveCharWidth, avgCharWidth);
    }
    aMetrics->aveCharWidth =
        NS_MAX(aMetrics->aveCharWidth, aMetrics->zeroOrAveCharWidth);
    if (aMetrics->aveCharWidth == 0.0) {
        aMetrics->aveCharWidth = aMetrics->spaceWidth;
    }
    if (aMetrics->zeroOrAveCharWidth == 0.0) {
        aMetrics->zeroOrAveCharWidth = aMetrics->aveCharWidth;
    }
    // Apparently hinting can mean that max_advance is not always accurate.
    aMetrics->maxAdvance =
        NS_MAX(aMetrics->maxAdvance, aMetrics->aveCharWidth);

    // gfxFont::Metrics::underlineOffset is the position of the top of the
    // underline.
    //
    // FT_FaceRec documentation describes underline_position as "the
    // center of the underlining stem".  This was the original definition
    // of the PostScript metric, but in the PostScript table of OpenType
    // fonts the metric is "the top of the underline"
    // (http://www.microsoft.com/typography/otspec/post.htm), and FreeType
    // (up to version 2.3.7) doesn't make any adjustment.
    //
    // Therefore get the underline position directly from the table
    // ourselves when this table exists.  Use FreeType's metrics for
    // other (including older PostScript) fonts.
    if (mFace->underline_position && mFace->underline_thickness) {
        aMetrics->underlineSize = mFace->underline_thickness * yScale;
        TT_Postscript *post = static_cast<TT_Postscript*>
            (FT_Get_Sfnt_Table(mFace, ft_sfnt_post));
        if (post && post->underlinePosition) {
            aMetrics->underlineOffset = post->underlinePosition * yScale;
        } else {
            aMetrics->underlineOffset = mFace->underline_position * yScale
                + 0.5 * aMetrics->underlineSize;
        }
    } else { // No underline info.
        // Imitate Pango.
        aMetrics->underlineSize = emHeight / 14.0;
        aMetrics->underlineOffset = -aMetrics->underlineSize;
    }

    if (os2 && os2->yStrikeoutSize && os2->yStrikeoutPosition) {
        aMetrics->strikeoutSize = os2->yStrikeoutSize * yScale;
        aMetrics->strikeoutOffset = os2->yStrikeoutPosition * yScale;
    } else { // No strikeout info.
        aMetrics->strikeoutSize = aMetrics->underlineSize;
        // Use OpenType spec's suggested position for Roman font.
        aMetrics->strikeoutOffset = emHeight * 409.0 / 2048.0
            + 0.5 * aMetrics->strikeoutSize;
    }
    SnapLineToPixels(aMetrics->strikeoutOffset, aMetrics->strikeoutSize);

    if (os2 && os2->ySuperscriptYOffset) {
        gfxFloat val = ScaleRoundDesignUnits(os2->ySuperscriptYOffset,
                                             ftMetrics.y_scale);
        aMetrics->superscriptOffset = NS_MAX(1.0, val);
    } else {
        aMetrics->superscriptOffset = aMetrics->xHeight;
    }
    
    if (os2 && os2->ySubscriptYOffset) {
        gfxFloat val = ScaleRoundDesignUnits(os2->ySubscriptYOffset,
                                             ftMetrics.y_scale);
        // some fonts have the incorrect sign. 
        val = fabs(val);
        aMetrics->subscriptOffset = NS_MAX(1.0, val);
    } else {
        aMetrics->subscriptOffset = aMetrics->xHeight;
    }

    aMetrics->maxHeight = aMetrics->maxAscent + aMetrics->maxDescent;

    // Make the line height an integer number of pixels so that lines will be
    // equally spaced (rather than just being snapped to pixels, some up and
    // some down).  Layout calculates line height from the emHeight +
    // internalLeading + externalLeading, but first each of these is rounded
    // to layout units.  To ensure that the result is an integer number of
    // pixels, round each of the components to pixels.
    aMetrics->emHeight = NS_floor(emHeight + 0.5);

    // maxHeight will normally be an integer, but round anyway in case
    // FreeType is configured differently.
    aMetrics->internalLeading =
        NS_floor(aMetrics->maxHeight - aMetrics->emHeight + 0.5);

    // Text input boxes currently don't work well with lineHeight
    // significantly less than maxHeight (with Verdana, for example).
    lineHeight = NS_floor(NS_MAX(lineHeight, aMetrics->maxHeight) + 0.5);
    aMetrics->externalLeading =
        lineHeight - aMetrics->internalLeading - aMetrics->emHeight;

    // Ensure emAscent + emDescent == emHeight
    gfxFloat sum = aMetrics->emAscent + aMetrics->emDescent;
    aMetrics->emAscent = sum > 0.0 ?
        aMetrics->emAscent * aMetrics->emHeight / sum : 0.0;
    aMetrics->emDescent = aMetrics->emHeight - aMetrics->emAscent;
}
Example #29
0
File: font.c Project: nenau/naev
/**
 * @brief Initializes a font.
 *
 *    @param font Font to load (NULL defaults to gl_defFont).
 *    @param fname Name of the font (from inside packfile, NULL defaults to default font).
 *    @param h Height of the font to generate.
 *    @return 0 on success.
 */
int gl_fontInit( glFont* font, const char *fname, const char *fallback, const unsigned int h )
{
   FT_Library library;
   FT_Face face;
   size_t bufsize;
   FT_Byte* buf;
   int i;
   glFontStash *stsh;
   char *used_font;

   /* See if we should override fonts. */
   used_font = NULL;
   if ((strcmp( fallback, FONT_DEFAULT_PATH )==0) &&
      (conf.font_name_default!=NULL)) {
      used_font = strdup( conf.font_name_default );
   }
   else if ((strcmp( fallback, FONT_MONOSPACE_PATH )==0) &&
      (conf.font_name_monospace!=NULL)) {
      used_font = strdup( conf.font_name_monospace );
   }
   if (used_font) {
      buf = (FT_Byte*)nfile_readFile( &bufsize, used_font );
      if (buf==NULL) {
         free(used_font);
         used_font = NULL;
      }
   }

   /* Try to use system font. */
   if (used_font==NULL) {
      used_font = gl_fontFind( fname );
      if (used_font) {
         buf = (FT_Byte*)nfile_readFile( &bufsize, used_font );
         if (buf==NULL) {
            free(used_font);
            used_font = NULL;
         }
      }
   }

   /* Fallback to packaged font. */
   if (used_font==NULL) {
      buf = ndata_read( (fallback!=NULL) ? fallback : FONT_DEFAULT_PATH, &bufsize );
      if (buf == NULL) {
         WARN(_("Unable to read font: %s"), (fallback!=NULL) ? fallback : FONT_DEFAULT_PATH);
         return -1;
      }
      used_font = strdup( fallback );
   }

   /* Get default font if not set. */
   if (font == NULL) {
      font = &gl_defFont;
      DEBUG( _("Using default font '%s'"), used_font );
   }

   /* Get font stash. */
   if (avail_fonts==NULL)
      avail_fonts = array_create( glFontStash );
   stsh = &array_grow( &avail_fonts );
   memset( stsh, 0, sizeof(glFontStash) );
   font->id = stsh - avail_fonts;
   font->h = (int)floor((double)h);

   /* Default sizes. */
   stsh->tw = DEFAULT_TEXTURE_SIZE;
   stsh->th = DEFAULT_TEXTURE_SIZE;
   stsh->h = font->h;

   /* Create a FreeType font library. */
   if (FT_Init_FreeType(&library)) {
      WARN(_("FT_Init_FreeType failed with font %s."),
            (used_font!=NULL) ? used_font : FONT_DEFAULT_PATH );
      return -1;
   }

   /* Object which freetype uses to store font info. */
   if (FT_New_Memory_Face( library, buf, bufsize, 0, &face )) {
      WARN(_("FT_New_Face failed loading library from %s"),
            (used_font!=NULL) ? used_font : FONT_DEFAULT_PATH );
      return -1;
   }

   /* Try to resize. */
   if (FT_IS_SCALABLE(face)) {
      if (FT_Set_Char_Size( face,
               0, /* Same as width. */
               h << 6, /* In 1/64th of a pixel. */
               96, /* Create at 96 DPI */
               96)) /* Create at 96 DPI */
         WARN(_("FT_Set_Char_Size failed."));
   }
   else
      WARN(_("Font isn't resizable!"));

   /* Select the character map. */
   if (FT_Select_Charmap( face, FT_ENCODING_UNICODE ))
      WARN(_("FT_Select_Charmap failed to change character mapping."));

   /* Initialize the unicode support. */
   for (i=0; i<HASH_LUT_SIZE; i++)
      stsh->lut[i] = -1;
   stsh->glyphs = array_create( glFontGlyph );
   stsh->tex    = array_create( glFontTex );

   /* Set up font stuff for next glyphs. */
   stsh->fontname = strdup( (used_font!=NULL) ? used_font : FONT_DEFAULT_PATH );
   stsh->face     = face;
   stsh->library  = library;
   stsh->fontdata = buf;

   /* Set up VBOs. */
   stsh->mvbo = 256;
   stsh->vbo_tex_data  = calloc( 8*stsh->mvbo, sizeof(GLfloat) );
   stsh->vbo_vert_data = calloc( 8*stsh->mvbo, sizeof(GLshort) );
   stsh->vbo_tex  = gl_vboCreateStatic( sizeof(GLfloat)*8*stsh->mvbo,  stsh->vbo_tex_data );
   stsh->vbo_vert = gl_vboCreateStatic( sizeof(GLshort)*8*stsh->mvbo, stsh->vbo_vert_data );

   /* Initializes ASCII. */
   for (i=0; i<128; i++)
      gl_fontGetGlyph( stsh, i );

#if 0
   /* We can now free the face and library */
   FT_Done_Face(face);
   FT_Done_FreeType(library);

   /* Free read buffer. */
   free(buf);
#endif

   return 0;
}