/* * fblib.c * * Adapted by Florian Klemenz for use in the fb_dash project * * Source and all credit goes to * http://raspberrycompote.blogspot.ie/2014/03/low-level-graphics-on-raspberry-pi-part_14.html * * Original work by J-P Rosti (a.k.a -rst- and 'Raspberry Compote') * * Licensed under the Creative Commons Attribution 3.0 Unported License * (http://creativecommons.org/licenses/by/3.0/deed.en_US) * * Distributed in the hope that this will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #include "fblib.h" // helper function to 'plot' a pixel in given color void put_pixel(char *fbp, int x, int y, int r, int g, int b) { // calculate the pixel's byte offset inside the buffer // note: x * 2 as every pixel is 2 consecutive bytes //unsigned int pix_offset = x * 2 + y * finfo.line_length; unsigned int pix_offset = x * 2 + y * (WIDTH * 2); // now this is about the same as 'fbp[pix_offset] = value' // but a bit more complicated for RGB565 //unsigned short c = ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); unsigned short c = ((r / 8) * 2048) + ((g / 4) * 32) + (b / 8); // write 'two bytes at once' *((unsigned short*)(fbp + pix_offset)) = c; } // helper function to draw a rectangle in given color void fill_rect(char *fbp, int x, int y, int w, int h, int r, int g, int b) { int cx, cy; for (cy = 0; cy < h; cy++) { for (cx = 0; cx < w; cx++) { put_pixel(fbp, x + cx, y + cy, r, g, b); } } } // helper function to draw a rectangle outline in given color void draw_rect(char *fbp, int x0, int y0, int w, int h, int r, int g, int b) { draw_line(fbp, x0, y0, x0 + w, y0, r, g, b); // top draw_line(fbp, x0, y0, x0, y0 + h, r, g, b); // left draw_line(fbp, x0, y0 + h, x0 + w, y0 + h, r, g, b); // bottom draw_line(fbp, x0 + w, y0, x0 + w, y0 + h, r, g, b); // right } // helper function to draw a circle outline in given color // (uses Bresenham's circle algorithm) void draw_circle(char *fbp, int x0, int y0, int radius, int r, int g, int b) { int x = radius; int y = 0; int radiusError = 1 - x; while(x >= y) { // top left put_pixel(fbp, -y + x0, -x + y0, r, g, b); // top right put_pixel(fbp, y + x0, -x + y0, r, g, b); // upper middle left put_pixel(fbp, -x + x0, -y + y0, r, g, b); // upper middle right put_pixel(fbp, x + x0, -y + y0, r, g, b); // lower middle left put_pixel(fbp, -x + x0, y + y0, r, g, b); // lower middle right put_pixel(fbp, x + x0, y + y0, r, g, b); // bottom left put_pixel(fbp, -y + x0, x + y0, r, g, b); // bottom right put_pixel(fbp, y + x0, x + y0, r, g, b); y++; if (radiusError < 0) { radiusError += 2 * y + 1; } else { x--; radiusError+= 2 * (y - x + 1); } } } // helper function to draw a filled circle in given color // (uses Bresenham's circle algorithm) void fill_circle(char *fbp, int x0, int y0, int radius, int r, int g, int b) { int x = radius; int y = 0; int radiusError = 1 - x; while(x >= y) { // top draw_line(fbp, -y + x0, -x + y0, y + x0, -x + y0, r, g, b); // upper middle draw_line(fbp, -x + x0, -y + y0, x + x0, -y + y0, r, g, b); // lower middle draw_line(fbp, -x + x0, y + y0, x + x0, y + y0, r, g, b); // bottom draw_line(fbp, -y + x0, x + y0, y + x0, x + y0, r, g, b); y++; if (radiusError < 0) { radiusError += 2 * y + 1; } else { x--; radiusError+= 2 * (y - x + 1); } } } // helper function to clear the screen - fill whole // screen with given color void clear_screen(char *fbp) { //memset(fbp, 0, vinfo.xres * vinfo.yres * 2); // 16Bit = 8Bit * 2 memset(fbp, 0, WIDTH * HEIGHT * 2); // 16Bit = 8Bit * 2 } // helper function to draw a line in given color // (uses Bresenham's line algorithm) void draw_line(char *fbp, int x0, int y0, int x1, int y1, int r, int g, int b) { int dx = x1 - x0; dx = (dx >= 0) ? dx : -dx; // abs() int dy = y1 - y0; dy = (dy >= 0) ? dy : -dy; // abs() int sx; int sy; if (x0 < x1) sx = 1; else sx = -1; if (y0 < y1) sy = 1; else sy = -1; int err = dx - dy; int e2; int done = 0; while (!done) { put_pixel(fbp, x0, y0, r, g, b); if ((x0 == x1) && (y0 == y1)) done = 1; else { e2 = 2 * err; if (e2 > -dy) { err = err - dy; x0 = x0 + sx; } if (e2 < dx) { err = err + dx; y0 = y0 + sy; } } } } void render_string(char *fbp, fbfont font, char *text, int x, int y, int r, int g, int b) { int text_length = strlen(text); printf("text_length = %d\n", text_length); int bytes_per_line = ceil(font.width / 8.0); printf("bytes_per_line = %d\n", bytes_per_line); int char_offset = bytes_per_line * font.height; // each character for (int char_pos = 0; char_pos < text_length; char_pos++) { //int char_code = 0; int char_code = *(text + char_pos); int x_offset = char_pos * font.width + x; // each line of pixels for (int line = 0; line < font.height; line++) { int y_pos = line + y; // each byte in a line of pixels for (int byte_num = 0; byte_num < bytes_per_line; byte_num++) { int byte_offset = line * bytes_per_line + byte_num; char current_byte = *((font.xbm + char_code * char_offset) + byte_offset); // each bit/pixel in a byte for (int bit_number = 0; bit_number < 8; bit_number++) { char mask = 1 << bit_number; if(current_byte & mask) { // plot the pixel printf("x"); int x_pos = x_offset + byte_num * 8 + bit_number; put_pixel(fbp, x_pos, y_pos, 255, 255, 255); } else { // leave empty (or maybe plot 'text backgr color') printf(" "); } } // end "for bit_number" } // end "for byte_num" printf("\n"); } // end "for line" } // end "for char_pos" }