... | ... |
@@ -20,6 +20,8 @@ |
20 | 20 |
#define DEFAULTTITLEPREFIX "re - " |
21 | 21 |
#define DEFAULTWINDOWWIDTH 80 |
22 | 22 |
#define DEFAULTWINDOWHEIGHT 66 |
23 |
+#define FONTCACHEXSIZE 512 |
|
24 |
+#define FONTCACHEYSIZE 512 |
|
23 | 25 |
|
24 | 26 |
#define RECTFILL(r,rx,ry,rw,rh) (r).x=(rx),(r).y=(ry),(r).w=(rw),(r).h=(rh) |
25 | 27 |
|
... | ... |
@@ -46,7 +48,7 @@ |
46 | 48 |
|
47 | 49 |
static int reui_fillrounded(SDL_Surface *dst, int xo, int yo, int w, int h, int r, const char *rgba); |
48 | 50 |
static int reui_triangle(SDL_Surface *dst, int x, int y, int w, int h, char direction, const char *rgba); |
49 |
- |
|
51 |
+static int reui_fontcachereset(reui_t *ui); |
|
50 | 52 |
|
51 | 53 |
reui_t * |
52 | 54 |
reui_init(int fontheight) |
... | ... |
@@ -79,7 +81,7 @@ reui_init(int fontheight) |
79 | 81 |
ui->screenw=screenrect.w; |
80 | 82 |
ui->screenh=screenrect.h; |
81 | 83 |
/* font */ |
82 |
- ui->fontheight=fontheight; |
|
84 |
+ ui->fontheight=fontheight; /* placeholder, will fill later with real value */ |
|
83 | 85 |
ui->fontdata=SDL_RWFromConstMem(hack_regular,SIZE_HACK_REGULAR); |
84 | 86 |
SDL_RWseek(ui->fontdata,0,RW_SEEK_SET); |
85 | 87 |
if(ui->fontdata==NULL |
... | ... |
@@ -99,6 +101,17 @@ reui_init(int fontheight) |
99 | 101 |
ui->fontwidth=s->w; |
100 | 102 |
SDL_FreeSurface(s),s=NULL; |
101 | 103 |
} |
104 |
+ /* font height */ |
|
105 |
+ { |
|
106 |
+ SDL_Surface *s; |
|
107 |
+ SDL_Color c={0,0,0,0}; |
|
108 |
+ if((s=TTF_RenderUTF8_Blended(ui->font,"gjpqy_",c))==NULL) { |
|
109 |
+ reui_free(ui),ui=NULL; |
|
110 |
+ return(NULL); |
|
111 |
+ } |
|
112 |
+ ui->fontheight=s->h; |
|
113 |
+ SDL_FreeSurface(s),s=NULL; |
|
114 |
+ } |
|
102 | 115 |
/* main window */ |
103 | 116 |
ui->w=ui->fontwidth*DEFAULTWINDOWWIDTH; |
104 | 117 |
ui->w=(ui->w>ui->screenw)?ui->screenw:ui->w; |
... | ... |
@@ -113,10 +126,15 @@ reui_init(int fontheight) |
113 | 126 |
|| (ui->scr=SDL_CreateTexture(ui->renderer,SDL_PIXELFORMAT_ARGB8888, |
114 | 127 |
SDL_TEXTUREACCESS_STREAMING,ui->w,ui->h))==NULL |
115 | 128 |
|| (ui->onepx=SDL_CreateTexture(ui->renderer,SDL_PIXELFORMAT_ARGB8888, |
116 |
- SDL_TEXTUREACCESS_STATIC,1,1))==NULL) { |
|
129 |
+ SDL_TEXTUREACCESS_STATIC,1,1))==NULL |
|
130 |
+ || (ui->fontcache=SDL_CreateTexture(ui->renderer,SDL_PIXELFORMAT_ARGB8888, |
|
131 |
+ SDL_TEXTUREACCESS_STATIC,FONTCACHEXSIZE,FONTCACHEYSIZE))==NULL) { |
|
117 | 132 |
reui_free(ui),ui=NULL; |
118 | 133 |
return(NULL); |
119 | 134 |
} |
135 |
+ /* font cache */ |
|
136 |
+ SDL_SetTextureBlendMode(ui->fontcache, SDL_BLENDMODE_BLEND); |
|
137 |
+ reui_fontcachereset(ui); |
|
120 | 138 |
/* finished */ |
121 | 139 |
ui->scrdirty=1; |
122 | 140 |
ui->rendererdirty=1; |
... | ... |
@@ -129,6 +147,8 @@ reui_free(reui_t *ui) |
129 | 147 |
{ |
130 | 148 |
if(ui==NULL) |
131 | 149 |
return; |
150 |
+ if(ui->fontcache!=NULL) |
|
151 |
+ SDL_DestroyTexture(ui->fontcache),ui->fontcache=NULL; |
|
132 | 152 |
if(ui->onepx!=NULL) |
133 | 153 |
SDL_DestroyTexture(ui->onepx),ui->onepx=NULL; |
134 | 154 |
if(ui->font!=NULL) |
... | ... |
@@ -143,7 +163,6 @@ reui_free(reui_t *ui) |
143 | 163 |
SDL_DestroyRenderer(ui->renderer),ui->renderer=NULL; |
144 | 164 |
if(ui->win!=NULL) |
145 | 165 |
SDL_DestroyWindow(ui->win),ui->win=NULL; |
146 |
- |
|
147 | 166 |
SDL_Quit(); |
148 | 167 |
free(ui),ui=NULL; |
149 | 168 |
} |
... | ... |
@@ -183,23 +202,29 @@ int |
183 | 202 |
reui_setfontheight(reui_t *ui, int fontheight) |
184 | 203 |
{ |
185 | 204 |
TTF_Font *newfont; |
186 |
- SDL_Surface *s; |
|
205 |
+ SDL_Surface *s,*s2; |
|
187 | 206 |
SDL_Color c={0,0,0,0}; |
188 | 207 |
if(ui==NULL || fontheight<=0) |
189 | 208 |
return(-1); /* sanity check failed */ |
190 | 209 |
SDL_RWseek(ui->fontdata,0,RW_SEEK_SET); |
191 | 210 |
if((newfont=TTF_OpenFontRW(ui->fontdata,0,fontheight))==NULL) |
192 | 211 |
return(-1); /* couln't setup new font */ |
193 |
- if((s=TTF_RenderUTF8_Blended(newfont,"m",c))==NULL) { |
|
212 |
+ if((s=TTF_RenderUTF8_Blended(newfont,"m",c))==NULL |
|
213 |
+ || (s2=TTF_RenderUTF8_Blended(newfont,"gjpqy_",c))==NULL) { |
|
214 |
+ if(s!=NULL) |
|
215 |
+ SDL_FreeSurface(s),s=NULL; |
|
194 | 216 |
TTF_CloseFont(newfont),newfont=NULL; |
195 | 217 |
return(-1); /* couldn't use new font */ |
196 | 218 |
} |
197 | 219 |
if(ui->font!=NULL) |
198 | 220 |
TTF_CloseFont(ui->font),ui->font=NULL; |
199 | 221 |
ui->font=newfont; |
200 |
- ui->fontheight=fontheight; |
|
222 |
+ ui->fontheight=s2->h; |
|
201 | 223 |
ui->fontwidth=s->w; |
202 | 224 |
SDL_FreeSurface(s),s=NULL; |
225 |
+ SDL_FreeSurface(s2),s2=NULL; |
|
226 |
+ /* font cache */ |
|
227 |
+ reui_fontcachereset(ui); |
|
203 | 228 |
return(0); |
204 | 229 |
} |
205 | 230 |
|
... | ... |
@@ -247,6 +272,7 @@ reui_present(reui_t *ui) |
247 | 272 |
int |
248 | 273 |
reui_write(reui_t *ui, int x, int y, const char *rgba, const char *str, int nchar) |
249 | 274 |
{ |
275 |
+#if 0 |
|
250 | 276 |
char buf[1024]; |
251 | 277 |
SDL_Surface *fgsurface; |
252 | 278 |
SDL_Texture *fg; |
... | ... |
@@ -274,6 +300,84 @@ reui_write(reui_t *ui, int x, int y, const char *rgba, const char *str, int ncha |
274 | 300 |
SDL_FreeSurface(fgsurface),fgsurface=NULL; |
275 | 301 |
SDL_DestroyTexture(fg),fg=NULL; |
276 | 302 |
return(0); |
303 |
+#else |
|
304 |
+ int curcol; |
|
305 |
+ char smallbuf[2]; |
|
306 |
+ int maxcached; |
|
307 |
+ int cachelines,cachecols; |
|
308 |
+ Uint32 *pixels; |
|
309 |
+ char buf[1024]; |
|
310 |
+ SDL_Surface *fgsurface; |
|
311 |
+ SDL_Texture *fg; |
|
312 |
+ SDL_Color c={((unsigned char *)rgba)[0], |
|
313 |
+ ((unsigned char *)rgba)[1], |
|
314 |
+ ((unsigned char *)rgba)[2], |
|
315 |
+ ((unsigned char *)rgba)[3]}; |
|
316 |
+ SDL_Color whitec={255,255,255,255}; |
|
317 |
+ SDL_Rect srcrect,dstrect; |
|
318 |
+ int i,n; |
|
319 |
+ int has_uncached; |
|
320 |
+ if(nchar<sizeof(buf)) { |
|
321 |
+ memcpy(buf,str,nchar); |
|
322 |
+ buf[nchar]='\0'; |
|
323 |
+ } else { |
|
324 |
+ memcpy(buf,str,sizeof(buf)-1); |
|
325 |
+ buf[sizeof(buf)-1]='\0'; |
|
326 |
+ } |
|
327 |
+ SDL_SetTextureColorMod(ui->fontcache, c.r, c.g, c.b); |
|
328 |
+ cachelines=(ui->fontheight>0)?(FONTCACHEYSIZE/ui->fontheight):0; |
|
329 |
+ cachecols=(ui->fontwidth>0)?(FONTCACHEXSIZE/ui->fontwidth):0; |
|
330 |
+ maxcached=cachelines*cachecols; |
|
331 |
+ /* write cached characters (or fill cache) */ |
|
332 |
+ has_uncached=0; |
|
333 |
+ for(i=0,curcol=-1;buf[i]!='\0';i++) { |
|
334 |
+ curcol+=(((buf[i]&0xc0)!=0x80)?1:0); /* this detects an utf-8 start byte, and advances one pos if true */ |
|
335 |
+ if(!(buf[i]>=FONTCACHESTART && buf[i]<=FONTCACHEEND) || maxcached==0) { |
|
336 |
+ has_uncached=1; |
|
337 |
+ continue; |
|
338 |
+ } |
|
339 |
+ /* fill cache if possible */ |
|
340 |
+ if(ui->usedfontcache<maxcached && ui->fontcachewhere[buf[i]-FONTCACHESTART]==0) { |
|
341 |
+ smallbuf[0]=buf[i],smallbuf[1]='\0'; |
|
342 |
+ if((fgsurface=TTF_RenderUTF8_Blended(ui->font,smallbuf,whitec))==NULL) |
|
343 |
+ return(-1); /* cannot create text */ |
|
344 |
+ SDL_LockSurface(fgsurface); |
|
345 |
+ pixels=(Uint32*)(fgsurface->pixels); |
|
346 |
+ RECTFILL(dstrect,(ui->usedfontcache%cachecols)*ui->fontwidth,(ui->usedfontcache/cachecols)*ui->fontheight,ui->fontwidth,ui->fontheight); |
|
347 |
+ SDL_UpdateTexture(ui->fontcache,&dstrect,pixels,sizeof(Uint32)*fgsurface->w); |
|
348 |
+ SDL_UnlockSurface(fgsurface); |
|
349 |
+ if(fgsurface!=NULL) |
|
350 |
+ SDL_FreeSurface(fgsurface),fgsurface=NULL; |
|
351 |
+ ui->usedfontcache++; |
|
352 |
+ ui->fontcachewhere[buf[i]-FONTCACHESTART]=ui->usedfontcache; /* one more than real pos, as 0 is not init */ |
|
353 |
+ } |
|
354 |
+ /* if cached, write from there and change the letter to space */ |
|
355 |
+ if(ui->fontcachewhere[buf[i]-FONTCACHESTART]!=0) { |
|
356 |
+ n=ui->fontcachewhere[buf[i]-FONTCACHESTART]-1; |
|
357 |
+ RECTFILL(srcrect,((n%cachecols)*ui->fontwidth),((n/cachecols)*ui->fontheight),ui->fontwidth,ui->fontheight); |
|
358 |
+ RECTFILL(dstrect,(x+ui->fontwidth*curcol),y,ui->fontwidth,ui->fontheight); |
|
359 |
+ SDL_RenderCopy(ui->renderer,ui->fontcache,&srcrect,&dstrect); |
|
360 |
+ buf[i]=' '; |
|
361 |
+ } else { |
|
362 |
+ has_uncached=1; |
|
363 |
+ } |
|
364 |
+ } |
|
365 |
+ /* write uncached characters */ |
|
366 |
+ if(has_uncached) { |
|
367 |
+ if((fgsurface=TTF_RenderUTF8_Blended(ui->font,buf,c))==NULL |
|
368 |
+ || (fg=SDL_CreateTextureFromSurface(ui->renderer,fgsurface))==NULL) { |
|
369 |
+ if(fgsurface!=NULL) |
|
370 |
+ SDL_FreeSurface(fgsurface),fgsurface=NULL; |
|
371 |
+ return(-1); |
|
372 |
+ } |
|
373 |
+ RECTFILL(dstrect,x,y,fgsurface->w,fgsurface->h); |
|
374 |
+ SDL_RenderCopy(ui->renderer,fg,NULL,&dstrect); |
|
375 |
+ SDL_FreeSurface(fgsurface),fgsurface=NULL; |
|
376 |
+ SDL_DestroyTexture(fg),fg=NULL; |
|
377 |
+ } |
|
378 |
+ ui->rendererdirty=1; |
|
379 |
+ return(0); |
|
380 |
+#endif |
|
277 | 381 |
} |
278 | 382 |
|
279 | 383 |
|
... | ... |
@@ -523,3 +627,12 @@ reui_triangle(SDL_Surface *dst, int x, int y, int w, int h, char direction, cons |
523 | 627 |
return(0); |
524 | 628 |
} |
525 | 629 |
|
630 |
+static int |
|
631 |
+reui_fontcachereset(reui_t *ui) |
|
632 |
+{ |
|
633 |
+ if(ui==NULL || ui->fontcache==NULL) |
|
634 |
+ return(-1); /* sanity check failed */ |
|
635 |
+ ui->usedfontcache=0; |
|
636 |
+ memset(ui->fontcachewhere,0,sizeof(ui->fontcachewhere)); |
|
637 |
+ return(0); |
|
638 |
+} |
... | ... |
@@ -17,6 +17,8 @@ |
17 | 17 |
#include "SDL_ttf.h" |
18 | 18 |
|
19 | 19 |
|
20 |
+#define FONTCACHESTART ' ' |
|
21 |
+#define FONTCACHEEND '~' |
|
20 | 22 |
|
21 | 23 |
typedef struct reui_t { |
22 | 24 |
int screenw,screenh; |
... | ... |
@@ -28,6 +30,9 @@ typedef struct reui_t { |
28 | 30 |
SDL_RWops *fontdata; |
29 | 31 |
TTF_Font *font; |
30 | 32 |
SDL_Texture *onepx; |
33 |
+ int usedfontcache; |
|
34 |
+ SDL_Texture *fontcache; |
|
35 |
+ int fontcachewhere[FONTCACHEEND-FONTCACHESTART]; |
|
31 | 36 |
int fontheight; |
32 | 37 |
int fontwidth; |
33 | 38 |
int scrdirty; |