Exemplo n.º 1
0
/*******************************************************************************
 *  ReadCharMetrics
 *
 *  Reads metrics for each glyph in a TrueType font.  Returns false for memory
 *  allocation or FreeType error; sets *p_metrics to NULL for non-fatal error.
 *
 */
static BOOL ReadCharMetrics(FT_Face face, AFM *afm, AFMMETRICS **p_metrics)
{
    FT_ULong	charcode, index;
    AFMMETRICS	*metrics;
    USHORT  	em_size = afm->WinMetrics.usUnitsPerEm;

    for (charcode = 0, index = 0; charcode < 65536; ++charcode)
    	if (pFT_Get_Char_Index(face, charcode) != 0)
	    ++index;	    	    	    	    	/* count # of glyphs */

    afm->NumofMetrics = index;

    *p_metrics = metrics = HeapAlloc(PSDRV_Heap, 0, index * sizeof(*metrics));
    if (metrics == NULL)
    	return FALSE;

    for (charcode = 0, index = 0; charcode < 65536; ++charcode)
    {
    	FT_UInt     glyph_index = pFT_Get_Char_Index(face, charcode);
	FT_Error    error;
	CHAR	    buffer[128];  	    	/* for glyph names */

	if (glyph_index == 0)
	    continue;

	error = pFT_Load_Glyph(face, glyph_index, GLYPH_LOAD_FLAGS);
	if (error != FT_Err_Ok)
	{
	    ERR("%s returned %i\n", "FT_Load_Glyph", error);
	    goto cleanup;
	}

	error = pFT_Get_Glyph_Name(face, glyph_index, buffer, sizeof(buffer));
	if (error != FT_Err_Ok)
	{
	    ERR("%s returned %i\n", "FT_Get_Glyph_Name", error);
	    goto cleanup;
    	}

	metrics[index].N = PSDRV_GlyphName(buffer);
	if (metrics[index].N == NULL)
	    goto cleanup;

	metrics[index].C = metrics[index].UV = charcode;
	metrics[index].WX = PSUnits(face->glyph->metrics.horiAdvance, em_size);

	++index;
    }

    if (afm->WinMetrics.sAvgCharWidth == 0)
    	afm->WinMetrics.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm);

    return TRUE;

    cleanup:
    	HeapFree(PSDRV_Heap, 0, metrics);

    return FALSE;
}
Exemplo n.º 2
0
bool CText::MakeFTChar(FT_Face face, char ch, int list_base, int textures[NUM_CHARS], float charsizes[NUM_CHARS][2], bool mipmaps)
{
	const int ich = ch;

	if(pFT_Load_Glyph(face,pFT_Get_Char_Index(face,ich),FT_LOAD_DEFAULT))
		return false;

	FT_Glyph glyph;
	if(pFT_Get_Glyph(face->glyph,&glyph))
		return false;

	bool empty=(pFT_Glyph_To_Bitmap(&glyph,FT_RENDER_MODE_NORMAL,0,1)!=0);
	FT_BitmapGlyph bitmap_glyph=(FT_BitmapGlyph)glyph;
	FT_Bitmap& bitmap=bitmap_glyph->bitmap;

	int width=1, height=1;
	if (!empty)
	{
		width=next_p2(bitmap.width);
		height=next_p2(bitmap.rows);

		unsigned char *expanded_data=(unsigned char *)malloc(2*width*height);
		if (!expanded_data)
		{
			pFT_Done_Glyph(glyph);
			return false;
		}

		for(int j=0; j<height; j++)
		{
			for(int i=0; i<width; i++)
			{
				expanded_data[2*(i+j*width)]=255;
				expanded_data[2*(i+j*width)+1] = 
					(i>=bitmap.width || j>=bitmap.rows) ?
					0 : bitmap.buffer[i + bitmap.width*j];
			}
		}

		glBindTexture(GL_TEXTURE_2D, textures[ich]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		if (mipmaps)
		{
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
			if (gluBuild2DMipmaps(GL_TEXTURE_2D,2,width,height,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,expanded_data)!=0)
			{
				free(expanded_data);
				pFT_Done_Glyph(glyph);
				return false;
			}
		}
		else
		{
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			glTexImage2D(	GL_TEXTURE_2D,
							0,
							GL_RGBA,
							width,
							height,
							0,
							GL_LUMINANCE_ALPHA,
							GL_UNSIGNED_BYTE,
							expanded_data);
		}

		free(expanded_data);
	}

	glNewList(list_base+ich,GL_COMPILE);
	{
		if (!empty)
		{
			glBindTexture(GL_TEXTURE_2D,textures[ich]);
			glPushMatrix();

			glTranslatef((float)bitmap_glyph->left, (float)(bitmap_glyph->top-bitmap.rows),0);

			float	x= (float)bitmap.width / (float)width,
					y= (float)bitmap.rows / (float)height;

			glBegin(GL_QUADS);
			{
				glNormal3f(0,0,1);
				glTexCoord2f(0,0); glVertex2f(0,(float)bitmap.rows);
				glTexCoord2f(x,0); glVertex2f((float)bitmap.width, (float)bitmap.rows);
				glTexCoord2f(x,y); glVertex2f((float)bitmap.width, 0);
				glTexCoord2f(0,y); glVertex2f(0,0);
			}
			glEnd();

			glPopMatrix();
		}

		glTranslatef((float)(face->glyph->advance.x>>6), 0, 0);
	}
	glEndList();

	charsizes[ich][0]=((float)face->glyph->advance.x/64.0f);
	charsizes[ich][1]=((float)face->size->metrics.height/64.0f);

	pFT_Done_Glyph(glyph);

	return true;
}