/*____________________________________________________________________________ Copyright 2000-2016 Adobe Systems Incorporated. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use these files except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ____________________________________________________________________________*/ #include "stdlib.h" #include "stdio.h" #include "string.h" #include "hb.h" #include "hb-ot.h" static const bool verbose = true; hb_feature_t *gFeatures; int gNbFeatures; hb_buffer_t *runTest(const char *testName, const char *fontfileName, unsigned int *in, int nbIn, unsigned int *select, int nbSelect) { FILE *f = fopen (fontfileName, "rb"); fseek(f, 0, SEEK_END); long fontsize = ftell(f); fseek(f, 0, SEEK_SET); char *fontdata = (char *)malloc (fontsize); fread(fontdata, fontsize, 1, f); fclose(f); if (verbose) { printf ("------------------------------- %s\n", testName); } // setup font hb_blob_t *blob = hb_blob_create(fontdata, fontsize, HB_MEMORY_MODE_WRITABLE, 0, 0); hb_face_t *face = hb_face_create(blob, 0); hb_font_t *font = hb_font_create(face); unsigned int upem = hb_face_get_upem (face); hb_font_set_scale(font, upem, upem); hb_ot_font_set_funcs (font); // setup buffer hb_buffer_t *buffer = hb_buffer_create(); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); hb_buffer_set_script(buffer, HB_SCRIPT_LATIN); hb_buffer_set_language(buffer, hb_language_from_string("en", 2)); hb_buffer_add_utf32(buffer, in, nbIn, 0, nbIn); // setup features hb_feature_t *features; int nbFeatures; if (nbSelect == 0) { nbFeatures = 1; features = (hb_feature_t *) malloc (sizeof (*features)); features[0].tag = HB_TAG('t', 'e', 's', 't'); features[0].value = 1; features[0].start = HB_FEATURE_GLOBAL_START; features[0].end = HB_FEATURE_GLOBAL_END; } else { nbFeatures = 0; features = (hb_feature_t *) malloc (sizeof (*features) * nbSelect); for (int i = 0; i < nbSelect; i++) { if (select[i] != -1) { features[nbFeatures].tag = HB_TAG('t', 'e', 's', 't'); features[nbFeatures].value = select[i]; features[nbFeatures].start = i; features[nbFeatures].end = i + 1; nbFeatures++; } } } gFeatures = features; gNbFeatures = nbFeatures; // shape hb_shape(font, buffer, features, nbFeatures); hb_blob_destroy(blob); hb_font_destroy(font); hb_face_destroy(face); //free(features); return buffer; } void printArray (const char* s, int *a, int n) { printf ("%s %d : ", s, n); for (int i = 0; i < n; i++) { printf (" %d", a[i]); } printf ("\n"); } void printUArray (const char* s, unsigned int *a, int n) { printArray (s, (int *) a, n); } bool gsub_test(const char *testName, const char *fontfileName, int nbIn, unsigned int *in, int nbSelect, unsigned int *select, int nbExpected, unsigned int *expected) { hb_buffer_t *buffer = runTest(testName, fontfileName, in, nbIn, select, nbSelect); // verify hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(buffer, 0); unsigned int nbActual = hb_buffer_get_length(buffer); bool ok = true; if (nbActual != nbExpected) ok = false; else { for (int i = 0; i < nbActual; i++) { if (actual[i].codepoint != expected [i]) { ok = false; break; } } } char test_name[255]; sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName); FILE *tests_file = fopen (test_name, "a+"); if (!ok) fprintf (tests_file, "#"); fprintf (tests_file, "../fonts/%s:--features=\"", fontfileName + 9); for (unsigned int i = 0; i < gNbFeatures; i++) { if (i != 0) fprintf (tests_file, ","); char buf[255]; hb_feature_to_string (&gFeatures[i], buf, sizeof (buf)); fprintf (tests_file, "%s", buf); } free (gFeatures); fprintf (tests_file, "\" --no-clusters --no-glyph-names --no-positions:"); for (unsigned int i = 0; i < nbIn; i++) { if (i != 0) fprintf (tests_file, ","); fprintf (tests_file, "U+%04X", in[i]); } fprintf (tests_file, ":["); for (unsigned int i = 0; i < nbActual; i++) { if (i != 0) fprintf (tests_file, "|"); fprintf (tests_file, "%d", expected[i]); } fprintf (tests_file, "]"); fprintf (tests_file, "\n"); fclose (tests_file); if (! ok) { printf ("******* GSUB %s\n", testName); printf ("expected %d:", nbExpected); for (int i = 0; i < nbExpected; i++) { printf (" %d", expected[i]); } printf ("\n"); printf (" actual %d:", nbActual); for (int i = 0; i < nbActual; i++) { printf (" %d", actual[i].codepoint); } printf ("\n"); } hb_buffer_destroy(buffer); return ok; } bool cmap_test(const char *testName, const char *fontfileName, int nbIn, unsigned int *in, int nbSelect, unsigned int *select, int nbExpected, unsigned int *expected) { hb_buffer_t *buffer = runTest(testName, fontfileName, in, nbIn, select, nbSelect); // verify hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(buffer, 0); unsigned int nbActual = hb_buffer_get_length(buffer); bool ok = true; if (nbActual != nbExpected) ok = false; else { for (int i = 0; i < nbActual; i++) { if (actual[i].codepoint != expected [i]) { ok = false; break; } } } char test_name[255]; sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName); FILE *tests_file = fopen (test_name, "a+"); if (!ok) fprintf (tests_file, "#"); fprintf (tests_file, "../fonts/%s:--features=\"", fontfileName + 9); for (unsigned int i = 0; i < gNbFeatures; i++) { if (i != 0) fprintf (tests_file, ","); char buf[255]; hb_feature_to_string (&gFeatures[i], buf, sizeof (buf)); fprintf (tests_file, "%s", buf); } free (gFeatures); fprintf (tests_file, "\" --no-clusters --no-glyph-names --no-positions:"); for (unsigned int i = 0; i < nbIn; i++) { if (i != 0) fprintf (tests_file, ","); fprintf (tests_file, "U+%04X", in[i]); } fprintf (tests_file, ":["); for (unsigned int i = 0; i < nbActual; i++) { if (i != 0) fprintf (tests_file, "|"); fprintf (tests_file, "%d", expected[i]); } fprintf (tests_file, "]"); fprintf (tests_file, "\n"); fclose (tests_file); if (! ok) { printf ("******* cmap %s\n", testName); printf ("expected %d:", nbExpected); for (int i = 0; i < nbExpected; i++) { printf (" %d", expected[i]); } printf ("\n"); printf (" actual %d:", nbActual); for (int i = 0; i < nbActual; i++) { printf (" %d", actual[i].codepoint); } printf ("\n"); } hb_buffer_destroy(buffer); return ok; } bool gpos_test(const char *testName, const char *fontfileName, int nbIn, unsigned int *in, int nbOut, unsigned int *out, int *x, int *y) { hb_buffer_t *buffer = runTest(testName, fontfileName, in, nbIn, 0, 0); // verify unsigned int nbActual; hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(buffer, &nbActual); hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); unsigned int *actualG = (unsigned int *) malloc(sizeof(*actualG) * nbActual); int *actualX = (int *) malloc(sizeof(*actualX) * nbActual); int *actualY = (int *) malloc(sizeof(*actualY) * nbActual); int curX = 0; int curY = 0; for (int i = 0; i < nbActual; i++) { actualG[i] = actual[i].codepoint; actualX[i] = curX + pos[i].x_offset; actualY[i] = curY + pos[i].y_offset; actualX[i] -= 1500 * i; curX += pos[i].x_advance; curY += pos[i].y_advance; } bool nbOk = true; bool xOk = true; bool yOk = true; if (nbActual != nbOut) nbOk = false; else { for (int i = 0; i < nbActual; i++) { if (actualX[i] != x[i]) { xOk = false; } if (actualY[i] != y[i]) { yOk = false; } } } bool ok = (nbOk && xOk && yOk); if (! ok) { printf ("******* GPOS %s\n", testName); if (! (nbOk && xOk)) { printArray ("expectedX", x, nbOut); printArray ("actualX ", actualX, nbActual); printf ("xadv/pos:"); for (int i = 0; i < nbOut; i++) { printf (" %d/%d", pos[i].x_advance, pos[i].x_offset); } printf ("\n"); } if (! (nbOk && yOk)) { printArray ("expectedY", y, nbOut); printArray ("actualY ", actualY, nbActual); printf ("yadv/pos:"); for (int i = 0; i < nbOut; i++) { printf (" %d/%d", pos[i].y_advance, pos[i].y_offset); } printf ("\n"); } } char test_name[255]; sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName); FILE *tests_file = fopen (test_name, "a+"); if (!ok) fprintf (tests_file, "#"); fprintf (tests_file, "../fonts/%s:--features=\"", fontfileName + 9); for (unsigned int i = 0; i < gNbFeatures; i++) { if (i != 0) fprintf (tests_file, ","); char buf[255]; hb_feature_to_string (&gFeatures[i], buf, sizeof (buf)); fprintf (tests_file, "%s", buf); } free (gFeatures); fprintf (tests_file, "\" --no-clusters --no-glyph-names --ned:"); for (unsigned int i = 0; i < nbIn; i++) { if (i != 0) fprintf (tests_file, ","); fprintf (tests_file, "U+%04X", in[i]); } fprintf (tests_file, ":["); for (unsigned int i = 0; i < nbActual; i++) { if (i != 0) fprintf (tests_file, "|"); fprintf (tests_file, "%d", /*it should be "out[i]"*/ actualG[i]); int expected_x = x[i] + 1500*i; int expected_y = y[i]; if (expected_x || expected_y) fprintf (tests_file, "@%d,%d", expected_x, expected_y); } fprintf (tests_file, "]"); fprintf (tests_file, "\n"); fclose (tests_file); hb_buffer_destroy(buffer); free(actualG); free(actualX); free(actualY); return ok; } int main(int argc, char **argv) { int failures = 0; int pass = 0; #include "hb-aots-tester.h" printf ("%d failures, %d pass\n", failures, pass); }