Bluechip's Graphics Library Version 1.3
Introduction
============
Not only does this library offer full clipping algorithms to Rockbox screen IO
but it also offers speed improvements ...and news just in means that future
versions will offer even more speed improvements.
This library will grow. Discussion is already underway for full sprite and
possible even 3D handling routines ...watch this space.
Version Notes
=============
As of V1, this manual is thrown together, I will tidy it up as I go along.
Library Overview
================
The library offers two sets of functions: "Safe" and "Unsafe"
The Safe functions contain full clipping algorithms. However, this safety
comes at the expense of a little speed loss.
The Unsafe functions do not have any time penalty. However, this speed benefit
means that the programmer MUST NOT attempt to write data outside of the LCD
screen boundaries.
Although the Unsafe routines are a little faster than the Rockbox core code,
they are also liable to the same problems.
When your code is compiled for "SIMULATOR", the bc_gfx() library will trap any
calls to Unsafe routines and safety check them; if any errors occur, they will
be reported to the debug console. If any of these errors exist at the time you
compile for TARGET, it is fairly safe to say that your application will "kill"
Rockbox.
Application Header
==================
At the top of your code, you will need to include TWO header files.
These must also be added in a specific order.
The FIRST header to include is one of the bc_Font files. If you do not plan to
use any of the bc_gfx() character printing functions, you must still include a
bc_Font file ...for this purpose bc_Font_Null exists.
The SECOND header file is for the bc_gfx() library calls.
You may also prefix these header files with a number of program specific
switches, which modify the precise behaviour of the bc_gfx() functions within
your application. To use these switches you will also need to include the
bc_types header file (to define TRUE and FALSE.)
The following is a chunk of code for you to cut and paste into your
application. Place this code at the top of your application code and modify
any of the switches you desire.
/*****************************************************************************
* bc_gfx() Library - Application Header
* (c) BlueChip, Cyborg Systems 2004
* http://homepage.ntlworld.com/cyborgsystems
*****************************************************************************/
/***********************************************
* Define TRUE and FALSE for switches
***********************************************/
#include "lib/bc_types.h"
/***********************************************
* bc_CLSI() can be defined as a relatively
* small "macro" for speed or as a fully fledged
* function for code streamlining.
*
* The default is MACRO mode, for speed
***********************************************/
#define USE_CLSI_MACRO TRUE
/***********************************************
* When using the hyper-fast "Unsafe" drawing
* functions, the simulator will warn of
* coding/clipping errors.
* Clipping errors will NOT crash the simulator,
* but may crash a Jukebox.
* The simulator will display an error message
* to the debug console if coding errors cause a
* clipping-error to occur.
* It may sometimes be useful to disable these
* warnings during early development of your
* code.
*
* The default is to display warnings
***********************************************/
#define WARN_CLIP_ERROR TRUE
/***********************************************
* The simulator adds a slight pause to every
* bc_update() call so that abusive refreshes
* are obvious during simulation.
* It may be desirable to disable this pause.
*
* The default is Pause Enabled
***********************************************/
#define USE_SIM_PAUSE TRUE
/**************************************************************
* Choose Your Font
* bc_Font_Null
* bc_Font_9x9
* bc_Font_8x9_AudioBC
**************************************************************/
#include "lib/bc_Font_Null.h"
/***********************************************
* Now the main bc_gfx() library definitions
***********************************************/
#include "lib/bc_gfx.h"
Main Setup
==========
You will also need to place a single line of code in your main() procedure
to initialise the engine before you use it.
** Failure to do so will cause your application to crash **
The line is simply:
bc_gfx_init(api);
And is normally placed immediately after the line
rb = api;
...within the function plugin_start()
Screen Orientation
==================
The bc_gfx() routines all assume the 'origin' of the screen (i.e. point {0,0})
to be at the TOP LEFT of the LCD display area.
The display is LCD_WIDTH pixels wide (that's the 'x' coordinate),
those pixels being numbered 0 ... LCD_WIDTH-1
The display is LCD_HEIGHT pixels wide (that's the 'y' coordinate),
those pixels being numbered 0 ... LCD_HEIGHT-1
The Clip Region
===============
Attempting to draw off the LCD screen is considered to be data draw to the Clip
Region.
If an attempt is made to draw to the Clip Region, one of four things will
happen depending on the routine called and the compile scenario.
Functions which comprise of all lower-case letters (e.g. bc_show();) will be
safe under all circumstances.
Functions which contain the main function call in upper-case letters
(e.g. bc_SHOW();) will cause an error.
If you are compiling a Simulator Build, any errors will be reported.
If you are compiling a Target Build, errors will cause 'unknown' behaviour, and
most likely crash Rockbox.
In summary:
1. lower-case call; Simulator build -> safe
2. lower-case call; Target build -> safe
3. upper-case call; Simulator build -> error warnings to debug console
4. upper-case call; Target build -> errors may cause crashes
Application Programmers Interface (API)
=======================================
Startup
-------
bc_gfx_init(api)
This must be called before attempting to call any other functions.
Failure to do so will cause your application to crash
'api' is taken to be the first parameter passed to plugin_start()
Updating the Screen
-------------------
All writes are directed to a frame buffer, the actual LCD will not be updated
until you request it. This is because LCD updating is comparatively slow and
updating after every plot is just not viable.
bc_update()
Refresh the LCD display from the frame buffer.
When compiled for target, this routine uses the Rockbox update procedure in
IRAM for maximum speed.
During simulation, bc_gfx() will add a slight pause so that abusive calls
to update() will be apparent during development.
bc_updateR(x,y, width,height)
Refresh any rectangular area of the LCD display from the frame buffer.
'x' & 'y' specify the pixel coordinate of the top-left hand corner of
the area, and 'width' & 'height' should be self explanatory.
When compiled for target, this routine uses the Rockbox update procedure in
IRAM for maximum speed.
During simulation, bc_gfx() will add a slight pause so that abusive calls
to update() will be apparent during development.
Clearing the Screen
-------------------
bc_CLS(colour)
The 'colour' may be either "BLACK" or "WHITE"
bc_CLSI()
This will invert the entire screen.
This is normally defined as a macro for speed, but you may choose to use a
function if code streamlining is an issue. Simply add:
#define USE_CLSI_MACRO FALSE
...before the line
#include "lib/bc_gfx.h"
...in your Application Header.
Controlling Individual Pixels
-----------------------------
bc_plot(x,y, mode)
'x' & 'y' and the pixel coordinates of the pixel to be modified.
The 'mode' may be one of the following:
mDraw or mFill Set pixel to black
mClear or mEmpty Set pixel to white
mXOR or mInvert Invert pixel
bc_PLOT(x,y)
The pixel at coordinate {x,y} will be set to black.
This is a macro, and is VERY fast.
bc_UNPLOT(x,y)
The pixel at coordinate {x,y} will be set to white.
This is a macro, and is VERY fast.
bc_XPLOT(x,y)
The pixel at coordinate {x,y} will be inverted.
This is a macro, and is VERY fast.
Drawing Lines & Boxes
---------------------
bc_line(x1,y1, x2,y2, mode)
bc_LINE(x1,y1, x2,y2, mode)
Draw a line from coordinates {x1,y1} to {x2,y2}
The 'mode' may be one of the following:
mDraw or mFill Set pixel to black
mClear or mEmpty Set pixel to white
mXOR or mInvert Invert pixel
bc_box(x,y, width,height, mode)
bc_BOX(x,y, width,height, mode)
Draw a box whose top-left corner is a coordinates {x,y} and with the
specified height and width.
Not that a box draw from {0,0} with width=10 and height=20 will have it's
bottom right hand corner at coordinate {9,19}
The 'mode' may be one of the following:
mDraw Draw the outline of the box in black
mClear Draw the outline of the box in white
mXOR Invert each pixel in the outline of the box
mFill Fill the specified area with black
mEmpty Fill the specified area with white
mInvert Invert each pixel in the specified area
Displaying Characters and Strings
---------------------------------
This is currently only possible with bc_Font files.
bc_putc(x,y, char, mode)
bc_PUTC(x,y, char, mode)
Using the selected bc_Font, print the ASCII character 'char' with the
top-left pixel at screen coordinates {x,y}
The 'mode' may be one of the following:
mDraw 0 = no effect 1 = set pixel to black
mClear 0 = no effect 1 = set pixel to white
mXOR 0 = no effect 1 = invert pixel
mFill 0 = set pixel to white 1 = set pixel to black
mEmpty 0 = set pixel to white 1 = set pixel to white
mInvert 0 = set pixel to black 1 = set pixel to white
bc_puts(x,y, string, mode)
bc_PUTS(x,y, string, mode)
Using the selected bc_Font, print the ASCII string 'string' with the
top-left pixel of the first character at screen coordinates {x,y}
The 'mode' may be one of the following:
mDraw 0 = no effect 1 = set pixel to black
mClear 0 = no effect 1 = set pixel to white
mXOR 0 = no effect 1 = invert pixel
mFill 0 = set pixel to white 1 = set pixel to black
mEmpty 0 = set pixel to white 1 = set pixel to white
mInvert 0 = set pixel to black 1 = set pixel to white
Displaying Sprites
------------------
For further information on defining your own sprites see the section of this
manual entitled "Defining Your Own Sprites"
bc_show(sprite, x,y, width,height, stride, mode)
bc_SHOW(sprite, x,y, width,height, stride, mode)
'sprite' is a pointer to an array of (unsigned char) which contains the
graphical sprite data.
'x' & 'y' specify the pixel coordinate where the top-left corner of the
sprite data will be shown.
'width' & 'height' specify the width and height of the sprite data.
'stride' is the number of bits per line in the data. This must be a
multiple of 8. The standard formula to calculate the stride of the sprite
is: (((((int)width)+7)/8)*8)
The 'mode' may be one of the following:
mDraw 0 = no effect 1 = set pixel to black
mClear 0 = no effect 1 = set pixel to white
mXOR 0 = no effect 1 = invert pixel
mFill 0 = set pixel to white 1 = set pixel to black
mEmpty 0 = set pixel to white 1 = set pixel to white
mInvert 0 = set pixel to black 1 = set pixel to white
bc_showR(sprite,rotation, x,y, width,height, stride, mode)
Only square sprites can be rotated!
'rotation' is the amount to rotate the sprite by:
0,1,2,3 = none 90^, 180^ 270^ (Clockwise)
This function is currently just a quick "it works" function, and needs
more consideration for future development.
There is NO "unsafe" version of this new function ...yet.
Defining Your Own Sprites
-------------------------
A sprite is a block of data which defines how to manuipulate each individual
pixel within a given area.
I'm not going to try and describe this in English, here are two examples.
The first has a width which is a multiple of 8, the second does not.
Take note that 15/8 resolves to 1, not 1.875
If you have any questions, please ask.
Example 1:
width = 9
height = 9
stride = ((width+7)/8)*8 = ((15)/8)*8 = (1)*8 = 8
/* +--------+ */ {
/* | ###### | 0111 1110 */ 0x7E,
/* |########| 1111 1111 */ 0xFF,
/* |### ##| 1110 0011 */ 0xE3,
/* |### ###| 1110 0111 */ 0xE7,
/* |####### | 1111 1110 */ 0xFE,
/* |### ###| 1110 0111 */ 0xE7,
/* |### ##| 1110 0011 */ 0xE3,
/* |########| 1111 1111 */ 0xFF,
/* | ###### | 0111 1110 */ 0x7E,
/* +--------+ */ },
Example 2:
width = 9
height = 9
stride = ((width+7)/8)*8 = ((16)/8)*8 = (2)*8 = 16
/* +---------+ */ {
/* | ####### | 0111 1111 0(000 0000) */ 0x7F,0x00,
/* |#########| 1111 1111 1(000 0000) */ 0xFF,0x80,
/* |### ##| 1110 0001 1(000 0000) */ 0xE1,0x80,
/* |### ###| 1110 0011 1(000 0000) */ 0xE3,0x80,
/* |######## | 1111 1111 0(000 0000) */ 0xFF,0x00,
/* |### ###| 1110 0011 1(000 0000) */ 0xE3,0x80,
/* |### ##| 1110 0001 1(000 0000) */ 0xE1,0x80,
/* |#########| 1111 1111 1(000 0000) */ 0xFF,0x80,
/* | ####### | 0111 1111 0(000 0000) */ 0x7F,0x00,
/* +---------+ */ },
|