If that fails, could you perhaps attach some sample
renderings in png format?



In order to try and factor out any effect of the GL side of things, I wrote a small stand-alone windows app which just loads a font, renders a single glyph, and then writes out the rendered bitmap in the glyph slot to a .png and .txt file. So there's nothing here but calling FreeType and then storing the resultant gray scale bitmap.

At first I didn't see a huge difference, but this was before changing the flags Werner suggested. I changed those (to ensure the byte code interpreter is enabled) and rebuilt this sample and it does look a little different. The text is brighter, so maybe there's a darkening happening when rendering to GL.

The FreeTypeGL rendering code is shown below. Its storing the gray scale image in a texture which gets treated as the alpha channel to render a solid rectangle. Since I'm doing 2D rendering with GL, there should be a 1-to-1 between the rendered pixels and the texture pixels so I don't believe any texture filtering should be ocurring.

*>>> setup the texture for the glyph
*
    err = FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL);
    FT_Bitmap      bitmap = glyph->bitmap;
    destWidth  = bitmap.width;
    destHeight = bitmap.rows;

    if(destWidth && destHeight)
    {
        glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
        glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        glBindTexture(GL_TEXTURE_2D, glTextureID);
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);

        glPopClientAttrib();
    }


//      0
//      +----+
//      |    |
//      |    |
//      |    |
//      +----+
//           1

    uv[0].X(static_cast<float>(xOffset) / static_cast<float>(width));
    uv[0].Y(static_cast<float>(yOffset) / static_cast<float>(height));
uv[1].X(static_cast<float>(xOffset + destWidth) / static_cast<float>(width)); uv[1].Y(static_cast<float>(yOffset + destHeight) / static_cast<float>(height));

    corner = FTPoint(glyph->bitmap_left, glyph->bitmap_top);

*>>> render the glyph texture
*
    float dx, dy;

    if(activeTextureID != glTextureID)
    {
        glBindTexture(GL_TEXTURE_2D, (GLuint)glTextureID);
        activeTextureID = glTextureID;
    }

    dx = floor(pen.Xf() + corner.Xf());
    dy = floor(pen.Yf() + corner.Yf());

    glBegin(GL_QUADS);
        glTexCoord2f(uv[0].Xf(), uv[0].Yf());
        glVertex2f(dx, dy);

        glTexCoord2f(uv[0].Xf(), uv[1].Yf());
        glVertex2f(dx, dy - destHeight);

        glTexCoord2f(uv[1].Xf(), uv[1].Yf());
        glVertex2f(dx + destWidth, dy - destHeight);

        glTexCoord2f(uv[1].Xf(), uv[0].Yf());
        glVertex2f(dx + destWidth, dy);
    glEnd();

    return advance;

<<attachment: glyph.png>>

rows=8
width=6
pitch=6
num_grays=256
pixel_mode=2
palette_mode=0

00 00 00 66 FF 00
00 00 39 E5 FF 00
00 19 D7 33 FF 00
06 BC 3C 00 FF 00
93 47 00 00 FF 00
FF FF FF FF FF FF
00 00 00 00 FF 00
00 00 00 00 FF 00
#include "main.h"
#include "SaveToPNG.h"
#include "SaveToTXT.h"

FT_Error   err         = 0;
FT_Library libFreeType = NULL;
FT_Face    fontFace    = NULL;
FT_UInt    glyphIndex  = 0;

int screenResX = 0;
int screenResY = 0;

#define FONT_FILE       "C:\\Windows\\Fonts\\l_10646.ttf" // Lucida Sans Unicode
#define FONT_POINT_SIZE 8
#define CHAR_TO_RENDER  _T('4')

#define PNG_FILE        _T("c:\\glyph.png")
#define TEXT_FILE       _T("c:\\glyph.txt")

#define ON_ERR(m) MessageBox(NULL,m,_T("ERROR!"),MB_OK); return 0

void Cleanup()
{
        if (fontFace != NULL)
        {
                FT_Done_Face(fontFace);
                fontFace = NULL;
        }

        if (libFreeType != NULL)
        {
                FT_Done_FreeType(libFreeType);
                libFreeType = NULL;
        }
}

