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;
}
Esempio n. 2
0
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;
}