Root/userspace/glue/font.ccp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// source/font.ccp: Font manager.
4// Copyright 2012 Bas Wijnen <wijnen@debian.org>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#include "devices.hh"
20
21#define screenw 320
22#define screenh 240
23
24struct Glyph:
25    unsigned width, height, baseline
26    unsigned data[1]
27
28static Iris::Display display
29static Iris::Caps caps, display_caps
30static unsigned slot, num_glyphs
31static unsigned long pages, base
32static Glyph **glyphs
33static char *fb
34static unsigned x, y
35
36static unsigned read_int (unsigned addr):
37    return *reinterpret_cast <unsigned *> (addr)
38
39static void load_font (Iris::Block font):
40    unsigned long long size = font.get_size ().value ()
41    pages = (size + PAGE_SIZE - 1) >> PAGE_BITS
42    caps = Iris::my_memory.create_caps (pages)
43    slot = caps.use ()
44    for unsigned i = 0; i < size; i += PAGE_SIZE:
45        Iris::Page page = Iris::Cap (slot, i >> PAGE_BITS)
46        Iris::set_recv_arg (page)
47        font.get_block (i)
48        Iris::my_memory.map (page, base + i)
49    num_glyphs = read_int (base)
50    glyphs = reinterpret_cast <Glyph **> (base + sizeof (int))
51    for unsigned i = 0; i < num_glyphs; ++i:
52        glyphs[i] = reinterpret_cast <Glyph *> (base + sizeof (int) + read_int (base + sizeof (int) + i * sizeof (int)))
53
54static void free_font ():
55    for unsigned i = 0; i < pages; ++i:
56        Iris::my_memory.destroy (Iris::Cap (slot, i))
57    Iris::my_memory.destroy (caps)
58    Iris::free_slot (slot)
59
60static unsigned draw_char (char c, unsigned &w, unsigned &h):
61    if c >= num_glyphs:
62        c = num_glyphs - 1
63    Glyph *g = glyphs[c]
64    w = g->width
65    h = g->height
66    for unsigned ty = 0; ty < h; ++ty:
67        unsigned py = ty + y - g->baseline
68        if py < 0 || py >= screenh:
69            continue
70        for unsigned tx = 0; tx < g->width; ++tx:
71            unsigned px = tx + x
72            if px < 0 || px >= screenw:
73                continue
74            unsigned p = g->data[ty * g->width + tx]
75            unsigned red = unsigned (p) & 0xff
76            unsigned green = unsigned (p >> 8) & 0xff
77            unsigned blue = unsigned (p >> 16) & 0xff
78            unsigned alpha = (unsigned (p >> 24) & 0xff) + 1
79            if alpha == 0x100:
80                fb[(py * 320 + px) * 4 + 2] = red
81                fb[(py * 320 + px) * 4 + 1] = green
82                fb[(py * 320 + px) * 4 + 0] = blue
83            else:
84                unsigned unalpha = 256 - alpha
85                fb[(py * 320 + px) * 4 + 2] = (fb[(py * 320 + px) * 4 + 2] * unalpha + red * alpha) >> 8
86                fb[(py * 320 + px) * 4 + 1] = (fb[(py * 320 + px) * 4 + 1] * unalpha + green * alpha) >> 8
87                fb[(py * 320 + px) * 4 + 0] = (fb[(py * 320 + px) * 4 + 0] * unalpha + blue * alpha) >> 8
88    return g->baseline
89
90static void get_size (char c, unsigned &w, unsigned &h, unsigned &b):
91    if c >= num_glyphs:
92        c = num_glyphs - 1
93    Glyph *g = glyphs[c]
94    w = g->width
95    h = g->height
96    b = g->baseline
97
98Iris::Num start ():
99    x = 0
100    y = 8
101    // Random address which is large enough to store a huge file.
102    base = 0x40000000
103    fb = reinterpret_cast <char *> (0x20000000)
104    Iris::Font self = Iris::my_receiver.create_capability (0)
105    Iris::my_parent.provide_capability <Iris::Font> (self.copy ())
106    Iris::free_cap (self)
107    Iris::Block font = Iris::my_parent.get_capability <Iris::Block> ()
108    load_font (font)
109    Iris::free_cap (font)
110    Iris::my_parent.init_done ()
111    bool have_display = false
112    while true:
113        Iris::wait ()
114        switch Iris::recv.data[0].l:
115            case Iris::Font::SET_DISPLAY:
116                Iris::Cap reply = Iris::get_reply ()
117                if have_display:
118                    Iris::free_cap (display)
119                have_display = true
120                display = Iris::get_arg ()
121                display_caps = display.map_fb (reinterpret_cast <unsigned> (fb))
122                reply.invoke ()
123                Iris::free_cap (reply)
124                break
125            case Iris::Font::LOAD_FONT:
126                free_font ()
127                font = Iris::get_arg ()
128                load_font (font)
129                Iris::free_cap (font)
130                Iris::recv.reply.invoke ()
131                break
132            case Iris::Font::SETUP:
133                // TODO: interface needs to be defined.
134                Iris::recv.reply.invoke ()
135                break
136            case Iris::Font::AT:
137                if Iris::recv.data[0].h & 1:
138                    x += Iris::recv.data[1].l
139                    if x > screenw:
140                        x = 0
141                        y += 16
142                        if y + 16 > screenh + 8:
143                            y = 8
144                else:
145                    x = Iris::recv.data[1].l
146                if Iris::recv.data[0].h & 2:
147                    y += Iris::recv.data[1].h
148                    if y + 16 > screenh + 8:
149                        y = 8
150                else:
151                    y = Iris::recv.data[1].h
152                Iris::recv.reply.invoke ()
153                break
154            case Iris::Font::WRITE:
155                Iris::Cap reply = Iris::get_reply ()
156                unsigned w, h
157                unsigned b = draw_char (Iris::recv.data[1].l, w, h)
158                x += w
159                if x + w > screenw:
160                    x = 0
161                    y += h
162                    if y + h > screenh + b:
163                        y = b
164                reply.invoke ()
165                Iris::free_cap (reply)
166                break
167            case Iris::Font::GET_POS:
168                Iris::recv.reply.invoke (x, y)
169                break
170            case Iris::Font::GET_SIZE:
171                unsigned w, h, b
172                get_size (Iris::recv.data[1].l, w, h, b)
173                Iris::recv.reply.invoke (Iris::Num (b, h), w)
174                break
175            default:
176                Iris::panic (0, "invalid operation type for lcd")
177                break
178

Archive Download this file

Branches:
master



interactive