break out printing into separate class (-2,014 bytes)

- stated savings is for any graphics only programs
  not using the printing code at all
This commit is contained in:
Josh Goebel 2016-02-11 08:57:06 -05:00 committed by Scott Allen
parent 5042811cec
commit 390e5919dc
5 changed files with 128 additions and 70 deletions

View File

@ -155,14 +155,16 @@ const byte PROGMEM score [] = {
0x80, 0x81, 0x90,0x45, 0,91, 0,136, 0x80, 0x82, 0x90,0x45, 0x91,0x2D, 7,83, 0x80, 0x81, 0xf0};
Arduboy arduboy;
AbPrinter text(arduboy);
void setup()
{
arduboy.begin();
arduboy.setTextSize(4);
arduboy.setCursor(0,0);
arduboy.print("Music\nDemo");
text.setSize(4);
text.setCursor(0,0);
text.print("Music\nDemo");
arduboy.display();
}
@ -191,8 +193,8 @@ void loop ()
}
arduboy.clear();
arduboy.setCursor(x,y);
arduboy.print("Music\nDemo");
text.setCursor(x,y);
text.print("Music\nDemo");
arduboy.display();
// play the tune if we aren't already

View File

@ -9,14 +9,10 @@ Arduboy::Arduboy()
frameCount = 0;
nextFrameStart = 0;
post_render = false;
// init not necessary, will be reset after first use
// lastFrameStart
// lastFrameDurationMs
// font rendering
cursor_x = 0;
cursor_y = 0;
textsize = 1;
}
void Arduboy::start() // deprecated
@ -714,47 +710,6 @@ void Arduboy::drawChar
}
}
void Arduboy::setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
void Arduboy::setTextSize(uint8_t s)
{
// textsize must always be 1 or higher
textsize = max(1,s);
}
void Arduboy::setTextWrap(boolean w)
{
wrap = w;
}
size_t Arduboy::write(uint8_t c)
{
if (c == '\n')
{
cursor_y += textsize*8;
cursor_x = 0;
}
else if (c == '\r')
{
// skip em
}
else
{
drawChar(cursor_x, cursor_y, c, 1, 0, textsize);
cursor_x += textsize*6;
if (wrap && (cursor_x > (WIDTH - textsize*6)))
{
// calling ourselves recursively for 'newline' is
// 12 bytes smaller than doing the same math here
write('\n');
}
}
}
void Arduboy::display()
{
this->paintScreen(sBuffer);
@ -765,7 +720,6 @@ unsigned char* Arduboy::getBuffer()
return sBuffer;
}
boolean Arduboy::pressed(uint8_t buttons)
{
return (buttonsState() & buttons) == buttons;

View File

@ -2,6 +2,7 @@
#define Arduboy_h
#include "core/core.h"
#include "ab_printer.h"
#include <Print.h>
#include <limits.h>
@ -28,7 +29,8 @@
// compare temperature to 2.5 internal reference and _BV(MUX5)
#define ADC_TEMP (_BV(REFS0) | _BV(REFS1) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))
class Arduboy : public Print, public ArduboyCore
class Arduboy : public ArduboyCore
{
public:
Arduboy();
@ -156,24 +158,8 @@ public:
/// Draws an ASCII character at a point.
void drawChar(int16_t x, int16_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size);
/// Sets the location of the screen cursor.
void setCursor(int16_t x, int16_t y);
/// Set text size
/**
* As mentioned in drawChar(), individual ASCII characters are 6x8 pixels
* (5x7 with spacing on two edges). The size is a pixel multiplier,
* so a size of 2 means each character will be 12x16, etc.
*/
void setTextSize(uint8_t s);
/// Sets whether text will wrap at screen edges.
void setTextWrap(boolean w);
unsigned char* getBuffer();
/// Writes a single ASCII character to the screen.
virtual size_t write(uint8_t);
/// Seeds the random number generator with entropy from the temperature, voltage reading, and microseconds since boot.
/**
@ -216,7 +202,6 @@ protected:
unsigned char sBuffer[(HEIGHT*WIDTH)/8];
// Adafruit stuff
protected:
int16_t cursor_x;
int16_t cursor_y;

54
src/ab_printer.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "Arduboy.h"
#include "ab_printer.h"
#include "glcdfont.c"
AbPrinter::AbPrinter(Arduboy &ab)
{
arduboy = &ab;
// font rendering
cursor_x = 0;
cursor_y = 0;
size = 1;
}
size_t AbPrinter::write(uint8_t c)
{
if (c == '\n')
{
cursor_y += size*8;
cursor_x = 0;
}
else if (c == '\r')
{
// skip em
}
else
{
arduboy->drawChar(cursor_x, cursor_y, c, 1, 0, size);
cursor_x += size*6;
if (wrap && (cursor_x > (WIDTH - size*6)))
{
// calling ourselves recursively for 'newline' is
// 12 bytes smaller than doing the same math here
write('\n');
}
}
}
void AbPrinter::setCursor(int16_t x, int8_t y)
{
cursor_x = x;
cursor_y = y;
}
void AbPrinter::setSize(uint8_t s)
{
// size must always be 1 or higher
size = max(1,s);
}
void AbPrinter::setWrap(boolean w)
{
wrap = w;
}

63
src/ab_printer.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef AbPrinter_h
#define AbPrinter_h
#include <Arduino.h>
#include "Arduboy.h"
#include <Print.h>
class Arduboy;
/// Separate class to break out Print subclassing
/**
* This is necessary because C++ keeps a virtual function lookup table around
* for the virtual function "write" that the Print subclass requires. That
* single reference to the "write" function in the vtable means "write" will
* always be compiled and including in the final ouput (even if it's never
* actually used in your sketch) - which means it's dependencies are also
# included:
*
* - drawChar
* - font (256 bytes!)
* - drawRect (for large font 'pixels')
* - cursor_x, cursor_y, wrap_mode, etc.
*
* This quickly adds up to 1 to 2kb of wasted space that many graphics
* based games never take advantage of. By breaking printing out into a
* separate class we prevent this. If you need it use it, if not then it
* will get dropped by the compiler during building.
*
*/
class AbPrinter : public Print
{
public:
AbPrinter(Arduboy &ab);
/// Writes a single ASCII character to the screen.
virtual size_t write(uint8_t);
/// Sets the location of the screen cursor.
void setCursor(int16_t x, int8_t y);
/// Set text size
/**
* As mentioned in drawChar(), individual ASCII characters are 6x8 pixels
* (5x7 with spacing on two edges). The size is a pixel multiplier,
* so a size of 2 means each character will be 12x16, etc.
*/
void setSize(uint8_t s);
/// Sets whether text will wrap at screen edges.
void setWrap(boolean w);
private:
Arduboy *arduboy;
protected:
int16_t cursor_x;
int8_t cursor_y;
uint8_t size;
boolean wrap; // If set, 'wrap' text at right edge of display
};
#endif