Exemplo n.º 1
0
Arquivo: ftenc.c Projeto: aosm/X11libs
unsigned 
FTRemap(FT_Face face, FTMappingPtr tm, unsigned code)
{
    unsigned index;
    char *name;
    unsigned glyph_index;

    if(tm->mapping) {
        if(tm->named) {
            name = FontEncName(code, tm->mapping);
            if(!name)
                return 0;
            glyph_index = FT_Get_Name_Index(face, name);
            return glyph_index;
        } else {
            index = FontEncRecode(code, tm->mapping) + tm->base;
            FT_Set_Charmap(face, tm->cmap);
            glyph_index = FT_Get_Char_Index(face, index);
            return glyph_index;
        }
    } else {
        if(code < 0x100) {
            index = code;
            FT_Set_Charmap(face, tm->cmap);
            glyph_index = FT_Get_Char_Index(face, index);
            return glyph_index;
        } else
            return 0;
    }
}
Exemplo n.º 2
0
static int
find_cmap(int type, int pid, int eid, FT_Face face)
{
    int i, n, rc;
    FT_CharMap cmap = NULL;

    n = face->num_charmaps;

    switch(type) {
    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
        for(i=0; i<n; i++) {
            cmap = face->charmaps[i];
            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
                rc = FT_Set_Charmap(face, cmap);
                if(rc == 0)
                    return 1;
            }
        }
        break;
    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
        /* prefer Microsoft Unicode */
        for(i=0; i<n; i++) {
            cmap = face->charmaps[i];
            if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
                rc = FT_Set_Charmap(face, cmap);
                if(rc == 0)
                    return 1;
            }
        }
        /* Try Apple Unicode */
        for(i=0; i<n; i++) {
            cmap = face->charmaps[i];
            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
                rc = FT_Set_Charmap(face, cmap);
                if(rc == 0)
                    return 1;
            }
        }
        /* ISO Unicode? */
        for(i=0; i<n; i++) {
            cmap = face->charmaps[i];
            if(cmap->platform_id == TT_PLATFORM_ISO) {
                rc = FT_Set_Charmap(face, cmap);
                if(rc == 0)
                    return 1;
            }
        }
        break;
    default:
        return 0;
    }
    return 0;
}
Exemplo n.º 3
0
  static FT_Error
  af_indic_metrics_init( AF_CJKMetrics  metrics,
                         FT_Face        face )
  {
    /* skip blue zone init in CJK routines */
    FT_CharMap  oldmap = face->charmap;


    metrics->units_per_em = face->units_per_EM;

    if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
      face->charmap = NULL;
    else
    {
      af_cjk_metrics_init_widths( metrics, face );
#if 0
      /* either need indic specific blue_chars[] or just skip blue zones */
      af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
#endif
      af_cjk_metrics_check_digits( metrics, face );
    }

    FT_Set_Charmap( face, oldmap );

    return FT_Err_Ok;
  }
Exemplo n.º 4
0
static gboolean
check_font_contain_text (FT_Face face,
                         const gchar *text)
{
  gunichar *string;
  glong len, idx, map;
  FT_CharMap charmap;
  gboolean retval;

  string = g_utf8_to_ucs4_fast (text, -1, &len);

  for (map = 0; map < face->num_charmaps; map++) {
    charmap = face->charmaps[map];
    FT_Set_Charmap (face, charmap);

    retval = TRUE;

    for (idx = 0; idx < len; idx++) {
      gunichar c = string[idx];

      if (!FT_Get_Char_Index (face, c)) {
        retval = FALSE;
        break;
      }
    }

    if (retval)
      break;
  }

  g_free (string);

  return retval;
}
Exemplo n.º 5
0
TTF_Font* TTF_New_Memory_Face(const FT_Byte* file_base, FT_Long file_size, int ptsize)
	{
	TTF_Font *font = (TTF_Font*)malloc(sizeof *font);
	if (font == NULL)
		E_Exit("TTF: Out of memory");
	memset(font, 0, sizeof(*font));

	if (FT_New_Memory_Face(library, file_base, file_size, 0, &font->face))
		E_Exit("TTF: Couldn't init font");
	FT_Face face = font->face;
	if (!FT_IS_SCALABLE(face))														// Make sure that our font face is scalable (global metrics)
		E_Exit("TTF: Font is not scalable");

	for (int i = 0; i < face->num_charmaps; i++)									// Set charmap for loaded font
		{
		FT_CharMap charmap = face->charmaps[i];
		if (charmap->platform_id == 3 && charmap->encoding_id == 1)					// Windows Unicode
			{
			FT_Set_Charmap(face, charmap);
			break;
			}
		}
 
	TTF_SetCharSize(font, ptsize);
	bool fontOK = false;
	if (!FT_Load_Glyph(face, 0, FT_LOAD_DEFAULT))									// Test pixel mode
		if (!FT_Render_Glyph(font->face->glyph, FT_RENDER_MODE_NORMAL))				// Render the glyph
			if (font->face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
				fontOK = true;
	if (!fontOK)
		E_Exit("TTF: Font is not 8 bits gray scale");
	return font;
	}
Exemplo n.º 6
0
static int check_freetypefont(PackedFile *pf)
{
	FT_Face face;
	FT_GlyphSlot glyph;
	FT_UInt glyph_index;
#if 0
	FT_CharMap charmap;
	FT_CharMap found;
	FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
	FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
	int n;
#endif
	int success = 0;

	err = FT_New_Memory_Face(library,
	                         pf->data,
	                         pf->size,
	                         0,
	                         &face);
	if (err) {
		success = 0;
		//XXX error("This is not a valid font");
	}
	else {

#if 0
		for (n = 0; n < face->num_charmaps; n++) {
			charmap = face->charmaps[n];
			if (charmap->platform_id == my_platform_id && charmap->encoding_id == my_encoding_id) {
				found = charmap;
				break;
			}
		}

		if (!found) { return 0; }

		/* now, select the charmap for the face object */
		err = FT_Set_Charmap(face, found);
		if (err) { return 0; }
#endif

		glyph_index = FT_Get_Char_Index(face, 'A');
		err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
		if (err) {
			success = 0;
		}
		else {
			glyph = face->glyph;
			if (glyph->format == ft_glyph_format_outline) {
				success = 1;
			}
			else {
				//XXX error("Selected Font has no outline data");
				success = 0;
			}
		}
	}
	
	return success;
}
    //==============================================================================
    static FTFaceWrapper::Ptr selectUnicodeCharmap (FTFaceWrapper* face)
    {
        if (face != nullptr)
            if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0)
                FT_Set_Charmap (face->face, face->face->charmaps[0]);

        return face;
    }
