static int gr_font_loadfrom( file * fp )
{
    char header[8];
    int bpp;
    int types, i, id;
    uint32_t y;
    FONT * f;
    PALETTE * pal = NULL;

    struct
    {
        int width ;
        int height ;
        int yoffset ;
        int fileoffset ;
    }
    oldchardata[256];

    _chardata chardata[256] ;

    if ( font_count == MAX_FONTS ) return -1 ;

    /* Read the file header */

    if ( !file_read( fp, header, 8 ) ) return -1;

    if (
        memcmp( header, FNT_MAGIC, 7 ) != 0 &&
        memcmp( header, FNX_MAGIC, 7 ) != 0 )
    {
        return -1;
    }

    bpp = header[7];
    if ( bpp == 0 ) bpp = 8;

    /* Read or ignore the palette */

    if ( bpp == 8 && !( pal = gr_read_pal_with_gamma( fp ) ) ) return -1 ;

    /* Read the character data (detect old format) */

    if ( header[2] == 'x' )
    {
        if ( !file_readSint32( fp, &types ) )
        {
            pal_destroy( pal );
            return -1 ;
        }
        if ( !file_read( fp, chardata, sizeof( chardata ) ) )
        {
            pal_destroy( pal );
            return -1 ;
        }
        for ( i = 0 ; i < 256 ; i++ )
        {
            ARRANGE_DWORD( &chardata[i].width );
            ARRANGE_DWORD( &chardata[i].height );
            ARRANGE_DWORD( &chardata[i].xadvance );
            ARRANGE_DWORD( &chardata[i].yadvance );
            ARRANGE_DWORD( &chardata[i].xoffset );
            ARRANGE_DWORD( &chardata[i].yoffset );
            ARRANGE_DWORD( &chardata[i].fileoffset );
        }
    }
    else
    {
        if ( !file_readSint32( fp, &types ) )
        {
            pal_destroy( pal );
            return -1 ;
        }
        if ( !file_read( fp, oldchardata, sizeof( oldchardata ) ) )
        {
            pal_destroy( pal );
            return -1 ;
        }
        for ( i = 0 ; i < 256 ; i++ )
        {
            ARRANGE_DWORD( &oldchardata[i].width );
            ARRANGE_DWORD( &oldchardata[i].height );
            ARRANGE_DWORD( &oldchardata[i].yoffset );
            ARRANGE_DWORD( &oldchardata[i].fileoffset );

            chardata[i].width      = oldchardata[i].width;
            chardata[i].height     = oldchardata[i].height;
            chardata[i].xoffset    = 0;
            chardata[i].yoffset    = oldchardata[i].yoffset;
            chardata[i].xadvance   = oldchardata[i].width;
            chardata[i].yadvance   = oldchardata[i].height + oldchardata[i].yoffset;
            chardata[i].fileoffset = oldchardata[i].fileoffset;
        }
    }

    /* Create the font */

    if ( header[2] == 'x' )
        id = gr_font_new( types, header[7] ) ;
    else
        id = gr_font_new( CHARSET_CP850, 8 ) ;

    if ( id == -1 )
    {
        pal_destroy( pal );
        return -1 ;
    }

    f = fonts[id];
    if ( !f )
    {
        gr_font_destroy( id );
        pal_destroy( pal );
        return -1 ;
    }

    /* Load the character bitmaps */

    for ( i = 0 ; i < 256 ; i++ )
    {
        GRAPH * gr;
        uint8_t * ptr;

        f->glyph[i].xadvance = chardata[i].xadvance ;
        f->glyph[i].yadvance = chardata[i].yadvance ;

        if ( chardata[i].fileoffset == 0 || chardata[i].width == 0 || chardata[i].height == 0 ) continue ;

        f->glyph[i].xoffset = chardata[i].xoffset ;
        f->glyph[i].yoffset = chardata[i].yoffset ;

        file_seek( fp, chardata[i].fileoffset, SEEK_SET ) ;
        f->glyph[i].bitmap = gr = bitmap_new( i, chardata[i].width, chardata[i].height, f->bpp ) ;
        if ( !gr )
        {
            gr_font_destroy( id );
            pal_destroy( pal );
            return -1 ;
        }
        bitmap_add_cpoint( gr, 0, 0 ) ;
        gr->format->palette = pal;
        pal_use( pal );

        for ( y = 0, ptr = gr->data; y < gr->height; y++, ptr += gr->pitch )
        {
            if ( !file_read( fp, ptr, gr->widthb ) ) break ;

            if ( gr->format->depth == 16 )
            {
                ARRANGE_WORDS( ptr, ( int )gr->width );
            }
            else if ( gr->format->depth == 32 )
            {
                ARRANGE_DWORDS( ptr, ( int )gr->width );
            }
        }

        f->glyph[i].yoffset = chardata[i].yoffset ;
    }
    if ( f->glyph[32].xadvance == 0 ) f->glyph[32].xadvance = f->glyph['j'].xadvance ;

    pal_destroy( pal ); // Elimino la instancia inicial

    return id ;
}
jfloat GraphiteLayoutShaper::shapeScriptRun(const SkPaint* paint, const UChar* chars,
        size_t count, bool isRTL, Vector<jfloat>* const outAdvances,
        Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos,
        jfloat startXPosition, uint32_t startScriptRun, size_t glyphBaseCount) {
    ALOGD("Shape Scrit Run with Graphite");
    SkTypeface *typeface = paint->getTypeface();
    mShapingGrFace = getCachedGrFace(typeface);

    unsigned int x_ppem;
    unsigned int y_ppem;
    int x_scale;
    int y_scale;
    getConversionFactor(x_ppem, y_ppem, x_scale, y_scale, paint);

    mShapingGrFont = gr_make_font_with_ops(x_ppem, paint, &GraphiteFontOps, mShapingGrFace);

    const uint16_t *charsScriptStart = chars ;
    const uint16_t *charsScriptEnd = chars + count;

    size_t numCP;
    char *pError;

    numCP = gr_count_unicode_characters(gr_utf16, charsScriptStart, charsScriptEnd, (const void **)(&pError));

#if DEBUG_GLYPHS
    ALOGD("Myanmar shape with Graphite, numCP = %d, grFont = %p, grFace = %p, pError = %p",
            numCP, mShapingGrFont, mShapingGrFace, pError);
#endif

    if(!mShapingGrFont || !mShapingGrFace || pError) {
        ALOGD("Invalid grFont is NULL, grFace is NULL or parse string error.");
        return 0.0;
    }

    mShapingSegment = gr_make_seg(mShapingGrFont, mShapingGrFace, 0, 0,
            gr_utf16, charsScriptStart, numCP, isRTL);
    cluster_t *clusters = getCluster(mShapingSegment, numCP);

#if DEBUG_GLYPHS
        ALOGD("Got from Graphite");
#endif

    const gr_slot *slot;
    size_t glyphIndex, clusterIndex = 0;
    jfloat totalFontRunAdvance = 0;
    for (slot = gr_seg_first_slot(mShapingSegment), glyphIndex = 0; slot;
            slot = gr_slot_next_in_segment(slot), ++ glyphIndex) {
#if DEBUG_GLYPHS
        ALOGD("         -- Glyph = %d, origin = (%f, %f), advance = (%f, %f)\n",
                gr_slot_gid(slot), gr_slot_origin_X(slot),
                gr_slot_origin_Y(slot),
                gr_slot_advance_X(slot, mShapingGrFace, mShapingGrFont),
                gr_slot_advance_Y(slot, mShapingGrFace, mShapingGrFont));
#endif
        if(glyphIndex == clusters[clusterIndex].base_glyph + clusters[clusterIndex].num_glyphs) {
            uint32_t clusterStart = clusters[clusterIndex].base_char + startScriptRun;
            jfloat startOrigin = outAdvances->itemAt(clusterStart);
            jfloat advance = gr_slot_origin_X(slot) - startOrigin;
            outAdvances->replaceAt(advance, clusterStart);

            ++ clusterIndex;
            clusterStart = clusters[clusterIndex].base_char + startScriptRun;
            outAdvances->replaceAt(gr_slot_origin_X(slot), clusterStart);
        }

        jfloat charRight = gr_slot_origin_X(slot) + gr_slot_advance_X(slot, mShapingGrFace, mShapingGrFont);
        if (charRight > totalFontRunAdvance) {
            totalFontRunAdvance = charRight;
        }

        jchar glyph = glyphBaseCount + gr_slot_gid(slot);
        outGlyphs->add(glyph);

        outPos->add(startXPosition + gr_slot_origin_X(slot));
        outPos->add(gr_slot_origin_Y(slot));
    }

    uint32_t clusterStart = clusters[clusterIndex].base_char + startScriptRun;
    jfloat startOrigin = outAdvances->itemAt(clusterStart);
    jfloat advance = totalFontRunAdvance - startOrigin;
    outAdvances->replaceAt(advance, clusterStart);

    if(mShapingSegment) {
        gr_seg_destroy(mShapingSegment);
        mShapingSegment = NULL;
    }

    if(mShapingGrFont) {
        gr_font_destroy(mShapingGrFont);
        mShapingGrFont = NULL;
    }
#if DEBUG_GLYPHS
    ALOGD("         -- totalFontRunAdvance = %f", totalFontRunAdvance);
#endif
    return totalFontRunAdvance;
}