Skip to content

Commit

Permalink
imported crunchy code from my old project
Browse files Browse the repository at this point in the history
  • Loading branch information
brht0 committed Oct 31, 2021
1 parent da20f4b commit 8cb673d
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
out
*.o
*.d
*.ttf

180 changes: 180 additions & 0 deletions FontCache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#include "FontCache.h"

CFontNode* CFontMap::operator[](int index){
if(index < 0 || index >= map_length)
return nullptr;

CFontNode* node = start;

while(index > 0){
node = node->next;
index --;
}

return node;
}

CFontGlyph CFont::CreateGlyph(char c, CFontGlyphInfo* info){
CFontGlyph glyph;

SDL_Surface* surface = TTF_RenderGlyph_Blended(font, c, color);
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

int w = surface->w;
int h = surface->h;

SDL_FreeSurface(surface);

glyph.texture = texture;

SDL_Rect rect = {0, 0, w, h};

info->rect = rect;

return glyph;
}

CFontGlyph* CFont::GetGlyph(char c, CFontGlyphInfo* info){
CFontNode* node = nodeMap[c - 0x20];

*info = node->glyphInfo;

return &node->glyph;
}

SDL_Rect CFont::GetTextSize(std::string text){
SDL_Rect rect = {0, 0, 0, 0};

for(char c : text){
CFontGlyphInfo info;
GetGlyph(c, &info);

rect.w += info.rect.w;
if(info.rect.h > rect.h)
rect.h = info.rect.h;
}
return rect;
}

CFont::CFont(SDL_Renderer* _renderer, const char* _fontfile, int _fontsize, SDL_Color _color)
: fontfile(_fontfile),
fontsize(_fontsize),
color(_color),
renderer(_renderer)
{
font = TTF_OpenFont(fontfile, fontsize);

nodeMap.map_length = 0;
nodeMap.start = nullptr;

CFontNode* fontnode = new CFontNode;
CFontGlyphInfo info;
fontnode->glyph = CreateGlyph(0x20, &info);
fontnode->glyphInfo = info;

nodeMap.start = fontnode;
nodeMap.map_length ++;

for(int c = 0x21; c <= 0x7E; c++){
CFontNode* new_fontnode = new CFontNode;
new_fontnode->glyph = CreateGlyph(c, &info);
new_fontnode->glyphInfo = info;

fontnode->next = new_fontnode;
new_fontnode->next = nullptr;

fontnode = new_fontnode;

nodeMap.map_length ++;
}
}

CFont::~CFont(){
CFontNode* node = nodeMap.start;
do{
if(node){
if(node->glyph.texture)
node->glyph.texture;
}
node = node->next;
} while(node);

TTF_CloseFont(font);
}

void CFont::DrawText(int x, int y, const char* text){
int w = 0;

SDL_Rect dst = {x, y, 0, 0};

for(int c = 0; c < strlen(text); c++){
CFontGlyphInfo info;
CFontGlyph* glyph = GetGlyph(text[c], &info);

dst.w = info.rect.w;
dst.h = info.rect.h;

SDL_RenderCopy(renderer, glyph->texture, &info.rect, &dst);

dst.x += dst.w;
}
}

void CFont::DrawTextCentered(int center_x, int center_y, const char* text){
SDL_Rect text_size = GetTextSize(text);

DrawText( center_x - text_size.w / 2, center_y - text_size.h / 2, text);
}

void CFont::DrawWrappedText(int x, int y, int w, std::string text){
std::string line_buffer = "";

bool first_in_line = true;

while(text.length() > 0){
std::string word;
int space_index = text.find_first_of(' ');

if(space_index == -1)
word = text;
else
word = text.substr(0, space_index);

if(!first_in_line)
line_buffer += ' ';

line_buffer += word;

SDL_Rect line_size = GetTextSize(line_buffer);

if(line_size.w > w){
if(first_in_line){
text = text.substr(line_buffer.length() + 1);
}
else{
line_buffer = line_buffer.substr(0, line_buffer.length() - word.length());
}

DrawText(x, y, line_buffer.c_str());

y += line_size.h;

first_in_line = true;

line_buffer.clear();
}
else{
if(text.length() <= word.length())
text = "";
else
text = text.substr(word.length() + 1);

first_in_line = false;
}

}

if(!line_buffer.empty()){
DrawText(x, y, line_buffer.c_str());
}
}
58 changes: 58 additions & 0 deletions FontCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef __FONTCACHE_H__
#define __FONTCACHE_H__

#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"

#include <iostream>
#include <cstring>
#include <sstream>

struct CFontGlyph{
SDL_Texture* texture;
};

struct CFontGlyphInfo{
SDL_Rect rect;
};

struct CFontNode{
CFontGlyph glyph;
CFontGlyphInfo glyphInfo;
CFontNode* next = nullptr;
};

struct CFontMap{
int map_length;
CFontNode* start = nullptr;

CFontNode* operator[](int index);
};

class CFont{
private:
const char* fontfile;
int fontsize;
SDL_Color color;

SDL_Renderer* renderer;
TTF_Font* font;

CFontMap nodeMap;

CFontGlyph CreateGlyph(char c, CFontGlyphInfo* info);

CFontGlyph* GetGlyph(char c, CFontGlyphInfo* info);

SDL_Rect GetTextSize(std::string text);

public:
CFont(SDL_Renderer* _renderer, const char* _fontfile, int _fontsize, SDL_Color _color);
~CFont();

void DrawText(int x, int y, const char* text);
void DrawTextCentered(int center_x, int center_y, const char* text);
void DrawWrappedText(int x, int y, int w, std::string text);
};

#endif // __FONTCACHE_H__
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
main:
g++ -o out *.cpp -lSDL2 -lSDL2_ttf
57 changes: 57 additions & 0 deletions demo_fontcache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"

#include <iostream>
#include <cstring>
#include <sstream>

#include "FontCache.h"

const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;

int main(int, char*[]){

SDL_Init(SDL_INIT_VIDEO);
TTF_Init();

SDL_Window* window = SDL_CreateWindow("FontCache Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);

SDL_Color white = {255, 255, 255, 255};

{
CFont font(renderer, "verdana.ttf", 65, white);

bool quit = false;
while(!quit){
SDL_Event e;
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT){
quit = true;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
SDL_RenderClear(renderer);

std::stringstream ss;
ss << (int)SDL_GetTicks();

std::string text = u8"number: " + ss.str();

font.DrawText(30, 10, text.c_str());

std::string text2 = "This is some text that I just wrote, test test test test test test test test test";
font.DrawWrappedText(0, 70, 800, text2);

SDL_RenderPresent(renderer);
}
}

SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

TTF_Quit();
SDL_Quit();
return 0;
}

0 comments on commit 8cb673d

Please sign in to comment.