harfbuzz/test/shaping/data/aots/hb-aots-tester.cpp

434 lines
12 KiB
C++
Raw Normal View History

/*____________________________________________________________________________
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;
hb_font_t *gFont;
hb_face_t *gFace;
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;
gFont = font;
gFace = face;
// 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 --font-funcs=ot:");
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;
curX += pos[i].x_advance;
if (hb_ot_layout_get_glyph_class (gFace, actualG[i]) != HB_OT_LAYOUT_GLYPH_CLASS_MARK)
curX -= 1500;
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, ":[");
int accumlatedAdvance = 0;
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] + accumlatedAdvance;
int expected_y = y[i];
if (expected_x || expected_y) fprintf (tests_file, "@%d,%d", expected_x, expected_y);
if (hb_ot_layout_get_glyph_class (gFace, actualG[i]) != HB_OT_LAYOUT_GLYPH_CLASS_MARK)
accumlatedAdvance += 1500;
}
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);
}