otl_subtable *caryll_read_gpos_mark_to_ligature(font_file_pointer data, uint32_t tableLength, uint32_t offset) { otl_subtable *_subtable; NEW(_subtable); subtable_gpos_mark_to_ligature *subtable = &(_subtable->gpos_mark_to_ligature); if (tableLength < offset + 12) goto FAIL; subtable->marks = caryll_read_coverage(data, tableLength, offset + read_16u(data + offset + 2)); subtable->bases = caryll_read_coverage(data, tableLength, offset + read_16u(data + offset + 4)); if (!subtable->marks || subtable->marks->numGlyphs == 0 || !subtable->bases || subtable->bases->numGlyphs == 0) goto FAIL; subtable->classCount = read_16u(data + offset + 6); uint32_t markArrayOffset = offset + read_16u(data + offset + 8); subtable->markArray = otl_read_mark_array(data, tableLength, markArrayOffset); if (!subtable->markArray || subtable->markArray->markCount != subtable->marks->numGlyphs) goto FAIL; uint32_t ligArrayOffset = offset + read_16u(data + offset + 10); checkLength(ligArrayOffset + 2 + 2 * subtable->bases->numGlyphs); if (read_16u(data + ligArrayOffset) != subtable->bases->numGlyphs) goto FAIL; NEW_N(subtable->ligArray, subtable->bases->numGlyphs); for (uint16_t j = 0; j < subtable->bases->numGlyphs; j++) { subtable->ligArray[j] = NULL; } for (uint16_t j = 0; j < subtable->bases->numGlyphs; j++) { uint32_t ligAttachOffset = ligArrayOffset + read_16u(data + ligArrayOffset + 2 + j * 2); NEW(subtable->ligArray[j]); subtable->ligArray[j]->anchors = NULL; checkLength(ligAttachOffset + 2); subtable->ligArray[j]->componentCount = read_16u(data + ligAttachOffset); checkLength(ligAttachOffset + 2 + 2 * subtable->ligArray[j]->componentCount * subtable->classCount); NEW_N(subtable->ligArray[j]->anchors, subtable->ligArray[j]->componentCount); uint32_t _offset = ligAttachOffset + 2; for (uint16_t k = 0; k < subtable->ligArray[j]->componentCount; k++) { NEW_N(subtable->ligArray[j]->anchors[k], subtable->classCount); for (uint16_t m = 0; m < subtable->classCount; m++) { uint32_t anchorOffset = read_16u(data + _offset); if (anchorOffset) { subtable->ligArray[j]->anchors[k][m] = otl_read_anchor(data, tableLength, ligAttachOffset + anchorOffset); } else { subtable->ligArray[j]->anchors[k][m].present = false; subtable->ligArray[j]->anchors[k][m].x = 0; subtable->ligArray[j]->anchors[k][m].y = 0; } _offset += 2; } } } goto OK; FAIL: DELETE(delete_mtl_subtable, _subtable); OK: return _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; }