Пример #1
0
  void
  Print_Type( FT_Face  face )
  {
    FT_Module  module;


    printf( "font type entries\n" );

    module = &face->driver->root;
    printf( "   FreeType driver: %s\n", module->clazz->module_name );

    /* Is it better to dump all sfnt tag names? */
    printf( "   sfnt wrapped:    %s\n",
            FT_IS_SFNT( face ) ? (char *)"yes" : (char *)"no" );

    /* isScalable? */
    comma_flag = 0;
    printf( "   type:            " );
    if ( FT_IS_SCALABLE( face ) )
    {
      Print_Comma( "scalable" );
      if ( FT_HAS_MULTIPLE_MASTERS( face ) )
        Print_Comma( "multiple masters" );
    }
    if ( FT_HAS_FIXED_SIZES( face ) )
      Print_Comma( "fixed size" );
    printf( "\n" );

    /* Direction */
    comma_flag = 0;
    printf( "   direction:       " );
    if ( FT_HAS_HORIZONTAL( face ) )
      Print_Comma( "horizontal" );

    if ( FT_HAS_VERTICAL( face ) )
      Print_Comma( "vertical" );

    printf( "\n" );

    printf( "   fixed width:     %s\n",
            FT_IS_FIXED_WIDTH( face ) ? (char *)"yes" : (char *)"no" );

    printf( "   glyph names:     %s\n",
            FT_HAS_GLYPH_NAMES( face ) ? (char *)"yes" : (char *)"no" );

    if ( FT_IS_SCALABLE( face ) )
    {
      printf( "   EM size:         %d\n", face->units_per_EM );
      printf( "   global BBox:     (%ld,%ld):(%ld,%ld)\n",
              face->bbox.xMin, face->bbox.yMin,
              face->bbox.xMax, face->bbox.yMax );
      printf( "   ascent:          %d\n", face->ascender );
      printf( "   descent:         %d\n", face->descender );
      printf( "   text height:     %d\n", face->height );
    }
  }
Пример #2
0
static int
glnames(
	GLYPH *glyph_list
)
{
#define MAX_NAMELEN	1024

#ifdef XP_PSTEXT
	char          buf[1024];
	long          i;
    FT_Error      error;

#ifdef XP_ONLY_BLOCKS
    extern unsigned long xp_font_block_offset;
    extern FTFontPtr     xp_xtf;
    int                  bc; /* block counter */
    
    
    /* FixMe: This code should use PsOut_Get_FreeType_Glyph_Name() instead of
     * duplicating the code
     */
    for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) {
        /* Remap X11 font index to FreeType font index */
        i = FTRemap(face, &xp_xtf->mapping, bc);
        
        if( i >= face->num_glyphs )
          continue;
#else
	for(i=0; i < face->num_glyphs; i++) {
#endif /* XP_ONLY_BLOCKS */
        if( FT_Has_PS_Glyph_Names(face) ) {
          error = FT_Get_Glyph_Name(face, i, buf, MAX_NAMELEN);
        }
        else
        {
          error = -1;
        }
    
		if( error ) {
          /* Check for unicode mapping
           * See Adobe document "Unicode and Glyph Names"
           * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp)
           */
          if( (xp_xtf->mapping.mapping->type == FONT_ENCODING_UNICODE) &&
              (i < 0xFFFE) )
          {
            sprintf(buf, "uni%04lx", i);
          }
          else
          {
            sprintf(buf, "ch%02lx", i);
          }
		}
		glyph_list[i].name = strdup(buf);
		if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, buf);
		if (glyph_list[i].name == NULL) {
			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
			exit(255);
		}
	}

	return 0;
#else
	char bf[1024];
	long i;

	if( ! FT_HAS_GLYPH_NAMES(face) ) {
		WARNING_1 fprintf(stderr, "Font has no glyph names\n");
		return 1;
	}

	for(i=0; i < face->num_glyphs; i++) {
		if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
			sprintf(bf, "_g_%d", i);
			WARNING_2 fprintf(stderr,
				"Glyph No. %d has no postscript name, becomes %s\n", i, bf);
		}
		glyph_list[i].name = strdup(bf);
		if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
		if (glyph_list[i].name == NULL) {
			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
			exit(255);
		}
	}

	return 0;
#endif /* XP_PSTEXT */
}

/*
 * Get the metrics of the glyphs.
 */

