mirror of
https://github.com/love2d/megasource.git
synced 2026-08-17 19:24:09 +02:00
update harfbuzz to 10.1.0
This commit is contained in:
@@ -0,0 +1,437 @@
|
||||
/*____________________________________________________________________________
|
||||
|
||||
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;
|
||||
|
||||
struct TestData
|
||||
{
|
||||
TestData(hb_buffer_t *buffer_,
|
||||
hb_face_t *face_,
|
||||
hb_font_t *font_,
|
||||
hb_feature_t *features_,
|
||||
int num_features_)
|
||||
: buffer(buffer_), face(face_), font(font_),
|
||||
features(features_), num_features(num_features_)
|
||||
{ }
|
||||
~TestData()
|
||||
{
|
||||
free (features);
|
||||
hb_face_destroy (face);
|
||||
hb_font_destroy (font);
|
||||
hb_buffer_destroy (buffer);
|
||||
}
|
||||
|
||||
hb_buffer_t *buffer;
|
||||
hb_face_t *face;
|
||||
hb_font_t *font;
|
||||
hb_feature_t *features;
|
||||
int num_features;
|
||||
};
|
||||
|
||||
TestData
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shape
|
||||
hb_shape(font, buffer, features, nbFeatures);
|
||||
|
||||
hb_blob_destroy(blob);
|
||||
|
||||
return TestData(buffer, face, font, features, nbFeatures);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
TestData data = runTest(testName,
|
||||
fontfileName,
|
||||
in, nbIn,
|
||||
select, nbSelect);
|
||||
|
||||
// verify
|
||||
hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, 0);
|
||||
unsigned int nbActual = hb_buffer_get_length(data.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 < data.num_features; i++)
|
||||
{
|
||||
if (i != 0) fprintf (tests_file, ",");
|
||||
char buf[255];
|
||||
hb_feature_to_string (&data.features[i], buf, sizeof (buf));
|
||||
fprintf (tests_file, "%s", buf);
|
||||
}
|
||||
fprintf (tests_file, "\" --single-par --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");
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TestData data = runTest(testName,
|
||||
fontfileName,
|
||||
in, nbIn,
|
||||
select, nbSelect);
|
||||
|
||||
// verify
|
||||
hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, 0);
|
||||
unsigned int nbActual = hb_buffer_get_length(data.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 < data.num_features; i++)
|
||||
{
|
||||
if (i != 0) fprintf (tests_file, ",");
|
||||
char buf[255];
|
||||
hb_feature_to_string (&data.features[i], buf, sizeof (buf));
|
||||
fprintf (tests_file, "%s", buf);
|
||||
}
|
||||
fprintf (tests_file, "\" --single-par --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");
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TestData data = runTest(testName,
|
||||
fontfileName,
|
||||
in, nbIn,
|
||||
0, 0);
|
||||
|
||||
// verify
|
||||
unsigned int nbActual;
|
||||
hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, &nbActual);
|
||||
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (data.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 (data.face, 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 < data.num_features; i++)
|
||||
{
|
||||
if (i != 0) fprintf (tests_file, ",");
|
||||
char buf[255];
|
||||
hb_feature_to_string (&data.features[i], buf, sizeof (buf));
|
||||
fprintf (tests_file, "%s", buf);
|
||||
}
|
||||
fprintf (tests_file, "\" --single-par --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 (data.face, actualG[i]) != HB_OT_LAYOUT_GLYPH_CLASS_MARK)
|
||||
accumlatedAdvance += 1500;
|
||||
}
|
||||
fprintf (tests_file, "]");
|
||||
|
||||
fprintf (tests_file, "\n");
|
||||
fclose (tests_file);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user