Exemplo n.º 8
0
  Charmap::Charmap(Face * face)
  : m_ftFace(*face->freetype()),
    m_error(0)
  {
    if(!m_ftFace->charmap)  
      m_error = FT_Set_Charmap(m_ftFace, m_ftFace->charmaps[0]);

    m_ftEncoding = m_ftFace->charmap->encoding;
  }
/*  See http://www.microsoft.com/typography/otspec/name.htm
    for a list of some possible platform-encoding pairs.
    We're interested in 0-3 aka 3-1 - UCS-2.
    Otherwise, fail. If a font has some unicode map, but lacks
    UCS-2 - it is a broken or irrelevant font. What exactly
    Freetype will select on face load (it promises most wide
    unicode, and if that will be slower that UCS-2 - left as
    an excercise to check. */
int force_ucs2_charmap(FT_Face ftf) {
    for(int i = 0; i < ftf->num_charmaps; i++)
        if ((  (ftf->charmaps[i]->platform_id == 0)
            && (ftf->charmaps[i]->encoding_id == 3))
           || ((ftf->charmaps[i]->platform_id == 3)
            && (ftf->charmaps[i]->encoding_id == 1)))
                return FT_Set_Charmap(ftf, ftf->charmaps[i]);
    return -1;
}
Exemplo n.º 10
0
/*  See http://www.microsoft.com/typography/otspec/name.htm for a list of some
    possible platform-encoding pairs.  We're interested in 0-3 aka 3-1 - UCS-2.
    Otherwise, fail. If a font has some unicode map, but lacks UCS-2 - it is a
    broken or irrelevant font. What exactly Freetype will select on face load
    (it promises most wide unicode, and if that will be slower that UCS-2 -
    left as an excercise to check. */
