1 /* mfl.c - General parts of Minimal Font Library
2 *
3 * Copyright (C) 2000 Boris Gjenero
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License, version 2.1, as published by the Free Software Foundation
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * You may contact Boris Gjenero at bgjenero@sympatico.ca
19 */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <libvisual/libvisual.h>
25 #include "libmfl.h"
26
27 #undef MFL_TEST
28
29 struct mfl_font_s {
30 int height;
31 unsigned char *data;
32 };
33
34 struct mfl_context_s {
35 void *buf;
36
37 unsigned int bpp;
38 unsigned int width;
39 unsigned int height;
40 unsigned int bpl;
41
42 unsigned long color;
43 mfl_font font;
44 int opmode;
45 };
46
mfl_LoadRawFont(const char * fname)47 mfl_font mfl_LoadRawFont(const char *fname) {
48 mfl_font f = NULL;
49 unsigned long int l;
50 FILE *ff;
51
52 /* Open font file */
53 ff = fopen(fname, "rb");
54 if (ff == NULL) goto lrf_open_fault;
55
56 /* Get length of font file */
57 if (fseek(ff, 0, SEEK_END) != 0) goto lrf_fault;
58 l = ftell(ff);
59
60 /* Seek to start */
61 if (fseek(ff, 0, SEEK_SET) != 0) goto lrf_fault;
62
63 /* Determine font height */
64 if (l & 0xff) goto lrf_fault; /* Unknown length */
65
66 /* Allocate data, fill out structure */
67 f = malloc(sizeof(struct mfl_font_s));
68 f->height = l >> 8;
69 f->data = malloc(l);
70
71 /* Read font data */
72 if (fread(f->data, 1, l, ff) != l) {
73 free(f->data);
74 free(f);
75 f = NULL;
76 }
77
78 lrf_fault:
79 /* Close input file */
80 fclose(ff);
81
82 lrf_open_fault:
83 return f;
84 }
85
mfl_DestroyFont(mfl_font f)86 void mfl_DestroyFont(mfl_font f) {
87 visual_log_return_if_fail(f != NULL);
88 free(f->data);
89 free(f);
90 }
91
92
mfl_CreateContext(void * buf,unsigned int bpp,unsigned int bpl,unsigned int width,unsigned int height)93 mfl_context mfl_CreateContext(void *buf, unsigned int bpp,
94 unsigned int bpl, unsigned int width,
95 unsigned int height) {
96 mfl_context cx = malloc(sizeof(struct mfl_context_s));
97
98 cx->buf = buf;
99 cx->bpp = bpp;
100 cx->bpl = bpl;
101 cx->width = width;
102 cx->height = height;
103
104 cx->font = NULL;
105 cx->opmode = MFL_NORMAL;
106
107 return cx;
108 }
109
mfl_DestroyContext(mfl_context cx)110 void mfl_DestroyContext(mfl_context cx) {
111 free(cx);
112 }
113
mfl_SetTextColor(mfl_context cx,unsigned long c)114 void mfl_SetTextColor(mfl_context cx, unsigned long c) {
115 cx->color = c;
116 }
117
mfl_SetFont(mfl_context cx,mfl_font f)118 void mfl_SetFont(mfl_context cx, mfl_font f) {
119 cx->font = f;
120 }
121
mfl_SetDrawMode(mfl_context cx,int mode)122 void mfl_SetDrawMode(mfl_context cx, int mode) {
123 cx->opmode = mode;
124 }
125
mfl_GetTextWidthL(const mfl_context cx,const char * s,int l)126 inline unsigned int mfl_GetTextWidthL(const mfl_context cx,
127 const char *s, int l) {
128 return l * 8;
129 }
130
mfl_GetTextWidth(const mfl_context cx,const char * s)131 inline unsigned int mfl_GetTextWidth(const mfl_context cx, const char *s) {
132 return mfl_GetTextWidthL(cx, s, strlen(s));
133 }
134
mfl_OutChar8(const mfl_context cx,int x,int y,char c)135 void mfl_OutChar8(const mfl_context cx, int x, int y, char c) {
136 unsigned int i;
137 int rows;
138 unsigned char smask, j;
139 unsigned char *fp;
140 unsigned char *dp, *ndp;
141 unsigned char *dpe;
142
143 if (cx->font == NULL) return;
144
145 /* Setup pointers */
146 fp = cx->font->data + (cx->font->height * c);
147
148 if (y < 0) {
149 rows = cx->font->height + y;
150 fp -= y;
151 y = 0;
152 } else {
153 rows = cx->font->height;
154 }
155 if (y + rows >= cx->height) {
156 rows = cx->height - y;
157 }
158 if (rows <= 0) return;
159
160 smask = 0x80;
161 if (x < 0) {
162 smask >>= -x;
163 x = 0;
164 if (smask == 0) return;
165 }
166
167 dp = (unsigned char *)cx->buf + (y * cx->bpl) + x;
168
169 /* Do it */
170 for (i = 0; i < rows; i++) {
171 dpe = dp + (cx->width - x);
172 ndp = dp + cx->bpl;
173 for (j = smask; j > 0 && dp < dpe; j >>= 1) {
174 if (*fp & j) {
175 switch(cx->opmode) {
176 case MFL_XOR: *dp ^= cx->color; break;
177 case MFL_OR: *dp |= cx->color; break;
178 case MFL_SETALL: *dp = 0xff; break;
179 /* If we don't recognize the style, revert to normal */
180 default: *dp = cx->color; break;
181 }
182 }
183 dp++;
184 }
185 fp++;
186 dp = ndp;
187 }
188 }
189
mfl_OutText8L(const mfl_context cx,int x,int y,const char * s,int l)190 void mfl_OutText8L(const mfl_context cx, int x, int y, const char *s, int l) {
191 const char *esp = s + l;
192
193 while (s < esp) {
194 mfl_OutChar8(cx, x, y, *s);
195 s++;
196 x+=8;
197 }
198 }
199
mfl_OutText8(const mfl_context cx,int x,int y,const char * s)200 void mfl_OutText8(const mfl_context cx, int x, int y, const char *s) {
201 mfl_OutText8L(cx, x, y, s, strlen(s));
202 }
203
204 #ifdef MFL_TEST
main(int argc,char ** argv)205 main(int argc, char **argv) {
206 #define SCREEN_X 78
207 #define SCREEN_Y 22
208 #define SCREEN_BPL (SCREEN_X + 1)
209
210 mfl_font f;
211 mfl_context c;
212 int i;
213 int y;
214
215 char screen[SCREEN_BPL * SCREEN_Y + 1];
216
217 for (i = 0; i < SCREEN_Y; i++) {
218 visual_mem_set(&(screen[i * SCREEN_BPL]), '.', SCREEN_X);
219 screen[i * SCREEN_BPL + SCREEN_X] = '\n';
220 }
221 screen[SCREEN_BPL * SCREEN_Y] = 0;
222
223 f = mfl_LoadRawFont("deffont");
224 c = mfl_CreateContext(screen, 8, SCREEN_BPL, SCREEN_X, SCREEN_Y);
225 mfl_SetTextColor(c, '*');
226 mfl_SetFont(c, f);
227
228 y = 0;
229 for (i = 1; i < argc; i++) {
230 mfl_OutText8(c, i, y, argv[i]);
231 y += 16;
232 }
233
234 puts(screen);
235 }
236 #endif
237
238
239
240