OLD | NEW |
(Empty) | |
| 1 #include <u.h> |
| 2 #include <libc.h> |
| 3 #include <draw.h> |
| 4 #include <memdraw.h> |
| 5 #include "a.h" |
| 6 |
| 7 uchar pjw[] = { |
| 8 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, |
| 9 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 10 0x20, 0x20, 0x20, 0x20, 0x6b, 0x32, 0x20, 0x20, |
| 11 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 12 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 13 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, |
| 14 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 15 0x34, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 16 0x20, 0x20, 0x20, 0x20, 0x34, 0x38, 0x20, 0x20, |
| 17 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 18 0x34, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 19 0x20, 0x20, 0x20, 0x35, 0x34, 0x31, 0x20, 0x80, |
| 20 0xff, 0x20, 0x00, 0x08, 0x00, 0x82, 0xc0, 0x16, |
| 21 0x7f, 0x04, 0x06, 0x04, 0x00, 0x83, 0xfc, 0x01, |
| 22 0x04, 0x06, 0x04, 0x07, 0x04, 0x00, 0x83, 0xf1, |
| 23 0x00, 0x50, 0x11, 0x04, 0x18, 0x04, 0x00, 0x84, |
| 24 0xd4, 0x40, 0x48, 0x04, 0x05, 0x00, 0x07, 0x04, |
| 25 0x00, 0x87, 0xc1, 0x44, 0x11, 0x04, 0x51, 0xbf, |
| 26 0xff, 0xff, 0x04, 0x00, 0x87, 0x16, 0xfe, 0x81, |
| 27 0x01, 0x40, 0x5f, 0xff, 0xff, 0x04, 0x00, 0x87, |
| 28 0x5f, 0xff, 0xe4, 0x00, 0x40, 0x01, 0x1f, 0xff, |
| 29 0x00, 0x00, 0x88, 0xfd, 0x7f, 0xff, 0xfd, 0x11, |
| 30 0x11, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x80, 0xe5, |
| 31 0x00, 0x03, 0x84, 0x50, 0x04, 0x10, 0x42, 0xff, |
| 32 0x00, 0x00, 0x80, 0x97, 0x00, 0x03, 0x84, 0x51, |
| 33 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x80, 0x67, |
| 34 0x00, 0x03, 0x84, 0xc4, 0x40, 0x41, 0x11, 0x3f, |
| 35 0x00, 0x75, 0x80, 0x4f, 0x00, 0x0b, 0x84, 0xd0, |
| 36 0x40, 0x00, 0x11, 0x1b, 0x82, 0xff, 0xff, 0xf5, |
| 37 0x04, 0x40, 0x84, 0xf0, 0x00, 0x00, 0x04, 0x5f, |
| 38 0x82, 0xff, 0xff, 0xe1, 0x04, 0x40, 0x84, 0xf4, |
| 39 0x00, 0x00, 0x01, 0x5b, 0x00, 0x1e, 0x80, 0x2f, |
| 40 0x04, 0x9e, 0x83, 0x00, 0x00, 0x00, 0x17, 0x82, |
| 41 0xff, 0xff, 0x40, 0x04, 0x96, 0x84, 0xfe, 0x40, |
| 42 0x00, 0x00, 0x0f, 0x82, 0xff, 0xfd, 0x00, 0x08, |
| 43 0xa2, 0x00, 0x0b, 0x80, 0x5f, 0x8b, 0xff, 0xf9, |
| 44 0x00, 0xb5, 0x11, 0x5f, 0xff, 0xa5, 0x64, 0x00, |
| 45 0x00, 0x1f, 0x85, 0xff, 0xf4, 0x01, 0x0a, 0xf5, |
| 46 0x42, 0x04, 0x2e, 0x81, 0x00, 0x2b, 0x87, 0xff, |
| 47 0xf0, 0x01, 0x0f, 0xe4, 0x54, 0xf0, 0x3f, 0x00, |
| 48 0x23, 0x80, 0x1f, 0x88, 0xff, 0xe0, 0x00, 0x4e, |
| 49 0x00, 0x04, 0x00, 0x00, 0x14, 0x00, 0x0b, 0x85, |
| 50 0xff, 0xd0, 0x00, 0x4c, 0x50, 0x44, 0x04, 0x22, |
| 51 0x81, 0x00, 0x0b, 0x00, 0x0b, 0x82, 0x49, 0xa6, |
| 52 0x6c, 0x00, 0x76, 0x00, 0x17, 0x00, 0x7d, 0x88, |
| 53 0x5e, 0xd6, 0xf9, 0xf1, 0x51, 0x11, 0x00, 0x00, |
| 54 0x3f, 0x88, 0xff, 0xf1, 0x02, 0x2e, 0xff, 0xf3, |
| 55 0xf4, 0x6a, 0x98, 0x00, 0x0b, 0x8b, 0xff, 0xf3, |
| 56 0x06, 0x2f, 0xff, 0xeb, 0xf8, 0xba, 0xa5, 0x04, |
| 57 0x00, 0xbf, 0x8b, 0xff, 0xf5, 0x42, 0x9f, 0xff, |
| 58 0xcf, 0xf9, 0x2b, 0xa5, 0xc0, 0x08, 0xff, 0x8b, |
| 59 0xff, 0xfc, 0xc5, 0xfd, 0x40, 0x3f, 0xfe, 0x0b, |
| 60 0xfb, 0x00, 0x0e, 0xff, 0x00, 0xae, 0x88, 0xfa, |
| 61 0x96, 0xff, 0xfa, 0x81, 0x54, 0x40, 0x1b, 0xff, |
| 62 0x00, 0x0b, 0x88, 0xfe, 0xaa, 0x96, 0x50, 0x59, |
| 63 0x41, 0x00, 0x7b, 0xff, 0x88, 0xff, 0xff, 0x53, |
| 64 0xff, 0xab, 0xc0, 0x00, 0x16, 0x54, 0x00, 0xba, |
| 65 0x8b, 0xff, 0xff, 0x43, 0xfe, 0xaf, 0xe8, 0x00, |
| 66 0x5a, 0x61, 0x41, 0xbf, 0xff, 0x8b, 0xff, 0xff, |
| 67 0xc2, 0xfe, 0xbf, 0xfd, 0x01, 0x59, 0x94, 0x51, |
| 68 0x1b, 0xff, 0x00, 0xef, 0x88, 0xfe, 0xeb, 0xed, |
| 69 0x95, 0x56, 0x51, 0x40, 0x0f, 0xff, 0x8b, 0xff, |
| 70 0xff, 0xe0, 0xfa, 0x92, 0xa6, 0x91, 0x11, 0x54, |
| 71 0x54, 0x0f, 0xff, 0x00, 0x0b, 0x84, 0xff, 0xa9, |
| 72 0xa4, 0x00, 0x01, 0x04, 0x17, 0x00, 0x6c, 0x88, |
| 73 0xba, 0xaf, 0xff, 0xfd, 0x96, 0x45, 0x40, 0x3f, |
| 74 0xff, 0x00, 0x00, 0x88, 0x2a, 0xbf, 0x6a, 0xa4, |
| 75 0x15, 0x54, 0x60, 0xbf, 0xff, 0x00, 0x00, 0x88, |
| 76 0xfa, 0xeb, 0x90, 0x00, 0x95, 0x41, 0xae, 0xff, |
| 77 0xff, 0x04, 0x0b, 0x84, 0xaa, 0xa5, 0x11, 0x45, |
| 78 0x05, 0x01, 0x49, 0x05, 0x27, 0x87, 0xae, 0xff, |
| 79 0xf9, 0x54, 0x11, 0x6e, 0xff, 0xff, 0x0c, 0x0b, |
| 80 0x85, 0xfa, 0x54, 0x56, 0xbb, 0xff, 0xff, 0x04, |
| 81 0x0b, 0x87, 0xab, 0xbf, 0xf6, 0x54, 0x43, 0xaf, |
| 82 0xff, 0xff, 0x04, 0x00, 0x87, 0x5a, 0xaa, 0x95, |
| 83 0x11, 0x46, 0xfb, 0xff, 0xff, 0x04, 0x00, 0x84, |
| 84 0xaa, 0x55, 0x10, 0x45, 0x07, 0x00, 0x17, 0x04, |
| 85 0x00, 0x84, 0x95, 0x54, 0x45, 0x14, 0x06, 0x00, |
| 86 0x5e, 0x04, 0x00, 0x87, 0xa5, 0x55, 0x50, 0x40, |
| 87 0x12, 0xff, 0xbf, 0xff, |
| 88 }; |
| 89 |
| 90 static Memimage* resample(int, int, Memimage*); |
| 91 |
| 92 void |
| 93 drawpjw(Memimage *m, Fontchar *fc, int x, int width, int height, int ascent) |
| 94 { |
| 95 int w, p[2]; |
| 96 Memimage *pm, *pm1, *pm2; |
| 97 Rectangle r; |
| 98 int margin; |
| 99 ········ |
| 100 w = width; |
| 101 |
| 102 // assume margin below baseline is |
| 103 // approximately how much room we should preserve at top above peter too |
| 104 margin = height - ascent; |
| 105 if(w > ascent-margin) |
| 106 w = ascent-margin; |
| 107 |
| 108 if(w < 9) |
| 109 w = 9; |
| 110 fc->width = w; |
| 111 |
| 112 pipe(p); |
| 113 write(p[1], pjw, sizeof pjw); |
| 114 close(p[1]); |
| 115 pm = readmemimage(p[0]); |
| 116 close(p[0]); |
| 117 if(pm == nil) |
| 118 goto Error; |
| 119 ········ |
| 120 pm1 = allocmemimage(pm->r, GREY8); |
| 121 memimagedraw(pm1, pm1->r, pm, pm->r.min, nil, ZP, S); |
| 122 pm2 = resample(w, w, pm1); |
| 123 memimagedraw(m, Rect(x, ascent-w, x+w, ascent), memwhite, ZP, nil, ZP, S
overD); |
| 124 memimagedraw(m, Rect(x, ascent-w, x+w, ascent), memblack, ZP, pm2, pm2->
r.min, SoverD); |
| 125 freememimage(pm2); |
| 126 freememimage(pm1); |
| 127 freememimage(pm); |
| 128 return; |
| 129 |
| 130 Error: |
| 131 // draw a box |
| 132 r = Rect(x, 0, x+width, height); |
| 133 memimagedraw(m, r, memwhite, ZP, nil, ZP, S); |
| 134 memimagedraw(m, insetrect(r, 3), memblack, ZP, nil, ZP, S); |
| 135 return; |
| 136 } |
| 137 |
| 138 #define K2 7 /* from -.7 to +.7 inclusive, meaning .2 into each adjacent pixe
l */ |
| 139 #define NK (2*K2+1) |
| 140 static double K[NK]; |
| 141 |
| 142 static void |
| 143 resamplex(uchar *in, int off, int d, int inx, uchar *out, int outx) |
| 144 { |
| 145 int i, x, k; |
| 146 double X, xx, v, rat; |
| 147 |
| 148 |
| 149 rat = (double)inx/(double)outx; |
| 150 for(x=0; x<outx; x++){ |
| 151 if(inx == outx){ |
| 152 /* don't resample if size unchanged */ |
| 153 out[off+x*d] = in[off+x*d]; |
| 154 continue; |
| 155 } |
| 156 v = 0.0; |
| 157 X = x*rat; |
| 158 for(k=-K2; k<=K2; k++){ |
| 159 xx = X + rat*k/10.; |
| 160 i = xx; |
| 161 if(i < 0) |
| 162 i = 0; |
| 163 if(i >= inx) |
| 164 i = inx-1; |
| 165 v += in[off+i*d] * K[K2+k]; |
| 166 } |
| 167 out[off+x*d] = v; |
| 168 } |
| 169 } |
| 170 |
| 171 static void |
| 172 resampley(uchar **in, int off, int iny, uchar **out, int outy) |
| 173 { |
| 174 int y, i, k; |
| 175 double Y, yy, v, rat; |
| 176 |
| 177 rat = (double)iny/(double)outy; |
| 178 for(y=0; y<outy; y++){ |
| 179 if(iny == outy){ |
| 180 /* don't resample if size unchanged */ |
| 181 out[y][off] = in[y][off]; |
| 182 continue; |
| 183 } |
| 184 v = 0.0; |
| 185 Y = y*rat; |
| 186 for(k=-K2; k<=K2; k++){ |
| 187 yy = Y + rat*k/10.; |
| 188 i = yy; |
| 189 if(i < 0) |
| 190 i = 0; |
| 191 if(i >= iny) |
| 192 i = iny-1; |
| 193 v += in[i][off] * K[K2+k]; |
| 194 } |
| 195 out[y][off] = v; |
| 196 } |
| 197 |
| 198 } |
| 199 |
| 200 static int |
| 201 max(int a, int b) |
| 202 { |
| 203 if(a > b) |
| 204 return a; |
| 205 return b; |
| 206 } |
| 207 |
| 208 static double |
| 209 fac(int L) |
| 210 { |
| 211 int i, f; |
| 212 |
| 213 f = 1; |
| 214 for(i=L; i>1; --i) |
| 215 f *= i; |
| 216 return f; |
| 217 } |
| 218 |
| 219 /*· |
| 220 * i0(x) is the modified Bessel function, Σ (x/2)^2L / (L!)² |
| 221 * There are faster ways to calculate this, but we precompute |
| 222 * into a table so let's keep it simple. |
| 223 */ |
| 224 static double |
| 225 i0(double x) |
| 226 { |
| 227 double v; |
| 228 int L; |
| 229 |
| 230 v = 1.0; |
| 231 for(L=1; L<10; L++) |
| 232 v += pow(x/2., 2*L)/pow(fac(L), 2); |
| 233 return v; |
| 234 } |
| 235 |
| 236 static double |
| 237 kaiser(double x, double tau, double alpha) |
| 238 { |
| 239 if(fabs(x) > tau) |
| 240 return 0.; |
| 241 return i0(alpha*sqrt(1-(x*x/(tau*tau))))/i0(alpha); |
| 242 } |
| 243 |
| 244 |
| 245 static Memimage* |
| 246 resample(int xsize, int ysize, Memimage *m) |
| 247 { |
| 248 int i, j, bpl, nchan; |
| 249 Memimage *new; |
| 250 uchar **oscan, **nscan; |
| 251 double v; |
| 252 |
| 253 for(i=-K2; i<=K2; i++){ |
| 254 K[K2+i] = kaiser(i/10., K2/10., 4.); |
| 255 /* print("%g %g\n", i/10., K[K2+i]); */ |
| 256 } |
| 257 |
| 258 /* normalize */ |
| 259 v = 0.0; |
| 260 for(i=0; i<NK; i++) |
| 261 v += K[i]; |
| 262 for(i=0; i<NK; i++) |
| 263 K[i] /= v; |
| 264 |
| 265 new = allocmemimage(Rect(0, 0, xsize, ysize), m->chan); |
| 266 if(new == nil) |
| 267 sysfatal("can't allocate new image: %r"); |
| 268 |
| 269 oscan = malloc(Dy(m->r)*sizeof(uchar*)); |
| 270 nscan = malloc(max(ysize, Dy(m->r))*sizeof(uchar*)); |
| 271 if(oscan == nil || nscan == nil) |
| 272 sysfatal("can't allocate: %r"); |
| 273 |
| 274 /* unload original image into scan lines */ |
| 275 bpl = bytesperline(m->r, m->depth); |
| 276 for(i=0; i<Dy(m->r); i++){ |
| 277 oscan[i] = malloc(bpl); |
| 278 if(oscan[i] == nil) |
| 279 sysfatal("can't allocate: %r"); |
| 280 j = unloadmemimage(m, Rect(m->r.min.x, m->r.min.y+i, m->r.max.x,
m->r.min.y+i+1), oscan[i], bpl); |
| 281 if(j != bpl) |
| 282 sysfatal("unloadmemimage"); |
| 283 } |
| 284 |
| 285 /* allocate scan lines for destination. we do y first, so need at least
Dy(m->r) lines */ |
| 286 bpl = bytesperline(Rect(0, 0, xsize, Dy(m->r)), m->depth); |
| 287 for(i=0; i<max(ysize, Dy(m->r)); i++){ |
| 288 nscan[i] = malloc(bpl); |
| 289 if(nscan[i] == nil) |
| 290 sysfatal("can't allocate: %r"); |
| 291 } |
| 292 |
| 293 /* resample in X */ |
| 294 nchan = m->depth/8; |
| 295 for(i=0; i<Dy(m->r); i++){ |
| 296 for(j=0; j<nchan; j++){ |
| 297 if(j==0 && m->chan==XRGB32) |
| 298 continue; |
| 299 resamplex(oscan[i], j, nchan, Dx(m->r), nscan[i], xsize)
; |
| 300 } |
| 301 free(oscan[i]); |
| 302 oscan[i] = nscan[i]; |
| 303 nscan[i] = malloc(bpl); |
| 304 if(nscan[i] == nil) |
| 305 sysfatal("can't allocate: %r"); |
| 306 } |
| 307 |
| 308 /* resample in Y */ |
| 309 for(i=0; i<xsize; i++) |
| 310 for(j=0; j<nchan; j++) |
| 311 resampley(oscan, nchan*i+j, Dy(m->r), nscan, ysize); |
| 312 |
| 313 /* pack data into destination */ |
| 314 bpl = bytesperline(new->r, m->depth); |
| 315 for(i=0; i<ysize; i++){ |
| 316 j = loadmemimage(new, Rect(0, i, xsize, i+1), nscan[i], bpl); |
| 317 if(j != bpl) |
| 318 sysfatal("loadmemimage: %r"); |
| 319 } |
| 320 return new; |
| 321 } |
OLD | NEW |