int force_ucs2_charmap( FT_Face face )
{
    int i;
    for(i = 0; i < face->num_charmaps; i++)
        if( ((face->charmaps[i]->platform_id == 0) && (face->charmaps[i]->encoding_id == 3))
         || ((face->charmaps[i]->platform_id == 3) && (face->charmaps[i]->encoding_id == 1)) )
            return FT_Set_Charmap( face, face->charmaps[i] );
    return -1;
}
Exemplo n.º 11
0
// load and store charsmaps
static void LoadCharsMaps(GFont2D& Font, const FT_Face Face) {

	GUInt32 i, numMaps;
	FT_ULong charCode;
	FT_UInt glyphIndex;
	FT_Error err;
	FT_CharMap *maps;
	FT_CharMap map;
	GEncodedChar encodedChar;
	GCharMap tmpMap;
	
	numMaps = Face->num_charmaps;
	maps = Face->charmaps;

	for (i = 0; i < numMaps; i++) {
		map = maps[i];
		err = FT_Set_Charmap(Face, map);
		if (err == 0) {
			// get first (valid) char code
			charCode = FT_Get_First_Char(Face, &glyphIndex);
			// if glyphIndex is 0, it means that charmap is empty
			if (glyphIndex != 0) {
				tmpMap.CharMap.clear();
				// store encoding informations
				tmpMap.PlatformID = map->platform_id;
				tmpMap.EncodingID = map->encoding_id;
				switch (map->encoding) {
					case FT_ENCODING_MS_SYMBOL: tmpMap.Encoding = G_ENCODING_MS_SYMBOL;
					case FT_ENCODING_UNICODE: tmpMap.Encoding = G_ENCODING_UNICODE;
					case FT_ENCODING_SJIS: tmpMap.Encoding = G_ENCODING_SJIS;
					case FT_ENCODING_GB2312: tmpMap.Encoding = G_ENCODING_GB2312;
					case FT_ENCODING_BIG5: tmpMap.Encoding = G_ENCODING_BIG5;
					case FT_ENCODING_WANSUNG: tmpMap.Encoding = G_ENCODING_WANSUNG;
					case FT_ENCODING_JOHAB: tmpMap.Encoding = G_ENCODING_JOHAB;
					case FT_ENCODING_ADOBE_STANDARD: tmpMap.Encoding = G_ENCODING_ADOBE_STANDARD;
					case FT_ENCODING_ADOBE_EXPERT: tmpMap.Encoding = G_ENCODING_ADOBE_EXPERT;
					case FT_ENCODING_ADOBE_CUSTOM: tmpMap.Encoding = G_ENCODING_ADOBE_CUSTOM;
					case FT_ENCODING_ADOBE_LATIN_1: tmpMap.Encoding = G_ENCODING_ADOBE_LATIN_1;
					case FT_ENCODING_OLD_LATIN_2: tmpMap.Encoding = G_ENCODING_OLD_LATIN_2;
					case FT_ENCODING_APPLE_ROMAN: tmpMap.Encoding = G_ENCODING_APPLE_ROMAN;
					default:
						tmpMap.Encoding = G_ENCODING_NONE;
				}
				while (glyphIndex != 0) {

					encodedChar.CharCode = (GUInt32)charCode;
					encodedChar.GlyphIndex = (GUInt32)(glyphIndex - 0);
					tmpMap.CharMap.push_back(encodedChar);
					charCode = FT_Get_Next_Char(Face, charCode, &glyphIndex);
				}
				// add the loaded charmap to the font
				Font.AddCharMap(tmpMap);
			}
		}
	}
}
Exemplo n.º 12
0
Arquivo: ttf2c.c Projeto: sgh/aos
void initialize_face(FT_Face* face, FT_Library* library, int height, const char* filename) {
	int error;

	fprintf(stderr,"Loading %s... ", filename);
	error = FT_New_Face( *library, filename, 0, face );
	if ( error == FT_Err_Unknown_File_Format ) {
		fprintf(stderr,"Error opening font file\n");
		exit(1);
	} else
	if ( error ) {
		fprintf(stderr,"another error code means that the font file could not \nbe opened or read, or simply that it is broken...");
	}

	FT_CharMap  found = 0;
	int n;
	for (n = 0; n < (*face)->num_charmaps; n++ ) {
		FT_CharMap  charmap = (*face)->charmaps[n];
#ifndef TTF2C
		printf("platform_id:%d  encoding_id:%d\n", charmap->platform_id, charmap->encoding_id);
#endif
		found = charmap;
		if ( charmap->platform_id == 3/*my_platform_id*/ && charmap->encoding_id == 1/*my_encoding_id*/ ) {
// #ifndef TTF2C
// 			fprintf(stderr,"found charmap\n");
// #endif
			break;
		}
	}

	if ( !found ) {
		fprintf(stderr,"Encoding not found\n");
		exit(1);
	}

	/* now, select the charmap for the face object */
	error = FT_Set_Charmap( *face, found );
	if ( error ) {
		fprintf(stderr,"Error setting encoding\n");
		exit(1);
	}

	int width  = 0;

	error = FT_Set_Char_Size((*face), 0, height*64, 72, 72);

	error = FT_Set_Pixel_Sizes((*face), 0, height);

	if (error) {
		fprintf(stderr,"(fixed size) ");
// 		exit(1);
	}
	
	fprintf(stderr,"ok\n");
}
Exemplo n.º 13
0
FTCharmap::FTCharmap( FTFace* face)
    :   ftFace( *(face->Face())),
        err(0)
{
    if( !ftFace->charmap)
    {
        err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
    }

    ftEncoding = ftFace->charmap->encoding;
}
Exemplo n.º 14
0
/*
 * Function    : libaroma_font_set_ucs2
 * Return Value: int
 * Descriptions: set ucs2 charmap for fontface
 */
int libaroma_font_set_ucs2(
    FT_Face ftf) {
  int i;
  for (i = 0; i < ftf->num_charmaps; i++) {
    if ((  (ftf->charmaps[i]->platform_id == 0)
           && (ftf->charmaps[i]->encoding_id == 3))
        || ((ftf->charmaps[i]->platform_id == 3)
            && (ftf->charmaps[i]->encoding_id == 1))) {
      return FT_Set_Charmap(ftf, ftf->charmaps[i]);
    }
  }
  return -1;
} /* End of libaroma_font_set_ucs2 */
Exemplo n.º 15
0
/**
 * Select Microfost Unicode CharMap, if the font has one.
 * Otherwise, let FreeType decide.
 */
static void charmap_magic(FT_Face face)
{
	int i;
	for (i = 0; i < face->num_charmaps; ++i) {
		FT_CharMap cmap = face->charmaps[i];
		unsigned pid = cmap->platform_id;
		unsigned eid = cmap->encoding_id;
		if (pid == 3 /*microsoft*/ && (eid == 1 /*unicode bmp*/ || eid == 10 /*full unicode*/)) {
			FT_Set_Charmap(face, cmap);
			return;
		}
	}

	if (!face->charmap) {
		if (face->num_charmaps == 0) {
			mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmaps);
			return;
		}
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmapAutodetected);
		FT_Set_Charmap(face, face->charmaps[0]);
		return;
	}
}
Exemplo n.º 16
0
/**
 * Select a good charmap, prefer Microsoft Unicode charmaps.
 * Otherwise, let FreeType decide.
 */
