add more low level drawing functions
This commit is contained in:
@@ -17,16 +17,64 @@
|
||||
#include "./fonts/zxpix_font.h"
|
||||
|
||||
LowLevelRenderer::LowLevelRenderer(uint8_t* buffer, int width, int height)
|
||||
: bit_buffer(buffer), V_WIDTH(width), V_HEIGHT(height), current_font(&font_acme_5_outlines) {}
|
||||
: bit_buffer(buffer), V_WIDTH(width), V_HEIGHT(height), current_font(&font_acme_5_outlines),
|
||||
clipping_enabled(false), clip_x(0), clip_y(0), clip_width(width), clip_height(height) {}
|
||||
|
||||
void LowLevelRenderer::set_font(const unsigned char (*font)[96][6]) {
|
||||
current_font = font;
|
||||
}
|
||||
|
||||
// Clipping functions
|
||||
void LowLevelRenderer::set_clip_rect(int x, int y, int width, int height) {
|
||||
clip_x = x;
|
||||
clip_y = y;
|
||||
clip_width = width;
|
||||
clip_height = height;
|
||||
clipping_enabled = true;
|
||||
}
|
||||
|
||||
void LowLevelRenderer::reset_clip_rect() {
|
||||
clipping_enabled = false;
|
||||
clip_x = 0;
|
||||
clip_y = 0;
|
||||
clip_width = V_WIDTH;
|
||||
clip_height = V_HEIGHT;
|
||||
}
|
||||
|
||||
bool LowLevelRenderer::is_clipping_enabled() const {
|
||||
return clipping_enabled;
|
||||
}
|
||||
|
||||
bool LowLevelRenderer::is_point_in_clip_rect(int x, int y) {
|
||||
if (!clipping_enabled) return true;
|
||||
return (x >= clip_x && x < clip_x + clip_width &&
|
||||
y >= clip_y && y < clip_y + clip_height);
|
||||
}
|
||||
|
||||
// Buffer operations
|
||||
void LowLevelRenderer::invert_buffer() {
|
||||
int buffer_size = (V_WIDTH * V_HEIGHT + 7) / 8; // Round up for bit buffer size
|
||||
for (int i = 0; i < buffer_size; ++i) {
|
||||
bit_buffer[i] = ~bit_buffer[i]; // Bitwise NOT to invert all bits
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelRenderer::clear_buffer() {
|
||||
int buffer_size = (V_WIDTH * V_HEIGHT + 7) / 8;
|
||||
for (int i = 0; i < buffer_size; ++i) {
|
||||
bit_buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelRenderer::set_pixel(int x, int y, bool on)
|
||||
{
|
||||
if (x < 0 || x >= V_WIDTH || y < 0 || y >= V_HEIGHT)
|
||||
return;
|
||||
|
||||
// Check clipping
|
||||
if (!is_point_in_clip_rect(x, y))
|
||||
return;
|
||||
|
||||
int bit_pos = y * V_WIDTH + x;
|
||||
if (on)
|
||||
bit_buffer[bit_pos / 8] |= (1 << (7 - (bit_pos % 8)));
|
||||
|
||||
@@ -33,9 +33,12 @@ private:
|
||||
int V_WIDTH;
|
||||
int V_HEIGHT;
|
||||
const unsigned char (*current_font)[96][6];
|
||||
bool clipping_enabled;
|
||||
int clip_x, clip_y, clip_width, clip_height;
|
||||
void draw_corner_arc(int center_x, int center_y, int radius, int quadrant, bool on);
|
||||
void fill_bottom_flat_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
|
||||
void fill_top_flat_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
|
||||
bool is_point_in_clip_rect(int x, int y);
|
||||
|
||||
public:
|
||||
LowLevelRenderer(uint8_t* buffer, int width, int height);
|
||||
@@ -56,6 +59,16 @@ public:
|
||||
void draw_polygon(const std::vector<std::pair<int, int>>& points, bool on);
|
||||
void draw_filled_polygon(const std::vector<std::pair<int, int>>& points, bool on);
|
||||
void draw_arc(int center_x, int center_y, int radius, int start_angle, int end_angle, bool on);
|
||||
|
||||
// Clipping functions
|
||||
void set_clip_rect(int x, int y, int width, int height);
|
||||
void reset_clip_rect();
|
||||
bool is_clipping_enabled() const;
|
||||
|
||||
// Buffer operations
|
||||
void invert_buffer();
|
||||
void clear_buffer();
|
||||
|
||||
void draw_circle(int x, int y, int radius, bool on);
|
||||
void draw_filled_circle(int x, int y, int radius, bool on);
|
||||
void draw_char_vcol(int x, int y, char c);
|
||||
|
||||
16
main.cpp
16
main.cpp
@@ -36,6 +36,7 @@ int main()
|
||||
|
||||
sf::Clock clock;
|
||||
bool toggle = false;
|
||||
bool inverted = false;
|
||||
|
||||
while (window.isOpen())
|
||||
{
|
||||
@@ -87,6 +88,14 @@ int main()
|
||||
{
|
||||
clock.restart();
|
||||
toggle = !toggle; // Change something every half second
|
||||
|
||||
// Invert display every 4 seconds (8 cycles)
|
||||
static int cycle_count = 0;
|
||||
cycle_count++;
|
||||
if (cycle_count % 8 == 0) {
|
||||
renderer.invert_buffer();
|
||||
inverted = !inverted;
|
||||
}
|
||||
|
||||
// Clear buffer
|
||||
for (int i = 0; i < sizeof(bit_buffer); i++)
|
||||
@@ -131,9 +140,14 @@ int main()
|
||||
renderer.draw_line(10, 200, 90, 250, true);
|
||||
renderer.draw_line(110, 200, 190, 250, true);
|
||||
|
||||
// Demonstrate clipping - draw a circle that gets clipped
|
||||
renderer.set_clip_rect(300, 200, 80, 60); // Small rectangle in bottom-right
|
||||
renderer.draw_filled_circle(340, 230, 40, true); // Circle that extends outside clip rect
|
||||
renderer.reset_clip_rect(); // Reset to full screen
|
||||
|
||||
// Text with different fonts
|
||||
renderer.set_font(&font_acme_5_outlines);
|
||||
renderer.draw_string_scaled(10, 10, "Drawing Demo", 2);
|
||||
renderer.draw_string_scaled(10, 10, inverted ? "INVERTED MODE" : "Drawing Demo", 2);
|
||||
|
||||
renderer.set_font(&font_5x5);
|
||||
renderer.draw_string_scaled(10, 270, command_buffer, 1);
|
||||
|
||||
Reference in New Issue
Block a user