Difference between revisions of "Printing Text"

From WikiPrizm
Jump to navigationJump to search
(Undo revision 1022 by ProgrammerNerd (talk))
m (PrintMiniMini does exist in libfxcg)
 
(One intermediate revision by one other user not shown)
Line 3: Line 3:
 
As seen in the [[Hello World]] tutorial, [[PrintXY]] is used to print text to the LCD.  This is only one way to print text on the Prizm. I will go over different methods to print out text below.
 
As seen in the [[Hello World]] tutorial, [[PrintXY]] is used to print text to the LCD.  This is only one way to print text on the Prizm. I will go over different methods to print out text below.
 
=== PrintXY ===
 
=== PrintXY ===
[[PrintXY]] is useful if you want to print out text to a specific location and you don't mind the [[PrintXY#Comments|limitation]] on the string parameter.  A common usage for PrintXY is for printing static text, like
+
[[PrintXY]] is the usual way to print text to a specific location on the screen. Note that it ignores the first two bytes of the string parameter, so you usually want to either pad the beginning of the string with any two characters or subtract two from the address of your string (beware the caveats discussed on the [[PrintXY#Comments|PrintXY page]]).
PrintXY(1,1,"Hello World!"-2,TEXT_MODE_NORMAL, TEXT_COLOR_BLACK);
+
 
If you want to use a non-static string, you can get around the string limitation by doing
 
char buffer[128];
 
 
// Do stuff with buffer+2
 
strcpy(buffer, "Hi there");
 
 
PrintXY(1,3,buffer-2,0,0); // ...,0,0); is the same as ...,TEXT_MODE_NORMAL, TEXT_COLOR_BLACK);
 
 
==== Formatting ====
 
==== Formatting ====
 
[[PrintXY]] gives you two ways to customize the printed text, '''''int''' display_mode'' and '''''int''' text_color''.  Display mode as 0 will set the display to the printed text with a white background.  1 will invert the text, flipping foreground (text_color) with the background (white) colors.  0x20 will OR the text to the screen (the background color is transparent). If you do
 
[[PrintXY]] gives you two ways to customize the printed text, '''''int''' display_mode'' and '''''int''' text_color''.  Display mode as 0 will set the display to the printed text with a white background.  1 will invert the text, flipping foreground (text_color) with the background (white) colors.  0x20 will OR the text to the screen (the background color is transparent). If you do
  PrintXY(1,1,"Hello"-2,0,TEXT_COLOR_RED);
+
  PrintXY(1,1," Hello",0,TEXT_COLOR_RED);
  PrintXY(1,1,"World"-2,0x20,TEXT_COLOR_BLUE);
+
  PrintXY(1,1," World",0x20,TEXT_COLOR_BLUE);
 
You will see the word 'World' printed on top of the word 'Hello'. Lastly, you can have 0x21 as the display mode.  This will work as an AND to the screen.  If both pixels (what would be drawn and what is already draw) are 'on', or have a color other than white, then the pixel on the screen isn't changed. Otherwise, the pixel on the screen will become white. You can test it yourself by doing
 
You will see the word 'World' printed on top of the word 'Hello'. Lastly, you can have 0x21 as the display mode.  This will work as an AND to the screen.  If both pixels (what would be drawn and what is already draw) are 'on', or have a color other than white, then the pixel on the screen isn't changed. Otherwise, the pixel on the screen will become white. You can test it yourself by doing
  PrintXY(1,1,"Hello"-2,0,0);
+
  PrintXY(1,1," Hello",0,0);
  PrintXY(1,1,"World"-2,0x21,TEXT_COLOR_RED);
+
  PrintXY(1,1," World",0x21,TEXT_COLOR_RED);
  
 
You have already seen me using colors when using [[PrintXY]].  You can get a list of all colors in the ''color.h'' file in the ''include'' folder in the PrizmSDK.  Note that you can only use the TEXT_COLOR_* ones.
 
You have already seen me using colors when using [[PrintXY]].  You can get a list of all colors in the ''color.h'' file in the ''include'' folder in the PrizmSDK.  Note that you can only use the TEXT_COLOR_* ones.
Line 36: Line 29:
  
 
  PrintMini(&x, &y, "abcdEFGH1234!@#$.,;'", 0, 0xffffffff, 0,0,COLOR_DARKGREEN, COLOR_GRAY, 1,0);
 
  PrintMini(&x, &y, "abcdEFGH1234!@#$.,;'", 0, 0xffffffff, 0,0,COLOR_DARKGREEN, COLOR_GRAY, 1,0);
As you can see, this function uses pointers. This is because [[PrintMini]] will update the position to after the last printed character. The second thing to note is that the string doesn't need garbage letters.  Now, this function doesn't have complete documentation, but enough exists to use it.  Also note that this function doesn't use ''TEXT_COLOR_*'' colors, but instead RGB565 colors.
+
As you can see, this function uses pointers. This is because [[PrintMini]] will update the position to after the last printed character. The color parameters are 16-bit [[Display#Color|RGB565]], rather than the <tt>TEXT_COLOR_*</tt> values used in the other text functions. The purposes of some of the parameters are unknown and should be left as they are here.
  
<span style="font-size:20px"><b><i>REMEMBER TO USE POINTERS TO INT VALUES!!!</i> This is NOT correct:</b></span>
+
The first two parameters to this function must be valid pointers. Beginners often try to force this function to take literal values cast to pointers, which will cause a crash.
  PrintMini((int*)0, (int*)0, ...
+
// Wrong!
You MUST actually point to an int value. This mistake has been done countless times and WILL cause a crash of the program or a forced reboot.
+
PrintMini(0, 0, ...);
 +
  // Also wrong, but the compiler won't warn
 +
  PrintMini((int*)0, (int*)0, ...);
 +
// Correct
 +
int x, y;
 +
PrintMini(&x, &y, ...)
 +
With the recommended compiler warnings enabled, the common mistake of the first example here will result in warnings at compile time. The second explicitly silences these warnings and does it wrong, such as a beginner might to do silence the compiler warnings.
  
 
=== Printing in MiniMini font ===
 
=== Printing in MiniMini font ===
'''''NOTE:''' This function doesn't exist in libfxcg yet!''
 
 
If you liked the Mini font because it is small, you should know that there is an ''even smaller'' 10 pixel high font.  This can be drawn using [[PrintMiniMini]].  It is a mix of [[PrintMini]] and [[PrintXY]] for the parameters.  Here is a sample:
 
If you liked the Mini font because it is small, you should know that there is an ''even smaller'' 10 pixel high font.  This can be drawn using [[PrintMiniMini]].  It is a mix of [[PrintMini]] and [[PrintXY]] for the parameters.  Here is a sample:
 
   int x = 0;
 
   int x = 0;
Line 57: Line 55:
  
 
== Working with Numbers ==
 
== Working with Numbers ==
One thing that is great for debugging, scores for games, etc., is being able to print out numbers.  You can use [[itoa]] to convert a number to text.  Note that [[itoa]] is located in the ''CONVERT_syscalls.h'' header and to also watch out for the [[PrintXY#Comments|PrintXY string limitation]].  Here is an example on printing out a number:
+
One thing that is great for debugging, scores for games, etc., is being able to print out numbers.  You can use [[itoa]] to convert a number to text.  Note that [[itoa]] is located in the ''CONVERT_syscalls.h'' header.  Here is an example on printing out a number:
 
  #include <display.h>
 
  #include <display.h>
 
  #include <keyboard.h>
 
  #include <keyboard.h>
Line 65: Line 63:
 
  {
 
  {
 
   int number = 12345;
 
   int number = 12345;
   unsigned char buffer[20]; // Be careful about the size. don't make it too small
+
  // This buffer must be large enough to hold a 32-bit signed number;
 +
  // 12 comes from ceil(log10(1 << 30)), plus one byte for a sign and one
 +
  // for a null terminator.
 +
   unsigned char buffer[12];
 
    
 
    
 
   itoa(number, buffer);
 
   itoa(number, buffer);
Line 75: Line 76:
 
  }
 
  }
 
This example uses Print_OS because Print_OS doesn't require 2 garbage characters.  This example also uses an '''''unsigned char*''' buffer'' rather than a '''''char*''' buffer''. To use PrintXY instead, you can use this:
 
This example uses Print_OS because Print_OS doesn't require 2 garbage characters.  This example also uses an '''''unsigned char*''' buffer'' rather than a '''''char*''' buffer''. To use PrintXY instead, you can use this:
  char buffer[20];  
+
  char buffer[14];  
  itoa(number,(unsigned char*)buffer); // Leave the garbage bytes alone
+
  itoa(number,(unsigned char*)buffer + 2); // Leave the garbage bytes alone
  PrintXY(1,1,buffer-2,0,TEXT_COLOR_BLUE);
+
  PrintXY(1,1,buffer,0,TEXT_COLOR_BLUE);
  
 
== Notes for PrintMini and PrintMiniMini ==
 
== Notes for PrintMini and PrintMiniMini ==
Now, one of the things that I see happening is
+
The utility of the pointer parameters to PrintMini may not obvious, but it's useful when you wish to perform computations based on the size of printed text. For example:
PrintMini((int*)10,(int*)15,...
 
This is '''not''' the correct usage for these functions.  (Note that if it was an int, the header would be adjusted to use an int, not an int*).  Now, you may wonder when this would be useful. Here is an example:
 
 
  int x = 0;
 
  int x = 0;
 
  int y = CELL_Y;
 
  int y = CELL_Y;

Latest revision as of 00:29, 26 March 2022

Printing text to the Prizm's screen isn't too easy and straight-forward. This tutorial will show you the ways (that are known) to print information to the screen.

Printing a String

As seen in the Hello World tutorial, PrintXY is used to print text to the LCD. This is only one way to print text on the Prizm. I will go over different methods to print out text below.

PrintXY

PrintXY is the usual way to print text to a specific location on the screen. Note that it ignores the first two bytes of the string parameter, so you usually want to either pad the beginning of the string with any two characters or subtract two from the address of your string (beware the caveats discussed on the PrintXY page).

Formatting

PrintXY gives you two ways to customize the printed text, int display_mode and int text_color. Display mode as 0 will set the display to the printed text with a white background. 1 will invert the text, flipping foreground (text_color) with the background (white) colors. 0x20 will OR the text to the screen (the background color is transparent). If you do

PrintXY(1,1,"  Hello",0,TEXT_COLOR_RED);
PrintXY(1,1,"  World",0x20,TEXT_COLOR_BLUE);

You will see the word 'World' printed on top of the word 'Hello'. Lastly, you can have 0x21 as the display mode. This will work as an AND to the screen. If both pixels (what would be drawn and what is already draw) are 'on', or have a color other than white, then the pixel on the screen isn't changed. Otherwise, the pixel on the screen will become white. You can test it yourself by doing

PrintXY(1,1,"  Hello",0,0);
PrintXY(1,1,"  World",0x21,TEXT_COLOR_RED);

You have already seen me using colors when using PrintXY. You can get a list of all colors in the color.h file in the include folder in the PrizmSDK. Note that you can only use the TEXT_COLOR_* ones.

Print_OS and locate_OS

Print_OS works by printing text that starts at a text cursor. the text cursor can be set with locate_OS. Here is an example:

locate_OS(1,1);
Print_OS("Hello ",0,0);
Print_OS("World!",0,0);

You will note that the text appears together. This is because Print_OS moves the text cursor when it prints.

This command can have the mode changed just like PrintXY, but not the color.

Printing in Mini font

The Prizm doesn't just let you print 8 lines of giant letters, it also lets you print in the Mini font using PrintMini. This function is a bit more complex, but has its advantages. Here is an example of how to print in the Mini font:

int x = 0; // This function uses pixels
int y = 0;
PrintMini(&x, &y, "abcdEFGH1234!@#$.,;'", 0, 0xffffffff, 0,0,COLOR_DARKGREEN, COLOR_GRAY, 1,0);

As you can see, this function uses pointers. This is because PrintMini will update the position to after the last printed character. The color parameters are 16-bit RGB565, rather than the TEXT_COLOR_* values used in the other text functions. The purposes of some of the parameters are unknown and should be left as they are here.

The first two parameters to this function must be valid pointers. Beginners often try to force this function to take literal values cast to pointers, which will cause a crash.

// Wrong!
PrintMini(0, 0, ...);
// Also wrong, but the compiler won't warn
PrintMini((int*)0, (int*)0, ...);
// Correct
int x, y;
PrintMini(&x, &y, ...)

With the recommended compiler warnings enabled, the common mistake of the first example here will result in warnings at compile time. The second explicitly silences these warnings and does it wrong, such as a beginner might to do silence the compiler warnings.

Printing in MiniMini font

If you liked the Mini font because it is small, you should know that there is an even smaller 10 pixel high font. This can be drawn using PrintMiniMini. It is a mix of PrintMini and PrintXY for the parameters. Here is a sample:

 int x = 0;
 int y = 0;
 PrintMiniMini(&x, &y, "abcdEFGH1234!@#$.,;'", 0b00010000, TEXT_COLOR_CYAN, 0);
 
 x = 0;
 y = 12;
 PrintMiniMini(&x, &y, "abcdEFGH1234!@#$.,;'", 0, TEXT_COLOR_CYAN, 0);

Like the warning above, you MUST use pointers to int values!!!

You may wonder why I have it executing twice. This is simply to show off the fact that the MiniMini font can be styled as bold at the same height. You should be familiar to the position pointers and the string. Unlike PrintMini, this function uses the 3 bit colors.

Working with Numbers

One thing that is great for debugging, scores for games, etc., is being able to print out numbers. You can use itoa to convert a number to text. Note that itoa is located in the CONVERT_syscalls.h header. Here is an example on printing out a number:

#include <display.h>
#include <keyboard.h>
#include <CONVERT_syscalls.h>

int main()
{
  int number = 12345;
  // This buffer must be large enough to hold a 32-bit signed number;
  // 12 comes from ceil(log10(1 << 30)), plus one byte for a sign and one
  // for a null terminator.
  unsigned char buffer[12];
  
  itoa(number, buffer);
  locate_OS(1,1);
  Print_OS(buffer,0,0);
  
  int key;
  while(1) GetKey(&key);
}

This example uses Print_OS because Print_OS doesn't require 2 garbage characters. This example also uses an unsigned char* buffer rather than a char* buffer. To use PrintXY instead, you can use this:

char buffer[14]; 
itoa(number,(unsigned char*)buffer + 2); // Leave the garbage bytes alone
PrintXY(1,1,buffer,0,TEXT_COLOR_BLUE);

Notes for PrintMini and PrintMiniMini

The utility of the pointer parameters to PrintMini may not obvious, but it's useful when you wish to perform computations based on the size of printed text. For example:

int x = 0;
int y = CELL_Y;
PrintMiniMini(&x, &y, "December", 0, TEXT_COLOR_CYAN, 1);
x = CELL_X + (CELL_WIDTH - x)/2;
PrintMiniMini(&x, &y, "December", 0, TEXT_COLOR_CYAN, 0);

What exactly is this code supposed to do? The example is used to draw the text "December" center-aligned in a cell located at CELL_X,CELL_Y.

int x = 0;
int y = CELL_Y;

The X value is set to 0 because the add-in needs to find the width of the text "December". The Y value is set to our target CELL_Y since it will not change.

PrintMiniMini(&x, &y, "December", 0, TEXT_COLOR_CYAN, 1);

This function would normally print the text out at (x,y), except the last parameter is 1. This causes the function to only change the X and Y values, but doesn't draw.

x = CELL_X + (CELL_WIDTH - x)/2;
PrintMiniMini(&x, &y, "December", 0, TEXT_COLOR_CYAN, 0);

Here, the X value is assigned the corrected value. (Given that CELL_WIDTH is the width of the cell the text is drawn in). The PrintMiniMini function is called again with a 0 as the last parameter, so it now draws the text center-aligned in the cell.