Pregunta

I've recently just started using the FreeType library and have started to attempt copying from the buffer into directx9 textures.

I'm currently getting however double letters appearing despite having copied from a buffer created through loading a single character as so :

enter image description here

[copy attempt of the character 'a']

The following is my current code:

void TexFont::freeTypeSave()
{
    static FT_Library  library;   /* handle to library     */
    static FT_Face     face;      /* handle to face object */

    if (FT_Init_FreeType(&library)) {
        NHelper::OutputDebugStringN("error");
    }

    if (FT_New_Face(library,TEXT("Fonts\\arial.ttf"),0,&face)) {
        NHelper::OutputDebugStringN("font load failed\n");
    }
    else {
        //NHelper::OutputDebugStringN("font faces: %d \n", face->num_faces);
    }

    static int error;
    static UINT width, height;
    static int mTtfSize = 64;
    static int mTtfResolution = 96;

    static IDirect3DTexture9* mTexture;
    static unsigned int mPixelBytes = 2;
    static unsigned int mDataSize = width * height * mPixelBytes;

    // size settings (convert font size to *64)
    FT_F26Dot6 ftSize = (FT_F26Dot6)(mTtfSize * (1 << 6));
    error=FT_Set_Char_Size(face, ftSize, 0, mTtfResolution, mTtfResolution);

    // load glyph + render
    error = FT_Load_Char( face, L'a', FT_LOAD_RENDER );
    if (error) 
        NHelper::OutputDebugStringN("could not load char");

    // start copy procedure
    width = face->glyph->bitmap.width;
    height = face->glyph->bitmap.rows;

    D3DXCreateTexture(
        g_engine->getDevice(),
        width, height,
        1, 0,
        D3DFMT_A8L8, D3DPOOL_MANAGED,
        &mTexture);

    D3DLOCKED_RECT lockedRect;
    mTexture->LockRect(0, &lockedRect,0, 0);   

    unsigned char* pSrcPixels = face->glyph->bitmap.buffer;
    unsigned char* pDestPixels = (unsigned char*)lockedRect.pBits;

    for(UINT i = 0; i < height; ++i)
    {
        //copy a row
        memcpy(pDestPixels, pSrcPixels, width * 2); //2 bytes per pixel (1byte alpha, 1byte greyscale)

        //advance row pointers
        pSrcPixels += face->glyph->bitmap.pitch;
        pDestPixels += lockedRect.Pitch;
    }
    NHelper::OutputDebugStringN("char width: %d, height: %d \n", width, height);

    mTexture->UnlockRect(0);

    D3DXSaveTextureToFileA("test.png",D3DXIFF_PNG, mTexture, 0);

    // release face
    FT_Done_Face(face);

    // library shutdown
    FT_Done_FreeType(library);
}

Any ideas on what's happening and how I could go around fixing this?

Note: changing the font size merely creates a larger image. I still get the same result.

--update--

Trying Drop's suggestion, I tried changing my memcpy(pDestPixels, pSrcPixels, width * 2);

to memcpy(pDestPixels, pSrcPixels, width * 1); It returns the following:

enter image description here

One glyph packed toward the left of the image, yet the image remaining the same size. (the glyph only takes up half of the image space)

¿Fue útil?

Solución

You loading chars as

FT_Load_Char( face, L'a', FT_LOAD_RENDER );

this means that

By default, the glyph is rendered in FT_RENDER_MODE_NORMAL mode

and

FT_RENDER_MODE_NORMAL This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps.

But you copying as 16-bit:

memcpy(pDestPixels, pSrcPixels, width * 2); //2 bytes per pixel (1byte alpha, 1byte greyscale)

You really don't need grayscale component in any character for proper rendering (you just need to know must you apply color to that pixel and how much). So, make all of your characters as 8-bit masks on loading. Then convert to 32-bit image just before rendering: apply your color in RGB components and set mask as A component. I do it in shader.

Hope it helps. Happy coding!

update 1

Due to now you are copying 8-bit source, memcpying 8-bits per pixel, obviously you also need to resize your target (mTexture) to be same bits per pixel: D3DFMT_A8 (8 bit) instead of D3DFMT_A8L8 ( 8 + 8 = 16 bits).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top