static void
glmetrics(
	GLYPH *glyph_list
)
{
	GLYPH          *g;
	int i;
	FT_Glyph_Metrics *met;
	FT_BBox bbox;
	FT_Glyph gly;

#ifdef XP_ONLY_BLOCKS
    extern unsigned long xp_font_block_offset;
    extern FTFontPtr     xp_xtf;
    int                  bc; /* block counter */
    
    for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) {
        /* Remap X11 font index to FreeType font index */
        i = FTRemap(face, &xp_xtf->mapping, bc);
        
        if( i >= face->num_glyphs )
          continue;
        
#else
	for(i=0; i < face->num_glyphs; i++) {
#endif /* XP_ONLY_BLOCKS */
		g = &(glyph_list[i]);

		if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
			fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
			continue;
		}

		met = &face->glyph->metrics;

		if(FT_HAS_HORIZONTAL(face)) {
			g->width = met->horiAdvance;
			g->lsb = met->horiBearingX;
		} else {
			WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
			g->width = met->width;
			g->lsb = 0;
		}

		if( FT_Get_Glyph(face->glyph, &gly) ) {
			fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
			continue;
		}

		FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
		g->xMin = bbox.xMin;
		g->yMin = bbox.yMin;
		g->xMax = bbox.xMax;
		g->yMax = bbox.yMax;

		g->ttf_pathlen = face->glyph->outline.n_points;
	}
}

/*
 * Get the original encoding of the font. 
 * Returns 1 for if the original encoding is Unicode, 2 if the
 * original encoding is other 16-bit, 0 if 8-bit.
 */

static int
glenc(
	GLYPH *glyph_list,
	int *encoding,
	int *unimap
)
{
#ifdef XP_PSTEXT
	int                  i,
                         e;
	unsigned             code;
    extern FTFontPtr     xp_xtf;
    extern unsigned long xp_font_block_offset;
        
    enc_found = 1;
    enc_type  = 0;
    
	for(i=0; i<ENCTABSZ; i++) {
		if(encoding[i] != -1)
			continue;

        /* Remap X11 font index to FreeType font index */
        code = FTRemap(face, &xp_xtf->mapping, xp_font_block_offset+i);

		if(code == 0)
			continue; /* .notdef */

		encoding[i] = code;
	}
        
	return enc_type;
#else
	int i, e;
	unsigned code;

	if(ISDBG(FT)) 
		for(e=0; e < face->num_charmaps; e++) {
			fprintf(stderr, "found encoding pid=%d eid=%d\n", 
				face->charmaps[e]->platform_id,
				face->charmaps[e]->encoding_id);
		}

	if(enc_found)
		goto populate_map;

	enc_type = 0;

	/* first check for an explicit PID/EID */

	if(force_pid != -1) {
		for(e=0; e < face->num_charmaps; e++) {
			if(face->charmaps[e]->platform_id == force_pid
			&& face->charmaps[e]->encoding_id == force_eid) {
				WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
					force_pid, force_eid);
				if( FT_Set_Charmap(face, face->charmaps[e]) ) {
					fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
					exit(1);
				}
				enc_type = 1;
				goto populate_map;
			}
		}
		fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
			force_pid, force_eid);
		exit(1);
	}

	/* next check for a direct Adobe mapping */

	if(!forcemap) {
		for(e=0; e < face->num_charmaps; e++) {
			if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
				WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
				if( FT_Set_Charmap(face, face->charmaps[e]) ) {
					fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
					exit(1);
				}
				goto populate_map;
			}
		}
	}

	for(e=0; e < face->num_charmaps; e++) {
		if(face->charmaps[e]->platform_id == 3) {
			switch(face->charmaps[e]->encoding_id) {
			case 0:
				WARNING_1 fputs("Found Symbol Encoding\n", stderr);
				break;
			case 1:
				WARNING_1 fputs("Found Unicode Encoding\n", stderr);
				enc_type = 1;
				break;
			default:
				WARNING_1 {
					fprintf(stderr,
					"****MS Encoding ID %d not supported****\n",
						face->charmaps[e]->encoding_id);
					fputs("Treating it like Symbol encoding\n", stderr);
				}
				break;
			}
			break;
		}
	}
	if(e >= face->num_charmaps) {
		WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
		e = 0;
	}
	
	if( FT_Set_Charmap(face, face->charmaps[e]) ) {
		fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
		exit(1);
	}

populate_map:
	enc_found = 1;
	for(i=0; i<ENCTABSZ; i++) {
		if(encoding[i] != -1)
			continue;
		if(enc_type == 1 || forcemap) {
			code = unimap[i];
			if(code == (unsigned) -1)
				continue;
		} else
			code = i;

		code = FT_Get_Char_Index(face, code);
		if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
		if(code == 0)
			continue; /* .notdef */
		encoding[i] = code;
	}

	return enc_type;
#endif /* XP_PSTEXT */
}
Пример #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 {
    }
}