3 % Copyright
1996-2006 Han The Thanh
<thanh@@pdftex.org
>
4 % Copyright
2006-2010 Taco Hoekwater
<taco@@luatex.org
>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software
; you can redistribute it and
/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation
; either version
2 of the License
, or
(at your
11 % option
) any later version.
13 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
14 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
25 #include
"font/writettf.h"
28 #define DEFAULT_NTABS
14
29 #define NEW_CMAP_SIZE
2
31 #define ttf_putchar
(A
) strbuf_putchar
(pdf-
>fb
, (A
))
32 #define ttf_offset
() strbuf_offset
(pdf-
>fb
)
33 #define ttf_seek_outbuf
(A
) strbuf_seek
(pdf-
>fb
, (A
))
35 unsigned char
*ttf_buffer
= NULL;
40 char
*name
; /* name of glyph
*/
41 long code
; /* charcode in case of subfonts
*/
42 long newindex
; /* new index of glyph in output file
*/
47 TTF_USHORT platform_id
;
48 TTF_USHORT encoding_id
;
49 TTF_USHORT language_id
;
53 TTF_USHORT new_offset
;
54 TTF_USHORT new_length
;
64 static TTF_USHORT ntabs
;
65 static TTF_USHORT upem
;
66 static TTF_FIXED post_format
;
67 static TTF_SHORT loca_format
;
68 static TTF_ULONG last_glyf_offset
;
69 static TTF_USHORT glyphs_count
;
70 static TTF_USHORT new_glyphs_count
;
71 static TTF_USHORT nhmtxs
;
72 static TTF_USHORT new_ntabs
;
74 glyph_entry
*glyph_tab
;
75 dirtab_entry
*dir_tab
;
77 static long
*glyph_index
;
78 static cmap_entry
*cmap_tab
, new_cmap_tab
[NEW_CMAP_SIZE
];
79 static name_record
*name_tab
;
80 static int name_record_num
;
81 static char
*name_buf
;
82 static int name_buf_size
;
83 static char
*glyph_name_buf
;
84 static TTF_ULONG checksum
;
85 static TTF_ULONG tab_length
;
86 static TTF_ULONG tmp_ulong
;
87 static TTF_ULONG checkSumAdjustment_offset
;
89 static ttfenc_entry ttfenc_tab
[256];
91 fd_entry
*fd_cur
; /* pointer to the current font descriptor
*/
93 static struct avl_table
*ttf_cmap_tree
= NULL;
97 @ This used to be macnames.c
100 char notdef
[] = ".notdef";
102 const char
*mac_glyph_names
[] = {
380 const char
*ambiguous_names
[] = {
381 "Delta", /* increment
*/
384 "Sigma", /* summation
*/
385 "dmacron", /* dslash
*/
386 "macron", /* overscore
*/
387 "periodcentered", /* middot
*/
391 static const char
*newtabnames
[] = {
408 @ Back to code. Low-level helpers first.
411 static ttf_cmap_entry
*new_ttf_cmap_entry
(void
)
414 e
= xtalloc
(1, ttf_cmap_entry
);
420 static void destroy_ttf_cmap_entry
(void
*pa
, void
*pb
)
424 p
= (ttf_cmap_entry
*) pa
;
432 if
(ttf_cmap_tree
!= NULL)
433 avl_destroy
(ttf_cmap_tree
, destroy_ttf_cmap_entry
);
436 static int comp_ttf_cmap_entry
(const void
*pa
, const void
*pb
, void
*p
)
438 const ttf_cmap_entry
*p1
= (const ttf_cmap_entry
*) pa
,
439 *p2
= (const ttf_cmap_entry
*) pb
;
442 assert
(p1-
>ttf_name
!= NULL && p2->ttf_name != NULL);
443 if
((i
= strcmp
(p1-
>ttf_name
, p2-
>ttf_name
)) != 0)
445 cmp_return
(p1-
>pid
, p2-
>pid
);
446 cmp_return
(p1-
>eid
, p2-
>eid
);
450 static unsigned char ttf_addchksm
(unsigned char b
)
452 tmp_ulong
= (tmp_ulong
<< 8) + b
;
454 if
(tab_length
% 4 == 0) {
455 checksum
+= tmp_ulong
;
461 static TTF_ULONG ttf_getchksm
(PDF pdf
)
463 while
(tab_length
% 4 != 0)
464 ttf_putchar
(ttf_addchksm
(0)); /* |ttf_addchksm| updates |tab_length|
*/
468 long ttf_putnum
(PDF pdf
, int s
, long n
)
471 char buf
[TTF_LONG_SIZE
+ 1], *p
= buf
;
473 *p
++ = (char
) (i
& 0xFF);
478 ttf_putchar
(ttf_addchksm
((unsigned char
) (*p--
)));
482 long ttf_getnum
(int s
)
488 normal_error
("ttf font","unexpected EOF");
496 static long ttf_funit
(long n
)
499 return
-((-n
/ upem
) * 1000 + ((-n
% upem
) * 1000) / upem
);
501 return
(n
/ upem
) * 1000 + ((n
% upem
) * 1000) / upem
;
504 static void ttf_ncopy
(PDF pdf
, int n
)
510 dirtab_entry
*ttf_name_lookup
(const char
*s
, boolean required
)
513 for
(tab
= dir_tab
; tab
- dir_tab
< ntabs
; tab
++) {
514 if
(strncmp
(tab-
>tag
, s
, 4) == 0)
517 if
(tab
- dir_tab
== ntabs
) {
519 formatted_error
("ttf font","can't find table '%s'", s
);
526 dirtab_entry
*ttf_seek_tab
(const char
*name
, TTF_LONG offset
)
528 dirtab_entry
*tab
= ttf_name_lookup
(name
, true
);
529 ttf_curbyte
= (int
) (tab-
>offset
+ (unsigned long
) offset
);
533 static void ttf_seek_off
(TTF_LONG offset
)
535 ttf_curbyte
= (int
) offset
;
538 static void ttf_copy_encoding
(void
)
544 static char buf
[SMALL_BUF_SIZE
];
545 struct avl_traverser t
;
546 ttfenc_entry
*e
= ttfenc_tab
;
548 assert
(fd_cur-
>tx_tree
!= NULL); /* this must be set in |create_fontdictionary|
*/
550 if
(fd_cur-
>fe
!= NULL) {
551 glyph_names
= fd_cur-
>fe-
>glyph_names
;
552 assert
(glyph_names
!= NULL);
554 for
(i
= 0; i
< 256; i
++)
555 ttfenc_tab
[i
].name
= (char
*) notdef
;
557 /* a workaround for a bug of AcroReader
4.0 */
558 if
(strcmp
(glyph_names
[97], "a") == 0) {
561 aa
= avl_probe
(fd_cur-
>tx_tree
, q
);
564 /* end of workaround
*/
566 /* take over collected characters from \TeX
, reencode them
*/
567 avl_t_init
(&t, fd_cur->tx_tree);
568 for
(q
= (int
*) avl_t_first
(&t, fd_cur->tx_tree); q != NULL;
569 q
= (int
*) avl_t_next
(&t)) {
570 assert
(*q
>= 0 && *q < 256);
571 ttfenc_tab
[*q
].name
= glyph_names
[*q
];
573 make_subset_tag
(fd_cur
);
574 } else if
(is_subfont
(fd_cur-
>fm
)) {
575 charcodes
= fd_cur-
>fm-
>subfont-
>charcodes
;
576 assert
(charcodes
!= NULL);
578 for
(i
= 0; i
< 256; i
++)
579 ttfenc_tab
[i
].code
= -1;
581 /* take over collected characters from \TeX
*/
582 avl_t_init
(&t, fd_cur->tx_tree);
583 for
(q
= (int
*) avl_t_first
(&t, fd_cur->tx_tree); q != NULL;
584 q
= (int
*) avl_t_next
(&t)) {
585 assert
(*q
>= 0 && *q < 256);
587 e-
>code
= charcodes
[*q
];
589 formatted_warning
("ttf font", "character %i in subfont %s is not mapped to any charcode", *q
, fd_cur-
>fm-
>tfm_name
);
591 assert
(e-
>code
< 0x10000);
592 sprintf
(buf
, "/c%4.4X", (int
) e-
>code
);
593 aa
= avl_probe
(fd_cur-
>gl_tree
, xstrdup
(buf
));
597 make_subset_tag
(fd_cur
);
604 #define ttf_append_byte
(B
)\
606 if
(name_tab
[i
].platform_id
== 3)\
611 static char
*strip_spaces_and_delims
(char
*s
, int l
)
613 static char buf
[SMALL_BUF_SIZE
];
617 assert
(l
>= 0 && l < (int) sizeof(buf));
619 for
(i
= 0; i
< l
; s
++, i
++) {
620 if
(*s
== '
(' ||
*s
== '
)' ||
*s
== '
<' ||
*s
== '
>' ||
621 *s
== '
[' ||
*s
== '
]' ||
*s
== '
{' ||
*s
== '
}' ||
622 *s
== '
/' ||
*s
== '
%' || isspace
((unsigned char
)*s
))
630 static void ttf_read_name
(void
)
633 dirtab_entry
*tab
= ttf_seek_tab
("name", TTF_USHORT_SIZE
);
634 char
*p
, buf
[SMALL_BUF_SIZE
];
635 name_record_num
= get_ushort
();
636 name_tab
= xtalloc
((unsigned
) name_record_num
, name_record
);
637 name_buf_size
= (int
) ((unsigned
) tab-
>length
-
638 (3 * TTF_USHORT_SIZE
+
639 (TTF_ULONG
) name_record_num
* 6 * TTF_USHORT_SIZE
));
640 name_buf
= xtalloc
((unsigned
) name_buf_size
, char
);
641 ttf_skip
(TTF_USHORT_SIZE
);
642 for
(i
= 0; i
< name_record_num
; i
++) {
643 name_tab
[i
].platform_id
= get_ushort
();
644 name_tab
[i
].encoding_id
= get_ushort
();
645 name_tab
[i
].language_id
= get_ushort
();
646 name_tab
[i
].name_id
= get_ushort
();
647 name_tab
[i
].length
= get_ushort
();
648 name_tab
[i
].offset
= get_ushort
();
650 for
(p
= name_buf
; p
- name_buf
< name_buf_size
; p
++)
652 /* look for PS font name
*/
653 for
(i
= 0; i
< name_record_num
; i
++) {
654 if
(name_tab
[i
].platform_id
== 1 &&
655 name_tab
[i
].encoding_id
== 0 && name_tab[i].name_id == 6) {
656 xfree
(fd_cur-
>fontname
);
658 xstrdup
(strip_spaces_and_delims
(name_buf
+ name_tab
[i
].offset
,
659 name_tab
[i
].length
));
660 fd_cur-
>font_dim
[FONTNAME_CODE
].set
= true
;
664 if
(!fd_cur-
>font_dim
[FONTNAME_CODE
].set
) {
665 for
(i
= 0; i
< name_record_num
; i
++) {
666 if
(name_tab
[i
].platform_id
== 3 &&
667 (name_tab
[i
].encoding_id
== 0 || name_tab
[i
].encoding_id
== 1)
668 && name_tab[i].name_id == 6) {
669 xfree
(fd_cur-
>fontname
);
670 assert
(name_tab
[i
].length
< sizeof
(buf
));
671 for
(j
= 0, p
= buf
; j
< name_tab
[i
].length
; j
+= 2)
672 *p
++ = name_buf
[name_tab
[i
].offset
+ j
+ 1];
675 xstrdup
(strip_spaces_and_delims
(buf
, (int
) strlen
(buf
)));
676 fd_cur-
>font_dim
[FONTNAME_CODE
].set
= true
;
683 static void ttf_read_mapx
(void
)
686 ttf_seek_tab
("maxp", TTF_FIXED_SIZE
);
688 xtalloc
((unsigned
) (1 + (glyphs_count
= get_ushort
())), glyph_entry
);
689 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< glyphs_count
; glyph
++) {
690 glyph-
>newindex
= -1;
691 glyph-
>newoffset
= 0;
692 glyph-
>name_index
= 0;
693 glyph-
>name
= (char
*) notdef
;
695 glyph_index
= xtalloc
((unsigned
) (glyphs_count
+ 1), long
);
696 glyph_index
[0] = 0; /* index of
".notdef" glyph
*/
697 glyph_index
[1] = 1; /* index of
".null" glyph
*/
700 void ttf_read_head
(void
)
703 2 * TTF_FIXED_SIZE
+ 2 * TTF_ULONG_SIZE
+ TTF_USHORT_SIZE
);
706 fd_cur-
>font_dim
[FONTBBOX1_CODE
].val
= (int
) ttf_funit
(get_fword
());
707 fd_cur-
>font_dim
[FONTBBOX2_CODE
].val
= (int
) ttf_funit
(get_fword
());
708 fd_cur-
>font_dim
[FONTBBOX3_CODE
].val
= (int
) ttf_funit
(get_fword
());
709 fd_cur-
>font_dim
[FONTBBOX4_CODE
].val
= (int
) ttf_funit
(get_fword
());
710 fd_cur-
>font_dim
[FONTBBOX1_CODE
].set
= true
;
711 fd_cur-
>font_dim
[FONTBBOX2_CODE
].set
= true
;
712 fd_cur-
>font_dim
[FONTBBOX3_CODE
].set
= true
;
713 fd_cur-
>font_dim
[FONTBBOX4_CODE
].set
= true
;
714 ttf_skip
(2 * TTF_USHORT_SIZE
+ TTF_SHORT_SIZE
);
715 loca_format
= get_short
();
718 void ttf_read_hhea
(void
)
720 ttf_seek_tab
("hhea", TTF_FIXED_SIZE
);
721 fd_cur-
>font_dim
[ASCENT_CODE
].val
= (int
) ttf_funit
(get_fword
());
722 fd_cur-
>font_dim
[DESCENT_CODE
].val
= (int
) ttf_funit
(get_fword
());
723 fd_cur-
>font_dim
[ASCENT_CODE
].set
= true
;
724 fd_cur-
>font_dim
[DESCENT_CODE
].set
= true
;
725 ttf_skip
(TTF_FWORD_SIZE
+ TTF_UFWORD_SIZE
+ 3 * TTF_FWORD_SIZE
+
727 nhmtxs
= get_ushort
();
730 void ttf_read_pclt
(void
)
732 if
(ttf_name_lookup
("PCLT", false
) == NULL)
734 ttf_seek_tab
("PCLT", TTF_FIXED_SIZE
+ TTF_ULONG_SIZE
+ TTF_USHORT_SIZE
);
735 fd_cur-
>font_dim
[XHEIGHT_CODE
].val
= (int
) ttf_funit
(get_ushort
());
736 ttf_skip
(2 * TTF_USHORT_SIZE
);
737 fd_cur-
>font_dim
[CAPHEIGHT_CODE
].val
= (int
) ttf_funit
(get_ushort
());
738 fd_cur-
>font_dim
[XHEIGHT_CODE
].set
= true
;
739 fd_cur-
>font_dim
[CAPHEIGHT_CODE
].set
= true
;
742 static void ttf_read_hmtx
(void
)
745 TTF_UFWORD last_advWidth
;
746 ttf_seek_tab
("hmtx", 0);
747 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< nhmtxs
; glyph
++) {
748 glyph-
>advWidth
= get_ufword
();
749 glyph-
>lsb
= (TTF_FWORD
) get_ufword
();
751 if
(nhmtxs
< glyphs_count
) {
752 last_advWidth
= glyph
[-1].advWidth
;
753 for
(; glyph
- glyph_tab
< glyphs_count
; glyph
++) {
754 glyph-
>advWidth
= last_advWidth
;
755 glyph-
>lsb
= (TTF_FWORD
) get_ufword
();
760 void ttf_read_post
(void
)
764 long int_part
, frac_part
;
766 TTF_FIXED italic_angle
;
769 const dirtab_entry
*tab
= ttf_seek_tab
("post", 0);
770 post_format
= get_fixed
();
771 italic_angle
= get_fixed
();
772 int_part
= (long
) (italic_angle
>> 16);
773 if
(int_part
> 0x7FFF) { /* a negative number
*/
774 int_part
= 0x10000 - int_part
;
777 frac_part
= (long
) (italic_angle
% 0x10000);
778 fd_cur-
>font_dim
[ITALIC_ANGLE_CODE
].val
=
779 (int
) (sign
* ((double
) int_part
+ (double
) frac_part
* 1.0 / 0x10000));
780 fd_cur-
>font_dim
[ITALIC_ANGLE_CODE
].set
= true
;
781 if
(glyph_tab
== NULL)
782 return
; /* being called from writeotf
() */
783 ttf_skip
(2 * TTF_FWORD_SIZE
+ 5 * TTF_ULONG_SIZE
);
784 switch
(post_format
) {
786 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< NMACGLYPHS
; glyph
++) {
787 glyph-
>name
= (const char
*) mac_glyph_names
[glyph
- glyph_tab
];
788 glyph-
>name_index
= (TTF_USHORT
) (glyph
- glyph_tab
);
792 nnames
= get_ushort
(); /* some fonts have this value different from nglyphs
*/
793 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< nnames
; glyph
++)
794 glyph-
>name_index
= get_ushort
();
796 (long
) ((long
) tab-
>length
-
797 (long
) ((long
) ttf_curbyte
- (long
) tab-
>offset
));
798 glyph_name_buf
= xtalloc
((unsigned
) length
, char
);
799 for
(p
= glyph_name_buf
; p
- glyph_name_buf
< length
;) {
800 for
(k
= get_byte
(); k
> 0; k--
)
804 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< nnames
; glyph
++) {
805 if
(glyph-
>name_index
< NMACGLYPHS
)
806 glyph-
>name
= mac_glyph_names
[glyph-
>name_index
];
809 k
= glyph-
>name_index
- NMACGLYPHS
;
817 formatted_warning
("ttf font", "unsupported format '%.8X' of 'post' table, assuming 3.0", (unsigned int
) post_format
);
819 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< NMACGLYPHS
; glyph
++) {
820 glyph-
>name_index
= (TTF_USHORT
) (glyph
- glyph_tab
);
825 static void ttf_read_loca
(void
)
828 ttf_seek_tab
("loca", 0);
829 if
(loca_format
!= 0)
830 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< glyphs_count
+ 1; glyph
++)
831 glyph-
>offset
= (TTF_LONG
) get_ulong
();
833 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< glyphs_count
+ 1; glyph
++)
834 glyph-
>offset
= get_ushort
() << 1;
837 void otc_read_tabdir
(int index
)
839 unsigned long i
, num
, rem
=0;
841 ttf_skip
(TTF_FIXED_SIZE
); /* ignore TTCTag 'ttcf'
*/
842 ttf_skip
(TTF_ULONG_SIZE
); /* ignorethe version number
*/
844 for
(i
= 0; i
< num
; i
++) {
845 if
(i
==index
) rem
= get_ulong
(); else ttf_skip
(TTF_ULONG_SIZE
);
847 ttf_skip
(rem
- TTF_FIXED_SIZE
- (num
+2)*TTF_ULONG_SIZE
);
848 ttf_skip
(TTF_FIXED_SIZE
); /* ignore the sfnt number
*/
849 dir_tab
= xtalloc
(ntabs
= get_ushort
(), dirtab_entry
);
850 ttf_skip
(3 * TTF_USHORT_SIZE
);
851 for
(tab
= dir_tab
; tab
- dir_tab
< ntabs
; tab
++) {
852 for
(i
= 0; i
< 4; i
++)
853 tab-
>tag
[i
] = get_char
();
854 tab-
>checksum
= get_ulong
();
855 tab-
>offset
= get_ulong
();
856 tab-
>length
= get_ulong
();
860 void ttf_read_tabdir
(void
)
864 ttf_skip
(TTF_FIXED_SIZE
); /* ignore the sfnt number
*/
865 dir_tab
= xtalloc
(ntabs
= get_ushort
(), dirtab_entry
);
866 ttf_skip
(3 * TTF_USHORT_SIZE
);
867 for
(tab
= dir_tab
; tab
- dir_tab
< ntabs
; tab
++) {
868 for
(i
= 0; i
< 4; i
++)
869 tab-
>tag
[i
] = get_char
();
870 tab-
>checksum
= get_ulong
();
871 tab-
>offset
= get_ulong
();
872 tab-
>length
= get_ulong
();
876 static ttf_cmap_entry
*ttf_read_cmap
(char
*ttf_name
, int pid
, int eid
,
879 seg_entry
*seg_tab
, *s
;
880 TTF_USHORT
*glyphId
, format
, segCount
;
881 TTF_USHORT ncmapsubtabs
, tmp_pid
, tmp_eid
;
882 TTF_ULONG cmap_offset
, tmp_offset
;
883 long n
, i
, k
, length
, index
;
884 ttf_cmap_entry tmp_e
, *p
;
887 /* look up in |ttf_cmap_tree| first
, return if found
*/
888 tmp_e.ttf_name
= ttf_name
;
889 tmp_e.pid
= (TTF_USHORT
) pid
;
890 tmp_e.eid
= (TTF_USHORT
) eid
;
891 if
(ttf_cmap_tree
== NULL) {
892 ttf_cmap_tree
= avl_create
(comp_ttf_cmap_entry
, NULL, &avl_xallocator);
893 assert
(ttf_cmap_tree
!= NULL);
895 p
= (ttf_cmap_entry
*) avl_find
(ttf_cmap_tree
, &tmp_e);
899 /* not found
, have to read it
*/
900 ttf_seek_tab
("cmap", TTF_USHORT_SIZE
); /* skip the table version number
(=0) */
901 ncmapsubtabs
= get_ushort
();
902 cmap_offset
= (TTF_ULONG
) (ttf_curbyte
- 2 * TTF_USHORT_SIZE
);
903 cmap_tab
= xtalloc
(ncmapsubtabs
, cmap_entry
);
904 for
(i
= 0; i
< ncmapsubtabs
; ++i
) {
905 tmp_pid
= get_ushort
();
906 tmp_eid
= get_ushort
();
907 tmp_offset
= get_ulong
();
908 if
(tmp_pid
== pid
&& tmp_eid == eid) {
909 ttf_seek_off
((TTF_LONG
) (cmap_offset
+ tmp_offset
));
910 format
= get_ushort
();
912 goto read_cmap_format_4
;
915 formatted_warning
("ttf font", "cmap format %i unsupported", format
);
921 formatted_warning
("ttf font", "cannot find cmap subtable for (pid,eid) = (%i,%i)", pid
, eid
);
924 /* initialize the new entry
*/
925 p
= new_ttf_cmap_entry
();
926 p-
>ttf_name
= xstrdup
(ttf_name
);
927 p-
>pid
= (TTF_USHORT
) pid
;
928 p-
>eid
= (TTF_USHORT
) eid
;
929 p-
>table
= xtalloc
(0x10000, long
);
930 for
(i
= 0; i
< 0x10000; ++i
)
931 p-
>table
[i
] = -1; /* unassigned yet
*/
933 /* read the subtable
*/
934 length
= get_ushort
(); /* length of subtable
*/
935 (void
) get_ushort
(); /* skip the version number
*/
936 segCount
= get_ushort
() / 2;
937 (void
) get_ushort
(); /* skip searchRange
*/
938 (void
) get_ushort
(); /* skip entrySelector
*/
939 (void
) get_ushort
(); /* skip rangeShift
*/
940 seg_tab
= xtalloc
(segCount
, seg_entry
);
941 for
(s
= seg_tab
; s
- seg_tab
< segCount
; s
++)
942 s-
>endCode
= get_ushort
();
943 (void
) get_ushort
(); /* skip reversedPad
*/
944 for
(s
= seg_tab
; s
- seg_tab
< segCount
; s
++)
945 s-
>startCode
= get_ushort
();
946 for
(s
= seg_tab
; s
- seg_tab
< segCount
; s
++)
947 s-
>idDelta
= get_ushort
();
948 for
(s
= seg_tab
; s
- seg_tab
< segCount
; s
++)
949 s-
>idRangeOffset
= get_ushort
();
950 length
-= 8 * TTF_USHORT_SIZE
+ 4 * segCount
* TTF_USHORT_SIZE
;
951 n
= length
/ TTF_USHORT_SIZE
; /* number of glyphID's
*/
952 glyphId
= xtalloc
((unsigned
) n
, TTF_USHORT
);
953 for
(i
= 0; i
< n
; i
++)
954 glyphId
[i
] = get_ushort
();
955 for
(s
= seg_tab
; s
- seg_tab
< segCount
; s
++) {
956 for
(i
= s-
>startCode
; i
<= s-
>endCode
; i
++) {
959 if
(s-
>idRangeOffset
!= 0xFFFF) {
960 if
(s-
>idRangeOffset
== 0)
961 index
= (s-
>idDelta
+ i
) & 0xFFFF;
963 k
= (i
- s-
>startCode
) + s-
>idRangeOffset
/ 2 +
964 (s
- seg_tab
) - segCount
;
965 assert
(k
>= 0 && k < n);
968 index
= (index
+ s-
>idDelta
) & 0xFFFF;
970 if
(index
>= glyphs_count
)
971 formatted_error
("ttf font",
972 "cmap issue, glyph index %li out of range [0..%i)",
973 index
, glyphs_count
);
974 if
(p-
>table
[i
] != -1)
975 formatted_warning
("ttf font",
976 "cmap issue, multiple glyphs are mapped to unicode %.4lX, %li will be used, %li is ignored)",
977 i
, p-
>table
[i
], index
);
985 aa
= avl_probe
(ttf_cmap_tree
, p
);
992 static void ttf_read_font
(void
)
995 if
(ttf_name_lookup
("PCLT", false
) == NULL)
997 if
(ttf_name_lookup
("fpgm", false
) == NULL)
999 if
(ttf_name_lookup
("cvt ", false
) == NULL)
1001 if
(ttf_name_lookup
("prep", false
) == NULL)
1013 static void ttf_reset_chksm
(PDF pdf
, dirtab_entry
* tab
)
1018 tab-
>offset
= (TTF_ULONG
) ttf_offset
();
1019 if
(tab-
>offset
% 4 != 0)
1020 formatted_warning
("ttf font","offset of `%4.4s' is not a multiple of 4", tab-
>tag
);
1024 static void ttf_set_chksm
(PDF pdf
, dirtab_entry
* tab
)
1026 tab-
>length
= (TTF_ULONG
) ttf_offset
() - tab-
>offset
;
1027 tab-
>checksum
= ttf_getchksm
(pdf
);
1030 static void ttf_copytab
(PDF pdf
, const char
*name
)
1033 dirtab_entry
*tab
= ttf_seek_tab
(name
, 0);
1034 ttf_reset_chksm
(pdf
, tab
);
1035 for
(i
= (long
) tab-
>length
; i
> 0; i--
)
1037 ttf_set_chksm
(pdf
, tab
);
1042 #define BYTE_ENCODING_LENGTH \
1043 ((256)*TTF_BYTE_SIZE
+ 3*TTF_USHORT_SIZE
)
1045 static void ttf_byte_encoding
(PDF pdf
)
1048 (void
) put_ushort
(0); /* format number
(0: byte encoding table
) */
1049 (void
) put_ushort
(BYTE_ENCODING_LENGTH
); /* length of table
*/
1050 (void
) put_ushort
(0); /* version number
*/
1051 for
(e
= ttfenc_tab
; e
- ttfenc_tab
< 256; e
++)
1052 if
(e-
>newindex
< 256) {
1053 put_byte
(e-
>newindex
);
1055 if
(e-
>name
!= notdef
)
1056 formatted_warning
("ttf font",
1057 "glyph '%s' has been mapped to '%s' in 'ttf_byte_encoding' cmap table",
1059 put_byte
(0); /* notdef
*/
1065 #define TRIMMED_TABLE_MAP_LENGTH
(TTF_USHORT_SIZE
*(5 + (256)))
1067 static void ttf_trimmed_table_map
(PDF pdf
)
1070 (void
) put_ushort
(6); /* format number
(6): trimmed table mapping
*/
1071 (void
) put_ushort
(TRIMMED_TABLE_MAP_LENGTH
);
1072 (void
) put_ushort
(0); /* version number
(0) */
1073 (void
) put_ushort
(0); /* first character code
*/
1074 (void
) put_ushort
(256); /* number of character code in table
*/
1075 for
(e
= ttfenc_tab
; e
- ttfenc_tab
< 256; e
++)
1076 (void
) put_ushort
(e-
>newindex
);
1081 #define SEG_MAP_DELTA_LENGTH
((16 + (256))*TTF_USHORT_SIZE
)
1083 static void ttf_seg_map_delta
(PDF pdf
)
1086 (void
) put_ushort
(4); /* format number
(4: segment mapping to delta values
) */
1087 (void
) put_ushort
(SEG_MAP_DELTA_LENGTH
);
1088 (void
) put_ushort
(0); /* version number
*/
1089 (void
) put_ushort
(4); /* 2*segCount
*/
1090 (void
) put_ushort
(4); /* searchRange
*/
1091 (void
) put_ushort
(1); /* entrySelector
*/
1092 (void
) put_ushort
(0); /* rangeShift
*/
1093 (void
) put_ushort
(0xF0FF); /* endCount
[0] */
1094 (void
) put_ushort
(0xFFFF); /* endCount
[1] */
1095 (void
) put_ushort
(0); /* reversedPad
*/
1096 (void
) put_ushort
(0xF000); /* startCount
[0] */
1097 (void
) put_ushort
(0xFFFF); /* startCount
[1] */
1098 (void
) put_ushort
(0); /* idDelta
[0] */
1099 (void
) put_ushort
(1); /* idDelta
[1] */
1100 (void
) put_ushort
(2 * TTF_USHORT_SIZE
); /* idRangeOffset
[0] */
1101 (void
) put_ushort
(0); /* idRangeOffset
[1] */
1102 for
(e
= ttfenc_tab
; e
- ttfenc_tab
< 256; e
++)
1103 (void
) put_ushort
(e-
>newindex
);
1108 #define CMAP_ENTRY_LENGTH
(2*TTF_USHORT_SIZE
+ TTF_ULONG_SIZE
)
1110 static void ttf_select_cmap
(void
)
1112 assert
(sizeof
(new_cmap_tab
) <= NEW_CMAP_SIZE
* sizeof
(cmap_entry
));
1113 new_cmap_tab
[0].platform_id
= 1; /* Macintosh
*/
1114 new_cmap_tab
[0].encoding_id
= 0; /* Symbol
; ignore code page
*/
1115 new_cmap_tab
[0].format
= (TTF_USHORT
) (new_glyphs_count
< 256 ?
0 /* byte encoding
*/
1116 : 6); /* trimmed table mapping
*/
1117 new_cmap_tab
[1].platform_id
= 3; /* Microsoft
*/
1118 new_cmap_tab
[1].encoding_id
= 0; /* Symbol
; ignore code page
*/
1119 new_cmap_tab
[1].format
= 4; /* segment mapping to delta
*/
1122 static void ttf_write_cmap
(PDF pdf
)
1126 dirtab_entry
*tab
= ttf_name_lookup
("cmap", true
);
1128 ttf_reset_chksm
(pdf
, tab
);
1129 (void
) put_ushort
(0); /* table version number
(0) */
1130 (void
) put_ushort
(NEW_CMAP_SIZE
); /* number of encoding tables
*/
1131 offset
= 2 * TTF_USHORT_SIZE
+ NEW_CMAP_SIZE
* CMAP_ENTRY_LENGTH
;
1132 for
(ce
= new_cmap_tab
; ce
- new_cmap_tab
< NEW_CMAP_SIZE
; ce
++) {
1133 ce-
>offset
= (TTF_ULONG
) offset
;
1134 switch
(ce-
>format
) {
1136 offset
+= BYTE_ENCODING_LENGTH
;
1139 offset
+= SEG_MAP_DELTA_LENGTH
;
1142 offset
+= TRIMMED_TABLE_MAP_LENGTH
;
1145 normal_error
("ttf font","invalid format (it should not have happened)");
1147 (void
) put_ushort
(ce-
>platform_id
);
1148 (void
) put_ushort
(ce-
>encoding_id
);
1149 put_ulong
((long
) ce-
>offset
);
1151 for
(ce
= new_cmap_tab
; ce
- new_cmap_tab
< NEW_CMAP_SIZE
; ce
++) {
1152 switch
(ce-
>format
) {
1154 ttf_byte_encoding
(pdf
);
1157 ttf_seg_map_delta
(pdf
);
1160 ttf_trimmed_table_map
(pdf
);
1164 ttf_set_chksm
(pdf
, tab
);
1169 static int prepend_subset_tags
(int index
, char
*p
)
1173 assert
(index
>= 0 && index < name_record_num && fd_cur->subset_tag != NULL);
1174 is_unicode
= (name_tab
[index
].platform_id
== 3);
1176 for
(i
= 0; i
< 6; ++i
) {
1178 *p
++ = fd_cur-
>subset_tag
[i
];
1184 strncpy
(p
, fd_cur-
>subset_tag
, 6);
1192 static void ttf_write_name
(PDF pdf
)
1196 int new_name_buf_size
;
1199 dirtab_entry
*tab
= ttf_name_lookup
("name", true
);
1200 if
(is_subsetted
(fd_cur-
>fm
)) {
1202 for
(i
= 0; i
< name_record_num
; i
++)
1203 l
+= name_tab
[i
].length
+ 14; /* maximum lengh of new stogare area
*/
1204 new_name_buf
= xtalloc
((unsigned
) l
, char
);
1205 /* additional space for subset tags
*/
1207 for
(i
= 0; i
< name_record_num
; i
++) {
1209 n-
>new_offset
= (TTF_USHORT
) (p
- new_name_buf
);
1210 if
((n-
>name_id
== 1 || n-
>name_id
== 3 ||
1211 n-
>name_id
== 4 || n-
>name_id
== 6) &&
1212 ((n-
>platform_id
== 1 && n->encoding_id == 0) ||
1213 (n-
>platform_id
== 3 && n->encoding_id == 0) ||
1214 (n-
>platform_id
== 3 && n->encoding_id == 1))) {
1215 l
= prepend_subset_tags
(i
, p
);
1219 memcpy
(p
, name_buf
+ n-
>offset
, n-
>length
);
1221 n-
>new_length
= (TTF_USHORT
) (n-
>length
+ l
);
1223 new_name_buf_size
= (int
) (p
- new_name_buf
);
1225 new_name_buf
= name_buf
;
1226 new_name_buf_size
= name_buf_size
;
1228 ttf_reset_chksm
(pdf
, tab
);
1229 (void
) put_ushort
(0); /* Format selector
*/
1230 (void
) put_ushort
(name_record_num
);
1231 (void
) put_ushort
(3 * TTF_USHORT_SIZE
+
1232 name_record_num
* 6 * TTF_USHORT_SIZE
);
1233 for
(i
= 0; i
< name_record_num
; i
++) {
1234 (void
) put_ushort
(name_tab
[i
].platform_id
);
1235 (void
) put_ushort
(name_tab
[i
].encoding_id
);
1236 (void
) put_ushort
(name_tab
[i
].language_id
);
1237 (void
) put_ushort
(name_tab
[i
].name_id
);
1238 (void
) put_ushort
(name_tab
[i
].new_length
);
1239 (void
) put_ushort
(name_tab
[i
].new_offset
);
1241 for
(p
= new_name_buf
; p
- new_name_buf
< new_name_buf_size
; p
++)
1243 ttf_set_chksm
(pdf
, tab
);
1244 if
(new_name_buf
!= name_buf
)
1245 xfree
(new_name_buf
);
1250 static void ttf_write_dirtab
(PDF pdf
)
1255 const int save_offset
= ttf_offset
();
1256 ttf_seek_outbuf
(TABDIR_OFF
);
1257 if
(is_subsetted
(fd_cur-
>fm
)) {
1258 for
(i
= 0; i
< DEFAULT_NTABS
; i
++) {
1259 tab
= ttf_name_lookup
(newtabnames
[i
], false
);
1262 for
(k
= 0; k
< 4; k
++)
1263 put_char
(tab-
>tag
[k
]);
1264 put_ulong
((long
) tab-
>checksum
);
1265 put_ulong
((long
) tab-
>offset
);
1266 put_ulong
((long
) tab-
>length
);
1269 for
(tab
= dir_tab
; tab
- dir_tab
< ntabs
; tab
++) {
1270 for
(k
= 0; k
< 4; k
++)
1271 put_char
(tab-
>tag
[k
]);
1272 put_ulong
((long
) tab-
>checksum
);
1273 put_ulong
((long
) tab-
>offset
);
1274 put_ulong
((long
) tab-
>length
);
1277 /* adjust checkSumAdjustment
*/
1280 for
(p
= (char
*) pdf-
>fb-
>data
, i
= 0; i
< (unsigned
) save_offset
;) {
1281 tmp_ulong
= (tmp_ulong
<< 8) + (TTF_ULONG
) * p
++;
1284 checksum
+= tmp_ulong
;
1289 formatted_warning
("ttf font","font length '%li' is not a multiple of 4", i
);
1290 checksum
<<= 8 * (4 - i
% 4);
1292 k
= 0xB1B0AFBA - checksum
;
1293 ttf_seek_outbuf
((int
) checkSumAdjustment_offset
);
1294 put_ulong
((long
) k
);
1295 ttf_seek_outbuf
(save_offset
);
1300 static void ttf_write_glyf
(PDF pdf
)
1305 dirtab_entry
*tab
= ttf_name_lookup
("glyf", true
);
1306 const long glyf_offset
= (long
) tab-
>offset
;
1307 const long new_glyf_offset
= ttf_offset
();
1308 ttf_reset_chksm
(pdf
, tab
);
1309 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++) {
1310 glyph_tab
[*id
].newoffset
= ttf_offset
() - new_glyf_offset
;
1311 if
(glyph_tab
[*id
].offset
!= glyph_tab
[*id
+ 1].offset
) {
1312 ttf_seek_off
(glyf_offset
+ glyph_tab
[*id
].offset
);
1314 ttf_ncopy
(pdf
, 4 * TTF_FWORD_SIZE
);
1317 flags
= copy_ushort
();
1319 if
(glyph_tab
[idx
].newindex
< 0) {
1320 glyph_tab
[idx
].newindex
= (TTF_SHORT
) new_glyphs_count
;
1321 glyph_index
[new_glyphs_count
++] = idx
;
1323 N.B.
: Here we change |new_glyphs_count|
,
1324 which appears in the condition of the |for| loop
1327 (void
) put_ushort
(glyph_tab
[idx
].newindex
);
1328 if
(flags
& ARG_1_AND_2_ARE_WORDS)
1329 ttf_ncopy
(pdf
, 2 * TTF_SHORT_SIZE
);
1331 ttf_ncopy
(pdf
, TTF_USHORT_SIZE
);
1332 if
(flags
& WE_HAVE_A_SCALE)
1333 ttf_ncopy
(pdf
, TTF_F2DOT14_SIZE
);
1334 else if
(flags
& WE_HAVE_AN_X_AND_Y_SCALE)
1335 ttf_ncopy
(pdf
, 2 * TTF_F2DOT14_SIZE
);
1336 else if
(flags
& WE_HAVE_A_TWO_BY_TWO)
1337 ttf_ncopy
(pdf
, 4 * TTF_F2DOT14_SIZE
);
1338 } while
(flags
& MORE_COMPONENTS);
1339 if
(flags
& WE_HAVE_INSTRUCTIONS)
1340 ttf_ncopy
(pdf
, copy_ushort
());
1342 ttf_ncopy
(pdf
, (int
)
1343 (glyph_tab
[*id
+ 1].offset
- glyph_tab
[*id
].offset
-
1344 TTF_USHORT_SIZE
- 4 * TTF_FWORD_SIZE
));
1347 last_glyf_offset
= (TTF_ULONG
) ttf_offset
() - (TTF_ULONG
) new_glyf_offset
;
1348 ttf_set_chksm
(pdf
, tab
);
1351 @ Reindexing glyphs
: we append index of used glyphs to |glyph_index|
1352 while going through |ttfenc_tab|. After appending a new entry to
1353 |glyph_index| we set field |newindex| of corresponding entries in both
1354 |glyph_tab| and |ttfenc_tab| to the newly created index.
1357 static void ttf_reindex_glyphs
(void
)
1363 ttf_cmap_entry
*cmap
= NULL;
1364 boolean cmap_not_found
= false
;
1366 for
(e
= ttfenc_tab
; e
- ttfenc_tab
< 256; e
++) {
1367 e-
>newindex
= 0; /* index of
".notdef" glyph
*/
1369 /* handle case of subfonts first
*/
1370 if
(is_subfont
(fd_cur-
>fm
)) {
1373 assert
(fd_cur-
>fm-
>pid
!= -1 && fd_cur->fm->eid != -1);
1374 if
(cmap
== NULL && !cmap_not_found) {
1376 ttf_read_cmap
(fd_cur-
>fm-
>ff_name
, fd_cur-
>fm-
>pid
,
1377 fd_cur-
>fm-
>eid
, true
);
1379 cmap_not_found
= true
;
1384 assert
(t
!= NULL && e->code < 0x10000);
1385 if
(t
[e-
>code
] < 0) {
1386 formatted_warning
("ttf font",
1387 "subfont %s has a wrong mapping, character %li -> 0x%4.4lX -> .notdef",
1388 fd_cur-
>fm-
>tfm_name
, (long
) (e
- ttfenc_tab
), e-
>code
);
1391 assert
(t
[e-
>code
] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */
1392 glyph
= glyph_tab
+ t
[e-
>code
];
1393 goto append_new_glyph
;
1396 /* handle case of reencoded fonts
*/
1397 if
(e-
>name
== notdef
)
1399 /* scan form `index123'
*/
1400 if
(sscanf
(e-
>name
, GLYPH_PREFIX_INDEX
"%i", &index) == 1) {
1401 if
(index
>= glyphs_count
) {
1402 formatted_warning
("ttf font","'%s' out of valid range [0..%i)", e-
>name
, glyphs_count
);
1405 glyph
= glyph_tab
+ index
;
1406 goto append_new_glyph
;
1408 /* scan form `uniABCD'
*/
1409 if
(sscanf
(e-
>name
, GLYPH_PREFIX_UNICODE
"%X", &index) == 1) {
1410 if
(cmap
== NULL && !cmap_not_found) {
1411 /* need to read the unicode mapping
, ie
(pid
,eid
) = (3,1) or
(0,3) */
1412 cmap
= ttf_read_cmap
(fd_cur-
>fm-
>ff_name
, 3, 1, false
);
1414 cmap
= ttf_read_cmap
(fd_cur-
>fm-
>ff_name
, 0, 3, false
);
1416 normal_warning
("ttf font", "no unicode mapping found, all 'uniXXXX' names will be ignored");
1417 cmap_not_found
= true
; /* once only
*/
1424 if
(t
[index
] != -1) {
1425 if
(t
[index
] >= glyphs_count
) {
1426 formatted_warning
("ttf font", "'%s' is mapped to index %li which is out of valid range [0..%i)",
1427 e-
>name
, t
[index
], glyphs_count
);
1430 glyph
= glyph_tab
+ t
[index
];
1431 goto append_new_glyph
;
1433 formatted_warning
("ttf font","unicode %s%.4X is not mapped to any glyph", GLYPH_PREFIX_UNICODE
, index
);
1437 /* look up by name
*/
1438 for
(glyph
= glyph_tab
; glyph
- glyph_tab
< glyphs_count
; glyph
++)
1439 if
(glyph-
>name
!= notdef
&& strcmp(glyph->name, e->name) == 0)
1441 if
(!(glyph
- glyph_tab
< glyphs_count
)) {
1442 formatted_warning
("ttf font","glyph '%s' not found", e-
>name
);
1446 assert
(glyph
> glyph_tab
&& glyph - glyph_tab < glyphs_count);
1447 if
(glyph-
>newindex
< 0) {
1448 glyph_index
[new_glyphs_count
] = (short
) (glyph
- glyph_tab
);
1449 glyph-
>newindex
= (TTF_SHORT
) new_glyphs_count
;
1452 e-
>newindex
= glyph-
>newindex
;
1456 @ To calculate the checkSum for the 'head' table which itself includes the
1457 checkSumAdjustment entry for the entire font
, do the following
:
1459 \item Set the checkSumAdjustment to
0.
1460 \item Calculate the checksum for all the tables including the 'head' table
1461 and enter that value into the table directory.
1462 \item Calculate the checksum for the entire font.
1463 \item Subtract that value from the hex value B1B0AFBA.
1464 \item Store the result in checkSumAdjustment.
1466 The checkSum for the 'head table which includes the checkSumAdjustment
1467 entry for the entire font is now incorrect. That is not a problem. Do not
1468 change it. An application attempting to verify that the 'head' table has
1469 not changed should calculate the checkSum for that table by not including
1470 the checkSumAdjustment value
, and compare the result with the entry in the
1473 The table directory also includes the offset of the associated tagged
1474 table from the beginning of the font file and the length of that table.
1478 static void ttf_write_head
(PDF pdf
)
1481 tab
= ttf_seek_tab
("head", 0);
1482 ttf_reset_chksm
(pdf
, tab
);
1483 ttf_ncopy
(pdf
, 2 * TTF_FIXED_SIZE
);
1484 checkSumAdjustment_offset
= (TTF_ULONG
) ttf_offset
();
1486 ttf_skip
(TTF_ULONG_SIZE
); /* skip checkSumAdjustment
*/
1487 ttf_ncopy
(pdf
, TTF_ULONG_SIZE
+ 2 * TTF_USHORT_SIZE
+ 16 +
1488 4 * TTF_FWORD_SIZE
+ 2 * TTF_USHORT_SIZE
+ TTF_SHORT_SIZE
);
1489 if
(is_subsetted
(fd_cur-
>fm
)) {
1490 (void
) put_short
(loca_format
);
1491 (void
) put_short
(0);
1493 ttf_ncopy
(pdf
, 2 * TTF_SHORT_SIZE
);
1494 ttf_set_chksm
(pdf
, tab
);
1499 static void ttf_write_hhea
(PDF pdf
)
1502 tab
= ttf_seek_tab
("hhea", 0);
1503 ttf_reset_chksm
(pdf
, tab
);
1504 ttf_ncopy
(pdf
, TTF_FIXED_SIZE
+ 3 * TTF_FWORD_SIZE
+ TTF_UFWORD_SIZE
+
1505 3 * TTF_FWORD_SIZE
+ 8 * TTF_SHORT_SIZE
);
1506 (void
) put_ushort
(new_glyphs_count
);
1507 ttf_set_chksm
(pdf
, tab
);
1512 static void ttf_write_htmx
(PDF pdf
)
1515 dirtab_entry
*tab
= ttf_seek_tab
("hmtx", 0);
1516 ttf_reset_chksm
(pdf
, tab
);
1517 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++) {
1518 put_ufword
(glyph_tab
[*id
].advWidth
);
1519 put_ufword
(glyph_tab
[*id
].lsb
);
1521 ttf_set_chksm
(pdf
, tab
);
1526 static void ttf_write_loca
(PDF pdf
)
1529 dirtab_entry
*tab
= ttf_seek_tab
("loca", 0);
1530 ttf_reset_chksm
(pdf
, tab
);
1532 if
(last_glyf_offset
>= 0x00020000 ||
(last_glyf_offset
& 1))
1535 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++)
1536 if
(glyph_tab
[*id
].newoffset
& 1) {
1540 if
(loca_format
!= 0) {
1541 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++)
1542 put_ulong
(glyph_tab
[*id
].newoffset
);
1543 put_ulong
((long
) last_glyf_offset
);
1545 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++)
1546 (void
) put_ushort
(glyph_tab
[*id
].newoffset
/ 2);
1547 (void
) put_ushort
((long
) (last_glyf_offset
/ 2));
1549 ttf_set_chksm
(pdf
, tab
);
1554 static void ttf_write_mapx
(PDF pdf
)
1556 dirtab_entry
*tab
= ttf_seek_tab
("maxp", TTF_FIXED_SIZE
+ TTF_USHORT_SIZE
);
1557 ttf_reset_chksm
(pdf
, tab
);
1558 put_fixed
(0x00010000);
1559 (void
) put_ushort
(new_glyphs_count
);
1560 ttf_ncopy
(pdf
, 13 * TTF_USHORT_SIZE
);
1561 ttf_set_chksm
(pdf
, tab
);
1566 static void ttf_write_OS2
(PDF pdf
)
1568 dirtab_entry
*tab
= ttf_seek_tab
("OS/2", 0);
1570 ttf_reset_chksm
(pdf
, tab
);
1571 version
= get_ushort
();
1573 formatted_error
("ttf font","unknown version '%.4X' of OS/2 table", version
);
1574 (void
) put_ushort
(0x0001); /* fix version to
1 */
1576 2 * TTF_USHORT_SIZE
+ 13 * TTF_SHORT_SIZE
+ 10 * TTF_BYTE_SIZE
);
1577 ttf_skip
(4 * TTF_ULONG_SIZE
); /* ulUnicodeRange
1--4 */
1578 put_ulong
(0x00000003); /* Basic Latin
+ Latin-1 Supplement
(0x0000--0x00FF) */
1579 put_ulong
(0x10000000); /* Private Use
(0xE000--0xF8FF) */
1580 put_ulong
(0x00000000);
1581 put_ulong
(0x00000000);
1582 ttf_ncopy
(pdf
, 4 * TTF_CHAR_SIZE
+ TTF_USHORT_SIZE
); /* achVendID
+ fsSelection
*/
1583 ttf_skip
(2 * TTF_USHORT_SIZE
);
1584 (void
) put_ushort
(0x0000); /* usFirstCharIndex
*/
1585 (void
) put_ushort
(0xF0FF); /* usLastCharIndex
*/
1586 ttf_ncopy
(pdf
, 5 * TTF_USHORT_SIZE
);
1587 /* for version
0 the OS
/2 table ends here
, the rest is for version
1 */
1588 put_ulong
(0x80000000); /* Symbol Character Set---don't use any code page
*/
1589 put_ulong
(0x00000000);
1590 ttf_set_chksm
(pdf
, tab
);
1595 static boolean unsafe_name
(const char
*s
)
1598 for
(p
= ambiguous_names
; *p
!= NULL; p
++)
1599 if
(strcmp
(s
, *p
) == 0)
1604 static void ttf_write_post
(PDF pdf
)
1606 dirtab_entry
*tab
= ttf_seek_tab
("post", TTF_FIXED_SIZE
);
1611 ttf_reset_chksm
(pdf
, tab
);
1612 if
(!fd_cur-
>write_ttf_glyph_names || post_format
== 0x00030000) {
1613 put_fixed
(0x00030000);
1615 TTF_FIXED_SIZE
+ 2 * TTF_FWORD_SIZE
+ 5 * TTF_ULONG_SIZE
);
1617 put_fixed
(0x00020000);
1619 TTF_FIXED_SIZE
+ 2 * TTF_FWORD_SIZE
+ 5 * TTF_ULONG_SIZE
);
1620 (void
) put_ushort
(new_glyphs_count
);
1622 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++) {
1623 glyph
= glyph_tab
+ *id
;
1624 if
(glyph-
>name_index
>= NMACGLYPHS || unsafe_name
(glyph-
>name
))
1625 glyph-
>name_index
= (TTF_USHORT
) (NMACGLYPHS
+ k
++);
1626 (void
) put_ushort
(glyph-
>name_index
);
1628 for
(id
= glyph_index
; id
- glyph_index
< new_glyphs_count
; id
++) {
1629 glyph
= glyph_tab
+ *id
;
1630 if
(glyph-
>name_index
>= NMACGLYPHS
) {
1632 l
= (int
) strlen
(s
);
1639 ttf_set_chksm
(pdf
, tab
);
1644 static void ttf_init_font
(PDF pdf
, int n
)
1647 for
(i
= 1, k
= 0; i
<= n
; i
<<= 1, k
++);
1648 put_fixed
(0x00010000); /* font version
*/
1649 (void
) put_ushort
(n
); /* number of tables
*/
1650 (void
) put_ushort
(i
<< 3); /* search range
*/
1651 (void
) put_ushort
(k
- 1); /* entry selector
*/
1652 (void
) put_ushort
((n
<< 4) - (i
<< 3)); /* range shift
*/
1653 ttf_seek_outbuf
(TABDIR_OFF
+ n
* 4 * TTF_ULONG_SIZE
);
1658 static void ttf_subset_font
(PDF pdf
)
1660 ttf_init_font
(pdf
, new_ntabs
);
1661 if
(ttf_name_lookup
("PCLT", false
) != NULL)
1662 ttf_copytab
(pdf
, "PCLT");
1663 if
(ttf_name_lookup
("fpgm", false
) != NULL)
1664 ttf_copytab
(pdf
, "fpgm");
1665 if
(ttf_name_lookup
("cvt ", false
) != NULL)
1666 ttf_copytab
(pdf
, "cvt ");
1667 if
(ttf_name_lookup
("prep", false
) != NULL)
1668 ttf_copytab
(pdf
, "prep");
1669 ttf_reindex_glyphs
();
1670 ttf_write_glyf
(pdf
);
1671 ttf_write_loca
(pdf
);
1673 ttf_write_head
(pdf
);
1674 ttf_write_hhea
(pdf
);
1675 ttf_write_htmx
(pdf
);
1676 ttf_write_mapx
(pdf
);
1677 ttf_write_name
(pdf
);
1678 ttf_write_post
(pdf
);
1679 ttf_write_cmap
(pdf
);
1680 ttf_write_dirtab
(pdf
);
1685 static void ttf_copy_font
(PDF pdf
)
1688 ttf_init_font
(pdf
, ntabs
);
1689 for
(tab
= dir_tab
; tab
- dir_tab
< ntabs
; tab
++) {
1690 if
(strncmp
(tab-
>tag
, "head", 4) == 0)
1691 ttf_write_head
(pdf
);
1693 ttf_copytab
(pdf
, tab-
>tag
);
1695 ttf_write_dirtab
(pdf
);
1700 void writettf
(PDF pdf
, fd_entry
* fd
)
1703 int file_opened
= 0;
1704 fd_cur
= fd
; /* |fd_cur| is global inside \.
{writettf.w
} */
1705 assert
(fd_cur-
>fm
!= NULL);
1706 assert
(is_truetype
(fd_cur-
>fm
));
1707 assert
(is_included
(fd_cur-
>fm
));
1709 if
(is_subsetted
(fd_cur-
>fm
) && (fd_cur->fe == NULL) && !is_subfont(fd_cur->fm)) {
1710 normal_error
("ttf font","subset must be a reencoded or a subfont");
1716 luatex_find_file
(fd_cur-
>fm-
>ff_name
, find_truetype_file_callback
);
1717 if
(cur_file_name
== NULL) {
1718 formatted_error
("ttf font","cannot find font file for reading '%s'", fd_cur-
>fm-
>ff_name
);
1720 callback_id
= callback_defined
(read_truetype_file_callback
);
1721 if
(callback_id
> 0) {
1722 if
(run_callback
(callback_id
, "S->bSd", cur_file_name
,
1723 &file_opened, &ttf_buffer, &ttf_size) &&
1724 file_opened
&& ttf_size > 0) {
1726 formatted_error
("ttf font","cannot open font file for reading '%s'", cur_file_name
);
1729 if
(!ttf_open
(cur_file_name
)) {
1730 formatted_error
("ttf font","cannot open font file for reading '%s'", cur_file_name
);
1735 if
(tracefilenames
) {
1736 if
(is_subsetted
(fd_cur-
>fm
))
1737 tex_printf
("<%s", cur_file_name
);
1739 tex_printf
("<<%s", cur_file_name
);
1741 fd_cur-
>ff_found
= true
;
1742 new_glyphs_count
= 2;
1743 new_ntabs
= DEFAULT_NTABS
;
1747 glyph_name_buf
= NULL;
1752 pdf_save_offset
(pdf
);
1755 if
(is_subsetted
(fd_cur-
>fm
)) {
1756 ttf_copy_encoding
();
1757 ttf_subset_font
(pdf
);
1760 ttf_length
= ttf_offset
();
1765 xfree
(glyph_name_buf
);
1768 if
(tracefilenames
) {
1769 if
(is_subsetted
(fd_cur-
>fm
))
1775 cur_file_name
= NULL;
1778 static void do_writeotf
(PDF pdf
, fd_entry
* fd
)
1786 tex_printf
("<<%s", cur_file_name
);
1788 /* read font parameters
*/
1789 if
(ttf_name_lookup
("head", false
) != NULL)
1791 if
(ttf_name_lookup
("hhea", false
) != NULL)
1793 if
(ttf_name_lookup
("PCLT", false
) != NULL)
1795 if
(ttf_name_lookup
("post", false
) != NULL)
1797 /* copy font file
*/
1798 tab
= ttf_seek_tab
("CFF ", 0);
1799 for
(i
= (long
) tab-
>length
; i
> 0; i--
)
1808 void writeotf
(PDF pdf
, fd_entry
* fd
)
1811 int file_opened
= 0;
1814 assert
(fd_cur-
>fm
!= NULL);
1815 assert
(is_opentype
(fd_cur-
>fm
));
1816 assert
(is_included
(fd_cur-
>fm
));
1821 luatex_find_file
(fd_cur-
>fm-
>ff_name
, find_opentype_file_callback
);
1822 if
(cur_file_name
== NULL) {
1823 formatted_error
("otf font","cannot find font file for reading '%s'", fd_cur-
>fm-
>ff_name
);
1825 callback_id
= callback_defined
(read_opentype_file_callback
);
1826 if
(callback_id
> 0) {
1827 if
(run_callback
(callback_id
, "S->bSd", cur_file_name
,
1828 &file_opened, &ttf_buffer, &ttf_size) &&
1829 file_opened
&& ttf_size > 0) {
1831 formatted_error
("otf font","cannot open font file for reading '%s'", cur_file_name
);
1834 if
(!otf_open
(cur_file_name
)) {
1835 formatted_error
("otf font","cannot open font file for reading '%s'", cur_file_name
);
1841 fd_cur-
>ff_found
= true
;
1842 do_writeotf
(pdf
, fd
);
1844 cur_file_name
= NULL;