void charmap_magic(ASS_Library *library, FT_Face face)
{
    int i;
    int ms_cmap = -1;

    // Search for a Microsoft Unicode cmap
    for (i = 0; i < face->num_charmaps; ++i) {
        FT_CharMap cmap = face->charmaps[i];
        unsigned pid = cmap->platform_id;
        unsigned eid = cmap->encoding_id;
        if (pid == 3 /*microsoft */
            && (eid == 1 /*unicode bmp */
                || eid == 10 /*full unicode */ )) {
            FT_Set_Charmap(face, cmap);
            return;
        } else if (pid == 3 && ms_cmap < 0)
            ms_cmap = i;
    }

    // Try the first Microsoft cmap if no Microsoft Unicode cmap was found
    if (ms_cmap >= 0) {
        FT_CharMap cmap = face->charmaps[ms_cmap];
        FT_Set_Charmap(face, cmap);
        return;
    }

    if (!face->charmap) {
        if (face->num_charmaps == 0) {
            ass_msg(library, MSGL_WARN, "Font face with no charmaps");
            return;
        }
        ass_msg(library, MSGL_WARN,
                "No charmap autodetected, trying the first one");
        FT_Set_Charmap(face, face->charmaps[0]);
        return;
    }
}
Exemplo n.º 17
0
cairo_font_face_t *Rcairo_set_font_face(int i, const char *file){
	cairo_font_face_t *c_face;
	cairo_status_t status;
	FT_Face face;
	FT_Error er;
	FT_CharMap found = 0; 
	FT_CharMap charmap; 
	int n; 

	/* Ensure that freetype library is ready */
	if (!Rcairo_ft_library){
		if (FT_Init_FreeType(&Rcairo_ft_library)){
			error("Failed to initialize freetype library in Rcairo_set_font_face!\n");
			return FALSE;
		}
	}

	er = FT_New_Face(Rcairo_ft_library, file, 0, &face);
	if ( er == FT_Err_Unknown_File_Format ) { 
		error("Unsupported font file format\n");
		return NULL;
	} else if ( er ) {
		error("Unknown font problem\n");
		return NULL;
	}
	for ( n = 0; n < face->num_charmaps; n++ ) { 
		charmap = face->charmaps[n]; 
		if ( charmap->platform_id == TT_PLATFORM_MACINTOSH) { 
			found = charmap; 
			break; 
		} 
	}

	/* Only do this for symbol font */
	if (found && i == 4){
		er = FT_Set_Charmap( face, found );
	} 

	c_face = cairo_ft_font_face_create_for_ft_face(face,FT_LOAD_DEFAULT);
	status = cairo_font_face_set_user_data (c_face, &key,
		face, (cairo_destroy_func_t) FT_Done_Face);
	if (status) {
	    cairo_font_face_destroy (c_face);
	    FT_Done_Face (face);
	    return NULL;
	}
	return c_face;
}
Exemplo n.º 18
0
/**
 * Loads the freetype font.
 * First type to load the fontname as if it were a path. If that fails,
 * try to resolve the filename of the font using fontconfig, where the
 * format is 'font family name' or 'font family name, font style'.
 */
static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *type)
{
	FT_Error error;

	if (StrEmpty(font_name)) return;

	error = FT_New_Face(_library, font_name, 0, face);

	if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, face);

	if (error == FT_Err_Ok) {
		DEBUG(freetype, 2, "Requested '%s', using '%s %s'", font_name, (*face)->family_name, (*face)->style_name);

		/* Attempt to select the unicode character map */
		error = FT_Select_Charmap(*face, ft_encoding_unicode);
		if (error == FT_Err_Ok) return; // Success

		if (error == FT_Err_Invalid_CharMap_Handle) {
			/* Try to pick a different character map instead. We default to
			 * the first map, but platform_id 0 encoding_id 0 should also
			 * be unicode (strange system...) */
			FT_CharMap found = (*face)->charmaps[0];
			int i;

			for (i = 0; i < (*face)->num_charmaps; i++) {
				FT_CharMap charmap = (*face)->charmaps[i];
				if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
					found = charmap;
				}
			}

			if (found != NULL) {
				error = FT_Set_Charmap(*face, found);
				if (error == FT_Err_Ok) return;
			}
		}
	}

	FT_Done_Face(*face);
	*face = NULL;

	ShowInfoF("Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", font_name, type, error);
}
Exemplo n.º 19
0
void FreeTypeLibrary::verifyCharacterMap(FT_Face face)
{
    //
    // GT: Verify the correct character mapping for MS windows 
    // as symbol fonts were being returned incorrectly
    //
    FT_CharMap charmap;
    if (face->charmap == NULL)
    {
        for (int n = 0; n < face->num_charmaps; n++) 
        { 
            charmap = face->charmaps[n]; 
            if (charmap->platform_id == TT_PLATFORM_MICROSOFT) 
            { 
                FT_Set_Charmap(face, charmap);
                break; 
            } 
        }
    }
}
Exemplo n.º 20
0
  af_cjk_metrics_init( AF_LatinMetrics  metrics,
                       FT_Face          face )
  {
    FT_CharMap  oldmap = face->charmap;


    metrics->units_per_em = face->units_per_EM;

    /* TODO are there blues? */

    if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
      face->charmap = NULL;

    /* latin's version would suffice */
    af_latin_metrics_init_widths( metrics, face, 0x7530 );

    FT_Set_Charmap( face, oldmap );

    return AF_Err_Ok;
  }
Exemplo n.º 21
0
    //==============================================================================
    FTFaceWrapper::Ptr createFace (const String& fontName, const String& fontStyle)
    {
        const KnownTypeface* ftFace = matchTypeface (fontName, fontStyle);

        if (ftFace == nullptr)  ftFace = matchTypeface (fontName, "Regular");
        if (ftFace == nullptr)  ftFace = matchTypeface (fontName, String::empty);

        if (ftFace != nullptr)
        {
            if (FTFaceWrapper::Ptr face = new FTFaceWrapper (library, ftFace->file, ftFace->faceIndex))
            {
                // If there isn't a unicode charmap then select the first one.
                if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0)
                    FT_Set_Charmap (face->face, face->face->charmaps[0]);

                return face;
            }
        }

        return nullptr;
    }
