// Simple demo of templates and method overloading in C++. // The draw_roman_numeral_ii function can be called with an // array_canvas and an int, an array_canvas and a “color”, or a // rect_counting_canvas and a “color”. // This is probably not the world’s best demo of templates and method // overloading, and it’s not really that well thought out. // Graphically, too, it’s unimpressive. #include typedef unsigned char color; static const int max_colors = 256; class palette_full { }; class array_canvas { int width, height; color *pixels; // This is stupid but if we were generating a GIF or in 1987 it // would be a sensible thing to do. int *palette; int palette_pointer; public: array_canvas(int width, int height) : width(width), height(height), pixels(new color[width * height]), palette(new int[max_colors]), palette_pointer(0) { } void draw_rect(int x, int y, int w, int h, color c) { for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { pixels[(y+i)*width + x+j] = c; } } } void draw_rect(int x, int y, int w, int h, int col) { draw_rect(x, y, w, h, allocate_color(col)); } color allocate_color(int col) { for (color i = 0; i < palette_pointer; i++) { if (col == palette[i]) return i; } if (palette_pointer == max_colors) { throw palette_full(); } palette[palette_pointer] = col; palette_pointer++; return (color)(palette_pointer-1); } void output_image(FILE *out) { // Generate PPM text format. fprintf(out, "P3\n%d %d\n%d\n", width, height, 255); for (int i = 0; i < palette_pointer; i++) { fprintf(out, "# palette[%d] = %d\n", i, palette[i]); } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int c = palette[pixels[i*width + j]]; int r = (c & 0xff0000) >> 16, g = (c & 0xff00) >> 8, b = c & 0xff; fprintf(out, "%s%d %d %d", j ? " " : "", r, g, b); } fprintf(out, "\n"); } } }; class rect_counting_canvas { int rects_drawn; int min_x, min_y, max_x, max_y; public: rect_counting_canvas() : rects_drawn(0), min_x(-1), min_y(-1), max_x(-1), max_y(-1) { } void draw_rect(int x, int y, int w, int h, color c) { rects_drawn++; if (min_x == -1 || x < min_x) min_x = x; if (max_x == -1 || x+w > max_x) max_x = x+w; if (min_y == -1 || y < min_y) min_y = y; if (max_y == -1 || y+h > max_y) max_y = y+h; } }; template void draw_roman_numeral_ii(canvas *cvs, int x, int y, int w, int h, col c) { cvs->draw_rect(x, y, w, h/3, c); cvs->draw_rect(x+w/5, y, w/5, h, c); cvs->draw_rect(x+3*w/5, y, w/5, h, c); cvs->draw_rect(x, y+2*h/3, w, h-2*h/3, c); } int main(int argc, char **argv) { array_canvas cvs(256, 256); cvs.draw_rect(0, 0, 256, 256, 0); draw_roman_numeral_ii(&cvs, 10, 10, 236, 236, 3780483); cvs.output_image(stdout); return 0; }