1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-02 20:47:18 +03:00
iris/source/font.ccp
2012-09-26 19:03:36 +02:00

180 lines
5.4 KiB
COBOL

#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// source/font.ccp: Font manager.
// Copyright 2012 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#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 <unsigned *> (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 <Glyph **> (base + sizeof (int))
for unsigned i = 0; i < num_glyphs; ++i:
glyphs[i] = reinterpret_cast <Glyph *> (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 <char *> (0x20000000)
Iris::Font self = Iris::my_receiver.create_capability (0)
Iris::my_parent.provide_capability <Iris::Font> (self.copy ())
Iris::free_cap (self)
//display = Iris::my_parent.get_capability <Iris::Display> ()
Iris::Block font = Iris::my_parent.get_capability <Iris::Block> ()
load_font (font)
Iris::free_cap (font)
Iris::my_parent.init_done ()
//display_caps = display.map_fb (reinterpret_cast <unsigned> (fb))
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 <unsigned> (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