Exemplo n.º 22
0
Arquivo: ftdump.c Projeto: xahgo/tama
  void
  Print_Charmaps( FT_Face  face )
  {
    int  i, active = -1;


    if ( face->charmap )
      active = FT_Get_Charmap_Index( face->charmap );

    /* CharMaps */
    printf( "charmaps\n" );

    for( i = 0; i < face->num_charmaps; i++ )
    {
      printf( "   %d: platform %d, encoding %d",
              i,
              face->charmaps[i]->platform_id,
              face->charmaps[i]->encoding_id );
      if ( i == active )
        printf( " (active)" );
      printf ( "\n" );

      if ( verbose )
      {
        FT_ULong  charcode;
        FT_UInt   gindex;


        FT_Set_Charmap( face, face->charmaps[i] );

        charcode = FT_Get_First_Char( face, &gindex );
        while ( gindex )
        {
          printf( "      0x%04lx => %d\n", charcode, gindex );
          charcode = FT_Get_Next_Char( face, charcode, &gindex );
        }
        printf( "\n" );
      }
    }
  }
Exemplo n.º 23
0
FTCharmap::FTCharmap(FTFace* face)
:   ftFace(*(face->Face())),
    err(0)
{
    if(!ftFace->charmap)
    {
        if(!ftFace->num_charmaps)
        {
            // This face doesn't even have one charmap!
            err = 0x96; // Invalid_CharMap_Format
            return;
        }

        err = FT_Set_Charmap(ftFace, ftFace->charmaps[0]);
    }

    ftEncoding = ftFace->charmap->encoding;

    for(unsigned int i = 0; i < FTCharmap::MAX_PRECOMPUTED; i++)
    {
        charIndexCache[i] = FT_Get_Char_Index(ftFace, i);
    }
}
Exemplo n.º 24
0
FTCharmap::FTCharmap(FTFace* face)
 : ftFace(*(face->Face())),
   charMap(),
   err(0)
{
	if(!ftFace->charmap){
		err = FT_Set_Charmap(ftFace, ftFace->charmaps[0]);
	}
    
	ftEncoding = ftFace->charmap->encoding;
	
	if(ftEncoding != ft_encoding_unicode){
		err = FT_Select_Charmap(ftFace, ft_encoding_unicode);
    
		if(!err){
			ftEncoding = ft_encoding_unicode;
    	}else{
			ftEncoding = ft_encoding_none;
			PP_WARNING("Unable to set encoding to unicode: Error code -> " << err);
    	}
    	charMap.clear();		
	}
}
Exemplo n.º 25
0
  af_latin_metrics_init( AF_LatinMetrics  metrics,
                         FT_Face          face )
  {
    FT_Error    error = AF_Err_Ok;
    FT_CharMap  oldmap = face->charmap;
    FT_UInt     ee;

    static const FT_Encoding  latin_encodings[] =
    {
      FT_ENCODING_UNICODE,
      FT_ENCODING_APPLE_ROMAN,
      FT_ENCODING_ADOBE_STANDARD,
      FT_ENCODING_ADOBE_LATIN_1,
      FT_ENCODING_NONE  /* end of list */
    };


    metrics->units_per_em = face->units_per_EM;

    /* do we have a latin charmap in there? */
    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
    {
      error = FT_Select_Charmap( face, latin_encodings[ee] );
      if ( !error )
        break;
    }

    if ( !error )
    {
      /* For now, compute the standard width and height from the `o'. */
      af_latin_metrics_init_widths( metrics, face, 'o' );
      af_latin_metrics_init_blues( metrics, face );
    }

    FT_Set_Charmap( face, oldmap );
    return AF_Err_Ok;
  }
Exemplo n.º 26
0
Arquivo: t1afm.c Projeto: dmdware/vec
  /* parse a PFM file -- for now, only read the kerning pairs */
  static FT_Error
  T1_Read_PFM( FT_Face       t1_face,
               FT_Stream     stream,
               AFM_FontInfo  fi )
  {
    FT_Error      error  = FT_Err_Ok;
    FT_Memory     memory = stream->memory;
    FT_Byte*      start;
    FT_Byte*      limit;
    FT_Byte*      p;
    AFM_KernPair  kp;
    FT_Int        width_table_length;
    FT_CharMap    oldcharmap;
    FT_CharMap    charmap;
    FT_Int        n;


    start = (FT_Byte*)stream->cursor;
    limit = (FT_Byte*)stream->limit;
    p     = start;

    /* Figure out how long the width table is.          */
    /* This info is a little-endian short at offset 99. */
    p = start + 99;
    if ( p + 2 > limit )
    {
      error = FT_THROW( Unknown_File_Format );
      goto Exit;
    }
    width_table_length = FT_PEEK_USHORT_LE( p );

    p += 18 + width_table_length;
    if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )
      /* extension table is probably optional */
      goto Exit;

    /* Kerning offset is 14 bytes from start of extensions table. */
    p += 14;
    p = start + FT_PEEK_ULONG_LE( p );

    if ( p == start )
      /* zero offset means no table */
      goto Exit;

    if ( p + 2 > limit )
    {
      error = FT_THROW( Unknown_File_Format );
      goto Exit;
    }

    fi->NumKernPair = FT_PEEK_USHORT_LE( p );
    p += 2;
    if ( p + 4 * fi->NumKernPair > limit )
    {
      error = FT_THROW( Unknown_File_Format );
      goto Exit;
    }

    /* Actually, kerning pairs are simply optional! */
    if ( fi->NumKernPair == 0 )
      goto Exit;

    /* allocate the pairs */
    if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
      goto Exit;

    /* now, read each kern pair */
    kp             = fi->KernPairs;
    limit          = p + 4 * fi->NumKernPair;

    /* PFM kerning data are stored by encoding rather than glyph index, */
    /* so find the PostScript charmap of this font and install it       */
    /* temporarily.  If we find no PostScript charmap, then just use    */
    /* the default and hope it is the right one.                        */
    oldcharmap = t1_face->charmap;
    charmap    = NULL;

    for ( n = 0; n < t1_face->num_charmaps; n++ )
    {
      charmap = t1_face->charmaps[n];
      /* check against PostScript pseudo platform */
      if ( charmap->platform_id == 7 )
      {
        error = FT_Set_Charmap( t1_face, charmap );
        if ( error )
          goto Exit;
        break;
      }
    }

    /* Kerning info is stored as:             */
    /*                                        */
    /*   encoding of first glyph (1 byte)     */
    /*   encoding of second glyph (1 byte)    */
    /*   offset (little-endian short)         */
    for ( ; p < limit ; p += 4 )
    {
      kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
      kp->index2 = FT_Get_Char_Index( t1_face, p[1] );

      kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);
      kp->y = 0;

      kp++;
    }

    if ( oldcharmap != NULL )
      error = FT_Set_Charmap( t1_face, oldcharmap );
    if ( error )
      goto Exit;

    /* now, sort the kern pairs according to their glyph indices */
    ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
              compare_kern_pairs );

  Exit:
    if ( error )
    {
      FT_FREE( fi->KernPairs );
      fi->NumKernPair = 0;
    }

    return error;
  }
