159d709d503bab6e2b61931737e662dd293b40578ccornelius/* 259d709d503bab6e2b61931737e662dd293b40578ccornelius ******************************************************************************* 359d709d503bab6e2b61931737e662dd293b40578ccornelius * 40596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * © 2016 and later: Unicode, Inc. and others. 564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * License & terms of use: http://www.unicode.org/copyright.html#License 664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * 764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert ******************************************************************************* 864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert ******************************************************************************* 964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * 1059d709d503bab6e2b61931737e662dd293b40578ccornelius * Copyright (C) 1999-2013, International Business Machines 1159d709d503bab6e2b61931737e662dd293b40578ccornelius * Corporation and others. All Rights Reserved. 1259d709d503bab6e2b61931737e662dd293b40578ccornelius * 1359d709d503bab6e2b61931737e662dd293b40578ccornelius ******************************************************************************* 1459d709d503bab6e2b61931737e662dd293b40578ccornelius */ 1559d709d503bab6e2b61931737e662dd293b40578ccornelius 1659d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/utypes.h" 1759d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/uclean.h" 1859d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/uchar.h" 1959d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/unistr.h" 2059d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/uscript.h" 2159d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/putil.h" 2259d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/ctest.h" 2359d709d503bab6e2b61931737e662dd293b40578ccornelius 2459d709d503bab6e2b61931737e662dd293b40578ccornelius#include "layout/LETypes.h" 2559d709d503bab6e2b61931737e662dd293b40578ccornelius#include "layout/LEScripts.h" 2659d709d503bab6e2b61931737e662dd293b40578ccornelius 2759d709d503bab6e2b61931737e662dd293b40578ccornelius#include "letsutil.h" 2859d709d503bab6e2b61931737e662dd293b40578ccornelius#include "letest.h" 2959d709d503bab6e2b61931737e662dd293b40578ccornelius 3059d709d503bab6e2b61931737e662dd293b40578ccornelius#include "xmlreader.h" 3159d709d503bab6e2b61931737e662dd293b40578ccornelius 3259d709d503bab6e2b61931737e662dd293b40578ccornelius#include "xmlparser.h" 3359d709d503bab6e2b61931737e662dd293b40578ccornelius 3459d709d503bab6e2b61931737e662dd293b40578ccornelius#include <stdlib.h> 3559d709d503bab6e2b61931737e662dd293b40578ccornelius#include <stdio.h> 3659d709d503bab6e2b61931737e662dd293b40578ccornelius#include <string.h> 3759d709d503bab6e2b61931737e662dd293b40578ccornelius 3859d709d503bab6e2b61931737e662dd293b40578ccornelius//U_NAMESPACE_USE 3959d709d503bab6e2b61931737e662dd293b40578ccornelius 4059d709d503bab6e2b61931737e662dd293b40578ccornelius#define CH_COMMA 0x002C 4159d709d503bab6e2b61931737e662dd293b40578ccornelius 4259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize) 4359d709d503bab6e2b61931737e662dd293b40578ccornelius{ 4459d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t offset = -1; 4559d709d503bab6e2b61931737e662dd293b40578ccornelius 4659d709d503bab6e2b61931737e662dd293b40578ccornelius arraySize = 1; 4759d709d503bab6e2b61931737e662dd293b40578ccornelius while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) { 4859d709d503bab6e2b61931737e662dd293b40578ccornelius arraySize += 1; 4959d709d503bab6e2b61931737e662dd293b40578ccornelius } 5059d709d503bab6e2b61931737e662dd293b40578ccornelius 5159d709d503bab6e2b61931737e662dd293b40578ccornelius le_uint32 *array = NEW_ARRAY(le_uint32, arraySize); 5259d709d503bab6e2b61931737e662dd293b40578ccornelius char number[16]; 5359d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 count = 0; 5459d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 start = 0, end = 0; 5559d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 len = 0; 5659d709d503bab6e2b61931737e662dd293b40578ccornelius 5759d709d503bab6e2b61931737e662dd293b40578ccornelius // trim leading whitespace 5859d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[start])) { 5959d709d503bab6e2b61931737e662dd293b40578ccornelius start += 1; 6059d709d503bab6e2b61931737e662dd293b40578ccornelius } 6159d709d503bab6e2b61931737e662dd293b40578ccornelius 6259d709d503bab6e2b61931737e662dd293b40578ccornelius while((end = numbers.indexOf(CH_COMMA, start)) >= 0) { 6359d709d503bab6e2b61931737e662dd293b40578ccornelius len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV); 6459d709d503bab6e2b61931737e662dd293b40578ccornelius number[len] = '\0'; 6559d709d503bab6e2b61931737e662dd293b40578ccornelius start = end + 1; 6659d709d503bab6e2b61931737e662dd293b40578ccornelius 6759d709d503bab6e2b61931737e662dd293b40578ccornelius sscanf(number, "%x", &array[count++]); 6859d709d503bab6e2b61931737e662dd293b40578ccornelius 6959d709d503bab6e2b61931737e662dd293b40578ccornelius // trim whitespace following the comma 7059d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[start])) { 7159d709d503bab6e2b61931737e662dd293b40578ccornelius start += 1; 7259d709d503bab6e2b61931737e662dd293b40578ccornelius } 7359d709d503bab6e2b61931737e662dd293b40578ccornelius } 7459d709d503bab6e2b61931737e662dd293b40578ccornelius 7559d709d503bab6e2b61931737e662dd293b40578ccornelius // trim trailing whitespace 7659d709d503bab6e2b61931737e662dd293b40578ccornelius end = numbers.length(); 7759d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[end - 1])) { 7859d709d503bab6e2b61931737e662dd293b40578ccornelius end -= 1; 7959d709d503bab6e2b61931737e662dd293b40578ccornelius } 8059d709d503bab6e2b61931737e662dd293b40578ccornelius 8159d709d503bab6e2b61931737e662dd293b40578ccornelius len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV); 8259d709d503bab6e2b61931737e662dd293b40578ccornelius number[len] = '\0'; 8359d709d503bab6e2b61931737e662dd293b40578ccornelius sscanf(number, "%x", &array[count]); 8459d709d503bab6e2b61931737e662dd293b40578ccornelius 8559d709d503bab6e2b61931737e662dd293b40578ccornelius return array; 8659d709d503bab6e2b61931737e662dd293b40578ccornelius} 8759d709d503bab6e2b61931737e662dd293b40578ccornelius 8859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize) 8959d709d503bab6e2b61931737e662dd293b40578ccornelius{ 9059d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t offset = -1; 9159d709d503bab6e2b61931737e662dd293b40578ccornelius 9259d709d503bab6e2b61931737e662dd293b40578ccornelius arraySize = 1; 9359d709d503bab6e2b61931737e662dd293b40578ccornelius while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) { 9459d709d503bab6e2b61931737e662dd293b40578ccornelius arraySize += 1; 9559d709d503bab6e2b61931737e662dd293b40578ccornelius } 9659d709d503bab6e2b61931737e662dd293b40578ccornelius 9759d709d503bab6e2b61931737e662dd293b40578ccornelius float *array = NEW_ARRAY(float, arraySize); 9859d709d503bab6e2b61931737e662dd293b40578ccornelius char number[32]; 9959d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 count = 0; 10059d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 start = 0, end = 0; 10159d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 len = 0; 10259d709d503bab6e2b61931737e662dd293b40578ccornelius 10359d709d503bab6e2b61931737e662dd293b40578ccornelius // trim leading whitespace 10459d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[start])) { 10559d709d503bab6e2b61931737e662dd293b40578ccornelius start += 1; 10659d709d503bab6e2b61931737e662dd293b40578ccornelius } 10759d709d503bab6e2b61931737e662dd293b40578ccornelius 10859d709d503bab6e2b61931737e662dd293b40578ccornelius while((end = numbers.indexOf(CH_COMMA, start)) >= 0) { 10959d709d503bab6e2b61931737e662dd293b40578ccornelius len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV); 11059d709d503bab6e2b61931737e662dd293b40578ccornelius number[len] = '\0'; 11159d709d503bab6e2b61931737e662dd293b40578ccornelius start = end + 1; 11259d709d503bab6e2b61931737e662dd293b40578ccornelius 11359d709d503bab6e2b61931737e662dd293b40578ccornelius sscanf(number, "%f", &array[count++]); 11459d709d503bab6e2b61931737e662dd293b40578ccornelius 11559d709d503bab6e2b61931737e662dd293b40578ccornelius // trim whiteapce following the comma 11659d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[start])) { 11759d709d503bab6e2b61931737e662dd293b40578ccornelius start += 1; 11859d709d503bab6e2b61931737e662dd293b40578ccornelius } 11959d709d503bab6e2b61931737e662dd293b40578ccornelius } 12059d709d503bab6e2b61931737e662dd293b40578ccornelius 12159d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[start])) { 12259d709d503bab6e2b61931737e662dd293b40578ccornelius start += 1; 12359d709d503bab6e2b61931737e662dd293b40578ccornelius } 12459d709d503bab6e2b61931737e662dd293b40578ccornelius 12559d709d503bab6e2b61931737e662dd293b40578ccornelius // trim trailing whitespace 12659d709d503bab6e2b61931737e662dd293b40578ccornelius end = numbers.length(); 12759d709d503bab6e2b61931737e662dd293b40578ccornelius while(u_isUWhiteSpace(numbers[end - 1])) { 12859d709d503bab6e2b61931737e662dd293b40578ccornelius end -= 1; 12959d709d503bab6e2b61931737e662dd293b40578ccornelius } 13059d709d503bab6e2b61931737e662dd293b40578ccornelius 13159d709d503bab6e2b61931737e662dd293b40578ccornelius len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV); 13259d709d503bab6e2b61931737e662dd293b40578ccornelius number[len] = '\0'; 13359d709d503bab6e2b61931737e662dd293b40578ccornelius sscanf(number, "%f", &array[count]); 13459d709d503bab6e2b61931737e662dd293b40578ccornelius 13559d709d503bab6e2b61931737e662dd293b40578ccornelius return array; 13659d709d503bab6e2b61931737e662dd293b40578ccornelius} 13759d709d503bab6e2b61931737e662dd293b40578ccornelius 13859d709d503bab6e2b61931737e662dd293b40578ccorneliusU_CDECL_BEGIN 13959d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid readTestFile(const char *testFilePath, TestCaseCallback callback) 14059d709d503bab6e2b61931737e662dd293b40578ccornelius{ 14159d709d503bab6e2b61931737e662dd293b40578ccornelius#if !UCONFIG_NO_REGULAR_EXPRESSIONS 14259d709d503bab6e2b61931737e662dd293b40578ccornelius UErrorCode status = U_ZERO_ERROR; 14359d709d503bab6e2b61931737e662dd293b40578ccornelius UXMLParser *parser = UXMLParser::createParser(status); 14459d709d503bab6e2b61931737e662dd293b40578ccornelius UXMLElement *root = parser->parseFile(testFilePath, status); 14559d709d503bab6e2b61931737e662dd293b40578ccornelius 14659d709d503bab6e2b61931737e662dd293b40578ccornelius if (root == NULL) { 14759d709d503bab6e2b61931737e662dd293b40578ccornelius log_err("Could not open the test data file: %s\n", testFilePath); 14859d709d503bab6e2b61931737e662dd293b40578ccornelius delete parser; 14959d709d503bab6e2b61931737e662dd293b40578ccornelius return; 15059d709d503bab6e2b61931737e662dd293b40578ccornelius } 15159d709d503bab6e2b61931737e662dd293b40578ccornelius 15259d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString test_case = UNICODE_STRING_SIMPLE("test-case"); 15359d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString test_text = UNICODE_STRING_SIMPLE("test-text"); 15459d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString test_font = UNICODE_STRING_SIMPLE("test-font"); 15559d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString result_glyphs = UNICODE_STRING_SIMPLE("result-glyphs"); 15659d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString result_indices = UNICODE_STRING_SIMPLE("result-indices"); 15759d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions"); 15859d709d503bab6e2b61931737e662dd293b40578ccornelius 15959d709d503bab6e2b61931737e662dd293b40578ccornelius // test-case attributes 16059d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString id_attr = UNICODE_STRING_SIMPLE("id"); 16159d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString script_attr = UNICODE_STRING_SIMPLE("script"); 16259d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString lang_attr = UNICODE_STRING_SIMPLE("lang"); 16359d709d503bab6e2b61931737e662dd293b40578ccornelius 16459d709d503bab6e2b61931737e662dd293b40578ccornelius // test-font attributes 16559d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString name_attr = UNICODE_STRING_SIMPLE("name"); 16659d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString ver_attr = UNICODE_STRING_SIMPLE("version"); 16759d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString cksum_attr = UNICODE_STRING_SIMPLE("checksum"); 16859d709d503bab6e2b61931737e662dd293b40578ccornelius 16959d709d503bab6e2b61931737e662dd293b40578ccornelius const UXMLElement *testCase; 17059d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t tc = 0; 17159d709d503bab6e2b61931737e662dd293b40578ccornelius 17259d709d503bab6e2b61931737e662dd293b40578ccornelius while((testCase = root->nextChildElement(tc)) != NULL) { 17359d709d503bab6e2b61931737e662dd293b40578ccornelius if (testCase->getTagName().compare(test_case) == 0) { 17459d709d503bab6e2b61931737e662dd293b40578ccornelius char *id = getCString(testCase->getAttribute(id_attr)); 17559d709d503bab6e2b61931737e662dd293b40578ccornelius char *script = getCString(testCase->getAttribute(script_attr)); 17659d709d503bab6e2b61931737e662dd293b40578ccornelius char *lang = getCString(testCase->getAttribute(lang_attr)); 17759d709d503bab6e2b61931737e662dd293b40578ccornelius char *fontName = NULL; 17859d709d503bab6e2b61931737e662dd293b40578ccornelius char *fontVer = NULL; 17959d709d503bab6e2b61931737e662dd293b40578ccornelius char *fontCksum = NULL; 18059d709d503bab6e2b61931737e662dd293b40578ccornelius const UXMLElement *element; 18159d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t ec = 0; 18259d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t charCount = 0; 18359d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t typoFlags = 3; // kerning + ligatures... 18459d709d503bab6e2b61931737e662dd293b40578ccornelius UScriptCode scriptCode; 18559d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 languageCode = -1; 18659d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString text, glyphs, indices, positions; 18759d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t glyphCount = 0, indexCount = 0, positionCount = 0; 18859d709d503bab6e2b61931737e662dd293b40578ccornelius TestResult expected = {0, NULL, NULL, NULL}; 18959d709d503bab6e2b61931737e662dd293b40578ccornelius 19059d709d503bab6e2b61931737e662dd293b40578ccornelius uscript_getCode(script, &scriptCode, 1, &status); 19159d709d503bab6e2b61931737e662dd293b40578ccornelius if (LE_FAILURE(status)) { 19259d709d503bab6e2b61931737e662dd293b40578ccornelius log_err("invalid script name: %s.\n", script); 19359d709d503bab6e2b61931737e662dd293b40578ccornelius goto free_c_strings; 19459d709d503bab6e2b61931737e662dd293b40578ccornelius } 19559d709d503bab6e2b61931737e662dd293b40578ccornelius 19659d709d503bab6e2b61931737e662dd293b40578ccornelius if (lang != NULL) { 19759d709d503bab6e2b61931737e662dd293b40578ccornelius languageCode = getLanguageCode(lang); 19859d709d503bab6e2b61931737e662dd293b40578ccornelius 19959d709d503bab6e2b61931737e662dd293b40578ccornelius if (languageCode < 0) { 20059d709d503bab6e2b61931737e662dd293b40578ccornelius log_err("invalid language name: %s.\n", lang); 20159d709d503bab6e2b61931737e662dd293b40578ccornelius goto free_c_strings; 20259d709d503bab6e2b61931737e662dd293b40578ccornelius } 20359d709d503bab6e2b61931737e662dd293b40578ccornelius } 20459d709d503bab6e2b61931737e662dd293b40578ccornelius 20559d709d503bab6e2b61931737e662dd293b40578ccornelius while((element = testCase->nextChildElement(ec)) != NULL) { 20659d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString tag = element->getTagName(); 20759d709d503bab6e2b61931737e662dd293b40578ccornelius 20859d709d503bab6e2b61931737e662dd293b40578ccornelius // TODO: make sure that each element is only used once. 20959d709d503bab6e2b61931737e662dd293b40578ccornelius if (tag.compare(test_font) == 0) { 21059d709d503bab6e2b61931737e662dd293b40578ccornelius fontName = getCString(element->getAttribute(name_attr)); 21159d709d503bab6e2b61931737e662dd293b40578ccornelius fontVer = getCString(element->getAttribute(ver_attr)); 21259d709d503bab6e2b61931737e662dd293b40578ccornelius fontCksum = getCString(element->getAttribute(cksum_attr)); 21359d709d503bab6e2b61931737e662dd293b40578ccornelius 21459d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (tag.compare(test_text) == 0) { 21559d709d503bab6e2b61931737e662dd293b40578ccornelius text = element->getText(TRUE); 21659d709d503bab6e2b61931737e662dd293b40578ccornelius charCount = text.length(); 21759d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (tag.compare(result_glyphs) == 0) { 21859d709d503bab6e2b61931737e662dd293b40578ccornelius glyphs = element->getText(TRUE); 21959d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (tag.compare(result_indices) == 0) { 22059d709d503bab6e2b61931737e662dd293b40578ccornelius indices = element->getText(TRUE); 22159d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (tag.compare(result_positions) == 0) { 22259d709d503bab6e2b61931737e662dd293b40578ccornelius positions = element->getText(TRUE); 22359d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 22459d709d503bab6e2b61931737e662dd293b40578ccornelius // an unknown tag... 22559d709d503bab6e2b61931737e662dd293b40578ccornelius char *cTag = getCString(&tag); 22659d709d503bab6e2b61931737e662dd293b40578ccornelius 22759d709d503bab6e2b61931737e662dd293b40578ccornelius log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag); 22859d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(cTag); 22959d709d503bab6e2b61931737e662dd293b40578ccornelius } 23059d709d503bab6e2b61931737e662dd293b40578ccornelius } 23159d709d503bab6e2b61931737e662dd293b40578ccornelius 23259d709d503bab6e2b61931737e662dd293b40578ccornelius expected.glyphs = (LEGlyphID *) getHexArray(glyphs, glyphCount); 23359d709d503bab6e2b61931737e662dd293b40578ccornelius expected.indices = (le_int32 *) getHexArray(indices, indexCount); 23459d709d503bab6e2b61931737e662dd293b40578ccornelius expected.positions = getFloatArray(positions, positionCount); 23559d709d503bab6e2b61931737e662dd293b40578ccornelius 23659d709d503bab6e2b61931737e662dd293b40578ccornelius expected.glyphCount = glyphCount; 23759d709d503bab6e2b61931737e662dd293b40578ccornelius 23859d709d503bab6e2b61931737e662dd293b40578ccornelius if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) { 23959d709d503bab6e2b61931737e662dd293b40578ccornelius log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n", 24059d709d503bab6e2b61931737e662dd293b40578ccornelius id, charCount, glyphCount, indexCount, positionCount); 24159d709d503bab6e2b61931737e662dd293b40578ccornelius goto free_expected; 24259d709d503bab6e2b61931737e662dd293b40578ccornelius }; 24359d709d503bab6e2b61931737e662dd293b40578ccornelius 24459d709d503bab6e2b61931737e662dd293b40578ccornelius (*callback)(id, fontName, fontVer, fontCksum, scriptCode, languageCode, text.getBuffer(), charCount, &expected); 24559d709d503bab6e2b61931737e662dd293b40578ccornelius 24659d709d503bab6e2b61931737e662dd293b40578ccorneliusfree_expected: 24759d709d503bab6e2b61931737e662dd293b40578ccornelius DELETE_ARRAY(expected.positions); 24859d709d503bab6e2b61931737e662dd293b40578ccornelius DELETE_ARRAY(expected.indices); 24959d709d503bab6e2b61931737e662dd293b40578ccornelius DELETE_ARRAY(expected.glyphs); 25059d709d503bab6e2b61931737e662dd293b40578ccornelius 25159d709d503bab6e2b61931737e662dd293b40578ccorneliusfree_c_strings: 25259d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(fontCksum); 25359d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(fontVer); 25459d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(fontName); 25559d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(lang); 25659d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(script); 25759d709d503bab6e2b61931737e662dd293b40578ccornelius freeCString(id); 25859d709d503bab6e2b61931737e662dd293b40578ccornelius } 25959d709d503bab6e2b61931737e662dd293b40578ccornelius } 26059d709d503bab6e2b61931737e662dd293b40578ccornelius 26159d709d503bab6e2b61931737e662dd293b40578ccornelius delete root; 26259d709d503bab6e2b61931737e662dd293b40578ccornelius delete parser; 26359d709d503bab6e2b61931737e662dd293b40578ccornelius#endif 26459d709d503bab6e2b61931737e662dd293b40578ccornelius} 26559d709d503bab6e2b61931737e662dd293b40578ccorneliusU_CDECL_END 266