1 /**
2  ** buildaux.c ---- generate and store a rotated character for a font
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu]
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  **/
18 
19 #include "libgrx.h"
20 #include "allocate.h"
21 #include "arith.h"
22 #include "memfill.h"
23 
GrBuildAuxiliaryBitmap(GrFont * f,int chr,int dir,int ul)24 char far *GrBuildAuxiliaryBitmap(GrFont *f,int chr,int dir,int ul)
25 {
26 	unsigned int idx = (unsigned int)chr - f->h.minchar;
27 	unsigned int bpos,rbpos,size,rsize,w,h;
28 	int  boff,rboff,rbinc;
29 	char far *stdmap,far *cvtmap;
30 	if(idx >= f->h.numchars) return(NULL);
31 	stdmap = &f->bitmap[f->chrinfo[idx].offset];
32 	dir = (dir & 3) + ((ul && (f->h.ulheight > 0)) ? 4 : 0);
33 	if(dir == GR_TEXT_RIGHT) return(stdmap);
34 	if(f->auxoffs[--dir] != NULL) {
35 	    unsigned int offs = f->auxoffs[dir][idx];
36 	    if(offs > 0) return(&f->auxmap[offs - 1]);
37 	}
38 	else {
39 	    size = sizeof(f->auxoffs[0][0]) * f->h.numchars;
40 	    f->auxoffs[dir] = farmalloc(size);
41 	    if(f->auxoffs[dir] == NULL) return(NULL);
42 	    memzero(f->auxoffs[dir],size);
43 	}
44 	h     = f->h.height;
45 	w     = f->chrinfo[idx].width;
46 	size  = h * (boff  = (w + 7) & ~7);
47 	rsize = w * (rboff = (h + 7) & ~7);
48 	switch(dir) {
49 	  case (GR_TEXT_RIGHT - 1 + 4):
50 	    rboff = boff;
51 	    rsize = size;
52 	    rbpos = 0;
53 	    rbinc = 1;
54 	    break;
55 	  case (GR_TEXT_DOWN - 1):              /* downward */
56 	  case (GR_TEXT_DOWN - 1 + 4):
57 	    rbpos = h - 1;
58 	    rbinc = rboff;
59 	    rboff = -1;
60 	    break;
61 	  case (GR_TEXT_LEFT - 1):              /* upside down, right to left */
62 	  case (GR_TEXT_LEFT - 1 + 4):
63 	    rboff = boff;
64 	    rsize = size;
65 	    rbpos = rsize - rboff + w - 1;
66 	    rbinc = -1;
67 	    rboff = -rboff;
68 	    break;
69 	  case (GR_TEXT_UP - 1):                /* upward */
70 	  case (GR_TEXT_UP - 1 + 4):
71 	    rbpos = rsize - rboff;
72 	    rbinc = -rboff;
73 	    rboff = 1;
74 	    break;
75 	  default:
76 	    return(NULL);
77 	}
78 	if((rsize >>= 3) == 0) return(NULL);
79 	if(rsize > (f->auxsize - f->auxnext)) {
80 	    /* add space for 32 (average) characters */
81 	    unsigned int newsize = (((f->h.width + 7) >> 3) * f->h.height) << 6;
82 	    newsize = umax(newsize,(rsize << 2));
83 	    newsize = umin(newsize,((unsigned int)(-4) - f->auxsize));
84 	    newsize += f->auxsize;
85 	    if(rsize > (newsize - f->auxnext)) return(NULL);
86 	    cvtmap = farmalloc(newsize);
87 	    if(cvtmap == NULL) return(NULL);
88 	    if(f->auxsize > 0) {
89 		memcpy(cvtmap,f->auxmap,f->auxsize);
90 		farfree(f->auxmap);
91 	    }
92 	    f->auxmap  = cvtmap;
93 	    f->auxsize = newsize;
94 	}
95 	cvtmap = &f->auxmap[f->auxnext];
96 	f->auxoffs[dir][idx] = f->auxnext + 1;
97 	f->auxnext += rsize;
98 	memfill_b(cvtmap,0,rsize);
99 	for(h = bpos = 0; bpos < size; bpos += boff,rbpos += rboff,h++) {
100 	    unsigned int bp    = bpos;
101 	    unsigned int bptop = bpos + w;
102 	    unsigned int rbp   = rbpos;
103 	    unsigned int ulrow = ul && ((h - f->h.ulpos) < f->h.ulheight);
104 	    for( ; bp < bptop; bp++,rbp += rbinc) {
105 		if(stdmap[bp >> 3] & (0x80 >> (bp & 7)) || ulrow) {
106 		    cvtmap[rbp >> 3] |= (0x80 >> (rbp & 7));
107 		}
108 	    }
109 	}
110 	return(cvtmap);
111 }
112 
113