Exemplo n.º 27
0
static pdf_font_desc *
pdf_load_simple_font(pdf_document *xref, pdf_obj *dict)
{
	pdf_obj *descriptor;
	pdf_obj *encoding;
	pdf_obj *widths;
	unsigned short *etable = NULL;
	pdf_font_desc *fontdesc = NULL;
	char *subtype;
	FT_Face face;
	FT_CharMap cmap;
	int symbolic;
	int kind;

	char *basefont;
	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;
	fz_context *ctx = xref->ctx;

	fz_var(fontdesc);
	fz_var(etable);

	basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont"));

	/* Load font file */
	fz_try(ctx)
	{
		fontdesc = pdf_new_font_desc(ctx);

		descriptor = pdf_dict_gets(dict, "FontDescriptor");
		if (descriptor)
			pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont);
		else
			pdf_load_builtin_font(ctx, fontdesc, basefont);

		/* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */
		if (descriptor && pdf_is_string(pdf_dict_gets(descriptor, "FontName")) &&
			!pdf_dict_gets(dict, "ToUnicode") &&
			!strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") &&
			pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4)
		{
			char *cp936fonts[] = {
				"\xCB\xCE\xCC\xE5", "SimSun,Regular",
				"\xBA\xDA\xCC\xE5", "SimHei,Regular",
				"\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular",
				"\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular",
				"\xC1\xA5\xCA\xE9", "SimLi,Regular",
				NULL
			};
			for (i = 0; cp936fonts[i]; i += 2)
				if (!strcmp(basefont, cp936fonts[i]))
					break;
			if (cp936fonts[i])
			{
				fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings");
				pdf_drop_font(ctx, fontdesc);
				fontdesc = pdf_new_font_desc(ctx);
				pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]);
				fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H");
				fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
				fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");

				face = fontdesc->font->ft_face;
				kind = ft_kind(face);
				goto skip_encoding;
			}
		}

		face = fontdesc->font->ft_face;
		kind = ft_kind(face);

		/* Encoding */

		symbolic = fontdesc->flags & 4;

		if (face->num_charmaps > 0)
			cmap = face->charmaps[0];
		else
			cmap = NULL;

		for (i = 0; i < face->num_charmaps; i++)
		{
			FT_CharMap test = face->charmaps[i];

			if (kind == TYPE1)
			{
				if (test->platform_id == 7)
					cmap = test;
			}

			if (kind == TRUETYPE)
			{
				if (test->platform_id == 1 && test->encoding_id == 0)
					cmap = test;
				if (test->platform_id == 3 && test->encoding_id == 1)
					cmap = test;
				if (symbolic && test->platform_id == 3 && test->encoding_id == 0)
					cmap = test;
			}
		}

		if (cmap)
		{
			fterr = FT_Set_Charmap(face, cmap);
			if (fterr)
				fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr));
		}
		else
			fz_warn(ctx, "freetype could not find any cmaps");

		etable = fz_malloc_array(ctx, 256, sizeof(unsigned short));
		fontdesc->size += 256 * sizeof(unsigned short);
		for (i = 0; i < 256; i++)
		{
			estrings[i] = NULL;
			etable[i] = 0;
		}

		encoding = pdf_dict_gets(dict, "Encoding");
		if (encoding)
		{
			if (pdf_is_name(encoding))
				pdf_load_encoding(estrings, pdf_to_name(encoding));

			if (pdf_is_dict(encoding))
			{
				pdf_obj *base, *diff, *item;

				base = pdf_dict_gets(encoding, "BaseEncoding");
				if (pdf_is_name(base))
					pdf_load_encoding(estrings, pdf_to_name(base));
				else if (!fontdesc->is_embedded && !symbolic)
					pdf_load_encoding(estrings, "StandardEncoding");

				diff = pdf_dict_gets(encoding, "Differences");
				if (pdf_is_array(diff))
				{
					n = pdf_array_len(diff);
					k = 0;
					for (i = 0; i < n; i++)
					{
						item = pdf_array_get(diff, i);
						if (pdf_is_int(item))
							k = pdf_to_int(item);
						if (pdf_is_name(item) && k >= 0 && k < nelem(estrings))
							estrings[k++] = pdf_to_name(item);
					}
				}
			}
		}

		/* start with the builtin encoding */
		for (i = 0; i < 256; i++)
			etable[i] = ft_char_index(face, i);

		fz_lock(ctx, FZ_LOCK_FREETYPE);

		/* built-in and substitute fonts may be a different type than what the document expects */
		subtype = pdf_to_name(pdf_dict_gets(dict, "Subtype"));
		if (!strcmp(subtype, "Type1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "MMType1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "TrueType"))
			kind = TRUETYPE;
		else if (!strcmp(subtype, "CIDFontType0"))
			kind = TYPE1;
		else if (!strcmp(subtype, "CIDFontType2"))
			kind = TRUETYPE;

		/* encode by glyph name where we can */
		if (kind == TYPE1)
		{
			for (i = 0; i < 256; i++)
			{
				if (estrings[i])
				{
					etable[i] = FT_Get_Name_Index(face, estrings[i]);
					if (etable[i] == 0)
					{
						int aglcode = pdf_lookup_agl(estrings[i]);
						const char **dupnames = pdf_lookup_agl_duplicates(aglcode);
						while (*dupnames)
						{
							etable[i] = FT_Get_Name_Index(face, (char*)*dupnames);
							if (etable[i])
								break;
							dupnames++;
						}
					}
				}
			}
		}

		/* encode by glyph name where we can */
		if (kind == TRUETYPE)
		{
			/* Unicode cmap */
			if (!symbolic && face->charmap && face->charmap->platform_id == 3)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						int aglcode = pdf_lookup_agl(estrings[i]);
						if (!aglcode)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, aglcode);
					}
				}
			}

			/* MacRoman cmap */
			else if (!symbolic && face->charmap && face->charmap->platform_id == 1)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						k = lookup_mre_code(estrings[i]);
						if (k <= 0)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, k);
					}
				}
			}

			/* Symbolic cmap */
			else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						etable[i] = FT_Get_Name_Index(face, estrings[i]);
						if (etable[i] == 0)
							etable[i] = ft_char_index(face, i);
					}
				}
			}
		}

		/* try to reverse the glyph names from the builtin encoding */
		for (i = 0; i < 256; i++)
		{
			if (etable[i] && !estrings[i])
			{
				if (FT_HAS_GLYPH_NAMES(face))
				{
					fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
					if (fterr)
						fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr));
					if (ebuffer[i][0])
						estrings[i] = ebuffer[i];
				}
				else
				{
					estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */
				}
			}
		}

		/* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */
		if (kind == TYPE1 && symbolic)
		{
			for (i = 0; i < 256; i++)
				if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i]))
					estrings[i] = (char*) pdf_standard[i];
		}

		fz_unlock(ctx, FZ_LOCK_FREETYPE);

		fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
		fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
		fontdesc->cid_to_gid_len = 256;
		fontdesc->cid_to_gid = etable;

		fz_try(ctx)
		{
			pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));
		}
		fz_catch(ctx)
		{
			fz_warn(ctx, "cannot load ToUnicode CMap");
		}

	skip_encoding:

		/* Widths */

		pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width);

		widths = pdf_dict_gets(dict, "Widths");
		if (widths)
		{
			int first, last;

			first = pdf_to_int(pdf_dict_gets(dict, "FirstChar"));
			last = pdf_to_int(pdf_dict_gets(dict, "LastChar"));

			if (first < 0 || last > 255 || first > last)
				first = last = 0;

			for (i = 0; i < last - first + 1; i++)
			{
				int wid = pdf_to_int(pdf_array_get(widths, i));
				pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid);
			}
		}
		else
		{
			fz_lock(ctx, FZ_LOCK_FREETYPE);
			fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
			if (fterr)
				fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr));
			for (i = 0; i < 256; i++)
			{
				pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i));
			}
			fz_unlock(ctx, FZ_LOCK_FREETYPE);
		}

		pdf_end_hmtx(ctx, fontdesc);
	}
	fz_catch(ctx)
	{
		if (fontdesc && etable != fontdesc->cid_to_gid)
			fz_free(ctx, etable);
		pdf_drop_font(ctx, fontdesc);
		fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}
	return fontdesc;
}
Exemplo n.º 28
0
void
xps_select_font_encoding(fz_font *font, int idx)
{
    FT_Face face = font->ft_face;
    FT_Set_Charmap(face, face->charmaps[idx]);
}
Exemplo n.º 29
0
  static FT_Error
  af_face_globals_compute_style_coverage( AF_FaceGlobals  globals )
  {
    FT_Error    error;
    FT_Face     face        = globals->face;
    FT_CharMap  old_charmap = face->charmap;
    FT_Byte*    gstyles     = globals->glyph_styles;
    FT_UInt     ss;
    FT_UInt     i;
    FT_UInt     dflt        = -1;


    /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
    FT_MEM_SET( globals->glyph_styles,
                AF_STYLE_UNASSIGNED,
                globals->glyph_count );

    error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
    if ( error )
    {
      /*
       * Ignore this error; we simply use the fallback style.
       * XXX: Shouldn't we rather disable hinting?
       */
      error = FT_Err_Ok;
      goto Exit;
    }

    /* scan each style in a Unicode charmap */
    for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
    {
      AF_StyleClass       style_class =
                            AF_STYLE_CLASSES_GET[ss];
      AF_ScriptClass      script_class =
                            AF_SCRIPT_CLASSES_GET[style_class->script];
      AF_Script_UniRange  range;


      if ( script_class->script_uni_ranges == NULL )
        continue;

      /*
       *  Scan all Unicode points in the range and set the corresponding
       *  glyph style index.
       */
      if ( style_class->coverage == AF_COVERAGE_DEFAULT )
      {
        if ( style_class->script == globals->module->default_script )
          dflt = ss;

        for ( range = script_class->script_uni_ranges;
              range->first != 0;
              range++ )
        {
          FT_ULong  charcode = range->first;
          FT_UInt   gindex;


          gindex = FT_Get_Char_Index( face, charcode );

          if ( gindex != 0                             &&
               gindex < (FT_ULong)globals->glyph_count &&
               gstyles[gindex] == AF_STYLE_UNASSIGNED  )
            gstyles[gindex] = (FT_Byte)ss;

          for (;;)
          {
            charcode = FT_Get_Next_Char( face, charcode, &gindex );

            if ( gindex == 0 || charcode > range->last )
              break;

            if ( gindex < (FT_ULong)globals->glyph_count &&
                 gstyles[gindex] == AF_STYLE_UNASSIGNED  )
              gstyles[gindex] = (FT_Byte)ss;
          }
        }
      }
      else
      {
        /* get glyphs not directly addressable by cmap */
        af_get_coverage( globals, style_class, gstyles );
      }
    }

    /* handle the default OpenType features of the default script ... */
    af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );

    /* ... and the remaining default OpenType features */
    for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
    {
      AF_StyleClass  style_class = AF_STYLE_CLASSES_GET[ss];


      if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
        af_get_coverage( globals, style_class, gstyles );
    }

    /* mark ASCII digits */
    for ( i = 0x30; i <= 0x39; i++ )
    {
      FT_UInt  gindex = FT_Get_Char_Index( face, i );


      if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
        gstyles[gindex] |= AF_DIGIT;
    }

  Exit:
    /*
     *  By default, all uncovered glyphs are set to the fallback style.
     *  XXX: Shouldn't we disable hinting or do something similar?
     */
    if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
    {
      FT_Long  nn;


      for ( nn = 0; nn < globals->glyph_count; nn++ )
      {
        if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED )
        {
          gstyles[nn] &= ~AF_STYLE_UNASSIGNED;
          gstyles[nn] |= globals->module->fallback_style;
        }
      }
    }

