static void deleteGSUBLigatureSubtable(otl_subtable *_subtable) { if (!_subtable) return; subtable_gsub_ligature *subtable = &(_subtable->gsub_ligature); if (subtable->from && subtable->to) { for (uint16_t j = 0; j < subtable->to->numGlyphs; j++) { caryll_delete_coverage(subtable->from[j]); } free(subtable->from); } caryll_delete_coverage(subtable->to); free(subtable); }
otl_subtable *caryll_read_gsub_ligature(font_file_pointer data, uint32_t tableLength, uint32_t offset) { otl_subtable *_subtable; NEW(_subtable); subtable_gsub_ligature *subtable = &(_subtable->gsub_ligature); subtable->from = NULL; subtable->to = NULL; checkLength(offset + 6); otl_coverage *startCoverage = caryll_read_coverage(data, tableLength, offset + read_16u(data + offset + 2)); if (!startCoverage) goto FAIL; uint16_t setCount = read_16u(data + offset + 4); if (setCount != startCoverage->numGlyphs) goto FAIL; checkLength(offset + 6 + setCount * 2); uint32_t ligatureCount = 0; for (uint16_t j = 0; j < setCount; j++) { uint32_t setOffset = offset + read_16u(data + offset + 6 + j * 2); checkLength(setOffset + 2); ligatureCount += read_16u(data + setOffset); checkLength(setOffset + 2 + read_16u(data + setOffset) * 2); } NEW(subtable->to); subtable->to->numGlyphs = ligatureCount; NEW_N(subtable->to->glyphs, ligatureCount); NEW_N(subtable->from, ligatureCount); for (uint16_t j = 0; j < ligatureCount; j++) { subtable->from[j] = NULL; }; uint16_t jj = 0; for (uint16_t j = 0; j < setCount; j++) { uint32_t setOffset = offset + read_16u(data + offset + 6 + j * 2); uint16_t lc = read_16u(data + setOffset); for (uint16_t k = 0; k < lc; k++) { uint32_t ligOffset = setOffset + read_16u(data + setOffset + 2 + k * 2); checkLength(ligOffset + 4); uint16_t ligComponents = read_16u(data + ligOffset + 2); checkLength(ligOffset + 2 + ligComponents * 2); subtable->to->glyphs[jj].gid = read_16u(data + ligOffset); subtable->to->glyphs[jj].name = NULL; NEW(subtable->from[jj]); subtable->from[jj]->numGlyphs = ligComponents; NEW_N(subtable->from[jj]->glyphs, ligComponents); subtable->from[jj]->glyphs[0].gid = startCoverage->glyphs[j].gid; subtable->from[jj]->glyphs[0].name = NULL; for (uint16_t m = 1; m < ligComponents; m++) { subtable->from[jj]->glyphs[m].gid = read_16u(data + ligOffset + 2 + m * 2); subtable->from[jj]->glyphs[m].name = NULL; } jj++; } } caryll_delete_coverage(startCoverage); return _subtable; FAIL: deleteGSUBLigatureSubtable(_subtable); return NULL; }
static void delete_mtl_subtable(otl_subtable *_subtable) { if (_subtable) { subtable_gpos_mark_to_ligature *subtable = &(_subtable->gpos_mark_to_ligature); if (subtable->marks) { caryll_delete_coverage(subtable->marks); } if (subtable->markArray) { otl_delete_mark_array(subtable->markArray); } if (subtable->bases) { if (subtable->ligArray) { for (uint16_t j = 0; j < subtable->bases->numGlyphs; j++) { delete_lig_attachment(subtable->ligArray[j]); } free(subtable->ligArray); } caryll_delete_coverage(subtable->bases); } free(_subtable); } }
bool consolidate_gsub_multi(caryll_font *font, table_otl *table, otl_subtable *_subtable, sds lookupName) { subtable_gsub_multi *subtable = &(_subtable->gsub_multi); consolidate_coverage(font, subtable->from, lookupName); for (uint16_t j = 0; j < subtable->from->numGlyphs; j++) { consolidate_coverage(font, subtable->to[j], lookupName); shrink_coverage(subtable->to[j], false); } gsub_multi_hash *h = NULL; for (uint16_t k = 0; k < subtable->from->numGlyphs; k++) { if (subtable->from->glyphs[k].name) { gsub_multi_hash *s; int fromid = subtable->from->glyphs[k].gid; HASH_FIND_INT(h, &fromid, s); if (!s) { NEW(s); s->fromid = subtable->from->glyphs[k].gid; s->fromname = subtable->from->glyphs[k].name; s->to = subtable->to[k]; HASH_ADD_INT(h, fromid, s); } else { caryll_delete_coverage(subtable->to[k]); } } else { caryll_delete_coverage(subtable->to[k]); } } HASH_SORT(h, by_from_id_multi); subtable->from->numGlyphs = HASH_COUNT(h); { gsub_multi_hash *s, *tmp; uint16_t j = 0; HASH_ITER(hh, h, s, tmp) { subtable->from->glyphs[j].gid = s->fromid; subtable->from->glyphs[j].name = s->fromname; subtable->to[j] = s->to; j++; HASH_DEL(h, s); free(s); } }
bool consolidate_gsub_ligature(caryll_font *font, table_otl *table, otl_subtable *_subtable, sds lookupName) { subtable_gsub_ligature *subtable = &(_subtable->gsub_ligature); consolidate_coverage(font, subtable->to, lookupName); for (uint16_t j = 0; j < subtable->to->numGlyphs; j++) { consolidate_coverage(font, subtable->from[j], lookupName); shrink_coverage(subtable->from[j], false); } uint16_t jj = 0; for (uint16_t k = 0; k < subtable->to->numGlyphs; k++) { if (subtable->to->glyphs[k].name && subtable->from[k]->numGlyphs) { subtable->to->glyphs[jj] = subtable->to->glyphs[k]; subtable->from[jj] = subtable->from[k]; jj++; } else { caryll_delete_coverage(subtable->from[k]); } } subtable->to->numGlyphs = jj; return false; }