summaryrefslogtreecommitdiff
path: root/libraries/daguerre
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-07-27 16:57:39 -0400
committerBenji Dial <benji@benjidial.net>2024-07-27 16:57:39 -0400
commitfbfc078e9f44c1c1e95c9c484f1d5650bcf631b7 (patch)
treecab539c8cbbac81d895b6f8be695f3f53bf8f4d5 /libraries/daguerre
parent9af5588c30c4126a2800aae1afcb0de2c373dc6c (diff)
downloadhilbert-os-fbfc078e9f44c1c1e95c9c484f1d5650bcf631b7.tar.gz
lots and lots of userspace stuff
Diffstat (limited to 'libraries/daguerre')
-rw-r--r--libraries/daguerre/include/daguerre.hpp209
-rw-r--r--libraries/daguerre/include/daguerre/fixed-font.hpp57
-rw-r--r--libraries/daguerre/include/daguerre/framebuffer.hpp9
-rw-r--r--libraries/daguerre/include/daguerre/general.hpp59
-rw-r--r--libraries/daguerre/include/daguerre/image.hpp118
-rw-r--r--libraries/daguerre/include/daguerre/impl/fixed-font.hpp59
-rw-r--r--libraries/daguerre/include/daguerre/impl/image.hpp217
-rw-r--r--libraries/daguerre/include/daguerre/ppm.hpp20
-rw-r--r--libraries/daguerre/include/daguerre/psf.hpp20
-rw-r--r--libraries/daguerre/makefile2
-rw-r--r--libraries/daguerre/source/daguerre.cpp110
-rw-r--r--libraries/daguerre/source/framebuffer.cpp12
-rw-r--r--libraries/daguerre/source/ppm.cpp60
-rw-r--r--libraries/daguerre/source/psf.cpp51
14 files changed, 683 insertions, 320 deletions
diff --git a/libraries/daguerre/include/daguerre.hpp b/libraries/daguerre/include/daguerre.hpp
deleted file mode 100644
index 9468826..0000000
--- a/libraries/daguerre/include/daguerre.hpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <stdint.h>
-#include <cstring>
-#include <cstdio>
-
-namespace daguerre {
-
- typedef uint32_t hilbert_color;
-
- struct rgb24 {
- uint8_t r;
- uint8_t g;
- uint8_t b;
- };
-
- template <class color_t>
- static inline void default_overlay(color_t &dest, const color_t &src) {
- dest = src;
- }
-
- static inline void default_overlay(hilbert_color &dest, const rgb24 &src) {
- dest = __euler_encode_color(src.r, src.g, src.b);
- }
-
- static inline void default_overlay(rgb24 &dest, const bool &src) {
- dest.r = src ? 255 : 0;
- dest.g = src ? 255 : 0;
- dest.b = src ? 255 : 0;
- }
-
- template <class color_t>
- class image {
-
- public:
- bool delete_buffer_on_destruct;
- color_t *buffer;
- unsigned width;
- unsigned height;
- unsigned pitch;//in sizeof(color_t)
-
- image()
- : delete_buffer_on_destruct(false), buffer(0), width(0), height(0),
- pitch(0) {}
-
- image(unsigned width, unsigned height)
- : delete_buffer_on_destruct(true), buffer(new color_t[width * height]),
- width(width), height(height), pitch(width) {}
-
- image(
- color_t *buffer, unsigned width, unsigned height, unsigned pitch,
- bool delete_buffer_on_destruct)
- : delete_buffer_on_destruct(delete_buffer_on_destruct), buffer(buffer),
- width(width), height(height), pitch(pitch) {}
-
- ~image() {
- if (delete_buffer_on_destruct && buffer)
- delete[] buffer;
- }
-
- template <class other_color_t,
- void overlay(color_t &, const other_color_t &) = default_overlay>
- image(const image<other_color_t> &other)
- : delete_buffer_on_destruct(true),
- buffer(new color_t[other.width * other.height]), width(other.width),
- height(other.height), pitch(other.width) {
- overlay_from<other_color_t, overlay>(other, 0, 0, 0, 0, width, height);
- }
-
- image(image<color_t> &&other)
- : delete_buffer_on_destruct(other.delete_buffer_on_destruct),
- buffer(other.buffer), width(other.width), height(other.height),
- pitch(other.pitch) {
- other.buffer = 0;
- }
-
- template <class other_color_t,
- void overlay(color_t &, const other_color_t &) = default_overlay>
- image<color_t> &operator =(const image<other_color_t> &other) {
- if (delete_buffer_on_destruct && buffer)
- delete[] buffer;
- delete_buffer_on_destruct = true;
- width = other.width;
- height = other.height;
- pitch = width;
- buffer = new color_t[width * height];
- overlay_from<other_color_t, overlay>(other, 0, 0, 0, 0, width, height);
- return *this;
- }
-
- image<color_t> &operator =(image<color_t> &&other) {
- if (delete_buffer_on_destruct && buffer)
- delete[] buffer;
- delete_buffer_on_destruct = other.delete_buffer_on_destruct;
- buffer = other.buffer;
- width = other.width;
- height = other.height;
- pitch = other.pitch;
- other.buffer = 0;
- return *this;
- }
-
- color_t get(unsigned x, unsigned y) const {
- return buffer[y * pitch + x];
- }
-
- void set(unsigned x, unsigned y, const color_t &c) {
- buffer[y * pitch + x] = c;
- }
-
- void copy_from(
- const image<color_t> &other, unsigned to_x, unsigned to_y,
- unsigned from_x, unsigned from_y, unsigned width, unsigned height) {
-
- color_t *to_start = buffer + pitch * to_y + to_x;
- const color_t *from_start = other.buffer + other.pitch * from_y + from_x;
-
- for (unsigned y = 0; y < height; ++y)
- std::memcpy(
- to_start + pitch * y, from_start + other.pitch * y,
- width * sizeof(color_t));
-
- }
-
- template <class other_color_t,
- void overlay(color_t &, const other_color_t &) = default_overlay>
- void overlay_from(
- const image<other_color_t> &other, unsigned to_x, unsigned to_y,
- unsigned from_x, unsigned from_y, unsigned width, unsigned height) {
-
- color_t *to_start = buffer + pitch * to_y + to_x;
- const other_color_t *from_start =
- other.buffer + other.pitch * from_y + from_x;
-
- for (unsigned y = 0; y < height; ++y)
- for (unsigned x = 0; x < width; ++x)
- overlay(to_start[pitch * y + x], from_start[other.pitch * y + x]);
-
- }
-
- };
-
- template <class color_t>
- void swap(image<color_t> &a, image<color_t> &b) {
- std::swap(a.delete_buffer_on_destruct, b.delete_buffer_on_destruct);
- std::swap(a.buffer, b.buffer);
- std::swap(a.width, b.width);
- std::swap(a.height, b.height);
- std::swap(a.pitch, b.pitch);
- }
-
- image<hilbert_color> get_hilbert_framebuffer();
-
- bool try_load_ppm(std::FILE *input, image<rgb24> &into);
-
- static inline bool try_load_ppm(const char *path, image<rgb24> &into) {
- std::FILE *f = std::fopen(path, "r");
- if (!f)
- return false;
- bool success = try_load_ppm(f, into);
- std::fclose(f);
- return success;
- }
-
- //TODO: unicode
- template <class color_t>
- class fixed_bitmap_font {
-
- public:
- unsigned width;
- unsigned height;
- image<color_t> glyphs[128];
-
- template <class target_color_t,
- void overlay(target_color_t &dest, const color_t &src) = default_overlay>
- void overlay_text(
- image<target_color_t> &target, unsigned x,
- unsigned y, const char *text) const {
-
- while (1) {
- uint8_t ch = (uint8_t)*text;
- if (ch == 0)
- return;
- if (ch < 128) {
- target.template overlay_from<color_t, overlay>(
- glyphs[ch], x, y, 0, 0, width, height);
- x += width;
- }
- ++text;
- }
-
- }
-
- };
-
- bool try_load_psf(std::FILE *input, fixed_bitmap_font<bool> &into);
-
- static inline bool try_load_psf(
- const char *path, fixed_bitmap_font<bool> &into) {
- std::FILE *f = std::fopen(path, "r");
- if (!f)
- return false;
- bool success = try_load_psf(f, into);
- std::fclose(f);
- return success;
- }
-
-}
diff --git a/libraries/daguerre/include/daguerre/fixed-font.hpp b/libraries/daguerre/include/daguerre/fixed-font.hpp
new file mode 100644
index 0000000..471163a
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/fixed-font.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include <daguerre/general.hpp>
+
+//TODO: support more than just ascii
+
+namespace daguerre {
+
+ //forward declare since these depend on each other
+ template <class color_t>
+ class image;
+
+ template <class color_t>
+ class fixed_font {
+
+ public:
+ int glyph_width;
+ int glyph_height;
+ image<color_t> glyphs[128];
+
+ //initializes every glyph to an empty image
+ fixed_font();
+
+ //initializes each glyph to have the right dimensions and
+ //a valid buffer, but does nothing to their contents.
+ fixed_font(int glyph_width, int glyph_height);
+
+ //moves the other font's glyphs here, then
+ //sets the other font to have empty images.
+ fixed_font(fixed_font<color_t> &&other);
+
+ //moves the other font's glyphs here, then
+ //sets the other font to have empty images.
+ fixed_font<color_t> &operator =(fixed_font<color_t> &&other);
+
+ //use one of the two constructors below instead
+ fixed_font(const fixed_font<color_t> &other) = delete;
+
+ //copies the other font's images here, passing them through conversion.
+ template <class other_color_t>
+ fixed_font(const fixed_font<other_color_t> &other,
+ converter_t<color_t, other_color_t> *conversion = &default_conversion);
+
+ //directly calls memcpy on the images' buffers. the second argument
+ //does nothing except distinguish this from the other copy constructor.
+ fixed_font(const fixed_font<color_t> &other, bool);
+
+ //use copy constructor and move assignment instead
+ fixed_font<color_t> &operator =(const fixed_font<color_t> &other) = delete;
+
+ ~fixed_font() = default;
+
+ };
+
+}
+
+#include <daguerre/impl/fixed-font.hpp>
diff --git a/libraries/daguerre/include/daguerre/framebuffer.hpp b/libraries/daguerre/include/daguerre/framebuffer.hpp
new file mode 100644
index 0000000..c9a5226
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/framebuffer.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+
+namespace daguerre {
+
+ image<hilbert_color> get_hilbert_framebuffer();
+
+}
diff --git a/libraries/daguerre/include/daguerre/general.hpp b/libraries/daguerre/include/daguerre/general.hpp
new file mode 100644
index 0000000..78c6919
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/general.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <euler/syscall.hpp>
+#include <stdint.h>
+
+namespace daguerre {
+
+ typedef euler::syscall::encoded_color hilbert_color;
+
+ struct rgb24 {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ };
+
+ template <class dest_t, class src_t>
+ using converter_t = void (dest_t &, const src_t &);
+
+ //copies src to dest
+ template <class color_t>
+ static inline void default_conversion(color_t &dest, const color_t &src) {
+ dest = src;
+ }
+
+ //encodes src and copies that to dest
+ static inline void default_conversion(hilbert_color &dest, const rgb24 &src) {
+ dest = euler::syscall::encode_color(src.r, src.g, src.b);
+ }
+
+ template <class dest_t, class src_t, class param_t>
+ using param_converter_t = void (dest_t &, const src_t &, const param_t &);
+
+ //if src is true, copies param to dest.
+ //if src is false, does nothing.
+ template <class color_t>
+ static inline void default_conversion(
+ color_t &dest, const bool &src, const color_t &param) {
+ if (src)
+ dest = param;
+ }
+
+ //intersects [to, to + length) with [min, max) at stores the result in
+ //[to, to + length). if anything was removed from either end, the same
+ //amount is removed from the same end(s) of [from, from + length)
+ static inline void make_safe(
+ int &to, int &from, int &length, int min, int max) {
+
+ if (to < min) {
+ from += min - to;
+ length -= min - to;
+ to = min;
+ }
+
+ if (to + length > max)
+ length = max - to;
+
+ }
+
+}
diff --git a/libraries/daguerre/include/daguerre/image.hpp b/libraries/daguerre/include/daguerre/image.hpp
new file mode 100644
index 0000000..4c44dd0
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/image.hpp
@@ -0,0 +1,118 @@
+#pragma once
+
+#include <daguerre/general.hpp>
+
+namespace daguerre {
+
+ //forward declare since these depend on each other
+ template <class color_t>
+ class fixed_font;
+
+ template <class color_t>
+ class image {
+
+ public:
+ bool delete_buffer_on_destruct;
+ int width;
+ int height;
+ color_t *buffer;
+ int buffer_pitch;//in sizeof(color_t)
+
+ //makes empty image
+ image();
+
+ //make image with specified dimensions, contents uninitialized
+ image(int width, int height);
+
+ //make image with specified dimensions and buffer
+ image(
+ int width, int height, color_t *buffer,
+ int buffer_pitch, bool delete_buffer_on_destruct);
+
+ //moves the other image's data here, and
+ //then sets the other image to an empty one.
+ image(image<color_t> &&other);
+
+ //moves the other image's data here, and
+ //then sets the other image to an empty one.
+ image<color_t> &operator =(image<color_t> &&other);
+
+ //use one of the two constructors below instead
+ image(const image<color_t> &other) = delete;
+
+ //copies the other image's data here, passing it through conversion
+ template <class other_color_t>
+ image(const image<other_color_t> &other,
+ converter_t<color_t, other_color_t> *conversion = &default_conversion);
+
+ //directly calls memcpy on the buffer. the second argument does
+ //nothing except distinguish this from the other copy constructor.
+ image(const image<color_t> &other, bool);
+
+ //use copy constructor and move assignment instead
+ image<color_t> &operator =(const image<color_t> &other) = delete;
+
+ ~image();
+
+ void fill(const color_t &color);
+
+ //does not check bounds
+ color_t &at(int x, int y);
+
+ //does not check bounds
+ const color_t &at(int x, int y) const;
+
+ image<color_t> stretch(int new_width, int new_height);
+
+ //copies the region here via memcpy. does not check bounds.
+ void copy_from(
+ const image<color_t> &other, int to_x, int to_y,
+ int from_x, int from_y, int width, int height);
+
+ //copies the entire image here via memcpy. does not check bounds.
+ void copy_from(const image<color_t> &other, int to_x, int to_y);
+
+ //copies the region here through conversion. does not check bounds.
+ template <class other_color_t>
+ void convert_from(
+ const image<other_color_t> &other, int to_x, int to_y,
+ int from_x, int from_y, int width, int height,
+ converter_t<color_t, other_color_t> *conversion = &default_conversion);
+
+ //copies the entire image here through conversion. does not check bounds.
+ template <class other_color_t>
+ void convert_from(
+ const image<other_color_t> &other, int to_x, int to_y,
+ converter_t<color_t, other_color_t> *conversion = &default_conversion);
+
+ //copies the region here through conversion. does not check bounds.
+ template <class other_color_t, class param_t>
+ void convert_from(
+ const param_t &param, const image<other_color_t> &other, int to_x,
+ int to_y, int from_x, int from_y, int width, int height,
+ param_converter_t<color_t, other_color_t, param_t> *conversion =
+ &default_conversion);
+
+ //copies the entire image here through conversion. does not check bounds.
+ template <class other_color_t, class param_t>
+ void convert_from(const param_t &param,
+ const image<other_color_t> &other, int to_x, int to_y,
+ param_converter_t<color_t, other_color_t, param_t> *conversion =
+ &default_conversion);
+
+ //does not check bounds or wrap text
+ template <class font_color_t, class param_t>
+ void render_text(
+ const fixed_font<font_color_t> &font,
+ const param_t &pararm, int x, int y, const char *text,
+ param_converter_t<color_t, font_color_t, param_t> *conversion =
+ &default_conversion);
+
+ };
+
+ template <class color_t>
+ void swap(image<color_t> &a, image<color_t> &b);
+
+}
+
+#include <daguerre/impl/image.hpp>
diff --git a/libraries/daguerre/include/daguerre/impl/fixed-font.hpp b/libraries/daguerre/include/daguerre/impl/fixed-font.hpp
new file mode 100644
index 0000000..dbff798
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/impl/fixed-font.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+//this file should only be included from <daguerre/fixed-font.hpp>
+
+#include <daguerre/image.hpp>
+#include <utility>
+
+namespace daguerre {
+
+ template<class color_t>
+ fixed_font<color_t>::fixed_font() : glyph_width(0), glyph_height(0) {}
+
+ template <class color_t>
+ fixed_font<color_t>::fixed_font(int glyph_width, int glyph_height)
+ : glyph_width(glyph_width), glyph_height(glyph_height) {
+ for (int i = 0; i < 128; ++i)
+ glyphs[i] = image<color_t>(glyph_width, glyph_height);
+ }
+
+ template <class color_t>
+ fixed_font<color_t>::fixed_font(fixed_font<color_t> &&other)
+ : glyph_width(other.glyph_width), glyph_height(other.glyph_height) {
+ for (int i = 0; 0 < 128; ++i)
+ glyphs[i] = std::move(other.glyphs[i]);
+ other.glyph_width = 0;
+ other.glyph_height = 0;
+ }
+
+ template <class color_t>
+ fixed_font<color_t> &fixed_font<color_t>::operator =(
+ fixed_font<color_t> &&other) {
+ glyph_width = other.glyph_width;
+ glyph_height = other.glyph_height;
+ for (int i = 0; 0 < 128; ++i)
+ glyphs[i] = std::move(other.glyphs[i]);
+ other.glyph_width = 0;
+ other.glyph_height = 0;
+ }
+
+ template <class color_t>
+ template <class other_color_t>
+ fixed_font<color_t>::fixed_font(
+ const fixed_font<other_color_t> &other,
+ converter_t<color_t, other_color_t> *conversion)
+ : glyph_width(other.glyph_width), glyph_height(other.glyph_height) {
+ for (int i = 0; i < 128; ++i)
+ glyphs[i] = image<color_t>(other.glyphs[i], conversion);
+ }
+
+ template <class color_t>
+ fixed_font<color_t>::fixed_font(const fixed_font<color_t> &other, bool)
+ : glyph_width(other.glyph_width), glyph_height(other.glyph_height) {
+ for (int i = 0; i < 128; ++i)
+ glyphs[i] = image<color_t>(other.glyphs[i], true);
+ }
+
+}
+
+#include <daguerre/image.hpp>
diff --git a/libraries/daguerre/include/daguerre/impl/image.hpp b/libraries/daguerre/include/daguerre/impl/image.hpp
new file mode 100644
index 0000000..1264879
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/impl/image.hpp
@@ -0,0 +1,217 @@
+#pragma once
+
+//this file should only be included from <daguerre/image.hpp>
+
+#include <daguerre/fixed-font.hpp>
+#include <algorithm>
+#include <cstring>
+
+namespace daguerre {
+
+ template <class color_t>
+ image<color_t>::image()
+ : delete_buffer_on_destruct(false), width(0),
+ height(0), buffer(0), buffer_pitch(0) {}
+
+ template <class color_t>
+ image<color_t>::image(int width, int height)
+ : delete_buffer_on_destruct(true), width(width), height(height),
+ buffer(new color_t[width * height]), buffer_pitch(width) {}
+
+ template <class color_t>
+ image<color_t>::image(
+ int width, int height, color_t *buffer,
+ int buffer_pitch, bool delete_buffer_on_destruct)
+ : delete_buffer_on_destruct(delete_buffer_on_destruct), width(width),
+ height(height), buffer(buffer), buffer_pitch(buffer_pitch) {}
+
+ template <class color_t>
+ image<color_t>::image(image<color_t> &&other)
+ : delete_buffer_on_destruct(other.delete_buffer_on_destruct),
+ width(other.width), height(other.height), buffer(other.buffer),
+ buffer_pitch(other.buffer_pitch) {
+
+ other.width = 0;
+ other.height = 0;
+ other.buffer = 0;
+
+ }
+
+ template<class color_t>
+ image<color_t> &image<color_t>::operator =(image<color_t> &&other) {
+
+ if (delete_buffer_on_destruct && buffer)
+ delete[] buffer;
+
+ delete_buffer_on_destruct = other.delete_buffer_on_destruct;
+ width = other.width;
+ height = other.height;
+ buffer = other.buffer;
+ buffer_pitch = other.buffer_pitch;
+
+ other.width = 0;
+ other.height = 0;
+ other.buffer = 0;
+
+ return *this;
+
+ }
+
+ template <class color_t>
+ template <class other_color_t>
+ image<color_t>::image(const image<other_color_t> &other,
+ converter_t<color_t, other_color_t> *conversion)
+ : delete_buffer_on_destruct(true), width(other.width),
+ height(other.height), buffer(new color_t[other.width * other.height]),
+ buffer_pitch(other.width) {
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ conversion(
+ buffer[y * buffer_pitch + x],
+ other.buffer[y * other.buffer_pitch + x]);
+
+ }
+
+ template <class color_t>
+ image<color_t>::image(const image<color_t> &other, bool)
+ : delete_buffer_on_destruct(true), width(width), height(other.height),
+ buffer(new color_t[other.width * other.height]),
+ buffer_pitch(other.width) {
+
+ if (buffer_pitch == other.buffer_pitch)
+ memcpy(buffer, other.buffer, (height - 1) * buffer_pitch + width);
+
+ else
+ for (int y = 0; y < height; ++y)
+ memcpy(buffer + y * buffer_pitch,
+ other.buffer + y * other.buffer_pitch,
+ sizeof(color_t) * width);
+
+ }
+
+ template <class color_t>
+ image<color_t>::~image() {
+ if (delete_buffer_on_destruct && buffer)
+ delete[] buffer;
+ }
+
+ template <class color_t>
+ void image<color_t>::fill(const color_t &color) {
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ buffer[y * buffer_pitch + x] = color;
+ }
+
+ template <class color_t>
+ color_t &image<color_t>::at(int x, int y) {
+ return buffer[y * buffer_pitch + x];
+ }
+
+ template <class color_t>
+ const color_t &image<color_t>::at(int x, int y) const {
+ return buffer[y * buffer_pitch + x];
+ }
+
+ template <class color_t>
+ image<color_t> image<color_t>::stretch(int new_width, int new_height) {
+ image<color_t> im(new_width, new_height);
+ for (int y = 0; y < new_height; ++y)
+ for (int x = 0; x < new_width; ++x)
+ im.at(x, y) = at(x * width / new_width, y * height / new_height);
+ return im;
+ }
+
+ template <class color_t>
+ void image<color_t>::copy_from(
+ const image<color_t> &other, int to_x, int to_y,
+ int from_x, int from_y, int width, int height) {
+
+ color_t *to = buffer + to_y * buffer_pitch + to_x;
+ const color_t *from = other.buffer + from_y * other.buffer_pitch + from_x;
+
+ for (int y = 0; y < height; ++y)
+ memcpy(
+ to + y * buffer_pitch,
+ from + y * other.buffer_pitch,
+ width * sizeof(color_t));
+
+ }
+
+ template <class color_t>
+ void image<color_t>::copy_from(
+ const image<color_t> &other, int to_x, int to_y) {
+ copy_from(other, to_x, to_y, 0, 0, other.width, other.height);
+ }
+
+ template <class color_t>
+ template <class other_color_t>
+ void image<color_t>::convert_from(
+ const image<other_color_t> &other, int to_x, int to_y,
+ int from_x, int from_y, int width, int height,
+ converter_t<color_t, other_color_t> *conversion) {
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ conversion(at(to_x + x, to_y + y), other.at(from_x + x, from_y + y));
+
+ }
+
+ template <class color_t>
+ template <class other_color_t>
+ void image<color_t>::convert_from(
+ const image<other_color_t> &other, int to_x, int to_y,
+ converter_t<color_t, other_color_t> *conversion) {
+ convert_from(other, to_x, to_y, 0, 0, other.width, other.y, conversion);
+ }
+
+ template <class color_t>
+ template <class other_color_t, class param_t>
+ void image<color_t>::convert_from(
+ const param_t &param, const image<other_color_t> &other, int to_x,
+ int to_y, int from_x, int from_y, int width, int height,
+ param_converter_t<color_t, other_color_t, param_t> *conversion) {
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ conversion(
+ at(to_x + x, to_y + y), other.at(from_x + x, from_y + y), param);
+
+ }
+
+ template <class color_t>
+ template <class other_color_t, class param_t>
+ void image<color_t>::convert_from(
+ const param_t &param, const image<other_color_t> &other, int to_x,
+ int to_y, param_converter_t<color_t, other_color_t, param_t> *conversion) {
+ convert_from(
+ param, other, to_x, to_y, 0, 0, other.width, other.y, conversion);
+ }
+
+ template <class color_t>
+ template <class font_color_t, class param_t>
+ void image<color_t>::render_text(
+ const fixed_font<font_color_t> &font,
+ const param_t &param, int x, int y, const char *text,
+ param_converter_t<color_t, font_color_t, param_t> *conversion) {
+
+ while (*text) {
+ int ch = *text;
+ if (ch >= 0 && ch < 128)
+ convert_from(param, font.glyphs[ch], x, y, conversion);
+ ++text;
+ x += font.glyph_width;
+ }
+
+ }
+
+ template <class color_t>
+ void swap(image<color_t> &a, image<color_t> &b) {
+ std::swap(a.delete_buffer_on_destruct, b.delete_buffer_on_destruct);
+ std::swap(a.width, b.width);
+ std::swap(a.height, b.height);
+ std::swap(a.buffer, b.buffer);
+ std::swap(a.buffer_pitch, b.buffer_pitch);
+ }
+
+}
diff --git a/libraries/daguerre/include/daguerre/ppm.hpp b/libraries/daguerre/include/daguerre/ppm.hpp
new file mode 100644
index 0000000..5249c98
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/ppm.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+#include <optional>
+#include <cstdio>
+
+namespace daguerre {
+
+ std::optional<image<rgb24>> try_load_ppm(FILE *input);
+
+ static inline std::optional<image<rgb24>> try_load_ppm(const char *path) {
+ FILE *f = fopen(path, "r");
+ if (!f)
+ return {};
+ auto result = try_load_ppm(f);
+ fclose(f);
+ return result;
+ }
+
+}
diff --git a/libraries/daguerre/include/daguerre/psf.hpp b/libraries/daguerre/include/daguerre/psf.hpp
new file mode 100644
index 0000000..e38cdc4
--- /dev/null
+++ b/libraries/daguerre/include/daguerre/psf.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <daguerre/fixed-font.hpp>
+#include <optional>
+#include <cstdio>
+
+namespace daguerre {
+
+ std::optional<fixed_font<bool>> try_load_psf(FILE *input);
+
+ static inline std::optional<fixed_font<bool>> try_load_psf(const char *path) {
+ FILE *f = fopen(path, "r");
+ if (!f)
+ return {};
+ auto result = try_load_psf(f);
+ fclose(f);
+ return result;
+ }
+
+}
diff --git a/libraries/daguerre/makefile b/libraries/daguerre/makefile
index 3505d35..f428193 100644
--- a/libraries/daguerre/makefile
+++ b/libraries/daguerre/makefile
@@ -1,5 +1,5 @@
SOURCES = \
- daguerre.cpp
+ framebuffer.cpp ppm.cpp psf.cpp
build/%.cpp.o: source/%.cpp
@mkdir -p $(@D)
diff --git a/libraries/daguerre/source/daguerre.cpp b/libraries/daguerre/source/daguerre.cpp
deleted file mode 100644
index 2f7fe4d..0000000
--- a/libraries/daguerre/source/daguerre.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <daguerre.hpp>
-
-namespace daguerre {
-
- image<hilbert_color> get_hilbert_framebuffer() {
- uint32_t width, height, pitch;
- hilbert_color *ptr = __euler_get_framebuffer(width, height, pitch);
- return image<hilbert_color>(ptr, width, height, pitch, false);
- }
-
- //TODO: make this more robust
- unsigned read_text_int(std::FILE *input) {
- unsigned n = 0;
- char ch;
- std::fread(&ch, 1, 1, input);
- if (ch == '#') {
- do
- std::fread(&ch, 1, 1, input);
- while (ch != '\n');
- std::fread(&ch, 1, 1, input);
- }
- do {
- n = n * 10 + ch - '0';
- std::fread(&ch, 1, 1, input);
- } while (ch >= '0' && ch <= '9');
- return n;
- }
-
- //only supports p6 format
- bool try_load_ppm(std::FILE *input, image<rgb24> &into) {
-
- char header[3];
- if (std::fread(header, 1, 3, input) != 3)
- return false;
-
- if (header[0] != 'P' || header[1] != '6' || header[2] != '\n')
- return false;
-
- unsigned width = read_text_int(input);
- unsigned height = read_text_int(input);
- unsigned max = read_text_int(input);
-
- into = image<rgb24>(width, height);
-
- for (unsigned y = 0; y < height; ++y)
- for (unsigned x = 0; x < width; ++x) {
- if (std::fread(&into.buffer[y * width + x].r, 1, 1, input) != 1)
- return false;
- if (std::fread(&into.buffer[y * width + x].g, 1, 1, input) != 1)
- return false;
- if (std::fread(&into.buffer[y * width + x].b, 1, 1, input) != 1)
- return false;
- }
-
- if (max != 255)
- for (unsigned v = 0; v < width * height; ++v) {
- into.buffer[v].r = ((uint16_t)into.buffer[v].r * 255) / max;
- into.buffer[v].g = ((uint16_t)into.buffer[v].g * 255) / max;
- into.buffer[v].b = ((uint16_t)into.buffer[v].b * 255) / max;
- }
-
- return true;
-
- }
-
- //assumes the font is in psf2 format, and has a unicode table
- bool try_load_psf(std::FILE *input, fixed_bitmap_font<bool> &into) {
-
- uint32_t header[8];
- if (std::fread(header, 4, 8, input) != 8)
- return false;
-
- const uint32_t glyphs_start = header[2];
- const uint32_t glyph_count = header[4];
- const uint32_t glyph_length = header[5];
- into.height = header[6];
- into.width = header[7];
-
- const uint32_t unicode_start = glyphs_start + glyph_count * glyph_length;
- std::fseek(input, unicode_start, SEEK_SET);
-
- uint32_t indices[128];
-
- for (uint32_t index = 0; index < glyph_count; ++index) {
- uint8_t ch;
- std::fread(&ch, 1, 1, input);
- if (ch < 128)
- indices[ch] = index;
- do
- std::fread(&ch, 1, 1, input);
- while (ch != 0xff);
- }
-
- for (uint8_t ch = 0; ch < 128; ++ch) {
- std::fseek(input, glyphs_start + glyph_length * indices[ch], SEEK_SET);
- into.glyphs[ch] = image<bool>(into.width, into.height);
- for (unsigned h = 0; h < into.height; ++h)
- for (unsigned wb = 0; wb < into.width; wb += 8) {
- uint8_t byte;
- std::fread(&byte, 1, 1, input);
- for (unsigned x = 0; x < 8 && wb + x < into.width; ++x)
- into.glyphs[ch].set(wb + x, h, (byte >> (7 - x)) & 1);
- }
- }
-
- return true;
-
- }
-
-}
diff --git a/libraries/daguerre/source/framebuffer.cpp b/libraries/daguerre/source/framebuffer.cpp
new file mode 100644
index 0000000..d4282ad
--- /dev/null
+++ b/libraries/daguerre/source/framebuffer.cpp
@@ -0,0 +1,12 @@
+#include <daguerre/framebuffer.hpp>
+
+namespace daguerre {
+
+ image<hilbert_color> get_hilbert_framebuffer() {
+ hilbert_color *ptr;
+ uint32_t width, height, pitch;
+ euler::syscall::get_framebuffer(ptr, width, height, pitch);
+ return image<hilbert_color>(width, height, ptr, pitch, false);
+ }
+
+}
diff --git a/libraries/daguerre/source/ppm.cpp b/libraries/daguerre/source/ppm.cpp
new file mode 100644
index 0000000..a4a7e27
--- /dev/null
+++ b/libraries/daguerre/source/ppm.cpp
@@ -0,0 +1,60 @@
+#include <daguerre/ppm.hpp>
+
+namespace daguerre {
+
+ //TODO: make this more robust
+ static unsigned read_text_int(FILE *input) {
+ unsigned n = 0;
+ char ch;
+ fread(&ch, 1, 1, input);
+ if (ch == '#') {
+ do
+ fread(&ch, 1, 1, input);
+ while (ch != '\n');
+ fread(&ch, 1, 1, input);
+ }
+ do {
+ n = n * 10 + ch - '0';
+ fread(&ch, 1, 1, input);
+ } while (ch >= '0' && ch <= '9');
+ return n;
+ }
+
+ //TODO: this only supports p6 format, and assumes max < 256
+ std::optional<image<rgb24>> try_load_ppm(FILE *input) {
+
+ char header[3];
+ if (fread(header, 1, 3, input) != 3)
+ return {};
+
+ if (header[0] != 'P' || header[1] != '6' || header[2] != '\n')
+ return {};
+
+ unsigned width = read_text_int(input);
+ unsigned height = read_text_int(input);
+ unsigned max = read_text_int(input);
+
+ image<rgb24> im(width, height);
+
+ for (unsigned y = 0; y < height; ++y)
+ for (unsigned x = 0; x < width; ++x) {
+ if (fread(&im.buffer[y * width + x].r, 1, 1, input) != 1)
+ return {};
+ if (fread(&im.buffer[y * width + x].g, 1, 1, input) != 1)
+ return {};
+ if (fread(&im.buffer[y * width + x].b, 1, 1, input) != 1)
+ return {};
+ }
+
+ if (max != 255)
+ for (unsigned v = 0; v < width * height; ++v) {
+ im.buffer[v].r = ((uint16_t)im.buffer[v].r * 255) / max;
+ im.buffer[v].g = ((uint16_t)im.buffer[v].g * 255) / max;
+ im.buffer[v].b = ((uint16_t)im.buffer[v].b * 255) / max;
+ }
+
+ return im;
+
+ }
+
+}
diff --git a/libraries/daguerre/source/psf.cpp b/libraries/daguerre/source/psf.cpp
new file mode 100644
index 0000000..81f722a
--- /dev/null
+++ b/libraries/daguerre/source/psf.cpp
@@ -0,0 +1,51 @@
+#include <daguerre/psf.hpp>
+
+namespace daguerre {
+
+ //TODO: this assumes the font is in psf2 format, and has a unicode table
+ std::optional<fixed_font<bool>> try_load_psf(FILE *input) {
+
+ uint32_t header[8];
+ if (fread(header, 4, 8, input) != 8)
+ return {};
+
+ const uint32_t glyphs_start = header[2];
+ const uint32_t glyph_count = header[4];
+ const uint32_t glyph_length = header[5];
+ const uint32_t height = header[6];
+ const uint32_t width = header[7];
+
+ fixed_font<bool> font(width, height);
+
+ const uint32_t unicode_start = glyphs_start + glyph_count * glyph_length;
+ fseek(input, unicode_start, SEEK_SET);
+
+ uint32_t indices[128];
+
+ for (uint32_t index = 0; index < glyph_count; ++index) {
+ uint8_t ch;
+ fread(&ch, 1, 1, input);
+ if (ch < 128)
+ indices[ch] = index;
+ do
+ if (fread(&ch, 1, 1, input) != 1)
+ return {};
+ while (ch != 0xff);
+ }
+
+ for (uint8_t ch = 0; ch < 128; ++ch) {
+ fseek(input, glyphs_start + glyph_length * indices[ch], SEEK_SET);
+ for (unsigned h = 0; h < height; ++h)
+ for (unsigned wb = 0; wb < width; wb += 8) {
+ uint8_t byte;
+ fread(&byte, 1, 1, input);
+ for (unsigned x = 0; x < 8 && wb + x < width; ++x)
+ font.glyphs[ch].at(wb + x, h) = (byte >> (7 - x)) & 1;
+ }
+ }
+
+ return font;
+
+ }
+
+}