#ifdef FT_DEBUG_LEVEL_TRACE

    FT_TRACE4(( "\n"
                "style coverage\n"
                "==============\n"
                "\n" ));

    for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
    {
      AF_StyleClass  style_class = AF_STYLE_CLASSES_GET[ss];
      FT_UInt        count       = 0;
      FT_Long        idx;


      FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));

      for ( idx = 0; idx < globals->glyph_count; idx++ )
      {
        if ( ( gstyles[idx] & ~AF_DIGIT ) == style_class->style )
        {
          if ( !( count % 10 ) )
            FT_TRACE4(( " " ));

          FT_TRACE4(( " %d", idx ));
          count++;

          if ( !( count % 10 ) )
            FT_TRACE4(( "\n" ));
        }
      }

      if ( !count )
        FT_TRACE4(( "  (none)\n" ));
      if ( count % 10 )
        FT_TRACE4(( "\n" ));
    }

#endif /* FT_DEBUG_LEVEL_TRACE */

    FT_Set_Charmap( face, old_charmap );
    return error;
  }
Exemplo n.º 30
0
  FTC_CMapCache_Lookup( FTC_CMapCache  cmap_cache,
                        FTC_FaceID     face_id,
                        FT_Int         cmap_index,
                        FT_UInt32      char_code )
  {
    FTC_Cache         cache = FTC_CACHE( cmap_cache );
    FTC_CMapQueryRec  query;
    FTC_Node          node;
    FT_Error          error;
    FT_UInt           gindex = 0;
    FT_Offset         hash;
    FT_Int            no_cmap_change = 0;


    if ( cmap_index < 0 )
    {
      /* Treat a negative cmap index as a special value, meaning that you */
      /* don't want to change the FT_Face's character map through this    */
      /* call.  This can be useful if the face requester callback already */
      /* sets the face's charmap to the appropriate value.                */

      no_cmap_change = 1;
      cmap_index     = 0;
    }

    if ( !cache )
    {
      FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));
      return 0;
    }

    query.face_id    = face_id;
    query.cmap_index = (FT_UInt)cmap_index;
    query.char_code  = char_code;

    hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );

