4 * This file is part of the ttf2pk package.
6 * Copyright 1997-1999 by
7 * Frederic Loyer <loyer@ensta.fr>
8 * Werner Lemberg <wl@gnu.org>
12 * This code has been derived from the program gsftopk.
13 * Here the original copyright.
17 * Copyright (c) 1994 Paul Vojta. All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #include <stddef.h> /* for size_t */
55 #define MAXPATHLEN 256
58 #define PK_PRE (char)247
60 #define PK_POST (char)245
61 #define PK_NOP (char)246
69 * Information from the .tfm file.
74 #define lh tfm_lengths[1]
75 #define bc tfm_lengths[2]
76 #define ec tfm_lengths[3]
77 #define nw tfm_lengths[4]
81 byte width_index
[256];
85 * Information on the bitmap currently being worked on.
100 * Here's the path searching stuff. First the typedefs and variables.
103 static char searchpath
[MAXPATHLEN
+ 1];
105 #define HUNKSIZE (MAXPATHLEN + 2)
107 struct spacenode
/* used for storage of directory names */
109 struct spacenode
*next
;
110 char *sp_end
; /* end of data for this chunk */
117 search_tfm(char **name
)
123 p
= TeX_search_tfm(name
);
126 strcpy(searchpath
, p
);
127 f
= fopen(searchpath
, "rb");
138 value
= (unsigned long)getc(f
) << 24;
139 value
|= (unsigned long)getc(f
) << 16;
140 value
|= (unsigned long)getc(f
) << 8;
141 value
|= (unsigned long)getc(f
);
149 static byte masks
[] = {0, 1, 3, 7, 017, 037, 077, 0177, 0377};
154 int base
; /* cost of this character if pk_dyn_f = 0 */
155 int deltas
[13]; /* cost of increasing pk_dyn_f from i to i+1 */
159 * Add up statistics for putting out the given shift count.
172 for (m
= 0x100; m
!= 0 && m
< n
; m
<<= 4)
174 if (m
!= 0 && (m
= (m
- n
) / 15) < 13)
178 ++deltas
[(208 - n
) / 15];
185 * Routines for storing the shift counts.
188 static Boolean odd
= False
;
197 *bitmap_end
++ = (part
<< 4) | n
;
226 pk_put_long(n
- pk_dyn_g
+ 15);
229 pk_put_nyb(pk_dyn_f
+ (n
- pk_dyn_f
+ 15) / 16);
230 pk_put_nyb((n
- pk_dyn_f
- 1) % 16);
245 /* clear out garbage bits in bitmap */
249 mask
= ~masks
[8 - width
% 8];
250 for (p
= bitmap
+ bytes_wide
- 1; p
< bitmap_end
; p
+= bytes_wide
)
254 /* Find the bounding box of the bitmap. */
263 if (bitmap
>= bitmap_end
) /* if bitmap is empty */
265 width
= height
= hoff
= voff
= 0;
269 p
= bitmap
+ bytes_wide
;
275 bitmap
+= bytes_wide
;
282 if (skip
< 2 || skip
> 3)
283 printf("Character has %d empty rows at top\n", skip
);
293 p
= bitmap_end
- bytes_wide
;
294 while (p
< bitmap_end
)
299 bitmap_end
-= bytes_wide
;
305 if (skip
< 2 || skip
> 3)
306 printf("Character has %d empty rows at bottom\n", skip
);
317 for (p
= bitmap
+ width
/ 8; p
< bitmap_end
; p
+= bytes_wide
)
319 if (mask
& (0x80 >> (width
% 8)))
329 if (skip
< 2 || skip
> 3)
330 printf("Character has %d empty columns at right\n", skip
);
340 for (p
= bitmap
+ skip
/ 8; p
< bitmap_end
; p
+= bytes_wide
)
342 if (mask
& (0x80 >> (skip
% 8)))
352 if (skip
< 2 || skip
> 3)
353 printf("Character has %d empty columns at left\n", skip
);
362 * Pack the bitmap using the rll method. (Return false if it's better
363 * to just pack the bits.)
369 static int *counts
= NULL
; /* area for saving bit counts */
370 static int maxcounts
= 0; /* size of this area */
371 unsigned int ncounts
; /* max to allow this time */
372 int *nextcount
; /* next count value */
374 int *counts_end
; /* pointer to end */
378 byte
*rowdup
; /* last row checked for dup */
379 byte paint_switch
; /* 0 or 0xff */
380 int bits_left
; /* bits left in row */
385 /* Allocate space for bit counts. */
387 ncounts
= (width
* height
+ 3) / 4;
388 if (ncounts
> maxcounts
)
392 counts
= (int *)mymalloc((ncounts
+ 2) * sizeof (int));
395 counts_end
= counts
+ ncounts
;
397 /* Form bit counts and collect statistics */
400 memset(deltas
, 0, sizeof (deltas
));
401 rowdup
= NULL
; /* last row checked for duplicates */
416 while (rowptr
< bitmap_end
) /* loop over shift counts */
418 int shift_count
= bits_left
;
425 if ((p
= rowptr
+= bytes_wide
) >= bitmap_end
)
429 shift_count
+= width
;
431 if (((*p
^ paint_switch
) & mask
) != 0)
438 while (*p
== paint_switch
&& bits_left
>= 8)
447 if (nextcount
>= counts_end
)
449 shift_count
-= bits_left
;
450 *nextcount
++ = shift_count
;
451 tallyup(shift_count
);
453 /* check for duplicate rows */
454 if (rowptr
!= rowdup
&& bits_left
!= width
)
457 byte
*q
= rowptr
+ bytes_wide
;
461 while (q
< bitmap_end
&& *p1
== *q
)
466 repeat_count
= (p1
- rowptr
) / bytes_wide
;
467 if (repeat_count
> 0)
469 *nextcount
++ = -repeat_count
;
470 if (repeat_count
== 1)
475 tallyup(repeat_count
);
477 rowptr
+= repeat_count
* bytes_wide
;
481 paint_switch
= ~paint_switch
;
489 for (p
= bitmap
; p
< bitmap_end
; p
+= bytes_wide
)
496 for (j
= 0; j
< width
; ++j
)
498 putchar(*p1
& mask
? '@' : '.');
499 if ((mask
>>= 1) == 0)
510 /* Determine the best pk_dyn_f */
513 cost
= base
+= 2 * (nextcount
- counts
);
515 for (i
= 1; i
< 14; ++i
)
517 base
+= deltas
[i
- 1];
525 /* last chance to bail out */
527 if (cost
* 4 > width
* height
)
530 /* Pack the bit counts */
532 pk_dyn_g
= 208 - 15 * pk_dyn_f
;
533 flag
|= pk_dyn_f
<< 4;
538 while (*nextcount
!= 0)
541 pk_put_count(*nextcount
);
543 if (*nextcount
== -1)
548 pk_put_count(-*nextcount
);
559 if (cost
!= 2 * (bitmap_end
- bitmap
))
560 printf("Cost miscalculation: expected %d, got %ld\n",
561 cost
, (long)(2 * (bitmap_end
- bitmap
)));
562 pk_len
= bitmap_end
- bitmap
;
572 int blib1
; /* bits left in byte */
573 int bits_left
; /* bits left in row */
584 for (rowptr
= bitmap
; rowptr
< bitmap_end
; rowptr
+= bytes_wide
)
597 nextbyte
|= *p
<< (blib2
- blib1
);
602 nextbyte
|= *p
>> (blib1
- blib2
);
606 if ((bits_left
-= n
) < 0)
611 if ((blib1
-= n
) == 0)
617 nextbyte
|= *p
>> (8 - blib2
);
630 /* fill up whole (destination) bytes */
632 while (bits_left
>= 8)
634 nextbyte
= *p
++ << (8 - blib1
);
635 *q
++ = nextbyte
| (*p
>> blib1
);
639 /* now do the remainder */
641 nextbyte
= *p
<< (8 - blib1
);
642 if (bits_left
> blib1
)
643 nextbyte
|= p
[1] >> blib1
;
644 blib2
= 8 - bits_left
;
657 putc(w
>> 8, pk_file
);
665 putc(w
>> 16, pk_file
);
666 putc(w
>> 8, pk_file
);
674 putc(w
>> 24, pk_file
);
675 putc(w
>> 16, pk_file
);
676 putc(w
>> 8, pk_file
);
689 oops("Premature end of file.");
695 * Open and read the tfm file.
699 TFMopen(char **filename
)
706 tfm_file
= search_tfm(filename
);
707 if (tfm_file
== NULL
)
708 oops("Cannot find tfm file.");
710 for (i
= 0; i
< 12; i
++)
715 j
= (int)((byte
)getc(tfm_file
)) << 8;
716 tfm_lengths
[i
] = j
| (int)((byte
)xgetc(tfm_file
));
719 checksum
= getlong(tfm_file
);
720 design
= getlong(tfm_file
);
721 fseek(tfm_file
, 4 * (lh
+ 6), 0);
723 for (cc
= bc
; cc
<= ec
; ++cc
)
725 width_index
[cc
] = (byte
)xgetc(tfm_file
);
727 (void)xgetc(tfm_file
);
728 (void)xgetc(tfm_file
);
729 (void)xgetc(tfm_file
);
732 for (i
= 0; i
< nw
; ++i
)
733 tfm_widths
[i
] = getlong(tfm_file
);
740 * Create pk file and write preamble.
744 PKopen(char *filename
,
754 if ((pk_file
= fopen(filename
, "wb")) == NULL
)
760 putc(PK_PRE
, pk_file
);
761 putc(PK_ID
, pk_file
);
766 fwrite(ident
, 1, i
, pk_file
);
769 ppp
= dpi
/ 72.27 * 65536.0 + 0.5;
770 putlong(ppp
); /* hppp */
771 putlong(ppp
); /* vppp */
777 int llx
, int lly
, int urx
, int ury
,
792 voff
= ury
- 2; /* Don't ask me why `-2' */
795 if (width
!= urx
- llx
|| height
!= ury
- lly
)
796 oops("Dimensions do not match: (%d - %d) (%d - %d) <=> %d %d",
797 llx
, lly
, urx
, ury
, width
, height
);
799 bytes_wide
= (width
+ 7) / 8;
800 bm_size
= bytes_wide
* height
;
801 bitmap_end
= bitmap
+ bm_size
;
805 if (height
== 0 || !pk_rll_cvt())
808 if (!width_index
[cc
])
811 tfm_wid
= tfm_widths
[width_index
[cc
]];
812 char_width
= tfm_wid
/ 1048576.0 * design
/ 1048576.0 * dpi
/ 72.27;
813 dm
= (long)(char_width
+ 0.5) - (char_width
< -0.5);
815 if (pk_len
+ 8 < 4 * 256 && tfm_wid
< (1<<24) &&
816 dm
>= 0 && dm
< 256 && width
< 256 && height
< 256 &&
817 hoff
>= -128 && hoff
< 128 && voff
>= -128 && voff
< 128)
819 putc(flag
| ((pk_len
+ 8) >> 8), pk_file
);
820 putc(pk_len
+ 8, pk_file
);
824 putc(width
, pk_file
);
825 putc(height
, pk_file
);
829 else if (pk_len
+ 13 < 3 * 65536L && tfm_wid
< (1<<24) &&
830 dm
>= 0 && dm
< 65536L && width
< 65536L && height
< 65536L &&
831 hoff
>= -65536L && hoff
< 65536L &&
832 voff
>= -65536L && voff
< 65536L)
834 putc(flag
| 4 | ((pk_len
+ 13) >> 16), pk_file
);
835 putshort(pk_len
+ 13);
846 putc(flag
| 7, pk_file
);
847 putlong(pk_len
+ 28);
850 putlong((long)(char_width
* 65536.0 + 0.5) - (char_width
< -0.5));
857 fwrite(bitmap
, 1, pk_len
, pk_file
);
864 putc(PK_POST
, pk_file
);
865 while (ftell(pk_file
) % 4 != 0)
866 putc(PK_NOP
, pk_file
);