#include #include #include "SDL_ttf_atlas.h" #include SDL_bool useDark, forceDark = 1; int renderStyle = 0; SDL_Texture*fontTexture; SDL_Renderer*renderer; std::unordered_map table; //It's more readable to use TTF_AtlasEntry* than mapping to an index int spaceXAdv16, baseline16, lineHeight16; int spaceXAdv20, baseline20, lineHeight20; static void DrawWindow(int textureWidth, int textureHeight); static void DrawString(const char*text, int x, int y, int spaceXAdv, int baseline, int lineHeight, Uint64 xorID); static Uint64 AtlasPred(void*user, int glyph) { return glyph ^ (Uint64)user; } int main(int argc, char *argv[]) { char buffer[4096]; const char*filename=0; for(int i=1; iascent + 2; auto q = table['q' | tag16]; lineHeight16 = baseline16 - (q->ascent - q->height); baseline20 = table['E' | tag20]->ascent + 2; auto q20 = table['q' | tag20]; lineHeight20 = baseline20 - (q20->ascent - q20->height); } DrawWindow(atlas.width, atlas.height); SDL_bool wantQuit = 0; SDL_Event event; while (!wantQuit) { if (!SDL_WaitEvent(&event)) { wantQuit = 1; break; } switch (event.type) { case SDL_EVENT_QUIT: { wantQuit = 1; } break; case SDL_EVENT_KEY_DOWN: { if (event.key.keysym.sym == SDLK_ESCAPE) { wantQuit = 1; break; } } break; } DrawWindow(atlas.width, atlas.height); } SDL_DestroyTexture(fontTexture); TTF_DestroyAtlas(&atlas); return 0; } static void DrawWindow(int textureWidth, int textureHeight) { //Choose background and text color of canvas, canvas BG is later if (useDark) { SDL_SetRenderDrawColor(renderer, 0x10, 0x10, 0x10, 255); SDL_SetTextureColorMod(fontTexture, 0xE0, 0xE0, 0xE0); } else { SDL_SetRenderDrawColor(renderer, 0xF0, 0xF0, 0xF0, 255); SDL_SetTextureColorMod(fontTexture, 0x10, 0x10, 0x10); } SDL_RenderClear(renderer); //Choose canvas background and draw our texture on top SDL_FRect r = {0, 0, textureWidth, textureHeight}; if (useDark) SDL_SetRenderDrawColor(renderer, 0, 0, 0x40, 255); else { SDL_SetRenderDrawColor(renderer, 0xC0, 0xC0, 0xFF, 255); } SDL_RenderFillRect(renderer, &r); SDL_RenderTexture(renderer, fontTexture, &r, &r); // To test missing characters we replace ~ and ` in our draw function const char *testString = "Test string pq ~ `\nYou may choose the line\nheight however you like\n\nThe quick brown fox\njumped over the lazy dog"; DrawString(testString, 1024+4, 20, spaceXAdv16, baseline16, lineHeight16, 16ULL<<32); SDL_SetTextureColorMod(fontTexture, 0x40, 0x80, 0x40); DrawString(testString, 1024+4, 240, spaceXAdv20, baseline20, lineHeight20, 20ULL<<32); //Y is intentionally missing to show we didn't load everything SDL_RenderPresent(renderer); } static void DrawString(const char*text, int x, int y, int spaceXAdv, int baseline, int lineHeight, Uint64 xorID) { if (!text) return; const char*p = text; int startX = x; while (*p) { Sint32 glyph = *p++; if (glyph == '~') { glyph = 0x2603; } //2603 is snowman ☃ which is likely missing in the choosen font if (glyph == '`') { glyph = 0xEC08; } //Private font if (glyph == ' ') { x += spaceXAdv; continue; } else if (glyph == '\n') { x = startX; y += lineHeight; continue; } TTF_AtlasEntry*e = table[ (table.contains(glyph ^ xorID) ? glyph : 0xFFFD) ^ xorID ]; SDL_assert(e); SDL_FRect srcRect = {e->canvasX, e->canvasY, e->width, e->height}; SDL_FRect dstRect = {x + e->left, y + baseline - e->ascent, e->width, e->height}; x += e->xAdv; SDL_RenderTexture(renderer, fontTexture, &srcRect, &dstRect); } }