-
Notifications
You must be signed in to change notification settings - Fork 2
/
TG_Text.c
234 lines (199 loc) · 5.23 KB
/
TG_Text.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <stdio.h>
#include <stdlib.h>
#include "TG.h"
#include "TG_Text.h"
#define N_ROWS 16
#define N_COLS 16
#define N_CHARS N_ROWS * N_COLS
//Font surface
static TG_Surface * bitmap;
TG_Font * TG_CreateFont(uint8_t * font, int16_t rows, int16_t cols)
{
TG_Font * t = (TG_Font*)malloc(sizeof(*t));
//Load font bitmap
t->surface = TG_LoadBmp(font);
//Check the font bitmap loaded ok
if(t->surface == NULL)
{
return NULL;
}
t->charWidth = t->surface->width / cols;
t->charHeight = t->surface->height / rows;
t->charXSpacing = 0;
t->charYSpacing = 0;
int currentChar = 0;
//Loop through each character in the bitmap
for(int row=0; row<rows; row++)
{
for(int col=0; col<cols; col++)
{
//Set the location of the character
t->chars[currentChar].x = t->charWidth * col;
t->chars[currentChar].y = t->charHeight * row;
currentChar++;
}
}
while(currentChar < 256)
{
t->chars[currentChar].x = 0;
t->chars[currentChar].y = 0;
currentChar++;
}
return t;
}
//Calculates the pixel width of a given string
uint16_t TG_TextWidth(TG_Font * font, uint8_t * text)
{
int width = 0, maxWidth = 0;
for(;;){
//Return when end of string is reached
if(*text == '\0')
return (maxWidth > width) ? maxWidth : width;
//New line
else if(*text == '\n')
{
if(width > maxWidth)
maxWidth = width;
width = 0;
}
width += font->charWidth;
//Increment character pointer
text++;
}
}
/*
* Draws the given amount of characters to a surface
*
* Returns 1 if end of string occurs before the given amount of
* characters have been drawn, otherwise returns 0.
*/
uint8_t TG_DrawText(TG_Surface * surface, TG_Font * font, int16_t x, int16_t y, uint8_t * text, int16_t amount, int16_t wrap, uint32_t color)
{
//Position on screen
TG_Point pos = { x, y };
//Pointer to last character to be drawn
uint8_t * stopAt = text + amount - 1;
for(;;)
{
//If wrapping is enabled and if the position is past the wrapping width
if(wrap && pos.x + font->charWidth > wrap)
{
//Wrap the text
pos.x = x;
pos.y += font->charHeight + font->charYSpacing;
}
//End of string
if(*text == '\0')
return 1;
//If limited number of characters and limit reached
else if(amount && text > stopAt)
return 0;
//New line
else if(*text == '\n')
{
pos.x = x;
pos.y += font->charHeight + font->charYSpacing;
}
//Tab
else if(*text == '\t')
{
pos.x += (font->charXSpacing * 4);
}
//Ignore CR
else if(*text == '\r');
//Space character, so leave a gap
else if(*text == ' ')
pos.x += font->charWidth;
//Normal character
else
{
TG_DrawChar(surface, font, pos.x, pos.y, *text, color);
pos.x += font->charWidth;
}
//Increment string pointer
text++;
}
}
/*int drawTextCursor(SDL_Surface * surface, vector2 *cursor, char * text, int amount, int wrap)
{
X start position
int startX = cursor->x;
Pointer to last character to be drawn
char * stopAt = text + amount - 1;
for(;;)
{
If wrapping is enabled and if the position is past the wrapping width
if(wrap && cursor->x + CHAR_WIDTH > wrap)
{
Wrap the text
cursor->x = startX;
cursor->y += CHAR_HEIGHT + CHAR_SPACING;
}
End of string
if(*text == '\0')
return 1;
If limited number of characters and limit reached
else if(amount && text > stopAt)
return 0;
New line
else if(*text == '\n')
{
cursor->x = startX;
cursor->y += CHAR_HEIGHT + CHAR_SPACING;
}
Tab
else if(*text == '\t')
{
cursor->x += (CHAR_SPACING * 4);
}
Ignore CR
else if(*text == '\r');
Space character, so leave a gap
else if(*text == ' ')
cursor->x += CHAR_WIDTH;
Normal character
else
{
Position of character in bitmap
SDL_Rect charRect = { chars[(unsigned char) *text].x,
chars[(unsigned char) *text].y , CHAR_WIDTH, CHAR_HEIGHT};
Area on screen to draw
SDL_Rect posRect = { cursor->x, cursor->y, CHAR_WIDTH, CHAR_HEIGHT};
SDL_BlitSurface(bitmap, &charRect, surface, &posRect);
cursor->x += CHAR_WIDTH;
}
Increment string pointer
text++;
}
}*/
void TG_DrawChar(TG_Surface * surface, TG_Font * font, int16_t x, int16_t y, uint8_t c, uint32_t color)
{
//Position of character in bitmap
uint16_t cX = font->chars[c].x;
uint16_t cY = font->chars[c].y;
//Set the starting position of the destination pointer
uint32_t * destPixel = surface->pixels + (y * surface->width);
//set the starting position of the src pointer
uint32_t * srcPixel = font->surface->pixels + (cY * font->surface->width);
uint16_t total = font->charWidth * font->charHeight;
uint16_t srcX = cX;
uint16_t destX = x;
for(uint16_t i = 0; i < total; i++)
{
//copy the source pixel to the destination pixel
if(*(srcPixel + srcX) != 0xFFFF00FF)
//*(destPixel + destX) = *(srcPixel + srcX);
*(destPixel + destX) = color;
//increment the pixel x positions
srcX++;
destX++;
//move to the next row of pixels
if(srcX == cX + font->charWidth)
{
srcPixel += font->surface->width;
destPixel += surface->width;
srcX = cX;
destX = x;
}
}
}