1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#if defined(HAVE_CORETEXT)
#include <ApplicationServices/ApplicationServices.h>
#elif defined(HAVE_FREETYPE)
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#elif defined(HAVE_WIN32)
#define NOMINMAX
#include <Windows.h>
#endif
#include <fstream>
#include <iostream>
#include <memory>
#include <vector>
#include "test-context.h"
#include "ots-memory-stream.h"
namespace {
int Usage(const char *argv0) {
std::fprintf(stderr, "Usage: %s <ttf file>\n", argv0);
return 1;
}
bool DumpResults(const uint8_t *result1, const size_t len1,
const uint8_t *result2, const size_t len2) {
std::ofstream out1("out1.ttf", std::ofstream::out | std::ofstream::binary);
std::ofstream out2("out2.ttf", std::ofstream::out | std::ofstream::binary);
if (!out1.good() || !out2.good())
return false;
out1.write(reinterpret_cast<const char*>(result1), len1);
out2.write(reinterpret_cast<const char*>(result2), len2);
if (!out1.good() || !out2.good())
return false;
return true;
}
// Platform specific implementations.
bool VerifyTranscodedFont(uint8_t *result, const size_t len);
#if defined(HAVE_CORETEXT)
bool VerifyTranscodedFont(uint8_t *result, const size_t len) {
CFDataRef data = CFDataCreate(0, result, len);
if (!data) {
return false;
}
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
CGFontRef cgFontRef = CGFontCreateWithDataProvider(dataProvider);
CGDataProviderRelease(dataProvider);
CFRelease(data);
if (!cgFontRef) {
return false;
}
size_t numGlyphs = CGFontGetNumberOfGlyphs(cgFontRef);
CGFontRelease(cgFontRef);
if (!numGlyphs) {
return false;
}
return true;
}
#elif defined(HAVE_FREETYPE)
bool VerifyTranscodedFont(uint8_t *result, const size_t len) {
FT_Library library;
FT_Error error = ::FT_Init_FreeType(&library);
if (error) {
return false;
}
FT_Face dummy;
error = ::FT_New_Memory_Face(library, result, len, 0, &dummy);
if (error) {
return false;
}
::FT_Done_Face(dummy);
::FT_Done_FreeType(library);
return true;
}
#elif defined(HAVE_WIN32)
// Windows
bool VerifyTranscodedFont(uint8_t *result, const size_t len) {
DWORD num_fonts = 0;
HANDLE handle = AddFontMemResourceEx(result, len, 0, &num_fonts);
if (!handle) {
return false;
}
RemoveFontMemResourceEx(handle);
return true;
}
#else
bool VerifyTranscodedFont(uint8_t *result, const size_t len) {
std::fprintf(stderr, "Can't verify the transcoded font on this platform.\n");
return false;
}
#endif
} // namespace
int main(int argc, char **argv) {
if (argc != 2) return Usage(argv[0]);
std::ifstream ifs(argv[1], std::ifstream::binary);
if (!ifs.good()) {
std::fprintf(stderr, "Failed to read file!\n");
return 1;
}
std::vector<uint8_t> in((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
// A transcoded font is usually smaller than an original font.
// However, it can be slightly bigger than the original one due to
// name table replacement and/or padding for glyf table.
//
// However, a WOFF font gets decompressed and so can be *much* larger than
// the original.
std::unique_ptr<uint8_t[]> result(new uint8_t[in.size() * 8]);
ots::MemoryStream output(result.get(), in.size() * 8);
ots::TestContext context(0);
if (!context.Process(&output, in.data(), in.size())) {
std::fprintf(stderr, "Failed to sanitize file!\n");
return 1;
}
const size_t result_len = output.Tell();
std::unique_ptr<uint8_t[]> result2(new uint8_t[result_len]);
ots::MemoryStream output2(result2.get(), result_len);
if (!context.Process(&output2, result.get(), result_len)) {
std::fprintf(stderr, "Failed to sanitize previous output!\n");
return 1;
}
const size_t result2_len = output2.Tell();
bool dump_results = false;
if (result2_len != result_len) {
std::fprintf(stderr, "Outputs differ in length\n");
dump_results = true;
} else if (std::memcmp(result2.get(), result.get(), result_len)) {
std::fprintf(stderr, "Outputs differ in content\n");
dump_results = true;
}
if (dump_results) {
std::fprintf(stderr, "Dumping results to out1.tff and out2.tff\n");
if (!DumpResults(result.get(), result_len, result2.get(), result2_len)) {
std::fprintf(stderr, "Failed to dump output files.\n");
return 1;
}
}
// Verify that original font can be opened by the font renderer. If this
// fails then no point in verfying the transcoded font.
if (!VerifyTranscodedFont(in.data(), in.size())) {
std::fprintf(stderr, "Failed to verify the original font\n");
return 0;
}
// Verify that the transcoded font can be opened by the font renderer for
// Linux (FreeType2), Mac OS X, or Windows.
if (!VerifyTranscodedFont(result.get(), result_len)) {
std::fprintf(stderr, "Failed to verify the transcoded font\n");
return 1;
}
return 0;
}
|