4 * Copyright (C) 2011-2014 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 = *(p++) << 8; \
24 #define OFFSET(val, base, p) val = base; \
29 /* this simple `Coverage_table' structure wastes memory... */
31 typedef struct Coverage_table_
33 FT_UShort num_glyph_idxs
;
34 FT_UShort
* glyph_idxs
;
39 TA_read_coverage_table(FT_Byte
* p
,
44 SFNT_Table
* GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
46 FT_UShort
* glyph_idxs
;
48 FT_UShort CoverageFormat
;
52 cov
->num_glyph_idxs
= 0;
53 cov
->glyph_idxs
= NULL
;
55 VALUE(CoverageFormat
, p
);
57 if (CoverageFormat
== 1)
64 /* rough sanity checks */
65 if (GlyphCount
* 2 > GPOS_table
->len
)
66 return FT_Err_Invalid_Table
;
67 if (p
- GPOS_table
->buf
> (ptrdiff_t)(GPOS_table
->len
- GlyphCount
* 2))
68 return FT_Err_Invalid_Table
;
70 glyph_idxs
= (FT_UShort
*)malloc(GlyphCount
* sizeof (FT_UShort
));
72 return FT_Err_Out_Of_Memory
;
75 for (i
= 0; i
< GlyphCount
; i
++)
84 cov
->num_glyph_idxs
= GlyphCount
;
87 else if (CoverageFormat
== 2)
98 /* rough sanity checks */
99 if (RangeCount
* 6 > GPOS_table
->len
)
100 return FT_Err_Invalid_Table
;
101 if (p
- GPOS_table
->buf
> (ptrdiff_t)(GPOS_table
->len
- RangeCount
* 6))
102 return FT_Err_Invalid_Table
;
108 for (i
= 0; i
< RangeCount
; i
++)
110 /* collect number of glyphs */
115 return FT_Err_Invalid_Table
;
117 p
+= 2; /* skip StartCoverageIndex */
118 count
+= end
- start
+ 1;
121 glyph_idxs
= (FT_UShort
*)malloc(count
* sizeof (FT_UShort
));
123 return FT_Err_Out_Of_Memory
;
128 /* loop again over p */
129 for (i
= 0; i
< RangeCount
; i
++)
136 p
+= 2; /* skip StartCoverageIndex */
138 for (j
= start
; j
<= end
; j
++)
139 glyph_idxs
[count
++] = j
;
142 cov
->num_glyph_idxs
= count
;
145 return FT_Err_Invalid_Table
;
147 cov
->glyph_idxs
= glyph_idxs
;
153 /* We add a subglyph for each composite glyph. */
154 /* Since subglyphs must contain at least one point, */
155 /* we have to adjust all AnchorPoints in GPOS AnchorTables accordingly. */
156 /* Using the `pointsums' array of the `GLYPH' structure */
157 /* it is straightforward to do that: */
158 /* Assuming that anchor point x is in the interval */
159 /* pointsums[n] <= x < pointsums[n + 1], */
160 /* the new point index is x + n. */
163 TA_update_anchor(FT_Byte
* p
,
168 SFNT_Table
* GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
169 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
170 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
171 GLYPH
* glyph
= &data
->glyphs
[glyph_idx
];
173 FT_UShort AnchorFormat
;
176 /* nothing to do for simple glyphs */
177 if (!glyph
->num_components
)
180 VALUE(AnchorFormat
, p
);
182 if (AnchorFormat
== 2)
184 FT_UShort AnchorPoint
;
188 p
+= 4; /* skip XCoordinate and YCoordinate */
189 VALUE(AnchorPoint
, p
);
192 if (p
> GPOS_table
->buf
+ GPOS_table
->len
)
193 return FT_Err_Invalid_Table
;
195 /* search point offset */
196 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
197 if (AnchorPoint
< glyph
->pointsums
[i
])
200 *(p
- 2) = HIGH(AnchorPoint
+ i
);
201 *(p
- 1) = LOW(AnchorPoint
+ i
);
209 TA_handle_cursive_lookup(FT_Byte
* Lookup
,
214 FT_UShort SubTableCount
;
219 p
+= 2; /* skip LookupFlag */
220 VALUE(SubTableCount
, p
);
223 for (; SubTableCount
> 0; SubTableCount
--)
225 FT_Byte
* CursivePosFormat1
;
227 FT_UShort EntryExitCount
;
233 OFFSET(CursivePosFormat1
, Lookup
, p
);
235 q
= CursivePosFormat1
;
236 q
+= 2; /* skip PosFormat */
237 OFFSET(Coverage
, CursivePosFormat1
, q
);
238 VALUE(EntryExitCount
, q
);
240 error
= TA_read_coverage_table(Coverage
, &cov
, sfnt
, font
);
245 if (cov
.num_glyph_idxs
!= EntryExitCount
)
247 error
= FT_Err_Invalid_Table
;
252 for (i
= 0; i
< EntryExitCount
; i
++)
254 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
255 FT_Byte
* EntryAnchor
;
260 OFFSET(EntryAnchor
, CursivePosFormat1
, q
);
261 error
= TA_update_anchor(EntryAnchor
, glyph_idx
, sfnt
, font
);
265 OFFSET(ExitAnchor
, CursivePosFormat1
, q
);
266 error
= TA_update_anchor(ExitAnchor
, glyph_idx
, sfnt
, font
);
271 free(cov
.glyph_idxs
);
272 cov
.glyph_idxs
= NULL
;
278 free(cov
.glyph_idxs
);
284 TA_handle_markbase_lookup(FT_Byte
* Lookup
,
289 FT_UShort SubTableCount
;
294 p
+= 2; /* skip LookupFlag */
295 VALUE(SubTableCount
, p
);
298 for (; SubTableCount
> 0; SubTableCount
--)
300 FT_Byte
* MarkBasePosFormat1
;
301 FT_Byte
* MarkCoverage
;
302 FT_Byte
* BaseCoverage
;
303 FT_UShort ClassCount
;
313 OFFSET(MarkBasePosFormat1
, Lookup
, p
);
315 q
= MarkBasePosFormat1
;
316 q
+= 2; /* skip PosFormat */
317 OFFSET(MarkCoverage
, MarkBasePosFormat1
, q
);
318 OFFSET(BaseCoverage
, MarkBasePosFormat1
, q
);
319 VALUE(ClassCount
, q
);
320 OFFSET(MarkArray
, MarkBasePosFormat1
, q
);
321 OFFSET(BaseArray
, MarkBasePosFormat1
, q
);
323 error
= TA_read_coverage_table(MarkCoverage
, &cov
, sfnt
, font
);
331 if (cov
.num_glyph_idxs
!= MarkCount
)
333 error
= FT_Err_Invalid_Table
;
338 for (i
= 0; i
< MarkCount
; i
++)
340 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
345 q
+= 2; /* skip Class */
346 OFFSET(MarkAnchor
, MarkArray
, q
);
347 error
= TA_update_anchor(MarkAnchor
, glyph_idx
, sfnt
, font
);
352 free(cov
.glyph_idxs
);
354 error
= TA_read_coverage_table(BaseCoverage
, &cov
, sfnt
, font
);
362 if (cov
.num_glyph_idxs
!= BaseCount
)
364 error
= FT_Err_Invalid_Table
;
369 for (i
= 0; i
< BaseCount
; i
++)
371 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
372 FT_UShort cc
= ClassCount
;
381 OFFSET(BaseAnchor
, BaseArray
, q
);
382 error
= TA_update_anchor(BaseAnchor
, glyph_idx
, sfnt
, font
);
388 free(cov
.glyph_idxs
);
389 cov
.glyph_idxs
= NULL
;
395 free(cov
.glyph_idxs
);
401 TA_handle_marklig_lookup(FT_Byte
* Lookup
,
406 FT_UShort SubTableCount
;
411 p
+= 2; /* skip LookupFlag */
412 VALUE(SubTableCount
, p
);
415 for (; SubTableCount
> 0; SubTableCount
--)
417 FT_Byte
* MarkLigPosFormat1
;
418 FT_Byte
* MarkCoverage
;
419 FT_Byte
* LigatureCoverage
;
420 FT_UShort ClassCount
;
423 FT_UShort LigatureCount
;
424 FT_Byte
* LigatureArray
;
430 OFFSET(MarkLigPosFormat1
, Lookup
, p
);
432 q
= MarkLigPosFormat1
;
433 q
+= 2; /* skip PosFormat */
434 OFFSET(MarkCoverage
, MarkLigPosFormat1
, q
);
435 OFFSET(LigatureCoverage
, MarkLigPosFormat1
, q
);
436 VALUE(ClassCount
, q
);
437 OFFSET(MarkArray
, MarkLigPosFormat1
, q
);
438 OFFSET(LigatureArray
, MarkLigPosFormat1
, q
);
440 error
= TA_read_coverage_table(MarkCoverage
, &cov
, sfnt
, font
);
448 if (cov
.num_glyph_idxs
!= MarkCount
)
450 error
= FT_Err_Invalid_Table
;
455 for (i
= 0; i
< MarkCount
; i
++)
457 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
462 q
+= 2; /* skip Class */
463 OFFSET(MarkAnchor
, MarkArray
, q
);
464 error
= TA_update_anchor(MarkAnchor
, glyph_idx
, sfnt
, font
);
469 free(cov
.glyph_idxs
);
471 error
= TA_read_coverage_table(LigatureCoverage
, &cov
, sfnt
, font
);
476 VALUE(LigatureCount
, q
);
479 if (cov
.num_glyph_idxs
!= LigatureCount
)
481 error
= FT_Err_Invalid_Table
;
486 for (i
= 0; i
< LigatureCount
; i
++)
488 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
489 FT_Byte
* LigatureAttach
;
490 FT_UShort ComponentCount
;
494 OFFSET(LigatureAttach
, LigatureArray
, q
);
497 VALUE(ComponentCount
, r
);
500 for (; ComponentCount
> 0; ComponentCount
--)
502 FT_UShort cc
= ClassCount
;
507 FT_Byte
* LigatureAnchor
;
511 OFFSET(LigatureAnchor
, LigatureAttach
, r
);
512 error
= TA_update_anchor(LigatureAnchor
, glyph_idx
, sfnt
, font
);
519 free(cov
.glyph_idxs
);
520 cov
.glyph_idxs
= NULL
;
526 free(cov
.glyph_idxs
);
532 TA_handle_markmark_lookup(FT_Byte
* Lookup
,
537 FT_UShort SubTableCount
;
542 p
+= 2; /* skip LookupFlag */
543 VALUE(SubTableCount
, p
);
546 for (; SubTableCount
> 0; SubTableCount
--)
548 FT_Byte
* MarkMarkPosFormat1
;
549 FT_Byte
* Mark1Coverage
;
550 FT_Byte
* Mark2Coverage
;
551 FT_UShort ClassCount
;
552 FT_UShort Mark1Count
;
554 FT_UShort Mark2Count
;
561 OFFSET(MarkMarkPosFormat1
, Lookup
, p
);
563 q
= MarkMarkPosFormat1
;
564 q
+= 2; /* skip PosFormat */
565 OFFSET(Mark1Coverage
, MarkMarkPosFormat1
, q
);
566 OFFSET(Mark2Coverage
, MarkMarkPosFormat1
, q
);
567 VALUE(ClassCount
, q
);
568 OFFSET(Mark1Array
, MarkMarkPosFormat1
, q
);
569 OFFSET(Mark2Array
, MarkMarkPosFormat1
, q
);
571 error
= TA_read_coverage_table(Mark1Coverage
, &cov
, sfnt
, font
);
576 VALUE(Mark1Count
, q
);
579 if (cov
.num_glyph_idxs
!= Mark1Count
)
581 error
= FT_Err_Invalid_Table
;
586 for (i
= 0; i
< Mark1Count
; i
++)
588 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
589 FT_Byte
* Mark1Anchor
;
593 q
+= 2; /* skip Class */
594 OFFSET(Mark1Anchor
, Mark1Array
, q
);
595 error
= TA_update_anchor(Mark1Anchor
, glyph_idx
, sfnt
, font
);
600 free(cov
.glyph_idxs
);
602 error
= TA_read_coverage_table(Mark2Coverage
, &cov
, sfnt
, font
);
607 VALUE(Mark2Count
, q
);
610 if (cov
.num_glyph_idxs
!= Mark2Count
)
612 error
= FT_Err_Invalid_Table
;
617 for (i
= 0; i
< Mark2Count
; i
++)
619 FT_UShort glyph_idx
= cov
.glyph_idxs
[i
];
620 FT_UShort cc
= ClassCount
;
625 FT_Byte
* Mark2Anchor
;
629 OFFSET(Mark2Anchor
, Mark2Array
, q
);
630 error
= TA_update_anchor(Mark2Anchor
, glyph_idx
, sfnt
, font
);
636 free(cov
.glyph_idxs
);
637 cov
.glyph_idxs
= NULL
;
643 free(cov
.glyph_idxs
);
654 TA_sfnt_update_GPOS_table(SFNT
* sfnt
,
657 SFNT_Table
* GPOS_table
;
661 FT_UShort LookupCount
;
665 if (sfnt
->GPOS_idx
== MISSING
)
668 GPOS_table
= &font
->tables
[sfnt
->GPOS_idx
];
669 buf
= GPOS_table
->buf
;
672 if (GPOS_table
->processed
)
675 p
+= 8; /* skip Version, ScriptList, and FeatureList */
676 OFFSET(LookupList
, buf
, p
);
679 VALUE(LookupCount
, p
);
682 for (; LookupCount
> 0; LookupCount
--)
685 FT_UShort LookupType
;
687 FT_Error error
= TA_Err_Ok
;
690 OFFSET(Lookup
, LookupList
, p
);
693 VALUE(LookupType
, q
);
695 if (LookupType
== Cursive
)
696 error
= TA_handle_cursive_lookup(Lookup
, q
, sfnt
, font
);
697 else if (LookupType
== MarkBase
)
698 error
= TA_handle_markbase_lookup(Lookup
, q
, sfnt
, font
);
699 else if (LookupType
== MarkLig
)
700 error
= TA_handle_marklig_lookup(Lookup
, q
, sfnt
, font
);
701 else if (LookupType
== MarkMark
)
702 error
= TA_handle_markmark_lookup(Lookup
, q
, sfnt
, font
);
708 GPOS_table
->checksum
= TA_table_compute_checksum(GPOS_table
->buf
,
710 GPOS_table
->processed
= 1;
715 /* end of tagpos.c */