#pypp 0 // Iris: micro-kernel for a capability-based operating system. // source/font.ccp: Font manager. // Copyright 2012 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "devices.hh" #define screenw 320 #define screenh 240 struct Glyph: unsigned width, height, baseline unsigned data[1] static Iris::Display display static Iris::Caps caps, display_caps static unsigned slot, num_glyphs static unsigned long pages, base static Glyph **glyphs static char *fb static unsigned x, y static unsigned read_int (unsigned addr): return *reinterpret_cast (addr) static void load_font (Iris::Block font): unsigned long long size = font.get_size ().value () pages = (size + PAGE_SIZE - 1) >> PAGE_BITS caps = Iris::my_memory.create_caps (pages) slot = caps.use () for unsigned i = 0; i < size; i += PAGE_SIZE: Iris::Page page = Iris::Cap (slot, i >> PAGE_BITS) Iris::set_recv_arg (page) font.get_block (i) Iris::my_memory.map (page, base + i) num_glyphs = read_int (base) glyphs = reinterpret_cast (base + sizeof (int)) for unsigned i = 0; i < num_glyphs; ++i: glyphs[i] = reinterpret_cast (base + sizeof (int) + read_int (base + sizeof (int) + i * sizeof (int))) static void free_font (): for unsigned i = 0; i < pages; ++i: Iris::my_memory.destroy (Iris::Cap (slot, i)) Iris::my_memory.destroy (caps) Iris::free_slot (slot) static unsigned draw_char (char c, unsigned &w, unsigned &h): if c >= num_glyphs: c = num_glyphs - 1 Glyph *g = glyphs[c] w = g->width h = g->height for unsigned ty = 0; ty < h; ++ty: unsigned py = ty + y - g->baseline if py < 0 || py >= screenh: continue for unsigned tx = 0; tx < g->width; ++tx: unsigned px = tx + x if px < 0 || px >= screenw: continue unsigned p = g->data[ty * g->width + tx] unsigned red = unsigned (p) & 0xff unsigned green = unsigned (p >> 8) & 0xff unsigned blue = unsigned (p >> 16) & 0xff unsigned alpha = (unsigned (p >> 24) & 0xff) + 1 if alpha == 0x100: fb[(py * 320 + px) * 4 + 2] = red fb[(py * 320 + px) * 4 + 1] = green fb[(py * 320 + px) * 4 + 0] = blue else: unsigned unalpha = 256 - alpha fb[(py * 320 + px) * 4 + 2] = (fb[(py * 320 + px) * 4 + 2] * unalpha + red * alpha) >> 8 fb[(py * 320 + px) * 4 + 1] = (fb[(py * 320 + px) * 4 + 1] * unalpha + green * alpha) >> 8 fb[(py * 320 + px) * 4 + 0] = (fb[(py * 320 + px) * 4 + 0] * unalpha + blue * alpha) >> 8 return g->baseline static void get_size (char c, unsigned &w, unsigned &h, unsigned &b): if c >= num_glyphs: c = num_glyphs - 1 Glyph *g = glyphs[c] w = g->width h = g->height b = g->baseline Iris::Num start (): x = 0 y = 8 // Random address which is large enough to store a huge file. base = 0x40000000 fb = reinterpret_cast (0x20000000) Iris::Font self = Iris::my_receiver.create_capability (0) Iris::my_parent.provide_capability (self.copy ()) Iris::free_cap (self) Iris::Block font = Iris::my_parent.get_capability () load_font (font) Iris::free_cap (font) Iris::my_parent.init_done () bool have_display = false while true: Iris::wait () switch Iris::recv.data[0].l: case Iris::Font::SET_DISPLAY: Iris::Cap reply = Iris::get_reply () if have_display: Iris::free_cap (display) have_display = true display = Iris::get_arg () display_caps = display.map_fb (reinterpret_cast (fb)) reply.invoke () Iris::free_cap (reply) break case Iris::Font::LOAD_FONT: free_font () font = Iris::get_arg () load_font (font) Iris::free_cap (font) Iris::recv.reply.invoke () break case Iris::Font::SETUP: // TODO: interface needs to be defined. Iris::recv.reply.invoke () break case Iris::Font::AT: if Iris::recv.data[0].h & 1: x += Iris::recv.data[1].l if x > screenw: x = 0 y += 16 if y + 16 > screenh + 8: y = 8 else: x = Iris::recv.data[1].l if Iris::recv.data[0].h & 2: y += Iris::recv.data[1].h if y + 16 > screenh + 8: y = 8 else: y = Iris::recv.data[1].h Iris::recv.reply.invoke () break case Iris::Font::WRITE: Iris::Cap reply = Iris::get_reply () unsigned w, h unsigned b = draw_char (Iris::recv.data[1].l, w, h) x += w if x + w > screenw: x = 0 y += h if y + h > screenh + b: y = b reply.invoke () Iris::free_cap (reply) break case Iris::Font::GET_POS: Iris::recv.reply.invoke (x, y) break case Iris::Font::GET_SIZE: unsigned w, h, b get_size (Iris::recv.data[1].l, w, h, b) Iris::recv.reply.invoke (Iris::Num (b, h), w) break default: Iris::panic (0, "invalid operation type for lcd") break