4 * Copyright (C) 2011-2022 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
19 /* the code below contains many redundancies; */
20 /* it has been written for clarity */
22 #define VALUE(val, p) val = NEXT_USHORT(p)
23 #define OFFSET(val, base, p) val = base + NEXT_USHORT(p)
26 /* this simple `Coverage_table' structure wastes memory... */
28 typedef struct Coverage_table_
30 FT_UShort num_glyph_idxs
;
31 FT_UShort
* glyph_idxs
;
36 TA_read_coverage_table(FT_Byte
* p
,
41 SFNT_Table
* GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
43 FT_UShort
* glyph_idxs
;
45 FT_UShort CoverageFormat
;
49 cov
->num_glyph_idxs
= 0;
50 cov
->glyph_idxs
= NULL
;
52 VALUE(CoverageFormat
, p
);
54 if (CoverageFormat
== 1)
61 /* rough sanity checks */
62 if (GlyphCount
* 2 > GPOS_table
->len
)
63 return FT_Err_Invalid_Table
;
64 if (p
- GPOS_table
->buf
> (ptrdiff_t)(GPOS_table
->len
- GlyphCount
* 2))
65 return FT_Err_Invalid_Table
;
67 glyph_idxs
= (FT_UShort
*)malloc(GlyphCount
* sizeof (FT_UShort
));
69 return FT_Err_Out_Of_Memory
;
72 for (i
= 0; i
< GlyphCount
; i
++)
81 cov
->num_glyph_idxs
= GlyphCount
;
84 else if (CoverageFormat
== 2)
95 /* rough sanity checks */
96 if (RangeCount
* 6 > GPOS_table
->len
)
97 return FT_Err_Invalid_Table
;
98 if (p
- GPOS_table
->buf
> (ptrdiff_t)(GPOS_table
->len
- RangeCount
* 6))
99 return FT_Err_Invalid_Table
;
105 for (i
= 0; i
< RangeCount
; i
++)
107 /* collect number of glyphs */
112 return FT_Err_Invalid_Table
;
114 p
+= 2; /* skip StartCoverageIndex */
115 count
+= end
- start
+ 1;
118 glyph_idxs
= (FT_UShort
*)malloc(count
* sizeof (FT_UShort
));
120 return FT_Err_Out_Of_Memory
;
125 /* loop again over p */
126 for (i
= 0; i
< RangeCount
; i
++)
133 p
+= 2; /* skip StartCoverageIndex */
135 for (j
= start
; j
<= end
; j
++)
136 glyph_idxs
[count
++] = j
;
139 cov
->num_glyph_idxs
= count
;
142 return FT_Err_Invalid_Table
;
144 cov
->glyph_idxs
= glyph_idxs
;
150 /* We add a subglyph for each composite glyph. */
151 /* Since subglyphs must contain at least one point, */
152 /* we have to adjust all AnchorPoints in GPOS AnchorTables accordingly. */
153 /* Using the `pointsums' array of the `GLYPH' structure */
154 /* it is straightforward to do that: */
155 /* Assuming that anchor point x is in the interval */
156 /* pointsums[n] <= x < pointsums[n + 1], */
157 /* the new point index is x + n. */
160 TA_update_anchor(FT_Byte
* p
,
165 SFNT_Table
* GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
166 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
167 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
168 GLYPH
* glyph
= &data
->glyphs
[glyph_idx
];
170 FT_UShort AnchorFormat
;
173 /* nothing to do for simple glyphs */
174 if (!glyph
->num_components
)
177 VALUE(AnchorFormat
, p
);
179 if (AnchorFormat
== 2)
181 FT_UShort AnchorPoint
;
185 p
+= 4; /* skip XCoordinate and YCoordinate */
186 VALUE(AnchorPoint
, p
);
189 if (p
> GPOS_table
->buf
+ GPOS_table
->len
)
190 return FT_Err_Invalid_Table
;
192 /* search point offset */
193 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
194 if (AnchorPoint
< glyph
->pointsums
[i
])
197 *(p
- 2) = HIGH(AnchorPoint
+ i
);
198 *(p
- 1) = LOW(AnchorPoint
+ i
);
206 TA_handle_cursive_lookup(FT_Byte
* Lookup
,
211 FT_UShort SubTableCount
;
216 p
+= 2; /* skip LookupFlag */
217 VALUE(SubTableCount
, p
);
220 for (; SubTableCount
> 0; SubTableCount
--)
222 FT_Byte
* CursivePosFormat1
;
224 FT_UShort EntryExitCount
;
230 OFFSET(CursivePosFormat1
, Lookup
, p
);
232 q
= CursivePosFormat1
;
233 q
+= 2; /* skip PosFormat */
234 OFFSET(Coverage
, CursivePosFormat1
, q
);
235 VALUE(EntryExitCount
, q
);
237 error
= TA_read_coverage_table(Coverage
, &cov
, sfnt
, font
);
242 if (cov
.num_glyph_idxs
!= EntryExitCount
)
244 error
= FT_Err_Invalid_Table
;
249 for (i
= 0; i
< EntryExitCount
; i
++)
251 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
252 FT_Byte
* EntryAnchor
;
256 OFFSET(EntryAnchor
, CursivePosFormat1
, q
);
257 error
= TA_update_anchor(EntryAnchor
, glyph_idx
, sfnt
, font
);
261 OFFSET(ExitAnchor
, CursivePosFormat1
, q
);
262 error
= TA_update_anchor(ExitAnchor
, glyph_idx
, sfnt
, font
);
267 free(cov
.glyph_idxs
);
268 cov
.glyph_idxs
= NULL
;
274 free(cov
.glyph_idxs
);
280 TA_handle_markbase_lookup(FT_Byte
* Lookup
,
285 FT_UShort SubTableCount
;
290 p
+= 2; /* skip LookupFlag */
291 VALUE(SubTableCount
, p
);
294 for (; SubTableCount
> 0; SubTableCount
--)
296 FT_Byte
* MarkBasePosFormat1
;
297 FT_Byte
* MarkCoverage
;
298 FT_Byte
* BaseCoverage
;
299 FT_UShort ClassCount
;
309 OFFSET(MarkBasePosFormat1
, Lookup
, p
);
311 q
= MarkBasePosFormat1
;
312 q
+= 2; /* skip PosFormat */
313 OFFSET(MarkCoverage
, MarkBasePosFormat1
, q
);
314 OFFSET(BaseCoverage
, MarkBasePosFormat1
, q
);
315 VALUE(ClassCount
, q
);
316 OFFSET(MarkArray
, MarkBasePosFormat1
, q
);
317 OFFSET(BaseArray
, MarkBasePosFormat1
, q
);
319 error
= TA_read_coverage_table(MarkCoverage
, &cov
, sfnt
, font
);
327 if (cov
.num_glyph_idxs
!= MarkCount
)
329 error
= FT_Err_Invalid_Table
;
334 for (i
= 0; i
< MarkCount
; i
++)
336 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
340 q
+= 2; /* skip Class */
341 OFFSET(MarkAnchor
, MarkArray
, q
);
342 error
= TA_update_anchor(MarkAnchor
, glyph_idx
, sfnt
, font
);
347 free(cov
.glyph_idxs
);
349 error
= TA_read_coverage_table(BaseCoverage
, &cov
, sfnt
, font
);
357 if (cov
.num_glyph_idxs
!= BaseCount
)
359 error
= FT_Err_Invalid_Table
;
364 for (i
= 0; i
< BaseCount
; i
++)
366 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
367 FT_UShort cc
= ClassCount
;
375 OFFSET(BaseAnchor
, BaseArray
, q
);
376 error
= TA_update_anchor(BaseAnchor
, glyph_idx
, sfnt
, font
);
382 free(cov
.glyph_idxs
);
383 cov
.glyph_idxs
= NULL
;
389 free(cov
.glyph_idxs
);
395 TA_handle_marklig_lookup(FT_Byte
* Lookup
,
400 FT_UShort SubTableCount
;
405 p
+= 2; /* skip LookupFlag */
406 VALUE(SubTableCount
, p
);
409 for (; SubTableCount
> 0; SubTableCount
--)
411 FT_Byte
* MarkLigPosFormat1
;
412 FT_Byte
* MarkCoverage
;
413 FT_Byte
* LigatureCoverage
;
414 FT_UShort ClassCount
;
417 FT_UShort LigatureCount
;
418 FT_Byte
* LigatureArray
;
424 OFFSET(MarkLigPosFormat1
, Lookup
, p
);
426 q
= MarkLigPosFormat1
;
427 q
+= 2; /* skip PosFormat */
428 OFFSET(MarkCoverage
, MarkLigPosFormat1
, q
);
429 OFFSET(LigatureCoverage
, MarkLigPosFormat1
, q
);
430 VALUE(ClassCount
, q
);
431 OFFSET(MarkArray
, MarkLigPosFormat1
, q
);
432 OFFSET(LigatureArray
, MarkLigPosFormat1
, q
);
434 error
= TA_read_coverage_table(MarkCoverage
, &cov
, sfnt
, font
);
442 if (cov
.num_glyph_idxs
!= MarkCount
)
444 error
= FT_Err_Invalid_Table
;
449 for (i
= 0; i
< MarkCount
; i
++)
451 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
455 q
+= 2; /* skip Class */
456 OFFSET(MarkAnchor
, MarkArray
, q
);
457 error
= TA_update_anchor(MarkAnchor
, glyph_idx
, sfnt
, font
);
462 free(cov
.glyph_idxs
);
464 error
= TA_read_coverage_table(LigatureCoverage
, &cov
, sfnt
, font
);
469 VALUE(LigatureCount
, q
);
472 if (cov
.num_glyph_idxs
!= LigatureCount
)
474 error
= FT_Err_Invalid_Table
;
479 for (i
= 0; i
< LigatureCount
; i
++)
481 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
482 FT_Byte
* LigatureAttach
;
483 FT_UShort ComponentCount
;
487 OFFSET(LigatureAttach
, LigatureArray
, q
);
490 VALUE(ComponentCount
, r
);
493 for (; ComponentCount
> 0; ComponentCount
--)
495 FT_UShort cc
= ClassCount
;
500 FT_Byte
* LigatureAnchor
;
503 OFFSET(LigatureAnchor
, LigatureAttach
, r
);
504 error
= TA_update_anchor(LigatureAnchor
, glyph_idx
, sfnt
, font
);
511 free(cov
.glyph_idxs
);
512 cov
.glyph_idxs
= NULL
;
518 free(cov
.glyph_idxs
);
524 TA_handle_markmark_lookup(FT_Byte
* Lookup
,
529 FT_UShort SubTableCount
;
534 p
+= 2; /* skip LookupFlag */
535 VALUE(SubTableCount
, p
);
538 for (; SubTableCount
> 0; SubTableCount
--)
540 FT_Byte
* MarkMarkPosFormat1
;
541 FT_Byte
* Mark1Coverage
;
542 FT_Byte
* Mark2Coverage
;
543 FT_UShort ClassCount
;
544 FT_UShort Mark1Count
;
546 FT_UShort Mark2Count
;
553 OFFSET(MarkMarkPosFormat1
, Lookup
, p
);
555 q
= MarkMarkPosFormat1
;
556 q
+= 2; /* skip PosFormat */
557 OFFSET(Mark1Coverage
, MarkMarkPosFormat1
, q
);
558 OFFSET(Mark2Coverage
, MarkMarkPosFormat1
, q
);
559 VALUE(ClassCount
, q
);
560 OFFSET(Mark1Array
, MarkMarkPosFormat1
, q
);
561 OFFSET(Mark2Array
, MarkMarkPosFormat1
, q
);
563 error
= TA_read_coverage_table(Mark1Coverage
, &cov
, sfnt
, font
);
568 VALUE(Mark1Count
, q
);
571 if (cov
.num_glyph_idxs
!= Mark1Count
)
573 error
= FT_Err_Invalid_Table
;
578 for (i
= 0; i
< Mark1Count
; i
++)
580 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
581 FT_Byte
* Mark1Anchor
;
584 q
+= 2; /* skip Class */
585 OFFSET(Mark1Anchor
, Mark1Array
, q
);
586 error
= TA_update_anchor(Mark1Anchor
, glyph_idx
, sfnt
, font
);
591 free(cov
.glyph_idxs
);
593 error
= TA_read_coverage_table(Mark2Coverage
, &cov
, sfnt
, font
);
598 VALUE(Mark2Count
, q
);
601 if (cov
.num_glyph_idxs
!= Mark2Count
)
603 error
= FT_Err_Invalid_Table
;
608 for (i
= 0; i
< Mark2Count
; i
++)
610 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
611 FT_UShort cc
= ClassCount
;
616 FT_Byte
* Mark2Anchor
;
619 OFFSET(Mark2Anchor
, Mark2Array
, q
);
620 error
= TA_update_anchor(Mark2Anchor
, glyph_idx
, sfnt
, font
);
626 free(cov
.glyph_idxs
);
627 cov
.glyph_idxs
= NULL
;
633 free(cov
.glyph_idxs
);
644 TA_sfnt_update_GPOS_table(SFNT
* sfnt
,
647 SFNT_Table
* GPOS_table
;
651 FT_UShort LookupCount
;
655 if (sfnt
->GPOS_idx
== MISSING
)
658 GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
659 buf
= GPOS_table
->buf
;
662 if (GPOS_table
->processed
)
665 p
+= 8; /* skip Version, ScriptList, and FeatureList */
666 OFFSET(LookupList
, buf
, p
);
669 VALUE(LookupCount
, p
);
672 for (; LookupCount
> 0; LookupCount
--)
675 FT_UShort LookupType
;
677 FT_Error error
= TA_Err_Ok
;
680 OFFSET(Lookup
, LookupList
, p
);
683 VALUE(LookupType
, q
);
685 if (LookupType
== Cursive
)
686 error
= TA_handle_cursive_lookup(Lookup
, q
, sfnt
, font
);
687 else if (LookupType
== MarkBase
)
688 error
= TA_handle_markbase_lookup(Lookup
, q
, sfnt
, font
);
689 else if (LookupType
== MarkLig
)
690 error
= TA_handle_marklig_lookup(Lookup
, q
, sfnt
, font
);
691 else if (LookupType
== MarkMark
)
692 error
= TA_handle_markmark_lookup(Lookup
, q
, sfnt
, font
);
698 GPOS_table
->checksum
= TA_table_compute_checksum(GPOS_table
->buf
,
700 GPOS_table
->processed
= 1;
705 /* end of tagpos.c */