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