int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int 
nCmdShow)
{
        // init FreeType
        err = FT_Init_FreeType(&libFreeType);
        if (err != 0)
        {
                ON_ERR(_T("Unable to init FreeType"));
        }

        // load face
        err = FT_New_Face(libFreeType,FONT_FILE,0,&fontFace);
        if (err != 0)
        {
                Cleanup();
                ON_ERR(_T("Unable to load font"));
        }

        // verify font face is scalable
        if (!FT_IS_SCALABLE(fontFace))
        {
                Cleanup();
                ON_ERR(_T("Font is not scalable"));
        }

        // get screen device resolution
        HDC hDC = CreateDC(_T("DISPLAY"),NULL,NULL,NULL);
        screenResX = GetDeviceCaps(hDC,LOGPIXELSX);
        screenResY = GetDeviceCaps(hDC,LOGPIXELSY);
        DeleteDC(hDC);

        // size the font face
        err = 
FT_Set_Char_Size(fontFace,0,FONT_POINT_SIZE*64,screenResX,screenResY);
        if (err != 0)
        {
                Cleanup();
                ON_ERR(_T("Unable to size the font"));
        }

        // get glyph index
        glyphIndex = FT_Get_Char_Index(fontFace,CHAR_TO_RENDER);
        if (glyphIndex == 0)
        {
                Cleanup();
                ON_ERR(_T("Undefined char code"));
        }

        // load glyph
        err = FT_Load_Glyph(fontFace,glyphIndex,FT_LOAD_DEFAULT);
        if (err != 0)
        {
                Cleanup();
                ON_ERR(_T("Unable to load glyph"));
        }

        // render glyph
        err = FT_Render_Glyph(fontFace->glyph,FT_RENDER_MODE_NORMAL);
        if (err != 0)
        {
                Cleanup();
                ON_ERR(_T("Unable to render the glyph"));
        }

        // save rendered glyph to PNG image file
        if (!SaveRenderedGlyphToPNG(fontFace->glyph->bitmap,PNG_FILE))
        {
                Cleanup();
                ON_ERR(_T("Unable to save the rendered glyph to an image 
file"));
        }

        // save rendered glyph to text file
        if (!SaveRenderedGlyphToTXT(fontFace->glyph->bitmap,TEXT_FILE))
        {
                Cleanup();
                ON_ERR(_T("Unable to save the rendered glyph to a text file"));
        }

        // done
        Cleanup();
        MessageBox(NULL,_T("Finished successfully!"),_T("Success!"),MB_OK);
        return 0;
}
#pragma once

// Modify the following defines if you have to target a platform prior to the 
ones specified below.
// Refer to MSDN for the latest info on corresponding values for different 
platforms.
#ifndef WINVER                          // Allow use of features specific to 
Windows XP or later.
#define WINVER 0x0501           // Change this to the appropriate value to 
target other versions of Windows.
#endif

#ifndef _WIN32_WINNT            // Allow use of features specific to Windows XP 
or later.                   
#define _WIN32_WINNT 0x0501     // Change this to the appropriate value to 
target other versions of Windows.
#endif                                          

#ifndef _WIN32_WINDOWS          // Allow use of features specific to Windows 98 
or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target 
Windows Me or later.
#endif

#ifndef _WIN32_IE                       // Allow use of features specific to IE 
6.0 or later.
#define _WIN32_IE 0x0600        // Change this to the appropriate value to 
target other versions of IE.
#endif

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from 
Windows headers
// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

// FreeType
#include <ft2build.h>
#include FT_FREETYPE_H

// libpng
#include <png.h>
#include "main.h"
#include "SaveToPNG.h"

png_structp   png_ptr = NULL;
png_infop     info_ptr = NULL;
unsigned long user_error = 0;

extern int screenResX;
extern int screenResY;

#define METERS_TO_INCHES 39.370079

void user_error_fn(png_structp png_ptr, png_const_charp png_errstr)
{
}

void user_warning_fn(png_structp png_ptr, png_const_charp png_errstr)
{
}

bool SaveRenderedGlyphToPNG(FT_Bitmap& bmp, LPCTSTR file)
{
        if (bmp.rows > PNG_UINT_32_MAX/png_sizeof(png_bytep))
                return false;

        FILE* fp = _tfopen(file,_T("wb"));
        if (!fp)
                return false;

        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                (png_voidp)(&user_error), user_error_fn, user_warning_fn);
        if (png_ptr == NULL)
        {
                fclose(fp);
                return false;
        }

        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
                fclose(fp);
                png_destroy_write_struct(&png_ptr,  NULL);
                return false;
        }

        if (setjmp(png_jmpbuf(png_ptr)))
        {
                fclose(fp);
                png_destroy_write_struct(&png_ptr, &info_ptr);
                return false;
        }

        png_init_io(png_ptr, fp);

        
png_set_IHDR(png_ptr,info_ptr,bmp.width,bmp.rows,8,PNG_COLOR_TYPE_GRAY,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);

        png_color_8 sig_bit;
        sig_bit.gray = 8;
        png_set_sBIT(png_ptr,info_ptr,&sig_bit);

        png_set_pHYs(png_ptr,info_ptr,
                (png_uint_32)(((double)screenResX * METERS_TO_INCHES) + 0.5),
                (png_uint_32)(((double)screenResY * METERS_TO_INCHES) + 0.5),
                PNG_RESOLUTION_METER);

        png_write_info(png_ptr,info_ptr);

        png_bytep * row_pointers = new png_bytep[bmp.rows];
        unsigned char* bufferPos = bmp.buffer;
        for (int row = 0; row < bmp.rows; row++)
        {
                row_pointers[row] = bufferPos;
                bufferPos += bmp.pitch;
        }

        png_write_image(png_ptr, row_pointers);

        png_write_end(png_ptr,info_ptr);

        png_destroy_write_struct(&png_ptr,&info_ptr);

        delete [] row_pointers;

        fflush(fp);
        fclose(fp);

        return true;
}
#pragma once

bool SaveRenderedGlyphToPNG(FT_Bitmap& bmp, LPCTSTR file);
#include "main.h"
#include "SaveToTXT.h"

bool SaveRenderedGlyphToTXT(FT_Bitmap& bmp, LPCTSTR file)
{
        FILE* fp = _tfopen(file,_T("wt"));
        if (!fp)
                return false;

        
_ftprintf(fp,_T("rows=%d\nwidth=%d\npitch=%d\nnum_grays=%d\npixel_mode=%d\npalette_mode=%d\n\n"),
                
bmp.rows,bmp.width,bmp.pitch,bmp.num_grays,bmp.pixel_mode,bmp.palette_mode);

        unsigned char* bufferPos = bmp.buffer;
        for (int row = 0; row < bmp.rows; row++)
        {
                for (int col = 0; col < bmp.width; col++)
                {
                        if (col > 0)
                                _ftprintf(fp,_T(" "));
                        _ftprintf(fp,_T("%02X"),bufferPos[col]);
                }
                _ftprintf(fp,_T("\n"));

                bufferPos += bmp.pitch;
        }


        fflush(fp);
        fclose(fp);

        return true;
}
#pragma once

bool SaveRenderedGlyphToTXT(FT_Bitmap& bmp, LPCTSTR file);
_______________________________________________
Freetype mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/freetype

Reply via email to