Have made it to 1-2 in K&R. Will go a little further in the book to see of I run into further problems with handling text with my new header and game loops.
I'm still starting out so of course if you see some issues/mistakes let me know.
prints.h
/*
* This is prints.h (for the Pandora handheld).
* GOAL: to create a header that defines a function prints() and it's initializer printsInit().
* I am creating this since I want other developers to be able to just include this header to create their first graphical "Hello world" program easily.
*
* prints( const char text[], SDL_surface *screen, SDL_Surface *abc[MAXCHAR], int v[7] )
*
* SDL_surface *screen - the SDL_surface created that will have the text written to it
* SDL_surface *abc - the character string that will be parsed
* int v[5] - I made this an int array for the easy of coding.
*
* example: prints( text, \ // the text you want to render
* screen, \ // the surface you want to render to
* chars, \ // the font you setup with printsInit
* v \ // the extra stuff
* );
*
* Here are the contents explained:
*
*
* v[0] - character width spacing (how far apart the letters are written on the x coord).
* v[1] - character height spacing
* v[2] - surface width in pixels (in the case of the Pandora 800 should be popular.
* v[3] - surface height in pixels (480 for full screen Pandora surface).
* v[4] - tab width (I like four, some like 2, others like 8...).
*
*
* printsInit( SDL_Surface *abc[MAXCHAR], char *fontPath, char *fontName, int fontSize, int color[4] )
*
* SDL_Surface *abc - an array of surfaces that we will render the letters to
* char *fontPath - the character string that defines the location where fonts are stored
* char *fontName - the TTF font to be rendered
* int fontSize - how large to render the TTF font to the surfaces created for each individual letter
* int color[4] - font color: color[0] = Red value, color[1] = Green value, color[2] = Blue value, color[3] = opacity (for use in SDL_Color rgb = {255,255,255,255})
*
*/
#include "SDL_ttf.h"
#define MAXCHAR 95 // the maximum number of printable characters to create (normally 95 for English ASCII)
#define TABWIDTH 4
/* printsInit */
int printsInit( SDL_Surface *abc[MAXCHAR], char *fontPath, char *fontName, int fontSize, SDL_Color color ) {
/* initialize SDL_ttf and check for errors. */
if ( TTF_Init() == -1 ) {
printf("Unable to initialize TTF: %s\n", TTF_GetError());
return 1;
}
int i = 0; /* our counter */
/* let's creat a variable with the full font path. */
char *fullFontPath;
fullFontPath = malloc(512 * sizeof(char)); /* Make sure it's large enough. */
strncpy( fullFontPath, fontPath, 512); /* Add the path. */
strncat( fullFontPath, fontName, 512); /* use strcat to append the fontName to the path. */
/* Open the font you would like to use for rendering. */
TTF_Font *font = TTF_OpenFont( fullFontPath, fontSize);
/* Check if file actually exists. */
if( font == NULL ) {
printf("Font not found!\n");
return -1;
}
/* Lets fill an array of little pre-rendered surfaces for each letter to save time. */
char letter[] = " "; /* Set the first character to space which is the beginning of ASCII printable characters. */
/* Now loop through the entire printable ASCII set and reder them to a surface. */
for ( i = 0; i < MAXCHAR; i++ ) {
abc
= TTF_RenderText_Blended( font, letter, color );
letter[0] += 1; /* this looks odd.. letter is a STRING not a char.. so [1] is always \0.
this increment turns a into b and b into c etc. */
}
/* free our malloc. */
free(fullFontPath);
TTF_CloseFont( font );
return 0;
}
/* Here is our prints function for writing TTF fonts to a SDL_Surface array. */
int prints( const char *text, SDL_Surface *surface, SDL_Surface *abc[MAXCHAR], int v[7] ) {
// check to see if anything is NULL
if ( text == NULL ) {
printf("character string is NULL\n");
return -1;
}
// tabcount will keep track of which column we are currently in.
int tabcount = 1;
/* create a SDL_Rect (x, y coord) in order to blit. */
SDL_Rect dest;
/* this modifies our variable that tells us WHERE to write our surface
* and how big to create the surface for each character. */
dest.x = 0;
dest.y = 0;
// set i for use
int i = 0;
for( ; i < MAXCHAR; i++ )
SDL_ConvertSurface( abc, surface->format, SDL_HWSURFACE );
i = 0;
/* Once we have all of the letters we may move on to rendering them to the screen. */
while ( text != '\0' ) {
// check for escape character.
while ( text == '\\' && text[i+1] != '\\' ) { // If the current character is "\".
// and the next char is not "\".
i++; // skip to the next character!
tabcount = 1; // reset our tab counter
switch ( text ) {
case 'n': // and the character is 'n' which indicates newline.
dest.y += v[1]; // Skip one line's worth of pixels DOWN on the surface.
dest.x = 0; // AND reset X to start all the way to the left.
i++; // Now increment to print the next character
break;
case 't': // and the character is 't' which idicates a tab.
// here we need to figure out which tab column to align to.
while(1) {
if ( dest.x < v[0]*v[4]*tabcount ) {
dest.x = v[0]*v[4]*tabcount;
break;
}
tabcount++;
}
i++; // skip past t
break;
case 'a': // and is a for "alert" do nothing.
i++; // increment past a.
break;
case 'b': // and is b for "backspace" so subtract letter width from x.
dest.x -= v[0];
i++; // increment past b.
break;
case 'f': // and is f for "formfeed" so go down one character height.
dest.y += v[1];
i++; // increment past f.
break;
case 'v': // and is v for "vertical tab" do nothing.
i++; // increment past v.
break;
case 'r': // and is r for "return" so return x to 0.
dest.x = 0;
i++; // increment past r.
break;
default: // The character is anything other than the aforementioned.
break; // Do nothing.
}
}
// check to see if the next printed character is off the screen (x axis)
if ( dest.x >= v[2])
{
dest.x = 0; // Go back to the beginning of the line.
dest.y += v[1]; // And go down one line.
}
// check to see if the next printed character is off the screen (y axis)
if ( dest.y >= v[3])
{
break; // just quit the loop if it is.
}
if ( text == '\0' ) {
break;
}
SDL_BlitSurface(abc[text-32], NULL, surface, &dest);
dest.x += v[0];
// Now if the current character is "\" then the next one is as well...
// see exception in the while() above
// so we need to increment past the next "\" AFTER we render the current one
// which we are doing here.
if ( text == '\\' )
{
i+=2;
}
else
{
i++; // Otherwise just increment the array to print the next character.
}
}
return 0;
}
fahr.c
/* fahr.c
* a simple "Hello world" type program using prints.h
*/
/* this has been modified to change font. */
#include "stdio.h"
#include "SDL.h"
#include "SDL_image.h"
#include "prints.h"
#define PRNTABL 95 // There are 95 printable letters in ASCII
int main( int argc, char *argv[] ) {
/* initial setup */
SDL_Surface *screen; // the surface that will be blitted to the screen
SDL_Event event; // event needed to capture input
short int running = 1; // boolian for the main game loop
int i = 0; // our incrementer
/* create the screen surface */
screen = SDL_SetVideoMode( 800, 480, 16, SDL_HWSURFACE ); // screen width, screen height, bits per pixel, screen option (0 is window)
//screen = SDL_SetVideoMode( 800, 480, 16, SDL_FULLSCREEN );
if( screen == NULL ) {
printf( "Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
SDL_Color color0 = { 175, 175, 255 }; // The color of our font { RRR, GGG, BBB }
SDL_Surface *letters[PRNTABL]; // surfaces to hold our font
int attributes[5] = { 8, // Letter spacing horizontally
16, // Letter spacing vertically
800, // surface width (in this case screen width)
480, // surface height
4 }; // spaces in a tab
/* Start SDL */
if ( SDL_Init( SDL_INIT_VIDEO ) == -1 ) {
printf("Unable to initialize SDL: %s\n", SDL_GetError() );
return 1;
}
atexit(SDL_Quit);
/* Create our font */
if ( printsInit( letters, "./fonts/", "ProggyCleanSZBP.ttf", 16, color0 ) == -1 ) { // letters, font path, font, font size, font color
printf("Unable to initialize prints\n");
return 1;
}
/* put your code here vvv */
// fahr to celsius variables:
int fahr, celsius;
int lower, upper, step;
lower = -40; // lower limit of conversion table
upper = 90; // upper limit of conversion table
step = 5; // our incrementer
fahr = lower;
char text[3200]; // our text array for printing our conversion table.
char conversionText[80]; // the buffer to hold the text of the conversion (to be cat'd to text[])
strncpy( text, "Farenheit to celsius conversion:\\t\\t\\t\\t\\t\\t\\t\\t\\t(Press 'q' or 'escape' to quit.)\\n\\n", 256 );
while( fahr <= upper ) {
celsius = 5 * (fahr-32) / 9;
sprintf( conversionText, "If the temperature is %dF\\tthen it is %dC.\\n", fahr, celsius);
strncat( text, conversionText , 3200 );
fahr = fahr + step;
}
/* main game loop */
while( running ) {
SDL_FillRect( screen, NULL, SDL_MapRGB( screen->format, 0, 0, 42 ) ); // add some color to the screen surface.
prints( text, screen, letters, attributes );
while( SDL_PollEvent( &event ) ) {
switch( event.type ) {
case SDL_KEYDOWN:
case SDL_KEYUP:
switch( event.key.keysym.sym ) {
case SDLK_q:
running = 0;
break;
case SDLK_ESCAPE:
running = 0;
break;
}
break;
case SDL_QUIT:
running = 0;
break;
}
}
// render screen to actual video buffer
SDL_UpdateRect( screen, 0, 0, 0, 0 );
SDL_Delay( 100 );
}
/* put your code here ^^^ */
// SDL_Delay( 9000 );
// Free our surfaces
SDL_FreeSurface( screen );
i = 0;
for ( ; i <= PRNTABL-1; i++ ) {
SDL_FreeSurface( letters );
}
return 0;
}
compile.sh
#!/bin/bash
gcc main.c `sdl-config --cflags --libs` -lSDL_ttf -lSDL_image
echo done!
(You shouldn't need "-lSDL_imge for this app since I didn't use any .pngs in it. )
compile-pandora.sh
#!/bin/bash
#pandora-gcc prints.c -o prints.panda `sdl-config --cflags --libs` -I/home/$USER/Code/pandora-dev/arm-2011.09/usr/include/SDL -lSDL_ttf
pandora-gcc main.c -o test.panda -I/home/$USER/Code/pandora-dev/arm-2011.09/usr/include/SDL -L/home/$USER/Code/pandora-dev/arm-2011.09/usr/lib -lts -lSDL -lfreetype -lpng -lz -ltiff -ljpeg -lSDL_ttf -lSDL_image -lpthread
echo done!
(remember to replace $USER for the path and change the path to the correct "pandora-dev" folder.)