How to render text in directx9 with stb_truetype?
Asked Answered
M

1

10

How to render a text with the stb_truetype library using D3D9 in C/C++? I looked in various forums/sites and in the library's documentation for some example in d3d9 and I didn't find any example.

Marlenmarlena answered 11/7, 2018 at 2:55 Comment(1)
The general answer to all questions of the form "How do I do X with Direct3D 9?" is: Don't use Direct3D 9, use Direct3D 11 instead. It's legacy and there's basically no reason to use it at all. See MSDN and this blog postHeurlin
A
5

One way to do this would be to create a D3D9 texture and then load the rendered text bitmap into it. You can then use the generated texture like any other texture.

#define STB_TRUETYPE_IMPLEMENTATION 
#include "stb_truetype.h"
IDirect3DTexture9 *LoadTextureFromText(const char *text)
{
    IDirect3DTexture9 *d3dTexture = 0;

    /* load font file */
    long size;
    unsigned char* fontBuffer;

    FILE* fontFile = fopen("C:\\path\\to\\font.ttf", "rb");
    fseek(fontFile, 0, SEEK_END);
    size = ftell(fontFile); /* how long is the file ? */
    fseek(fontFile, 0, SEEK_SET); /* reset */

    fontBuffer = (unsigned char*)malloc(size);

    fread(fontBuffer, size, 1, fontFile);
    fclose(fontFile);

    /* prepare font */
    stbtt_fontinfo info;
    if (!stbtt_InitFont(&info, fontBuffer, 0))
    {
        printf("failed\n");
    }

    int b_w = 512; /* bitmap width */
    int b_h = 128; /* bitmap height */
    int l_h = 64; /* line height */

    /* create a bitmap for the phrase */
    unsigned char* bitmap = (unsigned char*)calloc(b_w * b_h, sizeof(unsigned char));

    /* calculate font scaling */
    float scale = stbtt_ScaleForPixelHeight(&info, l_h);

    int x = 0;

    int ascent, descent, lineGap;
    stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);

    ascent *= scale;
    descent *= scale;

    int i;
    for (i = 0; i < strlen(text); ++i)
    {
        /* get bounding box for character (may be offset to account for chars that dip above or below the line */
        int c_x1, c_y1, c_x2, c_y2;
        stbtt_GetCodepointBitmapBox(&info, text[i], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);

        /* compute y (different characters have different heights */
        int y = ascent + c_y1;

        /* render character (stride and offset is important here) */
        int byteOffset = x + (y  * b_w);
        stbtt_MakeCodepointBitmap(&info, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, b_w, scale, scale, text[i]);

        /* how wide is this character */
        int ax;
        stbtt_GetCodepointHMetrics(&info, text[i], &ax, 0);
        x += ax * scale;

        /* add kerning */
        int kern;
        kern = stbtt_GetCodepointKernAdvance(&info, text[i], text[i + 1]);
        x += kern * scale;
    }

    //Create a D3D9 texture and load the generated image. The text bitmap is 1 channel.
    D3DXCreateTexture(direct3DDevice, b_w, b_h, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, (LPDIRECT3DTEXTURE9*)&d3dTexture);
    D3DLOCKED_RECT rect;
    d3dTexture->LockRect(0, &rect, NULL, 0);
    memcpy(rect.pBits, bitmap, b_w * b_h);
    d3dTexture->UnlockRect(0);

    free(fontBuffer);
    free(bitmap);

    return d3dTexture;
}
Abercrombie answered 14/7, 2018 at 15:36 Comment(3)
Your example helped me a lot, but I'm having a problem, I'm using ID3DXSprite to draw the texture, the text is drawing, but with a black box, why is this happening? Am I doing it wrong? Code(sorry for posting link, the code is too big to post in the comments): paste.ofcode.org/bZ7dwEwqHGdj8KG2xLMSGKMarlenmarlena
You didn't provide full code, I don't know who calls print_text or how the sprite was created. I'm no directx expert but I can take a look if you provide all the code.Abercrombie
D3DX9, D3DX10, and D3DX11 are all deprecated. You should move to using DirectX 11 instead, in which case you can use the SpriteFont class in the DirectX Tool Kit which is open source. See Living without D3DX. Note that if very high-quality and scalable text is important to you, then you should consider using Direct3D 11 with DirectWrite.Heurlin

© 2022 - 2024 — McMap. All rights reserved.