2
/******************************************************************************
3
* MODULE : glyph_shrink.cpp
4
* DESCRIPTION: shrinking glyphs for anti-aliasing
5
* COPYRIGHT : (C) 1999 Joris van der Hoeven
6
*******************************************************************************
7
* This software falls under the GNU general public license and comes WITHOUT
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
11
******************************************************************************/
13
#include "bitmap_font.hpp"
14
#include "renderer.hpp"
21
if (i <= (1 << l)) return l;
22
fatal_error ("too large shrinking factor", "shrink", "shrink.cpp");
23
return 0; // Because of bug in certain versions of g++
27
my_div (int a, int b) {
29
else return -((b-1-a)/b);
33
my_mod (int a, int b) {
35
else return b-1-((-1-a)%b);
39
my_norm (int a, int m) {
41
if (a<=(m>>1)) return a;
46
get_hor_shift (glyph gl, int xfactor, int tx) {
47
STACK_NEW_ARRAY (flag, bool, gl->width);
51
for (x=0; x<gl->width; x++) {
52
int max_count= 0, count=0, y;
53
for (y=0; y<gl->height; y++)
54
if (gl->get_1 (x,y)) count++;
56
max_count = max (max_count, count);
59
max_count= max (max_count, count);
60
flag[x]= (max_count>(gl->height>>1));
61
// if (flag[x]) cout << "*"; else cout << " ";
65
int first0=-1, first1=-1, last0=-1, last1=-1;
66
for (x=0; x<gl->width; x++)
68
if (first0<0) first0= x;
70
while ((x<gl->width) && flag[x]) x++;
71
if (first1<0) first1= x+ tx;
75
/* cout << first0 << ", " << first1 << ", "
76
<< last0 << ", " << last1 << "\n"; */
78
STACK_DELETE_ARRAY (flag);
80
if (first0==-1) return 0;
81
if (first0==last0) return my_mod (gl->xoff- first0, xfactor);
84
int d00= my_norm (last0- first0, xfactor);
85
int d01= my_norm (last1- first0, xfactor);
86
int d10= my_norm (last0- first1, xfactor);
87
int d11= my_norm (last1- first1, xfactor);
88
if ((d00<=d01) && (d00<=d10) && (d00<=d11)) { first= first0; last= last0; }
89
else if ((d01<=d10) && (d01<=d11)) { first= first0; last= last1; }
90
else if (d10<=d11) { first= first1; last= last0; }
91
else { first= first1; last= last1; }
93
int middle, rest= my_mod (last- first, xfactor);
94
if (rest <= (xfactor>>1)) middle= first+ (rest>>1);
95
else middle= first- ((xfactor-rest)>>1);
96
return my_mod (gl->xoff- middle, xfactor);
100
get_ver_shift (glyph gl, int yfactor, int ty) {
101
STACK_NEW_ARRAY (flag, bool, gl->height);
105
for (y=0; y<gl->height; y++) {
106
int max_count= 0, count=0, x;
107
for (x=0; x<gl->width; x++)
108
if (gl->get_1 (x,y)) count++;
110
max_count = max (max_count, count);
113
max_count= max (max_count, count);
114
flag[y]= (max_count>(gl->width>>1));
115
// if (flag[y]) cout << "*"; else cout << " ";
119
int first0=-1, first1=-1, last0=-1, last1=-1;
120
for (y=0; y<gl->height; y++)
122
if (first0<0) first0= y;
124
while ((y<gl->height) && flag[y]) y++;
125
if (first1<0) first1= y+ ty;
129
/* cout << first0 << ", " << first1 << ", "
130
<< last0 << ", " << last1 << "\n"; */
132
STACK_DELETE_ARRAY (flag);
134
if (first0==-1) return 0;
136
return my_mod (gl->height- gl->yoff- 1- first0, yfactor);
139
int d00= my_norm (last0- first0, yfactor);
140
int d01= my_norm (last1- first0, yfactor);
141
int d10= my_norm (last0- first1, yfactor);
142
int d11= my_norm (last1- first1, yfactor);
143
if ((d00<=d01) && (d00<=d10) && (d00<=d11)) { first= first0; last= last0; }
144
else if ((d01<=d10) && (d01<=d11)) { first= first0; last= last1; }
145
else if (d10<=d11) { first= first1; last= last0; }
146
else { first= first1; last= last1; }
148
int middle, rest= my_mod (last- first, yfactor);
149
if (rest <= (yfactor>>1)) middle= first+ (rest>>1);
150
else middle= first- ((yfactor-rest)>>1);
151
return my_mod (gl->height- gl->yoff- 1- middle, yfactor);
155
shrink (glyph gl, int xfactor, int yfactor,
156
int dx, int dy, int tx, int ty, SI& xo, SI& yo)
159
cout << "------------------------------------------------------------------------------\n";
160
cout << "Shift by " << dx << ", " << dy << "\n";
161
cout << "------------------------------------------------------------------------------\n\n";
165
int x1= dx- gl->xoff;
166
int x2= dx- gl->xoff+ gl->width+ tx;
167
int X1= my_div (x1, xfactor);
168
int X2= my_div (x2+xfactor-1, xfactor);
170
int y1= dy+ gl->yoff+ 1- gl->height;
171
int y2= dy+ gl->yoff+ 1+ ty;
172
int Y1= my_div (y1, yfactor);
173
int Y2= my_div (y2+yfactor-1, yfactor);
175
int frac_x= (dx- gl->xoff- X1*xfactor);
176
int frac_y= (dy+ gl->yoff- Y1*yfactor);
177
SI off_x = (((-X1) *xfactor+ dx)*PIXEL + ((tx*PIXEL)>>1))/xfactor;
178
SI off_y = (((Y2-1)*yfactor- dy)*PIXEL - ((ty*PIXEL)>>1))/yfactor;
181
int index, indey, entry;
182
int ww=(X2-X1)*xfactor, hh=(Y2-Y1)*yfactor;
183
STACK_NEW_ARRAY (bitmap, int, ww*hh);
184
for (i=0; i<ww*hh; i++) bitmap[i]=0;
185
for (y=0, index= ww*frac_y+ frac_x; y<gl->height; y++, index-=ww)
186
for (x=0; x<gl->width; x++)
188
for (j=0, indey=ww*ty; j<=ty; j++, indey-=ww) {
189
entry = index+indey+x;
190
for (i=0; i<=tx; i++, entry++)
194
int X, Y, sum, nr= xfactor*yfactor;
195
int new_depth= gl->depth+ log2i (nr);
196
if (new_depth > 8) new_depth= 8;
197
glyph CB (X2-X1, Y2-Y1, -X1, Y2-1, new_depth, gl->status);
198
for (Y=Y1; Y<Y2; Y++)
199
for (X=X1; X<X2; X++) {
201
indey= ((Y-Y1)*ww+ (X-X1))*xfactor;
202
for (j=0, index= indey; j<yfactor; j++, index+=ww)
203
for (i=0; i<xfactor; i++)
204
sum += bitmap[index+ i];
205
if (nr >= 64) sum= (64 * sum) / nr;
210
STACK_DELETE_ARRAY (bitmap);
212
// cout << CB << "\n";
217
shrink (glyph gl, int xfactor, int yfactor, SI& xo, SI& yo) {
218
if ((gl->width==0) || (gl->height==0))
219
fatal_error ("zero size character", "shrink", "glyph.cpp");
224
if ((gl->status==0) && (xfactor>1)) dx= get_hor_shift (gl, xfactor, tx);
225
// if ((gl->status==0) && (yfactor>1)) dy= get_ver_shift (gl, yfactor, ty);
227
glyph ret= shrink (gl, xfactor, yfactor, dx, dy, tx, ty, xo, yo);
228
if (ret->status != 0) {
229
if (ret->status&1) ret->adjust_top ();
230
if (ret->status&2) ret->adjust_bot ();