URI:
       tpjw.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpjw.c (8815B)
       ---
            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, SoverD);
          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 pixel */
          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 }