18 #include "ttf_manager.hpp"
25 typedef short int16_t;
27 typedef long long int64_t;
28 typedef unsigned short uint16_t;
29 typedef unsigned int uint32_t;
30 typedef unsigned long long uint64_t;
34 typedef int32_t VIndex
;
35 typedef int32_t Ordinal
;
47 #include "textlines.h"
49 #include "find_files.h"
55 #include "texture_handler.h"
59 #include "music_and_sound_g.h"
63 #include "interface.h"
70 #pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking
71 #pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking
73 extern enablerst enabler
;
74 extern texture_handlerst texture
;
76 extern interfacest gview
;
78 extern string errorlog_prefix
;
80 void process_object_lines(textlinesst
&lines
,string
&chktype
,string
&graphics_dir
);
82 // Add, then increment to the (possible) PBO alignment requirement
83 static void align(size_t &sz
, off_t inc
) {
85 while (sz
%64) sz
++; // So.. tired.. FIXME.
88 void graphicst::resize(int x
, int y
) {
90 init
.display
.grid_x
= x
;
91 init
.display
.grid_y
= y
;
92 setclipping(0, x
-1, 0, y
-1);
93 force_full_display_count
++;
94 screen_limit
= screen
+ dimx
* dimy
* 4;
97 void graphicst::addcoloredst(const char *str
,const char *colorstr
)
99 const int slen
= strlen(str
);
101 for(s
=0; s
< slen
&& screenx
< init
.display
.grid_x
; s
++)
107 if (s
>= slen
) break;
110 changecolor((colorstr
[s
] & 7),((colorstr
[s
] & 56))>>3,((colorstr
[s
] & 64))>>6);
115 static list
<ttf_id
> ttfstr
;
117 static void abbreviate_string_helper_hackaroundmissingcode(string
&str
, int len
) {
120 if((str
[0]=='A'||str
[0]=='a')&&
123 str
.erase(str
.begin()+1);
124 str
.erase(str
.begin());
126 if(str
.length()<=len
)return;
131 if((str
[0]=='A'||str
[0]=='a')&&
132 (str
[1]=='N'||str
[1]=='n')&&
135 str
.erase(str
.begin()+2);
136 str
.erase(str
.begin()+1);
137 str
.erase(str
.begin());
139 if(str
.length()<=len
)return;
144 if((str
[0]=='T'||str
[0]=='t')&&
145 (str
[1]=='H'||str
[1]=='h')&&
146 (str
[2]=='E'||str
[2]=='e')&&
149 str
.erase(str
.begin()+3);
150 str
.erase(str
.begin()+2);
151 str
.erase(str
.begin()+1);
152 str
.erase(str
.begin());
154 if(str
.length()<=len
)return;
161 for(l
=(int32_t)str
.length()-1;l
>=1;l
--)
163 if(str
[l
-1]==' ')continue;
176 str
.erase(str
.begin()+l
);
177 if(str
.length()<=len
)return;
181 if(str
.length()>len
)str
.resize(len
);
185 static void abbreviate_string_hackaroundmissingcode(string
&str
, int32_t len
)
187 if (ttf_manager
.ttf_active()) {
188 // We'll need to use TTF-aware text shrinking.
189 while (ttf_manager
.size_text(str
) > len
)
190 abbreviate_string_helper_hackaroundmissingcode(str
, str
.length() - 1);
191 } else if(str
.length()>len
){
192 // 1 letter = 1 tile.
193 abbreviate_string_helper_hackaroundmissingcode(str
, len
);
198 void graphicst::addst(const string
&str_orig
, justification just
, int space
)
200 if (!str_orig
.size())
202 string str
= str_orig
;
204 abbreviate_string_hackaroundmissingcode(str
, space
);
205 if (just
== not_truetype
|| !ttf_manager
.ttf_active()) {
207 for(s
=0;s
<str
.length()&&screenx
<init
.display
.grid_x
;s
++)
213 if(s
>=str
.length())break;
220 if (str
.size() > 2 && str
[0] == ':' && str
[1] == ' ')
221 str
[1] = '\t'; // EVIL HACK
222 struct ttf_id id
= {str
, screenf
, screenb
, screenbright
};
223 ttfstr
.push_back(id
);
224 // if (str.size() == 80) {
225 // cout << "(" << int(str[0]) << ") ";
227 // cout << screeny << "," << str.size() << ":" << str;
228 // if (just == justify_cont)
232 if (just
== justify_cont
)
233 return; // More later
234 // This string is done. Time to render.
235 ttf_details details
= ttf_manager
.get_handle(ttfstr
, just
);
236 const int handle
= details
.handle
;
237 const int offset
= details
.offset
;
238 int width
= details
.width
;
239 const int ourx
= screenx
+ offset
;
240 unsigned int * const s
= ((unsigned int*)screen
+ ourx
*dimy
+ screeny
);
241 if (s
< (unsigned int*)screen_limit
)
242 s
[0] = (((unsigned int)GRAPHICSTYPE_TTF
) << 24) | handle
;
243 // Also set the other tiles this text covers, but don't write past the end.
244 if (width
+ ourx
>= dimx
)
245 width
= dimx
- ourx
- 1;
246 for (int x
= 1; x
< width
; ++x
)
247 s
[x
* dimy
] = (((unsigned int)GRAPHICSTYPE_TTFCONT
) << 24) | handle
;
248 // Clean up, prepare for next string.
249 screenx
= ourx
+ width
;
254 void graphicst::erasescreen_clip()
258 for(x2
=clipx
[0];x2
<=clipx
[1];x2
++)
260 for(y2
=clipy
[0];y2
<=clipy
[1];y2
++)
268 void graphicst::erasescreen_rect(int x1
, int x2
, int y1
, int y2
)
271 for (int x
= x1
; x
<= x2
; x
++) {
272 for (int y
= y1
; y
<= y2
; y
++) {
279 void graphicst::erasescreen()
281 memset(screen
, 0, dimx
*dimy
*4);
283 memset(screentexpos
, 0, dimx
*dimy
*sizeof(long));
286 void graphicst::setclipping(long x1
,long x2
,long y1
,long y2
)
289 if(x2
>init
.display
.grid_x
-1)x2
=init
.display
.grid_x
-1;
291 if(y2
>init
.display
.grid_y
-1)y2
=init
.display
.grid_y
-1;
299 void graphicst::dim_colors(long x
,long y
,char dim
)
301 if(x
>=clipx
[0]&&x
<=clipx
[1]&&
302 y
>=clipy
[0]&&y
<=clipy
[1])
307 switch(screen
[x
*dimy
*4 + y
*4 + 2])
312 screen
[x
*dimy
*4 + y
*4 + 2]=1;
316 screen
[x
*dimy
*4 + y
*4 + 2]=3;
319 switch(screen
[x
*dimy
*4 + y
*4 + 1])
324 screen
[x
*dimy
*4 + y
*4 + 1]=1;
328 screen
[x
*dimy
*4 + y
*4 + 1]=3;
331 if(screen
[x
*dimy
*4 + y
*4 + 1]==screen
[x
*dimy
*4 + y
*4 + 2])screen
[x
*dimy
*4 + y
*4 + 1]=0;
332 screen
[x
*dimy
*4 + y
*4 + 3]=0;
333 if(screen
[x
*dimy
*4 + y
*4 + 1]==0&&screen
[x
*dimy
*4 + y
*4 + 2]==0&&screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 3]=1;
336 switch(screen
[x
*dimy
*4 + y
*4 + 2])
340 screen
[x
*dimy
*4 + y
*4 + 2]=6;
344 screen
[x
*dimy
*4 + y
*4 + 2]=3;
347 switch(screen
[x
*dimy
*4 + y
*4 + 1])
350 screen
[x
*dimy
*4 + y
*4 + 3]=0;
354 screen
[x
*dimy
*4 + y
*4 + 1]=6;
357 screen
[x
*dimy
*4 + y
*4 + 1]=3;
360 screen
[x
*dimy
*4 + y
*4 + 1]=3;
363 if(screen
[x
*dimy
*4 + y
*4 + 1]!=7)screen
[x
*dimy
*4 + y
*4 + 3]=0;
364 if(screen
[x
*dimy
*4 + y
*4 + 1]==screen
[x
*dimy
*4 + y
*4 + 2]&&
365 screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 1]=0;
366 if(screen
[x
*dimy
*4 + y
*4 + 1]==0&&screen
[x
*dimy
*4 + y
*4 + 2]==0&&screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 3]=1;
369 switch(screen
[x
*dimy
*4 + y
*4 + 2])
373 screen
[x
*dimy
*4 + y
*4 + 2]=6;
376 switch(screen
[x
*dimy
*4 + y
*4 + 1])
380 screen
[x
*dimy
*4 + y
*4 + 1]=6;
383 if(screen
[x
*dimy
*4 + y
*4 + 1]!=7)screen
[x
*dimy
*4 + y
*4 + 3]=0;
384 if(screen
[x
*dimy
*4 + y
*4 + 1]==screen
[x
*dimy
*4 + y
*4 + 2]&&
385 screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 1]=0;
386 if(screen
[x
*dimy
*4 + y
*4 + 1]==0&&screen
[x
*dimy
*4 + y
*4 + 2]==0&&screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 3]=1;
389 if(screen
[x
*dimy
*4 + y
*4 + 1]!=7)screen
[x
*dimy
*4 + y
*4 + 3]=0;
390 if(screen
[x
*dimy
*4 + y
*4 + 1]==screen
[x
*dimy
*4 + y
*4 + 2]&&
391 screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 1]=0;
392 if(screen
[x
*dimy
*4 + y
*4 + 1]==0&&screen
[x
*dimy
*4 + y
*4 + 2]==0&&screen
[x
*dimy
*4 + y
*4 + 3]==0)screen
[x
*dimy
*4 + y
*4 + 3]=1;
398 void graphicst::rain_color_square(long x
,long y
)
400 if(x
>=clipx
[0]&&x
<=clipx
[1]&&
401 y
>=clipy
[0]&&y
<=clipy
[1])
403 screen
[x
*dimy
*4 + y
*4 + 1]=1;
404 screen
[x
*dimy
*4 + y
*4 + 2]=0;
405 screen
[x
*dimy
*4 + y
*4 + 3]=1;
409 void graphicst::snow_color_square(long x
,long y
)
411 if(x
>=clipx
[0]&&x
<=clipx
[1]&&
412 y
>=clipy
[0]&&y
<=clipy
[1])
414 screen
[x
*dimy
*4 + y
*4 + 1]=7;
415 screen
[x
*dimy
*4 + y
*4 + 2]=0;
416 screen
[x
*dimy
*4 + y
*4 + 3]=1;
420 void graphicst::color_square(long x
,long y
,unsigned char f
,unsigned char b
,unsigned char br
)
422 if(x
>=clipx
[0]&&x
<=clipx
[1]&&
423 y
>=clipy
[0]&&y
<=clipy
[1])
425 screen
[x
*dimy
*4 + y
*4 + 1]=f
;
426 screen
[x
*dimy
*4 + y
*4 + 2]=b
;
427 screen
[x
*dimy
*4 + y
*4 + 3]=br
;
431 void graphicst::prepare_graphics(string
&src_dir
)
433 if(!init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
))return;
438 svector
<char *> processfilename
;
440 textlinesst setuplines
;
443 //LOAD THE OBJECT FILES UP INTO MEMORY
444 //MUST INSURE THAT THEY ARE LOADED IN THE PROPER ORDER, IN CASE THEY REFER TO EACH OTHER
446 chk
+="graphics/graphics_*";
450 find_files_by_pattern_with_exception(chk
.c_str(),processfilename
,"text");
452 string chktype
="GRAPHICS";
453 for(f
=0;f
<processfilename
.size();f
++)
455 strcpy(str
,src_dir
.c_str());
456 strcat(str
,"graphics/");
457 strcat(str
,processfilename
[f
]);
458 setuplines
.load_raw_to_lines(str
);
460 errorlog_prefix
="*** Error(s) found in the file \"";
461 errorlog_prefix
+=str
;
462 errorlog_prefix
+='\"';
463 process_object_lines(setuplines
,chktype
,src_dir
);
464 errorlog_prefix
.clear();
467 delete[] processfilename
[f
];
469 processfilename
.clear();
471 enabler
.reset_textures();
474 void graphicst::add_tile(long texp
,char addcolor
)
476 if(screenx
>=clipx
[0]&&screenx
<=clipx
[1]&&
477 screeny
>=clipy
[0]&&screeny
<=clipy
[1])
479 screentexpos
[screenx
*dimy
+ screeny
]=texp
;
480 screentexpos_addcolor
[screenx
*dimy
+ screeny
]=addcolor
;
481 screentexpos_grayscale
[screenx
*dimy
+ screeny
]=0;
485 void graphicst::add_tile_grayscale(long texp
,char cf
,char cbr
)
487 if(screenx
>=clipx
[0]&&screenx
<=clipx
[1]&&
488 screeny
>=clipy
[0]&&screeny
<=clipy
[1])
490 screentexpos
[screenx
*dimy
+ screeny
]=texp
;
491 screentexpos_addcolor
[screenx
*dimy
+ screeny
]=0;
492 screentexpos_grayscale
[screenx
*dimy
+ screeny
]=1;
493 screentexpos_cf
[screenx
*dimy
+ screeny
]=cf
;
494 screentexpos_cbr
[screenx
*dimy
+ screeny
]=cbr
;
498 void graphicst::draw_border(int x1
, int x2
, int y1
, int y2
) {
500 for (int x
= x1
; x
<= x2
; x
++) {
507 for (int y
= y1
+1; y
< y2
; y
++) {
515 void graphicst::get_mouse_text_coords(int32_t &mx
, int32_t &my
) {
516 mx
= mouse_x
; my
= mouse_y
;
521 //GRAB CURRENT SCREEN AT THE END OF THE LIST
522 viewscreenst
*currentscreen
=&gview
.view
;
523 while(currentscreen
->child
!=NULL
)currentscreen
=currentscreen
->child
;
525 //NO INTERFACE LEFT, LEAVE
526 if(currentscreen
==&gview
.view
)return;
528 if(currentscreen
->breakdownlevel
==INTERFACE_BREAKDOWN_NONE
)
530 currentscreen
->render();
532 else gps
.erasescreen();
534 // Render REC when recording macros. Definitely want this screen-specific. Or do we?
535 const Time now
= SDL_GetTicks();
536 if (enabler
.is_recording() && now
% 1000 > 500) {
538 gps
.changecolor(4,1,1);
541 // Render PLAY when playing a macro
542 if (enabler
.is_macro_playing() && now
% 1000 <= 500) {
544 gps
.changecolor(2,1,1);
547 // Render # <i> when building a repetition prefix
548 if (enabler
.prefix_building()) {
550 gps
.changecolor(3,1,1);
551 gps
.addst("#" + enabler
.prefix());
553 if (gps
.display_frames
) {
554 ostringstream fps_stream
;
555 fps_stream
<< "FPS: " << setw(3) << enabler
.calculate_fps() << " (" << enabler
.calculate_gfps() << ")";
556 string fps
= fps_stream
.str();
557 gps
.changecolor(7,3,1);
558 static gps_locator
fps_locator(0, 25);
559 fps_locator(fps
.size());