3232typedef enum {
3333 SCROLL_NONE ,
3434 SCROLL_SINE_WAVE ,
35- SCROLL_BOTTOM_TRADITIONAL
35+ SCROLL_BOTTOM_TRADITIONAL ,
36+ SCROLL_ROLLER_3D
3637} ScrollStyle ;
3738
3839typedef struct {
@@ -54,6 +55,7 @@ typedef struct {
5455 SDL_Texture * plasma_texture ;
5556 Uint32 * pixels ;
5657 TTF_Font * font ;
58+ TTF_Font * font_outline ;
5759 SDL_Surface * jack_surface ;
5860 SDL_Texture * jack_texture ;
5961 SDL_Surface * logo_surface ;
@@ -697,10 +699,11 @@ void render_scroll_text(DemoContext *ctx)
697699 float scroll_speed = 180.0 ;
698700 float scroll_offset = ctx -> global_time * scroll_speed ;
699701
700- if (ctx -> scroll_style == SCROLL_SINE_WAVE ) {
702+ if (ctx -> scroll_style == SCROLL_SINE_WAVE || ctx -> scroll_style == SCROLL_ROLLER_3D ) {
701703 /* Glyph cache with metrics */
702704 typedef struct {
703705 SDL_Texture * tex ;
706+ SDL_Texture * tex_outline ;
704707 int w , h ;
705708 int adv ;
706709 int valid ;
@@ -737,6 +740,16 @@ void render_scroll_text(DemoContext *ctx)
737740 gcache [ch ].h = surface -> h ;
738741 gcache [ch ].valid = 1 ;
739742 SDL_FreeSurface (surface );
743+
744+ /* Outline cache for 3D roller */
745+ if (ctx -> font_outline && ctx -> scroll_style == SCROLL_ROLLER_3D ) {
746+ SDL_Color black = {0 , 0 , 0 , 255 };
747+ SDL_Surface * os = TTF_RenderText_Blended (ctx -> font_outline , buffer , black );
748+ if (os ) {
749+ gcache [ch ].tex_outline = SDL_CreateTextureFromSurface (ctx -> renderer , os );
750+ SDL_FreeSurface (os );
751+ }
752+ }
740753 }
741754 }
742755
@@ -761,18 +774,53 @@ void render_scroll_text(DemoContext *ctx)
761774 while (char_x < -100 ) char_x += total_adv ;
762775
763776 if (char_x > -100 && char_x < WIDTH + 100 && gcache [ch ].valid ) {
764- float wave = sin (ctx -> global_time * 2.0 + i * 0.3 ) * 80.0 ;
777+ float phase = ctx -> global_time * 2.0f + i * 0.3f ;
778+ float wave = sinf (phase ) * 80.0f ;
765779 int y_pos = HEIGHT / 2 + (int )wave ;
766780
767781 /* Update color for gradient effect */
768782 int color_shift = (int )(ctx -> global_time * 100 + i * 10 ) % 360 ;
769783 Uint8 r = (Uint8 )(128 + 127 * sin (color_shift * PI / 180 ));
770784 Uint8 g = (Uint8 )(128 + 127 * sin ((color_shift + 120 ) * PI / 180 ));
771785 Uint8 b = (Uint8 )(128 + 127 * sin ((color_shift + 240 ) * PI / 180 ));
772- SDL_SetTextureColorMod (gcache [ch ].tex , r , g , b );
773786
774- SDL_Rect dest = {(int )char_x , y_pos - gcache [ch ].h / 2 , gcache [ch ].w , gcache [ch ].h };
775- SDL_RenderCopy (ctx -> renderer , gcache [ch ].tex , NULL , & dest );
787+ if (ctx -> scroll_style == SCROLL_ROLLER_3D ) {
788+ /* 3D roller with scale, outline, and glow */
789+ float scale = 1.0f + 0.25f * cosf (phase );
790+ int dw = (int )(gcache [ch ].w * scale );
791+ int dh = (int )(gcache [ch ].h * scale );
792+ SDL_Rect dest = {(int )char_x , y_pos - dh / 2 , dw , dh };
793+
794+ /* Outline behind */
795+ if (gcache [ch ].tex_outline ) {
796+ SDL_SetTextureColorMod (gcache [ch ].tex_outline , 0 , 0 , 0 );
797+ SDL_Rect od = dest ;
798+ od .x -= 1 ;
799+ od .y -= 1 ;
800+ SDL_RenderCopy (ctx -> renderer , gcache [ch ].tex_outline , NULL , & od );
801+ }
802+
803+ /* Main glyph with color */
804+ SDL_SetTextureColorMod (gcache [ch ].tex , r , g , b );
805+ SDL_RenderCopy (ctx -> renderer , gcache [ch ].tex , NULL , & dest );
806+
807+ /* Soft glow (additive, slightly larger, low alpha) */
808+ SDL_SetTextureBlendMode (gcache [ch ].tex , SDL_BLENDMODE_ADD );
809+ SDL_SetTextureAlphaMod (gcache [ch ].tex , 40 );
810+ SDL_Rect glow = dest ;
811+ glow .x -= 2 ;
812+ glow .y -= 2 ;
813+ glow .w += 4 ;
814+ glow .h += 4 ;
815+ SDL_RenderCopy (ctx -> renderer , gcache [ch ].tex , NULL , & glow );
816+ SDL_SetTextureAlphaMod (gcache [ch ].tex , 255 );
817+ SDL_SetTextureBlendMode (gcache [ch ].tex , SDL_BLENDMODE_BLEND );
818+ } else {
819+ /* Simple sine wave */
820+ SDL_SetTextureColorMod (gcache [ch ].tex , r , g , b );
821+ SDL_Rect dest = {(int )char_x , y_pos - gcache [ch ].h / 2 , gcache [ch ].w , gcache [ch ].h };
822+ SDL_RenderCopy (ctx -> renderer , gcache [ch ].tex , NULL , & dest );
823+ }
776824 }
777825
778826 /* Advance by glyph advance + kerning */
@@ -990,6 +1038,15 @@ int main(int argc, char *argv[])
9901038 return 1 ;
9911039 }
9921040
1041+ /* Load outline font for 3D roller effect */
1042+ SDL_RWops * font_outline_rw = SDL_RWFromConstMem (topaz_8_otf , topaz_8_otf_len );
1043+ if (font_outline_rw ) {
1044+ ctx .font_outline = TTF_OpenFontRW (font_outline_rw , 1 , 48 );
1045+ if (ctx .font_outline ) {
1046+ TTF_SetFontOutline (ctx .font_outline , 2 );
1047+ }
1048+ }
1049+
9931050 ctx .pixels = malloc (WIDTH * HEIGHT * sizeof (Uint32 ));
9941051
9951052 /* Create plasma texture (lower resolution for performance) */
@@ -1133,7 +1190,7 @@ int main(int argc, char *argv[])
11331190 /* Render current scene */
11341191 switch (ctx .current_scene ) {
11351192 case 0 :
1136- ctx .scroll_style = SCROLL_SINE_WAVE ;
1193+ ctx .scroll_style = SCROLL_ROLLER_3D ;
11371194 render_starfield (& ctx );
11381195 render_scroll_text (& ctx );
11391196 break ;
@@ -1198,6 +1255,9 @@ int main(int argc, char *argv[])
11981255 SDL_DestroyTexture (ctx .plasma_texture );
11991256 }
12001257 TTF_CloseFont (ctx .font );
1258+ if (ctx .font_outline ) {
1259+ TTF_CloseFont (ctx .font_outline );
1260+ }
12011261 SDL_DestroyTexture (ctx .texture );
12021262 SDL_DestroyRenderer (ctx .renderer );
12031263 SDL_DestroyWindow (ctx .window );
0 commit comments