#if 1
    FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
                          node, error );
#else
    error = FTC_Cache_Lookup( cache, hash, &query, &node );
#endif
    if ( error )
      goto Exit;

    FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <
                FTC_CMAP_INDICES_MAX );

    /* something rotten can happen with rogue clients */
    if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
                    FTC_CMAP_INDICES_MAX ) )
      return 0; /* XXX: should return appropriate error */

    gindex = FTC_CMAP_NODE( node )->indices[char_code -
                                            FTC_CMAP_NODE( node )->first];
    if ( gindex == FTC_CMAP_UNKNOWN )
    {
      FT_Face  face;


      gindex = 0;

      error = FTC_Manager_LookupFace( cache->manager,
                                      FTC_CMAP_NODE( node )->face_id,
                                      &face );
      if ( error )
        goto Exit;

      if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
      {
        FT_CharMap  old, cmap  = NULL;


        old  = face->charmap;
        cmap = face->charmaps[cmap_index];

        if ( old != cmap && !no_cmap_change )
          FT_Set_Charmap( face, cmap );

        gindex = FT_Get_Char_Index( face, char_code );

        if ( old != cmap && !no_cmap_change )
          FT_Set_Charmap( face, old );
      }

      FTC_CMAP_NODE( node )->indices[char_code -
                                     FTC_CMAP_NODE( node )->first]
        = (FT_UShort)gindex;
    }

  Exit:
    return gindex;
  }