зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1716117 - Build SkiaPDF with harfbuzz subsetting, and eliminate use of sfntly. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D117586
This commit is contained in:
Родитель
3050aa82c8
Коммит
5820669ad6
|
@ -35,9 +35,6 @@ DIRS += [
|
|||
if CONFIG["MOZ_ENABLE_SKIA"]:
|
||||
DIRS += ["skia"]
|
||||
|
||||
if CONFIG["MOZ_ENABLE_SKIA_PDF_SFNTLY"]:
|
||||
DIRS += ["sfntly/cpp/src"]
|
||||
|
||||
if CONFIG["ENABLE_TESTS"]:
|
||||
DIRS += ["tests/gtest"]
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
This directory contains the C++ port of SFNTLY,
|
||||
from https://github.com/googlei18n/sfntly/tree/master/cpp.
|
||||
|
||||
SFNTLY is distributed under the Apache license v2.0
|
||||
(see cpp/COPYING.txt).
|
|
@ -1,73 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'sample/chromium/font_subsetter.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'sample/chromium/font_subsetter.cc',
|
||||
'sample/chromium/subsetter_impl.cc',
|
||||
'sfntly/data/byte_array.cc',
|
||||
'sfntly/data/font_data.cc',
|
||||
'sfntly/data/font_input_stream.cc',
|
||||
'sfntly/data/font_output_stream.cc',
|
||||
'sfntly/data/growable_memory_byte_array.cc',
|
||||
'sfntly/data/memory_byte_array.cc',
|
||||
'sfntly/data/readable_font_data.cc',
|
||||
'sfntly/data/writable_font_data.cc',
|
||||
'sfntly/font.cc',
|
||||
'sfntly/font_factory.cc',
|
||||
'sfntly/port/file_input_stream.cc',
|
||||
'sfntly/port/lock.cc',
|
||||
'sfntly/port/memory_input_stream.cc',
|
||||
'sfntly/port/memory_output_stream.cc',
|
||||
'sfntly/table/bitmap/big_glyph_metrics.cc',
|
||||
'sfntly/table/bitmap/bitmap_glyph.cc',
|
||||
'sfntly/table/bitmap/bitmap_glyph_info.cc',
|
||||
'sfntly/table/bitmap/bitmap_size_table.cc',
|
||||
'sfntly/table/bitmap/composite_bitmap_glyph.cc',
|
||||
'sfntly/table/bitmap/ebdt_table.cc',
|
||||
'sfntly/table/bitmap/eblc_table.cc',
|
||||
'sfntly/table/bitmap/ebsc_table.cc',
|
||||
'sfntly/table/bitmap/glyph_metrics.cc',
|
||||
'sfntly/table/bitmap/index_sub_table.cc',
|
||||
'sfntly/table/bitmap/index_sub_table_format1.cc',
|
||||
'sfntly/table/bitmap/index_sub_table_format2.cc',
|
||||
'sfntly/table/bitmap/index_sub_table_format3.cc',
|
||||
'sfntly/table/bitmap/index_sub_table_format4.cc',
|
||||
'sfntly/table/bitmap/index_sub_table_format5.cc',
|
||||
'sfntly/table/bitmap/simple_bitmap_glyph.cc',
|
||||
'sfntly/table/bitmap/small_glyph_metrics.cc',
|
||||
'sfntly/table/byte_array_table_builder.cc',
|
||||
'sfntly/table/core/cmap_table.cc',
|
||||
'sfntly/table/core/font_header_table.cc',
|
||||
'sfntly/table/core/horizontal_device_metrics_table.cc',
|
||||
'sfntly/table/core/horizontal_header_table.cc',
|
||||
'sfntly/table/core/horizontal_metrics_table.cc',
|
||||
'sfntly/table/core/maximum_profile_table.cc',
|
||||
'sfntly/table/core/name_table.cc',
|
||||
'sfntly/table/core/os2_table.cc',
|
||||
'sfntly/table/font_data_table.cc',
|
||||
'sfntly/table/generic_table_builder.cc',
|
||||
'sfntly/table/header.cc',
|
||||
'sfntly/table/subtable.cc',
|
||||
'sfntly/table/table.cc',
|
||||
'sfntly/table/table_based_table_builder.cc',
|
||||
'sfntly/table/truetype/glyph_table.cc',
|
||||
'sfntly/table/truetype/loca_table.cc',
|
||||
'sfntly/tag.cc',
|
||||
'sfntly/tools/subsetter/glyph_table_subsetter.cc',
|
||||
'sfntly/tools/subsetter/subsetter.cc',
|
||||
'sfntly/tools/subsetter/table_subsetter_impl.cc',
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
AllowCompilerWarnings()
|
||||
|
||||
FINAL_LIBRARY = 'gkmedias'
|
||||
|
||||
DEFINES['SFNTLY_NO_EXCEPTION'] = 1
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
#include "font_subsetter.h"
|
||||
|
||||
template <typename T>
|
||||
class HexTo {
|
||||
public:
|
||||
explicit HexTo(const char* in) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << in;
|
||||
ss >> value_;
|
||||
}
|
||||
operator T() const { return value_; }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
bool LoadFile(const char* input_file_path, sfntly::ByteVector* input_buffer) {
|
||||
assert(input_file_path);
|
||||
assert(input_buffer);
|
||||
|
||||
FILE* input_file = NULL;
|
||||
#if defined WIN32
|
||||
fopen_s(&input_file, input_file_path, "rb");
|
||||
#else
|
||||
input_file = fopen(input_file_path, "rb");
|
||||
#endif
|
||||
if (input_file == NULL) {
|
||||
return false;
|
||||
}
|
||||
fseek(input_file, 0, SEEK_END);
|
||||
size_t file_size = ftell(input_file);
|
||||
fseek(input_file, 0, SEEK_SET);
|
||||
input_buffer->resize(file_size);
|
||||
size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file);
|
||||
fclose(input_file);
|
||||
return bytes_read == file_size;
|
||||
}
|
||||
|
||||
bool SaveFile(const char* output_file_path, const unsigned char* output_buffer,
|
||||
int buffer_length) {
|
||||
int byte_count = 0;
|
||||
if (buffer_length > 0) {
|
||||
FILE* output_file = NULL;
|
||||
#if defined WIN32
|
||||
fopen_s(&output_file, output_file_path, "wb");
|
||||
#else
|
||||
output_file = fopen(output_file_path, "wb");
|
||||
#endif
|
||||
if (output_file) {
|
||||
byte_count = fwrite(output_buffer, 1, buffer_length, output_file);
|
||||
fflush(output_file);
|
||||
fclose(output_file);
|
||||
}
|
||||
return buffer_length == byte_count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StringToGlyphId(const char* input, std::vector<unsigned int>* glyph_ids) {
|
||||
assert(input);
|
||||
std::string hex_csv = input;
|
||||
size_t start = 0;
|
||||
size_t end = hex_csv.find_first_of(",");
|
||||
while (end != std::string::npos) {
|
||||
glyph_ids->push_back(
|
||||
HexTo<unsigned int>(hex_csv.substr(start, end - start).c_str()));
|
||||
start = end + 1;
|
||||
end = hex_csv.find_first_of(",", start);
|
||||
}
|
||||
glyph_ids->push_back(HexTo<unsigned int>(hex_csv.substr(start).c_str()));
|
||||
return glyph_ids->size() > 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 5) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <input path> <output path> <font name> <glyph ids>\n",
|
||||
argv[0]);
|
||||
fprintf(stderr, "\tGlyph ids are comma separated hex values\n");
|
||||
fprintf(stderr, "\te.g. 20,1a,3b,4f\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfntly::ByteVector input_buffer;
|
||||
if (!LoadFile(argv[1], &input_buffer)) {
|
||||
fprintf(stderr, "ERROR: unable to load font file %s\n", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<unsigned int> glyph_ids;
|
||||
if (!StringToGlyphId(argv[4], &glyph_ids)) {
|
||||
fprintf(stderr, "ERROR: unable to parse input glyph id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char* output_buffer = NULL;
|
||||
int output_length =
|
||||
SfntlyWrapper::SubsetFont(argv[3],
|
||||
&(input_buffer[0]),
|
||||
input_buffer.size(),
|
||||
&(glyph_ids[0]),
|
||||
glyph_ids.size(),
|
||||
&output_buffer);
|
||||
|
||||
int result = SaveFile(argv[2], output_buffer, output_length) ? 1 : 0;
|
||||
delete[] output_buffer;
|
||||
return result;
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "font_subsetter.h"
|
||||
|
||||
#include "subsetter_impl.h"
|
||||
|
||||
int SfntlyWrapper::SubsetFont(const char* font_name,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size,
|
||||
const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer) {
|
||||
if (output_buffer == NULL ||
|
||||
original_font == NULL || font_size == 0 ||
|
||||
glyph_ids == NULL || glyph_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfntly::SubsetterImpl subsetter;
|
||||
if (!subsetter.LoadFont(font_name, original_font, font_size)) {
|
||||
return -1; // Load error or font not found.
|
||||
}
|
||||
|
||||
return subsetter.SubsetFont(glyph_ids, glyph_count, output_buffer);
|
||||
}
|
||||
|
||||
int SfntlyWrapper::SubsetFont(int font_index,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size,
|
||||
const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer) {
|
||||
if (output_buffer == NULL ||
|
||||
original_font == NULL || font_size == 0 ||
|
||||
glyph_ids == NULL || glyph_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfntly::SubsetterImpl subsetter;
|
||||
if (!subsetter.LoadFont(font_index, original_font, font_size)) {
|
||||
return -1; // Load error or font not found.
|
||||
}
|
||||
|
||||
return subsetter.SubsetFont(glyph_ids, glyph_count, output_buffer);
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
// File is originally from Chromium third_party/sfntly/src/subsetter.
|
||||
// Use as test case in sfntly so that problems can be caught in upstream early.
|
||||
#ifndef SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_
|
||||
#define SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class SfntlyWrapper {
|
||||
public:
|
||||
|
||||
// Font subsetting API
|
||||
//
|
||||
// Input TTF/TTC/OTF fonts, specify the glyph IDs to subset, and the subset
|
||||
// font is returned in |output_buffer| (caller to delete[]). Return value is
|
||||
// the length of output_buffer allocated.
|
||||
//
|
||||
// If subsetting fails, a negative value is returned. If none of the glyph
|
||||
// IDs specified is found, the function will return 0.
|
||||
//
|
||||
// |font_name| Font name, required for TTC files. If specified NULL,
|
||||
// the first available font is selected.
|
||||
// |original_font| Original font file contents.
|
||||
// |font_size| Size of |original_font| in bytes.
|
||||
// |glyph_ids| Glyph IDs to subset. If the specified glyph ID is not
|
||||
// found in the font file, it will be ignored silently.
|
||||
// |glyph_count| Number of glyph IDs in |glyph_ids|
|
||||
// |output_buffer| Generated subset font. Caller to delete[].
|
||||
static int SubsetFont(const char* font_name,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size,
|
||||
const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer);
|
||||
|
||||
|
||||
// Font subsetting API
|
||||
//
|
||||
// Input TTF/TTC/OTF fonts, specify the glyph IDs to subset, and the subset
|
||||
// font is returned in |output_buffer| (caller to delete[]). Return value is
|
||||
// the length of output_buffer allocated.
|
||||
//
|
||||
// If subsetting fails, a negative value is returned. If none of the glyph
|
||||
// IDs specified is found, the function will return 0.
|
||||
//
|
||||
// |font_name| Font index, ignored for non-TTC files, 0-indexed.
|
||||
// |original_font| Original font file contents.
|
||||
// |font_size| Size of |original_font| in bytes.
|
||||
// |glyph_ids| Glyph IDs to subset. If the specified glyph ID is not
|
||||
// found in the font file, it will be ignored silently.
|
||||
// |glyph_count| Number of glyph IDs in |glyph_ids|
|
||||
// |output_buffer| Generated subset font. Caller to delete[].
|
||||
static int SubsetFont(int font_index,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size,
|
||||
const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer);
|
||||
};
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_
|
|
@ -1,848 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subsetter_impl.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/uversion.h>
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
#include "sfntly/table/bitmap/ebdt_table.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format1.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format2.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format3.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format4.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format5.h"
|
||||
#include "sfntly/table/core/name_table.h"
|
||||
#include "sfntly/tag.h"
|
||||
#include "sfntly/data/memory_byte_array.h"
|
||||
#include "sfntly/port/memory_input_stream.h"
|
||||
#include "sfntly/port/memory_output_stream.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace sfntly;
|
||||
|
||||
/**
|
||||
* std::u16string and icu::UnicodeString can't be used here.
|
||||
* UChar is not always char16_t in some platforms. std::u16string is avoided.
|
||||
* icu::UnicodeString C++ API is also avoided to make it more portable across
|
||||
* platforms due to C++ ABI compatility issue.
|
||||
*/
|
||||
typedef std::basic_string<UChar> UCharString;
|
||||
|
||||
// The bitmap tables must be greater than 16KB to trigger bitmap subsetter.
|
||||
static const int BITMAP_SIZE_THRESHOLD = 16384;
|
||||
|
||||
void ConstructName(UChar* name_part, UCharString* name, int32_t name_id) {
|
||||
switch (name_id) {
|
||||
case NameId::kFullFontName:
|
||||
*name = name_part;
|
||||
break;
|
||||
case NameId::kFontFamilyName:
|
||||
case NameId::kPreferredFamily:
|
||||
case NameId::kWWSFamilyName: {
|
||||
UCharString original = *name;
|
||||
*name = name_part;
|
||||
*name += original;
|
||||
break;
|
||||
}
|
||||
case NameId::kFontSubfamilyName:
|
||||
case NameId::kPreferredSubfamily:
|
||||
case NameId::kWWSSubfamilyName:
|
||||
*name += name_part;
|
||||
break;
|
||||
default:
|
||||
// This name part is not used to construct font name (e.g. copyright).
|
||||
// Simply ignore it.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert UTF-8 string into UTF-16 string.
|
||||
//
|
||||
// Ill-formed input is replaced with U+FFFD.
|
||||
// Otherwise, return empty string if other error occurs during the conversion.
|
||||
UCharString ConvertFromUtf8(const char* src) {
|
||||
int32_t srcLength = strlen(src);
|
||||
int32_t destCapacity = srcLength + 1;
|
||||
UChar* buffer = new UChar[destCapacity];
|
||||
UCharString dest;
|
||||
if (buffer == NULL) {
|
||||
return dest;
|
||||
}
|
||||
int32_t destLength;
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
u_strFromUTF8WithSub(buffer, destCapacity, &destLength, src, srcLength,
|
||||
0xfffd, // Unicode replacement character
|
||||
NULL,
|
||||
&errorCode);
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
dest.append(buffer, destLength);
|
||||
}
|
||||
delete[] buffer;
|
||||
return dest;
|
||||
}
|
||||
|
||||
int32_t CaseCompareUtf16(const UCharString& str1,
|
||||
const UCharString& str2, uint32_t option) {
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
return u_strCaseCompare(str1.c_str(), str1.length(), str2.c_str(),
|
||||
str2.length(), option, &errorCode);
|
||||
}
|
||||
|
||||
int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id,
|
||||
int32_t name_id) {
|
||||
int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8;
|
||||
if (name_id == NameId::kFullFontName) {
|
||||
result |= 0xff;
|
||||
} else if (name_id == NameId::kPreferredFamily ||
|
||||
name_id == NameId::kPreferredSubfamily) {
|
||||
result |= 0xf;
|
||||
} else if (name_id == NameId::kWWSFamilyName ||
|
||||
name_id == NameId::kWWSSubfamilyName) {
|
||||
result |= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HasName(const char* font_name, Font* font) {
|
||||
UCharString font_string = ConvertFromUtf8(font_name);
|
||||
if (font_string.empty())
|
||||
return false;
|
||||
UCharString regular_suffix = ConvertFromUtf8(" Regular");
|
||||
UCharString alt_font_string = font_string;
|
||||
alt_font_string += regular_suffix;
|
||||
|
||||
typedef std::map<int32_t, UCharString> NameMap;
|
||||
NameMap names;
|
||||
NameTablePtr name_table = down_cast<NameTable*>(font->GetTable(Tag::name));
|
||||
if (name_table == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < name_table->NameCount(); ++i) {
|
||||
switch (name_table->NameId(i)) {
|
||||
case NameId::kFontFamilyName:
|
||||
case NameId::kFontSubfamilyName:
|
||||
case NameId::kFullFontName:
|
||||
case NameId::kPreferredFamily:
|
||||
case NameId::kPreferredSubfamily:
|
||||
case NameId::kWWSFamilyName:
|
||||
case NameId::kWWSSubfamilyName: {
|
||||
UChar* name_part = name_table->Name(i);
|
||||
if (name_part == NULL) {
|
||||
continue;
|
||||
}
|
||||
int32_t hash_code = HashCode(name_table->PlatformId(i),
|
||||
name_table->EncodingId(i),
|
||||
name_table->LanguageId(i),
|
||||
name_table->NameId(i));
|
||||
ConstructName(name_part, &(names[hash_code]), name_table->NameId(i));
|
||||
delete[] name_part;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!names.empty()) {
|
||||
for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) {
|
||||
if (CaseCompareUtf16(i->second, font_string, 0) == 0 ||
|
||||
CaseCompareUtf16(i->second, alt_font_string, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Font* FindFont(const char* font_name, const FontArray& font_array) {
|
||||
if (font_array.empty() || font_array[0] == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (font_name && strlen(font_name)) {
|
||||
for (FontArray::const_iterator i = font_array.begin(), e = font_array.end();
|
||||
i != e; ++i) {
|
||||
if (HasName(font_name, i->p_)) {
|
||||
return i->p_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return font_array[0].p_;
|
||||
}
|
||||
|
||||
bool ResolveCompositeGlyphs(GlyphTable* glyph_table,
|
||||
LocaTable* loca_table,
|
||||
const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
IntegerSet* glyph_id_processed) {
|
||||
if (glyph_table == NULL || loca_table == NULL ||
|
||||
glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sort and uniquify glyph ids.
|
||||
IntegerSet glyph_id_remaining;
|
||||
glyph_id_remaining.insert(0); // Always include glyph id 0.
|
||||
for (size_t i = 0; i < glyph_count; ++i) {
|
||||
glyph_id_remaining.insert(glyph_ids[i]);
|
||||
}
|
||||
|
||||
// Identify if any given glyph id maps to a composite glyph. If so, include
|
||||
// the glyphs referenced by that composite glyph.
|
||||
while (!glyph_id_remaining.empty()) {
|
||||
IntegerSet comp_glyph_id;
|
||||
for (IntegerSet::iterator i = glyph_id_remaining.begin(),
|
||||
e = glyph_id_remaining.end(); i != e; ++i) {
|
||||
if (*i < 0 || *i >= loca_table->num_glyphs()) {
|
||||
// Invalid glyph id, ignore.
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t length = loca_table->GlyphLength(*i);
|
||||
if (length == 0) {
|
||||
// Empty glyph, ignore.
|
||||
continue;
|
||||
}
|
||||
int32_t offset = loca_table->GlyphOffset(*i);
|
||||
|
||||
GlyphPtr glyph;
|
||||
glyph.Attach(glyph_table->GetGlyph(offset, length));
|
||||
if (glyph == NULL) {
|
||||
// Error finding glyph, ignore.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (glyph->GlyphType() == GlyphType::kComposite) {
|
||||
Ptr<GlyphTable::CompositeGlyph> comp_glyph =
|
||||
down_cast<GlyphTable::CompositeGlyph*>(glyph.p_);
|
||||
for (int32_t j = 0; j < comp_glyph->NumGlyphs(); ++j) {
|
||||
int32_t glyph_id = comp_glyph->GlyphIndex(j);
|
||||
if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() &&
|
||||
glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) {
|
||||
comp_glyph_id.insert(comp_glyph->GlyphIndex(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glyph_id_processed->insert(*i);
|
||||
}
|
||||
|
||||
glyph_id_remaining.clear();
|
||||
glyph_id_remaining = comp_glyph_id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetupGlyfBuilders(Font::Builder* font_builder,
|
||||
GlyphTable* glyph_table,
|
||||
LocaTable* loca_table,
|
||||
const IntegerSet& glyph_ids) {
|
||||
if (!font_builder || !glyph_table || !loca_table) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GlyphTableBuilderPtr glyph_table_builder =
|
||||
down_cast<GlyphTable::Builder*>(font_builder->NewTableBuilder(Tag::glyf));
|
||||
LocaTableBuilderPtr loca_table_builder =
|
||||
down_cast<LocaTable::Builder*>(font_builder->NewTableBuilder(Tag::loca));
|
||||
if (glyph_table_builder == NULL || loca_table_builder == NULL) {
|
||||
// Out of memory.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract glyphs and setup loca list.
|
||||
IntegerList loca_list;
|
||||
loca_list.resize(loca_table->num_glyphs());
|
||||
loca_list.push_back(0);
|
||||
int32_t last_glyph_id = 0;
|
||||
int32_t last_offset = 0;
|
||||
GlyphTable::GlyphBuilderList* glyph_builders =
|
||||
glyph_table_builder->GlyphBuilders();
|
||||
for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end();
|
||||
i != e; ++i) {
|
||||
int32_t length = loca_table->GlyphLength(*i);
|
||||
int32_t offset = loca_table->GlyphOffset(*i);
|
||||
|
||||
GlyphPtr glyph;
|
||||
glyph.Attach(glyph_table->GetGlyph(offset, length));
|
||||
|
||||
// Add glyph to new glyf table.
|
||||
ReadableFontDataPtr data = glyph->ReadFontData();
|
||||
WritableFontDataPtr copy_data;
|
||||
copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length()));
|
||||
data->CopyTo(copy_data);
|
||||
GlyphBuilderPtr glyph_builder;
|
||||
glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data));
|
||||
glyph_builders->push_back(glyph_builder);
|
||||
|
||||
// Configure loca list.
|
||||
for (int32_t j = last_glyph_id + 1; j <= *i; ++j) {
|
||||
loca_list[j] = last_offset;
|
||||
}
|
||||
|
||||
if (last_offset > std::numeric_limits<int32_t>::max() - length)
|
||||
return false;
|
||||
|
||||
last_offset += length;
|
||||
loca_list[*i + 1] = last_offset;
|
||||
last_glyph_id = *i;
|
||||
}
|
||||
for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) {
|
||||
loca_list[j] = last_offset;
|
||||
}
|
||||
loca_table_builder->SetLocaList(&loca_list);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HasOverlap(int32_t range_begin, int32_t range_end,
|
||||
const IntegerSet& glyph_ids) {
|
||||
if (range_begin == range_end)
|
||||
return glyph_ids.find(range_begin) != glyph_ids.end();
|
||||
|
||||
if (range_begin >= range_end)
|
||||
return false;
|
||||
|
||||
IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin);
|
||||
IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end);
|
||||
return left != right;
|
||||
}
|
||||
|
||||
// Initialize builder, returns false if glyph_id subset is not covered.
|
||||
// Not thread-safe, caller to ensure object life-time.
|
||||
bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc,
|
||||
const IntegerSet& glyph_ids) {
|
||||
BitmapLocaList loca_list;
|
||||
BitmapSizeTableBuilderList* strikes = eblc->BitmapSizeBuilders();
|
||||
|
||||
// Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then
|
||||
// ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are
|
||||
// >28K glyphs inside, where a typical usage will be <1K glyphs. Doing
|
||||
// the calls improperly will result in creation of >100K objects that
|
||||
// will be destroyed immediately, inducing significant slowness.
|
||||
IntegerList removed_strikes;
|
||||
for (size_t i = 0; i < strikes->size(); i++) {
|
||||
if (!HasOverlap((*strikes)[i]->StartGlyphIndex(),
|
||||
(*strikes)[i]->EndGlyphIndex(), glyph_ids)) {
|
||||
removed_strikes.push_back(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexSubTableBuilderList* index_builders =
|
||||
(*strikes)[i]->IndexSubTableBuilders();
|
||||
IntegerList removed_indexes;
|
||||
BitmapGlyphInfoMap info_map;
|
||||
for (size_t j = 0; j < index_builders->size(); ++j) {
|
||||
if ((*index_builders)[j] == NULL) {
|
||||
// Subtable is malformed, let's just skip it.
|
||||
removed_indexes.push_back(j);
|
||||
continue;
|
||||
}
|
||||
int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index();
|
||||
int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index();
|
||||
if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) {
|
||||
removed_indexes.push_back(j);
|
||||
continue;
|
||||
}
|
||||
for (IntegerSet::const_iterator gid = glyph_ids.begin(),
|
||||
gid_end = glyph_ids.end();
|
||||
gid != gid_end; gid++) {
|
||||
if (*gid < first_glyph_id) {
|
||||
continue;
|
||||
}
|
||||
if (*gid > last_glyph_id) {
|
||||
break;
|
||||
}
|
||||
BitmapGlyphInfoPtr info;
|
||||
info.Attach((*index_builders)[j]->GlyphInfo(*gid));
|
||||
if (info && info->length()) { // Do not include gid without bitmap
|
||||
info_map[*gid] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!info_map.empty()) {
|
||||
loca_list.push_back(info_map);
|
||||
} else {
|
||||
removed_strikes.push_back(i); // Detected null entries.
|
||||
}
|
||||
|
||||
// Remove unused index sub tables
|
||||
for (IntegerList::reverse_iterator j = removed_indexes.rbegin(),
|
||||
e = removed_indexes.rend();
|
||||
j != e; j++) {
|
||||
index_builders->erase(index_builders->begin() + *j);
|
||||
}
|
||||
}
|
||||
if (removed_strikes.size() == strikes->size() || loca_list.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (IntegerList::reverse_iterator i = removed_strikes.rbegin(),
|
||||
e = removed_strikes.rend(); i != e; i++) {
|
||||
strikes->erase(strikes->begin() + *i);
|
||||
}
|
||||
|
||||
if (strikes->empty()) { // no glyph covered, can safely drop the builders.
|
||||
return false;
|
||||
}
|
||||
|
||||
ebdt->SetLoca(&loca_list);
|
||||
ebdt->GlyphBuilders(); // Initialize the builder.
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source,
|
||||
BigGlyphMetrics::Builder* target) {
|
||||
target->SetHeight(static_cast<uint8_t>(source->Height()));
|
||||
target->SetWidth(static_cast<uint8_t>(source->Width()));
|
||||
target->SetHoriBearingX(static_cast<uint8_t>(source->HoriBearingX()));
|
||||
target->SetHoriBearingY(static_cast<uint8_t>(source->HoriBearingY()));
|
||||
target->SetHoriAdvance(static_cast<uint8_t>(source->HoriAdvance()));
|
||||
target->SetVertBearingX(static_cast<uint8_t>(source->VertBearingX()));
|
||||
target->SetVertBearingY(static_cast<uint8_t>(source->VertBearingY()));
|
||||
target->SetVertAdvance(static_cast<uint8_t>(source->VertAdvance()));
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca,
|
||||
int32_t* image_data_offset) {
|
||||
IndexSubTableFormat4BuilderPtr builder4;
|
||||
builder4.Attach(IndexSubTableFormat4::Builder::CreateBuilder());
|
||||
CodeOffsetPairBuilderList offset_pairs;
|
||||
|
||||
size_t offset = 0;
|
||||
int32_t lower_bound = b->first_glyph_index();
|
||||
int32_t upper_bound = b->last_glyph_index();
|
||||
int32_t last_gid = -1;
|
||||
BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound);
|
||||
BitmapGlyphInfoMap::const_iterator end = loca.end();
|
||||
if (i != end) {
|
||||
last_gid = i->first;
|
||||
builder4->set_first_glyph_index(last_gid);
|
||||
builder4->set_image_format(b->image_format());
|
||||
builder4->set_image_data_offset(*image_data_offset);
|
||||
}
|
||||
for (; i != end; i++) {
|
||||
int32_t gid = i->first;
|
||||
if (gid > upper_bound) {
|
||||
break;
|
||||
}
|
||||
offset_pairs.push_back(
|
||||
IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset));
|
||||
offset += i->second->length();
|
||||
last_gid = gid;
|
||||
}
|
||||
offset_pairs.push_back(
|
||||
IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset));
|
||||
builder4->set_last_glyph_index(last_gid);
|
||||
*image_data_offset += offset;
|
||||
builder4->SetOffsetArray(offset_pairs);
|
||||
|
||||
return builder4.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca,
|
||||
int32_t* image_data_offset) {
|
||||
IndexSubTableFormat5BuilderPtr new_builder;
|
||||
new_builder.Attach(IndexSubTableFormat5::Builder::CreateBuilder());
|
||||
|
||||
// Copy BigMetrics
|
||||
int32_t image_size = 0;
|
||||
if (b->index_format() == IndexSubTable::Format::FORMAT_2) {
|
||||
IndexSubTableFormat2BuilderPtr builder2 =
|
||||
down_cast<IndexSubTableFormat2::Builder*>(b);
|
||||
CopyBigGlyphMetrics(builder2->BigMetrics(), new_builder->BigMetrics());
|
||||
image_size = builder2->ImageSize();
|
||||
} else {
|
||||
IndexSubTableFormat5BuilderPtr builder5 =
|
||||
down_cast<IndexSubTableFormat5::Builder*>(b);
|
||||
BigGlyphMetricsBuilderPtr metrics_builder;
|
||||
CopyBigGlyphMetrics(builder5->BigMetrics(), new_builder->BigMetrics());
|
||||
image_size = builder5->ImageSize();
|
||||
}
|
||||
|
||||
IntegerList* glyph_array = new_builder->GlyphArray();
|
||||
size_t offset = 0;
|
||||
int32_t lower_bound = b->first_glyph_index();
|
||||
int32_t upper_bound = b->last_glyph_index();
|
||||
int32_t last_gid = -1;
|
||||
BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound);
|
||||
BitmapGlyphInfoMap::const_iterator end = loca.end();
|
||||
if (i != end) {
|
||||
last_gid = i->first;
|
||||
new_builder->set_first_glyph_index(last_gid);
|
||||
new_builder->set_image_format(b->image_format());
|
||||
new_builder->set_image_data_offset(*image_data_offset);
|
||||
new_builder->SetImageSize(image_size);
|
||||
}
|
||||
for (; i != end; i++) {
|
||||
int32_t gid = i->first;
|
||||
if (gid > upper_bound) {
|
||||
break;
|
||||
}
|
||||
glyph_array->push_back(gid);
|
||||
offset += i->second->length();
|
||||
last_gid = gid;
|
||||
}
|
||||
new_builder->set_last_glyph_index(last_gid);
|
||||
*image_data_offset += offset;
|
||||
return new_builder.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
SubsetIndexSubTable(IndexSubTable::Builder* builder,
|
||||
const BitmapGlyphInfoMap& loca,
|
||||
int32_t* image_data_offset) {
|
||||
switch (builder->index_format()) {
|
||||
case IndexSubTable::Format::FORMAT_1:
|
||||
case IndexSubTable::Format::FORMAT_3:
|
||||
case IndexSubTable::Format::FORMAT_4:
|
||||
return ConstructIndexFormat4(builder, loca, image_data_offset);
|
||||
case IndexSubTable::Format::FORMAT_2:
|
||||
case IndexSubTable::Format::FORMAT_5:
|
||||
return ConstructIndexFormat5(builder, loca, image_data_offset);
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// Not thread-safe, caller to ensure object life-time.
|
||||
void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) {
|
||||
BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders();
|
||||
if (size_builders == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t image_data_offset = EbdtTable::Offset::kHeaderLength;
|
||||
for (size_t strike = 0; strike < size_builders->size(); ++strike) {
|
||||
IndexSubTableBuilderList* index_builders =
|
||||
(*size_builders)[strike]->IndexSubTableBuilders();
|
||||
for (size_t index = 0; index < index_builders->size(); ++index) {
|
||||
IndexSubTable::Builder* new_builder_raw =
|
||||
SubsetIndexSubTable((*index_builders)[index], new_loca[strike],
|
||||
&image_data_offset);
|
||||
if (NULL != new_builder_raw) {
|
||||
(*index_builders)[index].Attach(new_builder_raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EBLC structure (from stuartg)
|
||||
// header
|
||||
// bitmapSizeTable[]
|
||||
// one per strike
|
||||
// holds strike metrics - sbitLineMetrics
|
||||
// holds info about indexSubTableArray
|
||||
// indexSubTableArray[][]
|
||||
// one per strike and then one per indexSubTable for that strike
|
||||
// holds info about the indexSubTable
|
||||
// the indexSubTable entries pointed to can be of different formats
|
||||
// indexSubTable
|
||||
// one per indexSubTableArray entry
|
||||
// tells how to get the glyphs
|
||||
// may hold the glyph metrics if they are uniform for all the glyphs in range
|
||||
// Please note that the structure can also be
|
||||
// {indexSubTableArray[], indexSubTables[]}[]
|
||||
// This way is also legal and in fact how Microsoft fonts are laid out.
|
||||
//
|
||||
// There is nothing that says that the indexSubTableArray entries and/or the
|
||||
// indexSubTable items need to be unique. They may be shared between strikes.
|
||||
//
|
||||
// EBDT structure:
|
||||
// header
|
||||
// glyphs
|
||||
// amorphous blob of data
|
||||
// different glyphs that are only able to be figured out from the EBLC table
|
||||
// may hold metrics - depends on the EBLC entry that pointed to them
|
||||
|
||||
// Subsetting EBLC table (from arthurhsu)
|
||||
// Most pages use only a fraction (hundreds or less) glyphs out of a given font
|
||||
// (which can have >20K glyphs for CJK). It's safe to assume that the subset
|
||||
// font will have sparse bitmap glyphs. So we reconstruct the EBLC table as
|
||||
// format 4 or 5 here.
|
||||
|
||||
enum BuildersToRemove {
|
||||
kRemoveNone,
|
||||
kRemoveBDAT,
|
||||
kRemoveBDATAndEBDT,
|
||||
kRemoveEBDT
|
||||
};
|
||||
|
||||
int SetupBitmapBuilders(Font* font, Font::Builder* font_builder,
|
||||
const IntegerSet& glyph_ids) {
|
||||
if (!font || !font_builder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if bitmap table exists.
|
||||
EbdtTablePtr ebdt_table = down_cast<EbdtTable*>(font->GetTable(Tag::EBDT));
|
||||
EblcTablePtr eblc_table = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
|
||||
bool use_ebdt = (ebdt_table != NULL && eblc_table != NULL);
|
||||
if (!use_ebdt) {
|
||||
ebdt_table = down_cast<EbdtTable*>(font->GetTable(Tag::bdat));
|
||||
eblc_table = down_cast<EblcTable*>(font->GetTable(Tag::bloc));
|
||||
if (ebdt_table == NULL || eblc_table == NULL) {
|
||||
return kRemoveNone;
|
||||
}
|
||||
}
|
||||
|
||||
// If the bitmap table's size is too small, skip subsetting.
|
||||
if (ebdt_table->DataLength() + eblc_table->DataLength() <
|
||||
BITMAP_SIZE_THRESHOLD) {
|
||||
return use_ebdt ? kRemoveBDAT : kRemoveNone;
|
||||
}
|
||||
|
||||
// Get the builders.
|
||||
EbdtTableBuilderPtr ebdt_table_builder = down_cast<EbdtTable::Builder*>(
|
||||
font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat,
|
||||
ebdt_table->ReadFontData()));
|
||||
EblcTableBuilderPtr eblc_table_builder = down_cast<EblcTable::Builder*>(
|
||||
font_builder->NewTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc,
|
||||
eblc_table->ReadFontData()));
|
||||
if (ebdt_table_builder == NULL || eblc_table_builder == NULL) {
|
||||
// Out of memory.
|
||||
return use_ebdt ? kRemoveBDAT : kRemoveNone;
|
||||
}
|
||||
|
||||
if (!InitializeBitmapBuilder(ebdt_table_builder, eblc_table_builder,
|
||||
glyph_ids)) {
|
||||
// Bitmap tables do not cover the glyphs in our subset.
|
||||
font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc);
|
||||
font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat);
|
||||
return use_ebdt ? kRemoveBDATAndEBDT : kRemoveEBDT;
|
||||
}
|
||||
|
||||
BitmapLocaList new_loca;
|
||||
ebdt_table_builder->GenerateLocaList(&new_loca);
|
||||
SubsetEBLC(eblc_table_builder, new_loca);
|
||||
|
||||
return use_ebdt ? kRemoveBDAT : kRemoveNone;
|
||||
}
|
||||
|
||||
SubsetterImpl::SubsetterImpl() {
|
||||
}
|
||||
|
||||
SubsetterImpl::~SubsetterImpl() {
|
||||
}
|
||||
|
||||
bool SubsetterImpl::LoadFont(int font_index,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size) {
|
||||
MemoryInputStream mis;
|
||||
mis.Attach(original_font, font_size);
|
||||
if (factory_ == NULL) {
|
||||
factory_.Attach(FontFactory::GetInstance());
|
||||
}
|
||||
|
||||
FontArray font_array;
|
||||
factory_->LoadFonts(&mis, &font_array);
|
||||
if (font_index < 0 || (size_t)font_index >= font_array.size()) {
|
||||
return false;
|
||||
}
|
||||
font_ = font_array[font_index].p_;
|
||||
return font_ != NULL;
|
||||
}
|
||||
|
||||
bool SubsetterImpl::LoadFont(const char* font_name,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size) {
|
||||
MemoryInputStream mis;
|
||||
mis.Attach(original_font, font_size);
|
||||
if (factory_ == NULL) {
|
||||
factory_.Attach(FontFactory::GetInstance());
|
||||
}
|
||||
|
||||
FontArray font_array;
|
||||
factory_->LoadFonts(&mis, &font_array);
|
||||
font_ = FindFont(font_name, font_array);
|
||||
return font_ != NULL;
|
||||
}
|
||||
|
||||
int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer) {
|
||||
if (factory_ == NULL || font_ == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find glyf and loca table.
|
||||
GlyphTablePtr glyph_table =
|
||||
down_cast<GlyphTable*>(font_->GetTable(Tag::glyf));
|
||||
LocaTablePtr loca_table = down_cast<LocaTable*>(font_->GetTable(Tag::loca));
|
||||
if (glyph_table == NULL || loca_table == NULL) {
|
||||
// We are not able to subset the font.
|
||||
return 0;
|
||||
}
|
||||
|
||||
IntegerSet glyph_id_processed;
|
||||
if (!ResolveCompositeGlyphs(glyph_table, loca_table,
|
||||
glyph_ids, glyph_count, &glyph_id_processed) ||
|
||||
glyph_id_processed.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FontPtr new_font;
|
||||
new_font.Attach(Subset(glyph_id_processed, glyph_table, loca_table));
|
||||
if (new_font == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MemoryOutputStream output_stream;
|
||||
factory_->SerializeFont(new_font, &output_stream);
|
||||
size_t length = output_stream.Size();
|
||||
if (length == 0 ||
|
||||
length > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*output_buffer = new unsigned char[length];
|
||||
memcpy(*output_buffer, output_stream.Get(), length);
|
||||
return length;
|
||||
}
|
||||
|
||||
// Long comments regarding TTF tables and PDF (from stuartg)
|
||||
//
|
||||
// According to PDF spec 1.4 (section 5.8), the following tables must be
|
||||
// present:
|
||||
// head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
|
||||
// cmap if font is used with a simple font dict and not a CIDFont dict
|
||||
//
|
||||
// Other tables we need to keep for PDF rendering to support zoom in/out:
|
||||
// bdat, bloc, ebdt, eblc, ebsc, gasp
|
||||
//
|
||||
// Special table:
|
||||
// CFF - if you have this table then you shouldn't have a glyf table and this
|
||||
// is the table with all the glyphs. Shall skip subsetting completely
|
||||
// since sfntly is not capable of subsetting it for now.
|
||||
// post - extra info here for printing on PostScript printers but maybe not
|
||||
// enough to outweigh the space taken by the names
|
||||
//
|
||||
// Tables to break apart:
|
||||
// name - could throw away all but one language and one platform strings/ might
|
||||
// throw away some of the name entries
|
||||
// cmap - could strip out non-needed cmap subtables
|
||||
// - format 4 subtable can be subsetted as well using sfntly
|
||||
//
|
||||
// Graphite tables:
|
||||
// silf, glat, gloc, feat - should be okay to strip out
|
||||
//
|
||||
// Tables that can be discarded:
|
||||
// OS/2 - everything here is for layout and description of the font that is
|
||||
// elsewhere (some in the PDF objects)
|
||||
// BASE, GDEF, GSUB, GPOS, JSTF - all used for layout
|
||||
// kern - old style layout
|
||||
// DSIG - this will be invalid after subsetting
|
||||
// hdmx - layout
|
||||
// PCLT - metadata that's not needed
|
||||
// vmtx - layout
|
||||
// vhea - layout
|
||||
// VDMX
|
||||
// VORG - not used by TT/OT - used by CFF
|
||||
// hsty - would be surprised to see one of these - used on the Newton
|
||||
// AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop,
|
||||
// Zapf, opbd, trak, fvar, gvar, avar, cvar
|
||||
// - these are all layout tables and once layout happens are not
|
||||
// needed anymore
|
||||
// LTSH - layout
|
||||
|
||||
CALLER_ATTACH
|
||||
Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf,
|
||||
LocaTable* loca) {
|
||||
// The const is initialized here to workaround VC bug of rendering all Tag::*
|
||||
// as 0. These tags represents the TTF tables that we will embed in subset
|
||||
// font.
|
||||
const int32_t TABLES_IN_SUBSET[] = {
|
||||
Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt,
|
||||
Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT,
|
||||
Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed,
|
||||
Tag::cmap, // Keep here for future tagged PDF development.
|
||||
Tag::name, // Keep here due to legal concerns: copyright info inside.
|
||||
};
|
||||
const size_t kTablesInSubSetSize =
|
||||
sizeof(TABLES_IN_SUBSET) / sizeof(TABLES_IN_SUBSET[0]);
|
||||
|
||||
// Setup font builders we need.
|
||||
FontBuilderPtr font_builder;
|
||||
font_builder.Attach(factory_->NewFontBuilder());
|
||||
IntegerSet remove_tags;
|
||||
|
||||
if (SetupGlyfBuilders(font_builder, glyf, loca, glyph_ids)) {
|
||||
remove_tags.insert(Tag::glyf);
|
||||
remove_tags.insert(Tag::loca);
|
||||
}
|
||||
|
||||
// For old Apple bitmap fonts, they have only bdats and bhed is identical
|
||||
// to head. As a result, we can't remove bdat tables for those fonts.
|
||||
int setup_result = SetupBitmapBuilders(font_, font_builder, glyph_ids);
|
||||
if (setup_result == kRemoveBDATAndEBDT || setup_result == kRemoveEBDT) {
|
||||
remove_tags.insert(Tag::EBDT);
|
||||
remove_tags.insert(Tag::EBLC);
|
||||
remove_tags.insert(Tag::EBSC);
|
||||
}
|
||||
|
||||
if (setup_result == kRemoveBDAT || setup_result == kRemoveBDATAndEBDT) {
|
||||
remove_tags.insert(Tag::bdat);
|
||||
remove_tags.insert(Tag::bloc);
|
||||
remove_tags.insert(Tag::bhed);
|
||||
}
|
||||
|
||||
IntegerSet allowed_tags;
|
||||
for (size_t i = 0; i < kTablesInSubSetSize; ++i)
|
||||
allowed_tags.insert(TABLES_IN_SUBSET[i]);
|
||||
|
||||
IntegerSet result;
|
||||
std::set_difference(allowed_tags.begin(), allowed_tags.end(),
|
||||
remove_tags.begin(), remove_tags.end(),
|
||||
std::inserter(result, result.end()));
|
||||
allowed_tags = result;
|
||||
|
||||
// Setup remaining builders.
|
||||
for (IntegerSet::const_iterator it = allowed_tags.begin();
|
||||
it != allowed_tags.end(); ++it) {
|
||||
int32_t tag = *it;
|
||||
Table* table = font_->GetTable(tag);
|
||||
if (table)
|
||||
font_builder->NewTableBuilder(tag, table->ReadFontData());
|
||||
}
|
||||
|
||||
return font_builder->Build();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
// File is originally from Chromium third_party/sfntly/src/subsetter.
|
||||
// Use as test case in sfntly so that problems can be caught in upstream early.
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_
|
||||
#define SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/table/truetype/glyph_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
#include "sfntly/tag.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// Smart pointer usage in sfntly:
|
||||
//
|
||||
// sfntly carries a smart pointer implementation like COM. Ref-countable object
|
||||
// type inherits from RefCounted<>, which have AddRef and Release just like
|
||||
// IUnknown (but no QueryInterface). Use a Ptr<> based smart pointer to hold
|
||||
// the object so that the object ref count is handled correctly.
|
||||
//
|
||||
// class Foo : public RefCounted<Foo> {
|
||||
// public:
|
||||
// static Foo* CreateInstance() {
|
||||
// Ptr<Foo> obj = new Foo(); // ref count = 1
|
||||
// return obj.detach();
|
||||
// }
|
||||
// };
|
||||
// typedef Ptr<Foo> FooPtr; // common short-hand notation
|
||||
// FooPtr obj;
|
||||
// obj.attach(Foo::CreatedInstance()); // ref count = 1
|
||||
// {
|
||||
// FooPtr obj2 = obj; // ref count = 2
|
||||
// } // ref count = 1, obj2 out of scope
|
||||
// obj.release(); // ref count = 0, object destroyed
|
||||
|
||||
class SubsetterImpl {
|
||||
public:
|
||||
SubsetterImpl();
|
||||
~SubsetterImpl();
|
||||
|
||||
bool LoadFont(const char* font_name,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size);
|
||||
bool LoadFont(int font_index,
|
||||
const unsigned char* original_font,
|
||||
size_t font_size);
|
||||
int SubsetFont(const unsigned int* glyph_ids,
|
||||
size_t glyph_count,
|
||||
unsigned char** output_buffer);
|
||||
|
||||
private:
|
||||
CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids,
|
||||
GlyphTable* glyf, LocaTable* loca);
|
||||
|
||||
FontFactoryPtr factory_;
|
||||
FontPtr font_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
#if _MSC_VER > 12
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#include "sample/subsetter/subset_util.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
#ifdef _CRTDBG_MAP_ALLOC
|
||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||
#endif
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Usage: subsetter <font file> <output file>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfntly::SubsetUtil subset_util;
|
||||
subset_util.Subset(argv[1], argv[2]);
|
||||
|
||||
#ifdef _CRTDBG_MAP_ALLOC
|
||||
_CrtDumpMemoryLeaks();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
// Remove VC++ nag on fopen.
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include "sample/subsetter/subset_util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/data/memory_byte_array.h"
|
||||
#include "sfntly/port/memory_output_stream.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/tag.h"
|
||||
#include "sfntly/tools/subsetter/subsetter.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
SubsetUtil::SubsetUtil() {
|
||||
}
|
||||
|
||||
SubsetUtil::~SubsetUtil() {
|
||||
}
|
||||
|
||||
void SubsetUtil::Subset(const char *input_file_path,
|
||||
const char *output_file_path) {
|
||||
UNREFERENCED_PARAMETER(output_file_path);
|
||||
ByteVector input_buffer;
|
||||
FILE* input_file = fopen(input_file_path, "rb");
|
||||
if (input_file == NULL) {
|
||||
fprintf(stderr, "file not found\n");
|
||||
return;
|
||||
}
|
||||
fseek(input_file, 0, SEEK_END);
|
||||
size_t file_size = ftell(input_file);
|
||||
fseek(input_file, 0, SEEK_SET);
|
||||
input_buffer.resize(file_size);
|
||||
size_t bytes_read = fread(&(input_buffer[0]), 1, file_size, input_file);
|
||||
UNREFERENCED_PARAMETER(bytes_read);
|
||||
fclose(input_file);
|
||||
|
||||
FontFactoryPtr factory;
|
||||
factory.Attach(FontFactory::GetInstance());
|
||||
|
||||
FontArray font_array;
|
||||
factory->LoadFonts(&input_buffer, &font_array);
|
||||
if (font_array.empty() || font_array[0] == NULL)
|
||||
return;
|
||||
|
||||
IntegerList glyphs;
|
||||
for (int32_t i = 0; i < 10; i++) {
|
||||
glyphs.push_back(i);
|
||||
}
|
||||
glyphs.push_back(11);
|
||||
glyphs.push_back(10);
|
||||
|
||||
Ptr<Subsetter> subsetter = new Subsetter(font_array[0], factory);
|
||||
subsetter->SetGlyphs(&glyphs);
|
||||
IntegerSet remove_tables;
|
||||
remove_tables.insert(Tag::DSIG);
|
||||
subsetter->SetRemoveTables(&remove_tables);
|
||||
|
||||
FontBuilderPtr font_builder;
|
||||
font_builder.Attach(subsetter->Subset());
|
||||
|
||||
FontPtr new_font;
|
||||
new_font.Attach(font_builder->Build());
|
||||
|
||||
// TODO(arthurhsu): glyph renumbering/Loca table
|
||||
// TODO(arthurhsu): alter CMaps
|
||||
|
||||
MemoryOutputStream output_stream;
|
||||
factory->SerializeFont(new_font, &output_stream);
|
||||
|
||||
FILE* output_file = fopen(output_file_path, "wb");
|
||||
fwrite(output_stream.Get(), 1, output_stream.Size(), output_file);
|
||||
fflush(output_file);
|
||||
fclose(output_file);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_
|
||||
#define SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class SubsetUtil {
|
||||
public:
|
||||
SubsetUtil();
|
||||
virtual ~SubsetUtil();
|
||||
|
||||
void Subset(const char* input_file_path, const char* output_file_path);
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/port/refcount.h"
|
||||
#include "subtly/character_predicate.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
// AcceptRange predicate
|
||||
AcceptRange::AcceptRange(int32_t start, int32_t end)
|
||||
: start_(start),
|
||||
end_(end) {
|
||||
}
|
||||
|
||||
AcceptRange::~AcceptRange() {}
|
||||
|
||||
bool AcceptRange::operator()(int32_t character) const {
|
||||
return start_ <= character && character <= end_;
|
||||
}
|
||||
|
||||
// AcceptSet predicate
|
||||
AcceptSet::AcceptSet(IntegerSet* characters)
|
||||
: characters_(characters) {
|
||||
}
|
||||
|
||||
AcceptSet::~AcceptSet() {
|
||||
delete characters_;
|
||||
}
|
||||
|
||||
bool AcceptSet::operator()(int32_t character) const {
|
||||
return characters_->find(character) != characters_->end();
|
||||
}
|
||||
|
||||
// AcceptAll predicate
|
||||
bool AcceptAll::operator()(int32_t character) const {
|
||||
UNREFERENCED_PARAMETER(character);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_
|
||||
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace subtly {
|
||||
class CharacterPredicate : virtual public sfntly::RefCount {
|
||||
public:
|
||||
CharacterPredicate() {}
|
||||
virtual ~CharacterPredicate() {}
|
||||
virtual bool operator()(int32_t character) const = 0;
|
||||
};
|
||||
|
||||
// All characters except for those between [start, end] are rejected
|
||||
class AcceptRange : public CharacterPredicate,
|
||||
public sfntly::RefCounted<AcceptRange> {
|
||||
public:
|
||||
AcceptRange(int32_t start, int32_t end);
|
||||
~AcceptRange();
|
||||
virtual bool operator()(int32_t character) const;
|
||||
|
||||
private:
|
||||
int32_t start_;
|
||||
int32_t end_;
|
||||
};
|
||||
|
||||
// All characters in IntegerSet
|
||||
// The set is OWNED by the predicate! Do not modify it.
|
||||
// It will be freed when the predicate is destroyed.
|
||||
class AcceptSet : public CharacterPredicate,
|
||||
public sfntly::RefCounted<AcceptSet> {
|
||||
public:
|
||||
explicit AcceptSet(sfntly::IntegerSet* characters);
|
||||
~AcceptSet();
|
||||
virtual bool operator()(int32_t character) const;
|
||||
|
||||
private:
|
||||
sfntly::IntegerSet* characters_;
|
||||
};
|
||||
|
||||
// All characters
|
||||
class AcceptAll : public CharacterPredicate,
|
||||
public sfntly::RefCounted<AcceptAll> {
|
||||
public:
|
||||
AcceptAll() {}
|
||||
~AcceptAll() {}
|
||||
virtual bool operator()(int32_t character) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/table/core/cmap_table.h"
|
||||
#include "sfntly/tag.h"
|
||||
#include "subtly/stats.h"
|
||||
#include "subtly/subsetter.h"
|
||||
#include "subtly/utils.h"
|
||||
|
||||
using namespace subtly;
|
||||
|
||||
void PrintUsage(const char* program_name) {
|
||||
fprintf(stdout, "Usage: %s <input_font_file>\n", program_name);
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
const char* program_name = argv[0];
|
||||
if (argc < 2) {
|
||||
PrintUsage(program_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char* input_font_path = argv[1];
|
||||
const char* output_font_path = argv[2];
|
||||
FontPtr font;
|
||||
font.Attach(subtly::LoadFont(input_font_path));
|
||||
|
||||
int32_t original_size = TotalFontSize(font);
|
||||
Ptr<Subsetter> subsetter = new Subsetter(font, NULL);
|
||||
Ptr<Font> new_font;
|
||||
new_font.Attach(subsetter->Subset());
|
||||
if (!new_font) {
|
||||
fprintf(stdout, "Cannot create subset.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
subtly::SerializeFont(output_font_path, new_font);
|
||||
subtly::PrintComparison(stdout, font, new_font);
|
||||
int32_t new_size = TotalFontSize(new_font);
|
||||
fprintf(stdout, "Went from %d to %d: %lf%% of original\n",
|
||||
original_size, new_size,
|
||||
static_cast<double>(new_size) / original_size * 100);
|
||||
return 0;
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subtly/font_assembler.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "sfntly/tag.h"
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/table/core/cmap_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
#include "sfntly/table/truetype/glyph_table.h"
|
||||
#include "sfntly/table/core/maximum_profile_table.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "subtly/font_info.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
FontAssembler::FontAssembler(FontInfo* font_info,
|
||||
IntegerSet* table_blacklist)
|
||||
: table_blacklist_(table_blacklist) {
|
||||
font_info_ = font_info;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
FontAssembler::FontAssembler(FontInfo* font_info)
|
||||
: table_blacklist_(NULL) {
|
||||
font_info_ = font_info;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void FontAssembler::Initialize() {
|
||||
font_factory_.Attach(sfntly::FontFactory::GetInstance());
|
||||
font_builder_.Attach(font_factory_->NewFontBuilder());
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* FontAssembler::Assemble() {
|
||||
// Assemble tables we can subset.
|
||||
if (!AssembleCMapTable() || !AssembleGlyphAndLocaTables()) {
|
||||
return NULL;
|
||||
}
|
||||
// For all other tables, either include them unmodified or don't at all.
|
||||
const TableMap* common_table_map =
|
||||
font_info_->GetTableMap(font_info_->fonts()->begin()->first);
|
||||
for (TableMap::const_iterator it = common_table_map->begin(),
|
||||
e = common_table_map->end(); it != e; ++it) {
|
||||
if (table_blacklist_
|
||||
&& table_blacklist_->find(it->first) != table_blacklist_->end()) {
|
||||
continue;
|
||||
}
|
||||
font_builder_->NewTableBuilder(it->first, it->second->ReadFontData());
|
||||
}
|
||||
return font_builder_->Build();
|
||||
}
|
||||
|
||||
bool FontAssembler::AssembleCMapTable() {
|
||||
// Creating the new CMapTable and the new format 4 CMap
|
||||
Ptr<CMapTable::Builder> cmap_table_builder =
|
||||
down_cast<CMapTable::Builder*>
|
||||
(font_builder_->NewTableBuilder(Tag::cmap));
|
||||
if (!cmap_table_builder)
|
||||
return false;
|
||||
Ptr<CMapTable::CMapFormat4::Builder> cmap_builder =
|
||||
down_cast<CMapTable::CMapFormat4::Builder*>
|
||||
(cmap_table_builder->NewCMapBuilder(CMapFormat::kFormat4,
|
||||
CMapTable::WINDOWS_BMP));
|
||||
if (!cmap_builder)
|
||||
return false;
|
||||
// Creating the segments and the glyph id array
|
||||
CharacterMap* chars_to_glyph_ids = font_info_->chars_to_glyph_ids();
|
||||
SegmentList* segment_list = new SegmentList;
|
||||
IntegerList* glyph_id_array = new IntegerList;
|
||||
int32_t last_chararacter = -2;
|
||||
int32_t last_offset = 0;
|
||||
Ptr<CMapTable::CMapFormat4::Builder::Segment> current_segment;
|
||||
|
||||
// For simplicity, we will have one segment per contiguous range.
|
||||
// To test the algorithm, we've replaced the original CMap with the CMap
|
||||
// generated by this code without removing any character.
|
||||
// Tuffy.ttf: CMap went from 3146 to 3972 bytes (1.7% to 2.17% of file)
|
||||
// AnonymousPro.ttf: CMap went from 1524 to 1900 bytes (0.96% to 1.2%)
|
||||
for (CharacterMap::iterator it = chars_to_glyph_ids->begin(),
|
||||
e = chars_to_glyph_ids->end(); it != e; ++it) {
|
||||
int32_t character = it->first;
|
||||
int32_t glyph_id = it->second.glyph_id();
|
||||
if (character != last_chararacter + 1) { // new segment
|
||||
if (current_segment != NULL) {
|
||||
current_segment->set_end_count(last_chararacter);
|
||||
segment_list->push_back(current_segment);
|
||||
}
|
||||
// start_code = character
|
||||
// end_code = -1 (unknown for now)
|
||||
// id_delta = 0 (we don't use id_delta for this representation)
|
||||
// id_range_offset = last_offset (offset into the glyph_id_array)
|
||||
current_segment =
|
||||
new CMapTable::CMapFormat4::Builder::
|
||||
Segment(character, -1, 0, last_offset);
|
||||
}
|
||||
glyph_id_array->push_back(glyph_id);
|
||||
last_offset += DataSize::kSHORT;
|
||||
last_chararacter = character;
|
||||
}
|
||||
// The last segment is still open.
|
||||
current_segment->set_end_count(last_chararacter);
|
||||
segment_list->push_back(current_segment);
|
||||
// Updating the id_range_offset for every segment.
|
||||
for (int32_t i = 0, num_segs = segment_list->size(); i < num_segs; ++i) {
|
||||
Ptr<CMapTable::CMapFormat4::Builder::Segment> segment = segment_list->at(i);
|
||||
segment->set_id_range_offset(segment->id_range_offset()
|
||||
+ (num_segs - i + 1) * DataSize::kSHORT);
|
||||
}
|
||||
// Adding the final, required segment.
|
||||
current_segment =
|
||||
new CMapTable::CMapFormat4::Builder::Segment(0xffff, 0xffff, 1, 0);
|
||||
segment_list->push_back(current_segment);
|
||||
// Writing the segments and glyph id array to the CMap
|
||||
cmap_builder->set_segments(segment_list);
|
||||
cmap_builder->set_glyph_id_array(glyph_id_array);
|
||||
delete segment_list;
|
||||
delete glyph_id_array;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FontAssembler::AssembleGlyphAndLocaTables() {
|
||||
Ptr<LocaTable::Builder> loca_table_builder =
|
||||
down_cast<LocaTable::Builder*>
|
||||
(font_builder_->NewTableBuilder(Tag::loca));
|
||||
Ptr<GlyphTable::Builder> glyph_table_builder =
|
||||
down_cast<GlyphTable::Builder*>
|
||||
(font_builder_->NewTableBuilder(Tag::glyf));
|
||||
|
||||
GlyphIdSet* resolved_glyph_ids = font_info_->resolved_glyph_ids();
|
||||
IntegerList loca_list;
|
||||
// Basic sanity check: all LOCA tables are of the same size
|
||||
// This is necessary but not suficient!
|
||||
int32_t previous_size = -1;
|
||||
for (FontIdMap::iterator it = font_info_->fonts()->begin();
|
||||
it != font_info_->fonts()->end(); ++it) {
|
||||
Ptr<LocaTable> loca_table =
|
||||
down_cast<LocaTable*>(font_info_->GetTable(it->first, Tag::loca));
|
||||
int32_t current_size = loca_table->header_length();
|
||||
if (previous_size != -1 && current_size != previous_size) {
|
||||
return false;
|
||||
}
|
||||
previous_size = current_size;
|
||||
}
|
||||
|
||||
// Assuming all fonts referenced by the FontInfo are the subsets of the same
|
||||
// font, their loca tables should all have the same sizes.
|
||||
// We'll just get the size of the first font's LOCA table for simplicty.
|
||||
Ptr<LocaTable> first_loca_table =
|
||||
down_cast<LocaTable*>
|
||||
(font_info_->GetTable(font_info_->fonts()->begin()->first, Tag::loca));
|
||||
int32_t num_loca_glyphs = first_loca_table->num_glyphs();
|
||||
loca_list.resize(num_loca_glyphs);
|
||||
loca_list.push_back(0);
|
||||
int32_t last_glyph_id = 0;
|
||||
int32_t last_offset = 0;
|
||||
GlyphTable::GlyphBuilderList* glyph_builders =
|
||||
glyph_table_builder->GlyphBuilders();
|
||||
|
||||
for (GlyphIdSet::iterator it = resolved_glyph_ids->begin(),
|
||||
e = resolved_glyph_ids->end(); it != e; ++it) {
|
||||
// Get the glyph for this resolved_glyph_id.
|
||||
int32_t resolved_glyph_id = it->glyph_id();
|
||||
int32_t font_id = it->font_id();
|
||||
// Get the LOCA table for the current glyph id.
|
||||
Ptr<LocaTable> loca_table =
|
||||
down_cast<LocaTable*>
|
||||
(font_info_->GetTable(font_id, Tag::loca));
|
||||
int32_t length = loca_table->GlyphLength(resolved_glyph_id);
|
||||
int32_t offset = loca_table->GlyphOffset(resolved_glyph_id);
|
||||
|
||||
// Get the GLYF table for the current glyph id.
|
||||
Ptr<GlyphTable> glyph_table =
|
||||
down_cast<GlyphTable*>
|
||||
(font_info_->GetTable(font_id, Tag::glyf));
|
||||
GlyphPtr glyph;
|
||||
glyph.Attach(glyph_table->GetGlyph(offset, length));
|
||||
|
||||
// The data reference by the glyph is copied into a new glyph and
|
||||
// added to the glyph_builders belonging to the glyph_table_builder.
|
||||
// When Build gets called, all the glyphs will be built.
|
||||
Ptr<ReadableFontData> data = glyph->ReadFontData();
|
||||
Ptr<WritableFontData> copy_data;
|
||||
copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length()));
|
||||
data->CopyTo(copy_data);
|
||||
GlyphBuilderPtr glyph_builder;
|
||||
glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data));
|
||||
glyph_builders->push_back(glyph_builder);
|
||||
|
||||
// If there are missing glyphs between the last glyph_id and the
|
||||
// current resolved_glyph_id, since the LOCA table needs to have the same
|
||||
// size, the offset is kept the same.
|
||||
loca_list.resize(std::max(loca_list.size(),
|
||||
static_cast<size_t>(resolved_glyph_id + 2)));
|
||||
for (int32_t i = last_glyph_id + 1; i <= resolved_glyph_id; ++i)
|
||||
loca_list[i] = last_offset;
|
||||
last_offset += length;
|
||||
loca_list[resolved_glyph_id + 1] = last_offset;
|
||||
last_glyph_id = resolved_glyph_id + 1;
|
||||
}
|
||||
// If there are missing glyph ids, their loca entries must all point
|
||||
// to the same offset as the last valid glyph id making them all zero length.
|
||||
for (int32_t i = last_glyph_id + 1; i <= num_loca_glyphs; ++i)
|
||||
loca_list[i] = last_offset;
|
||||
loca_table_builder->SetLocaList(&loca_list);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "subtly/font_info.h"
|
||||
|
||||
#include "sfntly/tag.h"
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/table/core/cmap_table.h"
|
||||
#include "sfntly/table/truetype/glyph_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
|
||||
namespace subtly {
|
||||
// Assembles FontInfo into font builders.
|
||||
// Does not take ownership of data passed to it.
|
||||
class FontAssembler : public sfntly::RefCounted<FontAssembler> {
|
||||
public:
|
||||
// font_info is the FontInfo which will be used for the new font
|
||||
// table_blacklist is used to decide which tables to exclude from the
|
||||
// final font.
|
||||
FontAssembler(FontInfo* font_info, sfntly::IntegerSet* table_blacklist);
|
||||
explicit FontAssembler(FontInfo* font_info);
|
||||
~FontAssembler() { }
|
||||
|
||||
// Assemble a new font from the font info object.
|
||||
virtual CALLER_ATTACH sfntly::Font* Assemble();
|
||||
|
||||
sfntly::IntegerSet* table_blacklist() const { return table_blacklist_; }
|
||||
void set_table_blacklist(sfntly::IntegerSet* table_blacklist) {
|
||||
table_blacklist_ = table_blacklist;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool AssembleCMapTable();
|
||||
virtual bool AssembleGlyphAndLocaTables();
|
||||
|
||||
virtual void Initialize();
|
||||
|
||||
private:
|
||||
sfntly::Ptr<FontInfo> font_info_;
|
||||
sfntly::Ptr<sfntly::FontFactory> font_factory_;
|
||||
sfntly::Ptr<sfntly::Font::Builder> font_builder_;
|
||||
sfntly::IntegerSet* table_blacklist_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subtly/font_info.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "subtly/character_predicate.h"
|
||||
|
||||
#include "sfntly/tag.h"
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/table/core/cmap_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
#include "sfntly/table/truetype/glyph_table.h"
|
||||
#include "sfntly/table/core/maximum_profile_table.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/refcount.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
/******************************************************************************
|
||||
* GlyphId class
|
||||
******************************************************************************/
|
||||
GlyphId::GlyphId(int32_t glyph_id, FontId font_id)
|
||||
: glyph_id_(glyph_id),
|
||||
font_id_(font_id) {
|
||||
}
|
||||
|
||||
bool GlyphId::operator==(const GlyphId& other) const {
|
||||
return glyph_id_ == other.glyph_id();
|
||||
}
|
||||
|
||||
bool GlyphId::operator<(const GlyphId& other) const {
|
||||
return glyph_id_ < other.glyph_id();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FontInfo class
|
||||
******************************************************************************/
|
||||
FontInfo::FontInfo()
|
||||
: chars_to_glyph_ids_(new CharacterMap),
|
||||
resolved_glyph_ids_(new GlyphIdSet),
|
||||
fonts_(new FontIdMap) {
|
||||
}
|
||||
|
||||
FontInfo::FontInfo(CharacterMap* chars_to_glyph_ids,
|
||||
GlyphIdSet* resolved_glyph_ids,
|
||||
FontIdMap* fonts) {
|
||||
chars_to_glyph_ids_ = new CharacterMap(chars_to_glyph_ids->begin(),
|
||||
chars_to_glyph_ids->end());
|
||||
resolved_glyph_ids_ = new GlyphIdSet(resolved_glyph_ids->begin(),
|
||||
resolved_glyph_ids->end());
|
||||
fonts_ = new FontIdMap(fonts->begin(), fonts->end());
|
||||
}
|
||||
|
||||
FontInfo::~FontInfo() {
|
||||
delete chars_to_glyph_ids_;
|
||||
delete resolved_glyph_ids_;
|
||||
delete fonts_;
|
||||
}
|
||||
|
||||
FontDataTable* FontInfo::GetTable(FontId font_id, int32_t tag) {
|
||||
if (!fonts_)
|
||||
return NULL;
|
||||
FontIdMap::iterator it = fonts_->find(font_id);
|
||||
if (it == fonts_->end())
|
||||
return NULL;
|
||||
return it->second->GetTable(tag);
|
||||
}
|
||||
|
||||
const TableMap* FontInfo::GetTableMap(FontId font_id) {
|
||||
if (!fonts_)
|
||||
return NULL;
|
||||
FontIdMap::iterator it = fonts_->find(font_id);
|
||||
if (it == fonts_->end())
|
||||
return NULL;
|
||||
return it->second->GetTableMap();
|
||||
}
|
||||
|
||||
void FontInfo::set_chars_to_glyph_ids(CharacterMap* chars_to_glyph_ids) {
|
||||
*chars_to_glyph_ids_ = *chars_to_glyph_ids;
|
||||
}
|
||||
|
||||
void FontInfo::set_resolved_glyph_ids(GlyphIdSet* resolved_glyph_ids) {
|
||||
*resolved_glyph_ids_ = *resolved_glyph_ids;
|
||||
}
|
||||
|
||||
void FontInfo::set_fonts(FontIdMap* fonts) {
|
||||
*fonts_ = *fonts;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FontSourcedInfoBuilder class
|
||||
******************************************************************************/
|
||||
FontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font, FontId font_id)
|
||||
: font_(font),
|
||||
font_id_(font_id),
|
||||
predicate_(NULL) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
FontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font,
|
||||
FontId font_id,
|
||||
CharacterPredicate* predicate)
|
||||
: font_(font),
|
||||
font_id_(font_id),
|
||||
predicate_(predicate) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void FontSourcedInfoBuilder::Initialize() {
|
||||
Ptr<CMapTable> cmap_table = down_cast<CMapTable*>(font_->GetTable(Tag::cmap));
|
||||
// We prefer Windows BMP format 4 cmaps.
|
||||
cmap_.Attach(cmap_table->GetCMap(CMapTable::WINDOWS_BMP));
|
||||
// But if none is found,
|
||||
if (!cmap_) {
|
||||
return;
|
||||
}
|
||||
loca_table_ = down_cast<LocaTable*>(font_->GetTable(Tag::loca));
|
||||
glyph_table_ = down_cast<GlyphTable*>(font_->GetTable(Tag::glyf));
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontInfo* FontSourcedInfoBuilder::GetFontInfo() {
|
||||
CharacterMap* chars_to_glyph_ids = new CharacterMap;
|
||||
bool success = GetCharacterMap(chars_to_glyph_ids);
|
||||
if (!success) {
|
||||
delete chars_to_glyph_ids;
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Error creating character map.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
GlyphIdSet* resolved_glyph_ids = new GlyphIdSet;
|
||||
success = ResolveCompositeGlyphs(chars_to_glyph_ids, resolved_glyph_ids);
|
||||
if (!success) {
|
||||
delete chars_to_glyph_ids;
|
||||
delete resolved_glyph_ids;
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Error resolving composite glyphs.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
Ptr<FontInfo> font_info = new FontInfo;
|
||||
font_info->set_chars_to_glyph_ids(chars_to_glyph_ids);
|
||||
font_info->set_resolved_glyph_ids(resolved_glyph_ids);
|
||||
FontIdMap* font_id_map = new FontIdMap;
|
||||
font_id_map->insert(std::make_pair(font_id_, font_));
|
||||
font_info->set_fonts(font_id_map);
|
||||
delete chars_to_glyph_ids;
|
||||
delete resolved_glyph_ids;
|
||||
delete font_id_map;
|
||||
return font_info.Detach();
|
||||
}
|
||||
|
||||
bool FontSourcedInfoBuilder::GetCharacterMap(CharacterMap* chars_to_glyph_ids) {
|
||||
if (!cmap_ || !chars_to_glyph_ids)
|
||||
return false;
|
||||
chars_to_glyph_ids->clear();
|
||||
CMapTable::CMap::CharacterIterator* character_iterator = cmap_->Iterator();
|
||||
if (!character_iterator)
|
||||
return false;
|
||||
while (character_iterator->HasNext()) {
|
||||
int32_t character = character_iterator->Next();
|
||||
if (!predicate_ || (*predicate_)(character)) {
|
||||
chars_to_glyph_ids->insert
|
||||
(std::make_pair(character,
|
||||
GlyphId(cmap_->GlyphId(character), font_id_)));
|
||||
}
|
||||
}
|
||||
delete character_iterator;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FontSourcedInfoBuilder::ResolveCompositeGlyphs(CharacterMap* chars_to_glyph_ids,
|
||||
GlyphIdSet* resolved_glyph_ids) {
|
||||
if (!chars_to_glyph_ids || !resolved_glyph_ids)
|
||||
return false;
|
||||
resolved_glyph_ids->clear();
|
||||
resolved_glyph_ids->insert(GlyphId(0, font_id_));
|
||||
IntegerSet* unresolved_glyph_ids = new IntegerSet;
|
||||
// Since composite glyph elements might themselves be composite, we would need
|
||||
// to recursively resolve the elements too. To avoid the recursion we
|
||||
// create two sets, |unresolved_glyph_ids| for the unresolved glyphs,
|
||||
// initially containing all the ids and |resolved_glyph_ids|, initially empty.
|
||||
// We'll remove glyph ids from |unresolved_glyph_ids| until it is empty and,
|
||||
// if the glyph is composite, add its elements to the unresolved set.
|
||||
for (CharacterMap::iterator it = chars_to_glyph_ids->begin(),
|
||||
e = chars_to_glyph_ids->end(); it != e; ++it) {
|
||||
unresolved_glyph_ids->insert(it->second.glyph_id());
|
||||
}
|
||||
// As long as there are unresolved glyph ids.
|
||||
while (!unresolved_glyph_ids->empty()) {
|
||||
// Get the corresponding glyph.
|
||||
int32_t glyph_id = *(unresolved_glyph_ids->begin());
|
||||
unresolved_glyph_ids->erase(unresolved_glyph_ids->begin());
|
||||
if (glyph_id < 0 || glyph_id > loca_table_->num_glyphs()) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "%d larger than %d or smaller than 0\n", glyph_id,
|
||||
loca_table_->num_glyphs());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
int32_t length = loca_table_->GlyphLength(glyph_id);
|
||||
if (length == 0) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Zero length glyph %d\n", glyph_id);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
int32_t offset = loca_table_->GlyphOffset(glyph_id);
|
||||
GlyphPtr glyph;
|
||||
glyph.Attach(glyph_table_->GetGlyph(offset, length));
|
||||
if (glyph == NULL) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "GetGlyph returned NULL for %d\n", glyph_id);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
// Mark the glyph as resolved.
|
||||
resolved_glyph_ids->insert(GlyphId(glyph_id, font_id_));
|
||||
// If it is composite, add all its components to the unresolved glyph set.
|
||||
if (glyph->GlyphType() == GlyphType::kComposite) {
|
||||
Ptr<GlyphTable::CompositeGlyph> composite_glyph =
|
||||
down_cast<GlyphTable::CompositeGlyph*>(glyph.p_);
|
||||
int32_t num_glyphs = composite_glyph->NumGlyphs();
|
||||
for (int32_t i = 0; i < num_glyphs; ++i) {
|
||||
int32_t glyph_id = composite_glyph->GlyphIndex(i);
|
||||
if (resolved_glyph_ids->find(GlyphId(glyph_id, -1))
|
||||
== resolved_glyph_ids->end()) {
|
||||
unresolved_glyph_ids->insert(glyph_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete unresolved_glyph_ids;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_INFO_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_INFO_H_
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/table/core/cmap_table.h"
|
||||
#include "sfntly/table/truetype/glyph_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
|
||||
namespace subtly {
|
||||
class CharacterPredicate;
|
||||
|
||||
typedef int32_t FontId;
|
||||
typedef std::map<FontId, sfntly::Ptr<sfntly::Font> > FontIdMap;
|
||||
|
||||
// Glyph id pair that contains the loca table glyph id as well as the
|
||||
// font id that has the glyph table this glyph belongs to.
|
||||
class GlyphId {
|
||||
public:
|
||||
GlyphId(int32_t glyph_id, FontId font_id);
|
||||
~GlyphId() {}
|
||||
|
||||
bool operator==(const GlyphId& other) const;
|
||||
bool operator<(const GlyphId& other) const;
|
||||
|
||||
int32_t glyph_id() const { return glyph_id_; }
|
||||
void set_glyph_id(const int32_t glyph_id) { glyph_id_ = glyph_id; }
|
||||
FontId font_id() const { return font_id_; }
|
||||
void set_font_id(const FontId font_id) { font_id_ = font_id; }
|
||||
|
||||
private:
|
||||
int32_t glyph_id_;
|
||||
FontId font_id_;
|
||||
};
|
||||
|
||||
typedef std::map<int32_t, GlyphId> CharacterMap;
|
||||
typedef std::set<GlyphId> GlyphIdSet;
|
||||
|
||||
// Font information used for FontAssembler in the construction of a new font.
|
||||
// Will make copies of character map, glyph id set and font id map.
|
||||
class FontInfo : public sfntly::RefCounted<FontInfo> {
|
||||
public:
|
||||
// Empty FontInfo object.
|
||||
FontInfo();
|
||||
// chars_to_glyph_ids maps characters to GlyphIds for CMap construction
|
||||
// resolved_glyph_ids defines GlyphIds which should be in the final font
|
||||
// fonts is a map of font ids to fonts to reference any needed table
|
||||
FontInfo(CharacterMap* chars_to_glyph_ids,
|
||||
GlyphIdSet* resolved_glyph_ids,
|
||||
FontIdMap* fonts);
|
||||
virtual ~FontInfo();
|
||||
|
||||
// Gets the table with the specified tag from the font corresponding to
|
||||
// font_id or NULL if there is no such font/table.
|
||||
// font_id is the id of the font that contains the table
|
||||
// tag identifies the table to be obtained
|
||||
virtual sfntly::FontDataTable* GetTable(FontId font_id, int32_t tag);
|
||||
// Gets the table map of the font whose id is font_id
|
||||
virtual const sfntly::TableMap* GetTableMap(FontId);
|
||||
|
||||
CharacterMap* chars_to_glyph_ids() const { return chars_to_glyph_ids_; }
|
||||
// Takes ownership of the chars_to_glyph_ids CharacterMap.
|
||||
void set_chars_to_glyph_ids(CharacterMap* chars_to_glyph_ids);
|
||||
GlyphIdSet* resolved_glyph_ids() const { return resolved_glyph_ids_; }
|
||||
// Takes ownership of the glyph_ids GlyphIdSet.
|
||||
void set_resolved_glyph_ids(GlyphIdSet* glyph_ids);
|
||||
FontIdMap* fonts() const { return fonts_; }
|
||||
// Takes ownership of the fonts FontIdMap.
|
||||
void set_fonts(FontIdMap* fonts);
|
||||
|
||||
private:
|
||||
CharacterMap* chars_to_glyph_ids_;
|
||||
GlyphIdSet* resolved_glyph_ids_;
|
||||
FontIdMap* fonts_;
|
||||
};
|
||||
|
||||
// FontSourcedInfoBuilder is used to create a FontInfo object from a Font
|
||||
// optionally specifying a CharacterPredicate to filter out some of
|
||||
// the font's characters.
|
||||
// It does not take ownership or copy the values its constructor receives.
|
||||
class FontSourcedInfoBuilder :
|
||||
public sfntly::RefCounted<FontSourcedInfoBuilder> {
|
||||
public:
|
||||
FontSourcedInfoBuilder(sfntly::Font* font, FontId font_id);
|
||||
FontSourcedInfoBuilder(sfntly::Font* font,
|
||||
FontId font_id,
|
||||
CharacterPredicate* predicate);
|
||||
virtual ~FontSourcedInfoBuilder() { }
|
||||
|
||||
virtual CALLER_ATTACH FontInfo* GetFontInfo();
|
||||
|
||||
protected:
|
||||
bool GetCharacterMap(CharacterMap* chars_to_glyph_ids);
|
||||
bool ResolveCompositeGlyphs(CharacterMap* chars_to_glyph_ids,
|
||||
GlyphIdSet* resolved_glyph_ids);
|
||||
void Initialize();
|
||||
|
||||
private:
|
||||
sfntly::Ptr<sfntly::Font> font_;
|
||||
FontId font_id_;
|
||||
CharacterPredicate* predicate_;
|
||||
|
||||
sfntly::Ptr<sfntly::CMapTable::CMap> cmap_;
|
||||
sfntly::Ptr<sfntly::LocaTable> loca_table_;
|
||||
sfntly::Ptr<sfntly::GlyphTable> glyph_table_;
|
||||
};
|
||||
}
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_INFO_H_
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subtly/merger.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "subtly/character_predicate.h"
|
||||
#include "subtly/font_assembler.h"
|
||||
#include "subtly/font_info.h"
|
||||
#include "subtly/utils.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
/******************************************************************************
|
||||
* Merger class
|
||||
******************************************************************************/
|
||||
Merger::Merger(FontArray* fonts) {
|
||||
if (!fonts) {
|
||||
return;
|
||||
}
|
||||
int32_t num_fonts = fonts->size();
|
||||
for (int32_t i = 0; i < num_fonts; ++i) {
|
||||
fonts_.insert(std::make_pair(i, fonts->at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* Merger::Merge() {
|
||||
Ptr<FontInfo> merged_info;
|
||||
merged_info.Attach(MergeFontInfos());
|
||||
if (!merged_info) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Could not create merged font info\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
Ptr<FontAssembler> font_assembler = new FontAssembler(merged_info);
|
||||
return font_assembler->Assemble();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontInfo* Merger::MergeFontInfos() {
|
||||
Ptr<FontInfo> font_info = new FontInfo;
|
||||
font_info->set_fonts(&fonts_);
|
||||
for (FontIdMap::iterator it = fonts_.begin(),
|
||||
e = fonts_.end(); it != e; ++it) {
|
||||
Ptr<FontSourcedInfoBuilder> info_builder =
|
||||
new FontSourcedInfoBuilder(it->second, it->first, NULL);
|
||||
Ptr<FontInfo> current_font_info;
|
||||
current_font_info.Attach(info_builder->GetFontInfo());
|
||||
if (!current_font_info) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Couldn't create font info. "
|
||||
"No subset will be generated.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
font_info->chars_to_glyph_ids()->insert(
|
||||
current_font_info->chars_to_glyph_ids()->begin(),
|
||||
current_font_info->chars_to_glyph_ids()->end());
|
||||
font_info->resolved_glyph_ids()->insert(
|
||||
current_font_info->resolved_glyph_ids()->begin(),
|
||||
current_font_info->resolved_glyph_ids()->end());
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr, "Counts: chars_to_glyph_ids: %d; resoved_glyph_ids: %d\n",
|
||||
font_info->chars_to_glyph_ids()->size(),
|
||||
font_info->resolved_glyph_ids()->size());
|
||||
#endif
|
||||
}
|
||||
return font_info.Detach();
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_
|
||||
|
||||
#include "subtly/character_predicate.h"
|
||||
#include "subtly/font_info.h"
|
||||
|
||||
namespace sfntly {
|
||||
class Font;
|
||||
}
|
||||
|
||||
namespace subtly {
|
||||
// Merges the subsets in the font array into a single font.
|
||||
class Merger : public sfntly::RefCounted<Merger> {
|
||||
public:
|
||||
explicit Merger(sfntly::FontArray* fonts);
|
||||
virtual ~Merger() { }
|
||||
|
||||
// Performs merging returning the subsetted font.
|
||||
virtual CALLER_ATTACH sfntly::Font* Merge();
|
||||
|
||||
protected:
|
||||
virtual CALLER_ATTACH FontInfo* MergeFontInfos();
|
||||
|
||||
private:
|
||||
FontIdMap fonts_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "subtly/merger.h"
|
||||
#include "subtly/stats.h"
|
||||
#include "subtly/utils.h"
|
||||
|
||||
using namespace subtly;
|
||||
|
||||
void PrintUsage(const char* program_name) {
|
||||
fprintf(stdout, "Usage: %s <input_font_file1> <input_font_file2> ..."
|
||||
"<input_font_filen> <output_font_file>\n",
|
||||
program_name);
|
||||
}
|
||||
|
||||
void CheckLoading(const char* font_path, Font* font) {
|
||||
if (!font || font->num_tables() == 0) {
|
||||
fprintf(stderr, "Could not load font %s. Terminating.\n", font_path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
if (argc < 3) {
|
||||
PrintUsage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
FontArray fonts;
|
||||
for (int32_t i = 1; i < argc - 1; ++i) {
|
||||
Ptr<Font> font;
|
||||
font.Attach(LoadFont(argv[i]));
|
||||
CheckLoading(argv[i], font);
|
||||
fonts.push_back(font);
|
||||
}
|
||||
|
||||
Ptr<Merger> merger = new Merger(&fonts);
|
||||
FontPtr new_font;
|
||||
new_font.Attach(merger->Merge());
|
||||
|
||||
fprintf(stderr, "Serializing font to %s\n", argv[argc - 1]);
|
||||
SerializeFont(argv[argc - 1], new_font);
|
||||
if (!new_font) {
|
||||
fprintf(stdout, "Cannot create merged font.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/table/table.h"
|
||||
#include "sfntly/tag.h"
|
||||
#include "subtly/stats.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
int32_t TotalFontSize(Font* font) {
|
||||
int32_t size = 0;
|
||||
const TableMap* table_map = font->GetTableMap();
|
||||
for (TableMap::const_iterator it = table_map->begin(),
|
||||
e = table_map->end(); it != e; ++it) {
|
||||
size += it->second->DataLength();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
double TableSizePercent(Font* font, int32_t tag) {
|
||||
TablePtr table = font->GetTable(tag);
|
||||
return static_cast<double>(table->DataLength()) / TotalFontSize(font) * 100;
|
||||
}
|
||||
|
||||
void PrintComparison(FILE* out, Font* font, Font* new_font) {
|
||||
fprintf(out, "====== Table Comparison (original v. subset) ======\n");
|
||||
const TableMap* tables = font->GetTableMap();
|
||||
for (TableMap::const_iterator it = tables->begin(),
|
||||
e = tables->end(); it != e; ++it) {
|
||||
char *name = TagToString(it->first);
|
||||
int32_t size = it->second->DataLength();
|
||||
fprintf(out, "-- %s: %d (%lf%%) ", name, size,
|
||||
TableSizePercent(font, it->first));
|
||||
delete[] name;
|
||||
|
||||
Ptr<FontDataTable> new_table = new_font->GetTable(it->first);
|
||||
int32_t new_size = 0;
|
||||
double size_percent = 0;
|
||||
if (new_table) {
|
||||
new_size = new_table->DataLength();
|
||||
size_percent = subtly::TableSizePercent(new_font, it->first);
|
||||
}
|
||||
|
||||
if (new_size == size) {
|
||||
fprintf(out, "| same size\n");
|
||||
} else {
|
||||
fprintf(out, "-> %d (%lf%%) | %lf%% of original\n", new_size,
|
||||
size_percent, static_cast<double>(new_size) / size * 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintStats(FILE* out, Font* font) {
|
||||
fprintf(out, "====== Table Stats ======\n");
|
||||
const TableMap* tables = font->GetTableMap();
|
||||
for (TableMap::const_iterator it = tables->begin(),
|
||||
e = tables->end(); it != e; ++it) {
|
||||
char *name = TagToString(it->first);
|
||||
int32_t size = it->second->DataLength();
|
||||
fprintf(out, "-- %s: %d (%lf%%)\n", name, size,
|
||||
TableSizePercent(font, it->first));
|
||||
delete[] name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_STATS_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_STATS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
class Font;
|
||||
}
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
int32_t TotalFontSize(Font* font);
|
||||
|
||||
double TableSizePercent(Font* font, int32_t tag);
|
||||
|
||||
void PrintComparison(FILE* out, Font* font, Font* new_font);
|
||||
|
||||
void PrintStats(FILE* out, Font* font);
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_STATS_H_
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subtly/subsetter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/tag.h"
|
||||
#include "subtly/character_predicate.h"
|
||||
#include "subtly/font_assembler.h"
|
||||
#include "subtly/font_info.h"
|
||||
#include "subtly/utils.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
/******************************************************************************
|
||||
* Subsetter class
|
||||
******************************************************************************/
|
||||
Subsetter::Subsetter(Font* font, CharacterPredicate* predicate)
|
||||
: font_(font),
|
||||
predicate_(predicate) {
|
||||
}
|
||||
|
||||
Subsetter::Subsetter(const char* font_path, CharacterPredicate* predicate)
|
||||
: predicate_(predicate) {
|
||||
font_.Attach(LoadFont(font_path));
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* Subsetter::Subset() {
|
||||
Ptr<FontSourcedInfoBuilder> info_builder =
|
||||
new FontSourcedInfoBuilder(font_, 0, predicate_);
|
||||
|
||||
Ptr<FontInfo> font_info;
|
||||
font_info.Attach(info_builder->GetFontInfo());
|
||||
if (!font_info) {
|
||||
#if defined (SUBTLY_DEBUG)
|
||||
fprintf(stderr,
|
||||
"Couldn't create font info. No subset will be generated.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
IntegerSet* table_blacklist = new IntegerSet;
|
||||
table_blacklist->insert(Tag::DSIG);
|
||||
Ptr<FontAssembler> font_assembler = new FontAssembler(font_info,
|
||||
table_blacklist);
|
||||
Ptr<Font> font_subset;
|
||||
font_subset.Attach(font_assembler->Assemble());
|
||||
delete table_blacklist;
|
||||
return font_subset.Detach();
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_
|
||||
|
||||
#include "sfntly/font.h"
|
||||
// Cannot remove this header due to Ptr<T> instantiation issue
|
||||
#include "subtly/character_predicate.h"
|
||||
|
||||
namespace subtly {
|
||||
// Subsets a given font using a character predicate.
|
||||
class Subsetter : public sfntly::RefCounted<Subsetter> {
|
||||
public:
|
||||
Subsetter(sfntly::Font* font, CharacterPredicate* predicate);
|
||||
Subsetter(const char* font_path, CharacterPredicate* predicate);
|
||||
virtual ~Subsetter() { }
|
||||
|
||||
// Performs subsetting returning the subsetted font.
|
||||
virtual CALLER_ATTACH sfntly::Font* Subset();
|
||||
|
||||
private:
|
||||
sfntly::Ptr<sfntly::Font> font_;
|
||||
sfntly::Ptr<CharacterPredicate> predicate_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "subtly/character_predicate.h"
|
||||
#include "subtly/stats.h"
|
||||
#include "subtly/subsetter.h"
|
||||
#include "subtly/utils.h"
|
||||
|
||||
using namespace subtly;
|
||||
|
||||
void PrintUsage(const char* program_name) {
|
||||
fprintf(stdout, "Usage: %s <input_font_file> <output_font_file>"
|
||||
"<start_char> <end_char>\n", program_name);
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
const char* program_name = argv[0];
|
||||
if (argc < 5) {
|
||||
PrintUsage(program_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char* input_font_path = argv[1];
|
||||
const char* output_font_path = argv[2];
|
||||
FontPtr font;
|
||||
font.Attach(subtly::LoadFont(input_font_path));
|
||||
if (font->num_tables() == 0) {
|
||||
fprintf(stderr, "Could not load font %s.\n", input_font_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char* start_char = argv[3];
|
||||
const char* end_char = argv[4];
|
||||
if (start_char[1] != 0) {
|
||||
fprintf(stderr, "Start character %c invalid.\n", start_char[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (end_char[1] != 0) {
|
||||
fprintf(stderr, "Start character %c invalid.\n", end_char[0]);
|
||||
exit(1);
|
||||
}
|
||||
int32_t original_size = TotalFontSize(font);
|
||||
|
||||
|
||||
Ptr<CharacterPredicate> range_predicate =
|
||||
new AcceptRange(start_char[0], end_char[0]);
|
||||
Ptr<Subsetter> subsetter = new Subsetter(font, range_predicate);
|
||||
Ptr<Font> new_font;
|
||||
new_font.Attach(subsetter->Subset());
|
||||
if (!new_font) {
|
||||
fprintf(stdout, "Cannot create subset.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
subtly::SerializeFont(output_font_path, new_font);
|
||||
subtly::PrintComparison(stdout, font, new_font);
|
||||
int32_t new_size = TotalFontSize(new_font);
|
||||
fprintf(stdout, "Went from %d to %d: %lf%% of original\n",
|
||||
original_size, new_size,
|
||||
static_cast<double>(new_size) / original_size * 100);
|
||||
return 0;
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "subtly/utils.h"
|
||||
|
||||
#include "sfntly/data/growable_memory_byte_array.h"
|
||||
#include "sfntly/data/memory_byte_array.h"
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/port/file_input_stream.h"
|
||||
#include "sfntly/port/memory_output_stream.h"
|
||||
|
||||
namespace subtly {
|
||||
using namespace sfntly;
|
||||
|
||||
CALLER_ATTACH Font* LoadFont(const char* font_path) {
|
||||
Ptr<FontFactory> font_factory;
|
||||
font_factory.Attach(FontFactory::GetInstance());
|
||||
FontArray fonts;
|
||||
LoadFonts(font_path, font_factory, &fonts);
|
||||
return fonts[0].Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font::Builder* LoadFontBuilder(const char* font_path) {
|
||||
FontFactoryPtr font_factory;
|
||||
font_factory.Attach(FontFactory::GetInstance());
|
||||
FontBuilderArray builders;
|
||||
LoadFontBuilders(font_path, font_factory, &builders);
|
||||
return builders[0].Detach();
|
||||
}
|
||||
|
||||
void LoadFonts(const char* font_path, FontFactory* factory, FontArray* fonts) {
|
||||
FileInputStream input_stream;
|
||||
input_stream.Open(font_path);
|
||||
factory->LoadFonts(&input_stream, fonts);
|
||||
input_stream.Close();
|
||||
}
|
||||
|
||||
void LoadFontBuilders(const char* font_path,
|
||||
FontFactory* factory,
|
||||
FontBuilderArray* builders) {
|
||||
FileInputStream input_stream;
|
||||
input_stream.Open(font_path);
|
||||
factory->LoadFontsForBuilding(&input_stream, builders);
|
||||
input_stream.Close();
|
||||
}
|
||||
|
||||
bool SerializeFont(const char* font_path, Font* font) {
|
||||
if (!font_path)
|
||||
return false;
|
||||
FontFactoryPtr font_factory;
|
||||
font_factory.Attach(FontFactory::GetInstance());
|
||||
return SerializeFont(font_path, font_factory, font);
|
||||
}
|
||||
|
||||
bool SerializeFont(const char* font_path, FontFactory* factory, Font* font) {
|
||||
if (!font_path || !factory || !font)
|
||||
return false;
|
||||
// Serializing the font to a stream.
|
||||
MemoryOutputStream output_stream;
|
||||
factory->SerializeFont(font, &output_stream);
|
||||
// Serializing the stream to a file.
|
||||
FILE* output_file = NULL;
|
||||
#if defined WIN32
|
||||
fopen_s(&output_file, font_path, "wb");
|
||||
#else
|
||||
output_file = fopen(font_path, "wb");
|
||||
#endif
|
||||
if (output_file == static_cast<FILE*>(NULL))
|
||||
return false;
|
||||
for (size_t i = 0; i < output_stream.Size(); ++i) {
|
||||
fwrite(&(output_stream.Get()[i]), 1, 1, output_file);
|
||||
}
|
||||
fflush(output_file);
|
||||
fclose(output_file);
|
||||
return true;
|
||||
}
|
||||
};
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_
|
||||
#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_
|
||||
|
||||
#include "sfntly/font.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
|
||||
namespace subtly {
|
||||
CALLER_ATTACH sfntly::Font* LoadFont(const char* font_path);
|
||||
CALLER_ATTACH sfntly::Font::Builder* LoadFontBuilder(const char* font_path);
|
||||
|
||||
void LoadFonts(const char* font_path, sfntly::FontFactory* factory,
|
||||
sfntly::FontArray* fonts);
|
||||
void LoadFontBuilders(const char* font_path,
|
||||
sfntly::FontFactory* factory,
|
||||
sfntly::FontBuilderArray* builders);
|
||||
|
||||
bool SerializeFont(const char* font_path, sfntly::Font* font);
|
||||
bool SerializeFont(const char* font_path, sfntly::FontFactory* factory,
|
||||
sfntly::Font* font);
|
||||
}
|
||||
|
||||
#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/byte_array.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "sfntly/port/exception_type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
const int32_t ByteArray::COPY_BUFFER_SIZE = 8192;
|
||||
|
||||
ByteArray::~ByteArray() {}
|
||||
|
||||
int32_t ByteArray::SetFilledLength(int32_t filled_length) {
|
||||
filled_length_ = std::min<int32_t>(filled_length, storage_length_);
|
||||
return filled_length_;
|
||||
}
|
||||
|
||||
int32_t ByteArray::Get(int32_t index) {
|
||||
if (index < 0 || index >= Length())
|
||||
return -1;
|
||||
return InternalGet(index) & 0xff;
|
||||
}
|
||||
|
||||
int32_t ByteArray::Get(int32_t index, std::vector<uint8_t>* b) {
|
||||
assert(b);
|
||||
return Get(index, &((*b)[0]), 0, b->size());
|
||||
}
|
||||
|
||||
int32_t ByteArray::Get(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(b);
|
||||
if (index < 0 || index >= filled_length_)
|
||||
return 0;
|
||||
|
||||
if (length <= 0)
|
||||
return 0;
|
||||
|
||||
int32_t actual_length = std::min<int32_t>(length, filled_length_ - index);
|
||||
return InternalGet(index, b, offset, actual_length);
|
||||
}
|
||||
|
||||
void ByteArray::Put(int32_t index, uint8_t b) {
|
||||
if (index < 0 || index >= Size()) {
|
||||
#if defined (SFNTLY_NO_EXCEPTION)
|
||||
return;
|
||||
#else
|
||||
throw IndexOutOfBoundException(
|
||||
"Attempt to write outside the bounds of the data");
|
||||
#endif
|
||||
}
|
||||
InternalPut(index, b);
|
||||
filled_length_ = std::max<int32_t>(filled_length_, index + 1);
|
||||
}
|
||||
|
||||
int32_t ByteArray::Put(int index, std::vector<uint8_t>* b) {
|
||||
assert(b);
|
||||
return Put(index, &((*b)[0]), 0, b->size());
|
||||
}
|
||||
|
||||
int32_t ByteArray::Put(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(b);
|
||||
if (index < 0 || index >= Size()) {
|
||||
#if defined (SFNTLY_NO_EXCEPTION)
|
||||
return 0;
|
||||
#else
|
||||
throw IndexOutOfBoundException(
|
||||
"Attempt to write outside the bounds of the data");
|
||||
#endif
|
||||
}
|
||||
int32_t actual_length = std::min<int32_t>(length, Size() - index);
|
||||
int32_t bytes_written = InternalPut(index, b, offset, actual_length);
|
||||
filled_length_ = std::max<int32_t>(filled_length_, index + bytes_written);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int32_t ByteArray::CopyTo(ByteArray* array) {
|
||||
return CopyTo(array, 0, Length());
|
||||
}
|
||||
|
||||
int32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) {
|
||||
return CopyTo(0, array, offset, length);
|
||||
}
|
||||
|
||||
int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array,
|
||||
int32_t src_offset, int32_t length) {
|
||||
assert(array);
|
||||
if (array->Size() < dst_offset + length) { // insufficient space
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> b(COPY_BUFFER_SIZE);
|
||||
int32_t bytes_read = 0;
|
||||
int32_t index = 0;
|
||||
int32_t remaining_length = length;
|
||||
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
|
||||
while ((bytes_read =
|
||||
Get(index + src_offset, &(b[0]), 0, buffer_length)) > 0) {
|
||||
int bytes_written = array->Put(index + dst_offset, &(b[0]), 0, bytes_read);
|
||||
UNREFERENCED_PARAMETER(bytes_written);
|
||||
index += bytes_read;
|
||||
remaining_length -= bytes_read;
|
||||
buffer_length = std::min<int32_t>(b.size(), remaining_length);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
int32_t ByteArray::CopyTo(OutputStream* os) {
|
||||
return CopyTo(os, 0, Length());
|
||||
}
|
||||
|
||||
int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) {
|
||||
std::vector<uint8_t> b(COPY_BUFFER_SIZE);
|
||||
int32_t bytes_read = 0;
|
||||
int32_t index = 0;
|
||||
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
|
||||
while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) {
|
||||
os->Write(&b, 0, bytes_read);
|
||||
index += bytes_read;
|
||||
buffer_length = std::min<int32_t>(b.size(), length - index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
bool ByteArray::CopyFrom(InputStream* is, int32_t length) {
|
||||
std::vector<uint8_t> b(COPY_BUFFER_SIZE);
|
||||
int32_t bytes_read = 0;
|
||||
int32_t index = 0;
|
||||
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
|
||||
while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
|
||||
if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) {
|
||||
#if defined (SFNTLY_NO_EXCEPTION)
|
||||
return 0;
|
||||
#else
|
||||
throw IOException("Error writing bytes.");
|
||||
#endif
|
||||
}
|
||||
index += bytes_read;
|
||||
length -= bytes_read;
|
||||
buffer_length = std::min<int32_t>(b.size(), length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ByteArray::CopyFrom(InputStream* is) {
|
||||
std::vector<uint8_t> b(COPY_BUFFER_SIZE);
|
||||
int32_t bytes_read = 0;
|
||||
int32_t index = 0;
|
||||
int32_t buffer_length = COPY_BUFFER_SIZE;
|
||||
while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
|
||||
if (Put(index, &b[0], 0, bytes_read) != bytes_read) {
|
||||
#if defined (SFNTLY_NO_EXCEPTION)
|
||||
return 0;
|
||||
#else
|
||||
throw IOException("Error writing bytes.");
|
||||
#endif
|
||||
}
|
||||
index += bytes_read;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(int32_t filled_length,
|
||||
int32_t storage_length,
|
||||
bool growable) {
|
||||
Init(filled_length, storage_length, growable);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(int32_t filled_length, int32_t storage_length) {
|
||||
Init(filled_length, storage_length, false);
|
||||
}
|
||||
|
||||
void ByteArray::Init(int32_t filled_length,
|
||||
int32_t storage_length,
|
||||
bool growable) {
|
||||
storage_length_ = storage_length;
|
||||
growable_ = growable;
|
||||
SetFilledLength(filled_length);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The sfntly Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_
|
||||
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/input_stream.h"
|
||||
#include "sfntly/port/output_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// An abstraction to a contiguous array of bytes.
|
||||
// C++ port of this class assumes that the data are stored in a linear region
|
||||
// like std::vector.
|
||||
class ByteArray : virtual public RefCount {
|
||||
public:
|
||||
virtual ~ByteArray();
|
||||
|
||||
// Gets the current filled and readable length of the array.
|
||||
int32_t Length() const { return filled_length_; }
|
||||
|
||||
// Gets the maximum size of the array. This is the maximum number of bytes that
|
||||
// the array can hold and all of it may not be filled with data or even fully
|
||||
// allocated yet.
|
||||
int32_t Size() const { return storage_length_; }
|
||||
|
||||
// Determines whether or not this array is growable or of fixed size.
|
||||
bool growable() const { return growable_; }
|
||||
|
||||
int32_t SetFilledLength(int32_t filled_length);
|
||||
|
||||
// Gets the byte from the given index.
|
||||
// @param index the index into the byte array
|
||||
// @return the byte or -1 if reading beyond the bounds of the data
|
||||
virtual int32_t Get(int32_t index);
|
||||
|
||||
// Gets the bytes from the given index and fill the buffer with them. As many
|
||||
// bytes as will fit into the buffer are read unless that would go past the
|
||||
// end of the array.
|
||||
// @param index the index into the byte array
|
||||
// @param b the buffer to put the bytes read into
|
||||
// @return the number of bytes read from the buffer
|
||||
virtual int32_t Get(int32_t index, std::vector<uint8_t>* b);
|
||||
|
||||
// Gets the bytes from the given index and fill the buffer with them starting
|
||||
// at the offset given. As many bytes as the specified length are read unless
|
||||
// that would go past the end of the array.
|
||||
// @param index the index into the byte array
|
||||
// @param b the buffer to put the bytes read into
|
||||
// @param offset the location in the buffer to start putting the bytes
|
||||
// @param length the number of bytes to put into the buffer
|
||||
// @return the number of bytes read from the buffer
|
||||
virtual int32_t Get(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
|
||||
// Puts the specified byte into the array at the given index unless that would
|
||||
// be beyond the length of the array and it isn't growable.
|
||||
virtual void Put(int32_t index, uint8_t b);
|
||||
|
||||
// Puts the specified bytes into the array at the given index. The entire
|
||||
// buffer is put into the array unless that would extend beyond the length and
|
||||
// the array isn't growable.
|
||||
virtual int32_t Put(int32_t index, std::vector<uint8_t>* b);
|
||||
|
||||
// Puts the specified bytes into the array at the given index. All of the bytes
|
||||
// specified are put into the array unless that would extend beyond the length
|
||||
// and the array isn't growable. The bytes to be put into the array are those
|
||||
// in the buffer from the given offset and for the given length.
|
||||
// @param index the index into the ByteArray
|
||||
// @param b the bytes to put into the array
|
||||
// @param offset the offset in the bytes to start copying from
|
||||
// @param length the number of bytes to copy into the array
|
||||
// @return the number of bytes actually written
|
||||
virtual int32_t Put(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
|
||||
// Fully copies this ByteArray to another ByteArray to the extent that the
|
||||
// destination array has storage for the data copied.
|
||||
virtual int32_t CopyTo(ByteArray* array);
|
||||
|
||||
// Copies a segment of this ByteArray to another ByteArray.
|
||||
// @param array the destination
|
||||
// @param offset the offset in this ByteArray to start copying from
|
||||
// @param length the maximum length in bytes to copy
|
||||
// @return the number of bytes copied
|
||||
virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length);
|
||||
|
||||
// Copies this ByteArray to another ByteArray.
|
||||
// @param dstOffset the offset in the destination array to start copying to
|
||||
// @param array the destination
|
||||
// @param srcOffset the offset in this ByteArray to start copying from
|
||||
// @param length the maximum length in bytes to copy
|
||||
// @return the number of bytes copied
|
||||
virtual int32_t CopyTo(int32_t dst_offset,
|
||||
ByteArray* array,
|
||||
int32_t src_offset,
|
||||
int32_t length);
|
||||
|
||||
// Copies this ByteArray to an OutputStream.
|
||||
// @param os the destination
|
||||
// @return the number of bytes copied
|
||||
virtual int32_t CopyTo(OutputStream* os);
|
||||
|
||||
// Copies this ByteArray to an OutputStream.
|
||||
// @param os the destination
|
||||
// @param offset
|
||||
// @param length
|
||||
// @return the number of bytes copied
|
||||
virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
|
||||
|
||||
// Copies from the InputStream into this ByteArray.
|
||||
// @param is the source
|
||||
// @param length the number of bytes to copy
|
||||
virtual bool CopyFrom(InputStream* is, int32_t length);
|
||||
|
||||
// Copies everything from the InputStream into this ByteArray.
|
||||
// @param is the source
|
||||
virtual bool CopyFrom(InputStream* is);
|
||||
|
||||
protected:
|
||||
// filledLength the length that is "filled" and readable counting from offset.
|
||||
// storageLength the maximum storage size of the underlying data.
|
||||
// growable is the storage growable - storageLength is the max growable size.
|
||||
ByteArray(int32_t filled_length, int32_t storage_length, bool growable);
|
||||
ByteArray(int32_t filled_length, int32_t storage_length);
|
||||
void Init(int32_t filled_length, int32_t storage_length, bool growable);
|
||||
|
||||
// Internal subclass API
|
||||
|
||||
// Stores the byte at the index given.
|
||||
// @param index the location to store at
|
||||
// @param b the byte to store
|
||||
virtual void InternalPut(int32_t index, uint8_t b) = 0;
|
||||
|
||||
// Stores the array of bytes at the given index.
|
||||
// @param index the location to store at
|
||||
// @param b the bytes to store
|
||||
// @param offset the offset to start from in the byte array
|
||||
// @param length the length of the byte array to store from the offset
|
||||
// @return the number of bytes actually stored
|
||||
virtual int32_t InternalPut(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) = 0;
|
||||
|
||||
// Gets the byte at the index given.
|
||||
// @param index the location to get from
|
||||
// @return the byte stored at the index
|
||||
virtual uint8_t InternalGet(int32_t index) = 0;
|
||||
|
||||
// Gets the bytes at the index given of the given length.
|
||||
// @param index the location to start getting from
|
||||
// @param b the array to put the bytes into
|
||||
// @param offset the offset in the array to put the bytes into
|
||||
// @param length the length of bytes to read
|
||||
// @return the number of bytes actually ready
|
||||
virtual int32_t InternalGet(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) = 0;
|
||||
|
||||
// Close this instance of the ByteArray.
|
||||
virtual void Close() = 0;
|
||||
|
||||
// C++ port only, raw pointer to the first element of storage.
|
||||
virtual uint8_t* Begin() = 0;
|
||||
|
||||
// Java toString() not ported.
|
||||
|
||||
static const int32_t COPY_BUFFER_SIZE;
|
||||
|
||||
private:
|
||||
//bool bound_; // unused, comment out
|
||||
int32_t filled_length_;
|
||||
int32_t storage_length_;
|
||||
bool growable_;
|
||||
};
|
||||
typedef Ptr<ByteArray> ByteArrayPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/font_data.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
#include "sfntly/port/logging.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
int32_t FontData::Size() const {
|
||||
return std::min<int32_t>(array_->Size() - bound_offset_, bound_length_);
|
||||
}
|
||||
|
||||
void FontData::Bound(int32_t offset, int32_t length) {
|
||||
// Inputs should not be negative.
|
||||
CHECK(offset >= 0);
|
||||
CHECK(length >= 0);
|
||||
|
||||
// Check to make sure |bound_offset_| will not overflow.
|
||||
CHECK(bound_offset_ <= std::numeric_limits<int32_t>::max() - offset);
|
||||
const int32_t new_offset = bound_offset_ + offset;
|
||||
|
||||
if (length == GROWABLE_SIZE) {
|
||||
// When |length| has the special value of GROWABLE_SIZE, it means the size
|
||||
// should not have any artificial limits, thus it is just the underlying
|
||||
// |array_|'s size. Just make sure |new_offset| is still within bounds.
|
||||
CHECK(new_offset <= array_->Size());
|
||||
} else {
|
||||
// When |length| has any other value, |new_offset| + |length| points to the
|
||||
// end of the array. Make sure that is within bounds, but use subtraction to
|
||||
// avoid an integer overflow.
|
||||
CHECK(new_offset <= array_->Size() - length);
|
||||
}
|
||||
|
||||
bound_offset_ = new_offset;
|
||||
bound_length_ = length;
|
||||
}
|
||||
|
||||
int32_t FontData::Length() const {
|
||||
return std::min<int32_t>(array_->Length() - bound_offset_, bound_length_);
|
||||
}
|
||||
|
||||
FontData::FontData(ByteArray* ba) {
|
||||
Init(ba);
|
||||
}
|
||||
|
||||
FontData::FontData(FontData* data, int32_t offset, int32_t length) {
|
||||
Init(data->array_);
|
||||
Bound(data->bound_offset_ + offset, length);
|
||||
}
|
||||
|
||||
FontData::FontData(FontData* data, int32_t offset) {
|
||||
Init(data->array_);
|
||||
Bound(data->bound_offset_ + offset,
|
||||
(data->bound_length_ == GROWABLE_SIZE)
|
||||
? GROWABLE_SIZE : data->bound_length_ - offset);
|
||||
}
|
||||
|
||||
FontData::~FontData() {}
|
||||
|
||||
void FontData::Init(ByteArray* ba) {
|
||||
array_ = ba;
|
||||
bound_offset_ = 0;
|
||||
bound_length_ = GROWABLE_SIZE;
|
||||
}
|
||||
|
||||
int32_t FontData::BoundOffset(int32_t offset) const {
|
||||
return offset + bound_offset_;
|
||||
}
|
||||
|
||||
int32_t FontData::BoundLength(int32_t offset, int32_t length) const {
|
||||
return std::min<int32_t>(length, bound_length_ - offset);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "sfntly/data/byte_array.h"
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
struct DataSize {
|
||||
enum {
|
||||
kBYTE = 1,
|
||||
kCHAR = 1,
|
||||
kUSHORT = 2,
|
||||
kSHORT = 2,
|
||||
kUINT24 = 3,
|
||||
kULONG = 4,
|
||||
kLONG = 4,
|
||||
kFixed = 4,
|
||||
kFUNIT = 4,
|
||||
kFWORD = 2,
|
||||
kUFWORD = 2,
|
||||
kF2DOT14 = 2,
|
||||
kLONGDATETIME = 8,
|
||||
kTag = 4,
|
||||
kGlyphID = 2,
|
||||
kOffset = 2
|
||||
};
|
||||
};
|
||||
|
||||
class FontData : virtual public RefCount {
|
||||
public:
|
||||
// Gets the maximum size of the FontData. This is the maximum number of bytes
|
||||
// that the font data can hold and all of it may not be filled with data or
|
||||
// even fully allocated yet.
|
||||
// @return the maximum size of this font data
|
||||
virtual int32_t Size() const;
|
||||
|
||||
// Sets limits on the size of the FontData. The FontData is then only
|
||||
// visible within the bounds set.
|
||||
// @param offset the start of the new bounds
|
||||
// @param length the number of bytes in the bounded array
|
||||
virtual void Bound(int32_t offset, int32_t length);
|
||||
|
||||
// Makes a slice of this FontData. The returned slice will share the data with
|
||||
// the original <code>FontData</code>.
|
||||
// @param offset the start of the slice
|
||||
// @param length the number of bytes in the slice
|
||||
// @return a slice of the original FontData
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length) = 0;
|
||||
|
||||
// Makes a bottom bound only slice of this array. The returned slice will
|
||||
// share the data with the original <code>FontData</code>.
|
||||
// @param offset the start of the slice
|
||||
// @return a slice of the original FontData
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset) = 0;
|
||||
|
||||
// Gets the length of the data.
|
||||
virtual int32_t Length() const;
|
||||
|
||||
protected:
|
||||
// Constructor.
|
||||
// @param ba the byte array to use for the backing data
|
||||
explicit FontData(ByteArray* ba);
|
||||
|
||||
// Constructor.
|
||||
// @param data the data to wrap
|
||||
// @param offset the offset to start the wrap from
|
||||
// @param length the length of the data wrapped
|
||||
FontData(FontData* data, int32_t offset, int32_t length);
|
||||
|
||||
// Constructor.
|
||||
// @param data the data to wrap
|
||||
// @param offset the offset to start the wrap from
|
||||
FontData(FontData* data, int32_t offset);
|
||||
virtual ~FontData();
|
||||
|
||||
void Init(ByteArray* ba);
|
||||
|
||||
// Gets the offset in the underlying data taking into account any bounds on
|
||||
// the data.
|
||||
// @param offset the offset to get the bound compensated offset for
|
||||
// @return the bound compensated offset
|
||||
int32_t BoundOffset(int32_t offset) const;
|
||||
|
||||
// Gets the length in the underlying data taking into account any bounds on
|
||||
// the data.
|
||||
// @param offset the offset that the length is being used at
|
||||
// @param length the length to get the bound compensated length for
|
||||
// @return the bound compensated length
|
||||
int32_t BoundLength(int32_t offset, int32_t length) const;
|
||||
|
||||
static const int32_t GROWABLE_SIZE = INT_MAX;
|
||||
|
||||
// TODO(arthurhsu): style guide violation: refactor this protected member
|
||||
ByteArrayPtr array_;
|
||||
|
||||
private:
|
||||
int32_t bound_offset_;
|
||||
int32_t bound_length_;
|
||||
};
|
||||
typedef Ptr<FontData> FontDataPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/font_input_stream.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
FontInputStream::FontInputStream(InputStream* is)
|
||||
: stream_(is), position_(0), length_(0), bounded_(false) {
|
||||
}
|
||||
|
||||
FontInputStream::FontInputStream(InputStream* is, size_t length)
|
||||
: stream_(is), position_(0), length_(length), bounded_(true) {
|
||||
}
|
||||
|
||||
FontInputStream::~FontInputStream() {
|
||||
// Do not close here, underlying InputStream will close themselves.
|
||||
}
|
||||
|
||||
int32_t FontInputStream::Length() {
|
||||
if (bounded_)
|
||||
return length_;
|
||||
if (stream_)
|
||||
return stream_->Length();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FontInputStream::Available() {
|
||||
if (stream_)
|
||||
return stream_->Available();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FontInputStream::Close() {
|
||||
if (stream_) {
|
||||
stream_->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void FontInputStream::Mark(int32_t readlimit) {
|
||||
if (stream_) {
|
||||
stream_->Mark(readlimit);
|
||||
}
|
||||
}
|
||||
|
||||
bool FontInputStream::MarkSupported() {
|
||||
if (stream_) {
|
||||
return stream_->MarkSupported();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FontInputStream::Reset() {
|
||||
if (stream_) {
|
||||
stream_->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t FontInputStream::Read() {
|
||||
if (!stream_ || (bounded_ && position_ >= length_)) {
|
||||
return -1;
|
||||
}
|
||||
int32_t b = stream_->Read();
|
||||
if (b >= 0) {
|
||||
position_++;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
int32_t FontInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
|
||||
if (!stream_ || offset < 0 || length < 0 ||
|
||||
(bounded_ && position_ >= length_)) {
|
||||
return -1;
|
||||
}
|
||||
int32_t bytes_to_read =
|
||||
bounded_ ? std::min<int32_t>(length, (int32_t)(length_ - position_)) :
|
||||
length;
|
||||
int32_t bytes_read = stream_->Read(b, offset, bytes_to_read);
|
||||
position_ += bytes_read;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int32_t FontInputStream::Read(std::vector<uint8_t>* b) {
|
||||
return Read(b, 0, b->size());
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadChar() {
|
||||
return Read();
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadUShort() {
|
||||
return 0xffff & (Read() << 8 | Read());
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadShort() {
|
||||
return ((Read() << 8 | Read()) << 16) >> 16;
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadUInt24() {
|
||||
return 0xffffff & (Read() << 16 | Read() << 8 | Read());
|
||||
}
|
||||
|
||||
int64_t FontInputStream::ReadULong() {
|
||||
return 0xffffffffL & ReadLong();
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadULongAsInt() {
|
||||
int64_t ulong = ReadULong();
|
||||
return ((int32_t)ulong) & ~0x80000000;
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadLong() {
|
||||
return Read() << 24 | Read() << 16 | Read() << 8 | Read();
|
||||
}
|
||||
|
||||
int32_t FontInputStream::ReadFixed() {
|
||||
return ReadLong();
|
||||
}
|
||||
|
||||
int64_t FontInputStream::ReadDateTimeAsLong() {
|
||||
return (int64_t)ReadULong() << 32 | ReadULong();
|
||||
}
|
||||
|
||||
int64_t FontInputStream::Skip(int64_t n) {
|
||||
if (stream_) {
|
||||
int64_t skipped = stream_->Skip(n);
|
||||
position_ += skipped;
|
||||
return skipped;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/input_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// An input stream for reading font data.
|
||||
// The data types used are as listed:
|
||||
// BYTE 8-bit unsigned integer.
|
||||
// CHAR 8-bit signed integer.
|
||||
// USHORT 16-bit unsigned integer.
|
||||
// SHORT 16-bit signed integer.
|
||||
// UINT24 24-bit unsigned integer.
|
||||
// ULONG 32-bit unsigned integer.
|
||||
// LONG 32-bit signed integer.
|
||||
// Fixed 32-bit signed fixed-point number (16.16)
|
||||
// FUNIT Smallest measurable distance in the em space.
|
||||
// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
|
||||
// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
|
||||
// FUnits.
|
||||
// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
|
||||
// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
|
||||
// January 1, 1904. The value is represented as a signed 64-bit
|
||||
// integer.
|
||||
|
||||
// Note: Original class inherits from Java's FilterOutputStream, which wraps
|
||||
// an InputStream within. In C++, we directly do the wrapping without
|
||||
// defining another layer of abstraction. The wrapped output stream is
|
||||
// *NOT* reference counted (because it's meaningless to ref-count an I/O
|
||||
// stream).
|
||||
class FontInputStream : public InputStream {
|
||||
public:
|
||||
// Constructor.
|
||||
// @param is input stream to wrap
|
||||
explicit FontInputStream(InputStream* is);
|
||||
|
||||
// Constructor for a bounded font input stream.
|
||||
// @param is input stream to wrap
|
||||
// @param length the maximum length of bytes to read
|
||||
FontInputStream(InputStream* is, size_t length);
|
||||
|
||||
virtual ~FontInputStream();
|
||||
|
||||
virtual int32_t Length();
|
||||
virtual int32_t Available();
|
||||
virtual void Close();
|
||||
virtual void Mark(int32_t readlimit);
|
||||
virtual bool MarkSupported();
|
||||
virtual void Reset();
|
||||
|
||||
virtual int32_t Read();
|
||||
virtual int32_t Read(std::vector<uint8_t>* buffer);
|
||||
virtual int32_t Read(std::vector<uint8_t>* buffer, int32_t offset, int32_t length);
|
||||
|
||||
// Get the current position in the stream in bytes.
|
||||
// @return the current position in bytes
|
||||
virtual int64_t position() { return position_; }
|
||||
|
||||
virtual int32_t ReadChar();
|
||||
virtual int32_t ReadUShort();
|
||||
virtual int32_t ReadShort();
|
||||
virtual int32_t ReadUInt24();
|
||||
virtual int64_t ReadULong();
|
||||
virtual int32_t ReadULongAsInt();
|
||||
virtual int32_t ReadLong();
|
||||
virtual int32_t ReadFixed();
|
||||
virtual int64_t ReadDateTimeAsLong();
|
||||
virtual int64_t Skip(int64_t n); // n can be negative.
|
||||
|
||||
private:
|
||||
InputStream* stream_;
|
||||
int64_t position_;
|
||||
int64_t length_; // Bound on length of data to read.
|
||||
bool bounded_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/font_output_stream.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
FontOutputStream::FontOutputStream(OutputStream* os)
|
||||
: stream_(os),
|
||||
position_(0) {
|
||||
}
|
||||
|
||||
FontOutputStream::~FontOutputStream() {
|
||||
// Do not close, underlying stream shall clean up themselves.
|
||||
}
|
||||
|
||||
void FontOutputStream::Write(uint8_t b) {
|
||||
if (stream_) {
|
||||
stream_->Write(b);
|
||||
position_++;
|
||||
}
|
||||
}
|
||||
|
||||
void FontOutputStream::Write(std::vector<uint8_t>* b) {
|
||||
if (b) {
|
||||
Write(b, 0, b->size());
|
||||
position_ += b->size();
|
||||
}
|
||||
}
|
||||
|
||||
void FontOutputStream::Write(std::vector<uint8_t>* b, int32_t off, int32_t len) {
|
||||
assert(b);
|
||||
assert(stream_);
|
||||
if (off < 0 || len < 0 || off + len < 0 ||
|
||||
static_cast<size_t>(off + len) > b->size()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException();
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
stream_->Write(b, off, len);
|
||||
position_ += len;
|
||||
}
|
||||
|
||||
void FontOutputStream::Write(uint8_t* b, int32_t off, int32_t len) {
|
||||
assert(b);
|
||||
assert(stream_);
|
||||
if (off < 0 || len < 0 || off + len < 0) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException();
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
stream_->Write(b, off, len);
|
||||
position_ += len;
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteChar(uint8_t c) {
|
||||
Write(c);
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteUShort(int32_t us) {
|
||||
Write((uint8_t)((us >> 8) & 0xff));
|
||||
Write((uint8_t)(us & 0xff));
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteShort(int32_t s) {
|
||||
WriteUShort(s);
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteUInt24(int32_t ui) {
|
||||
Write((uint8_t)(ui >> 16) & 0xff);
|
||||
Write((uint8_t)(ui >> 8) & 0xff);
|
||||
Write((uint8_t)ui & 0xff);
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteULong(int64_t ul) {
|
||||
Write((uint8_t)((ul >> 24) & 0xff));
|
||||
Write((uint8_t)((ul >> 16) & 0xff));
|
||||
Write((uint8_t)((ul >> 8) & 0xff));
|
||||
Write((uint8_t)(ul & 0xff));
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteLong(int64_t l) {
|
||||
WriteULong(l);
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteFixed(int32_t f) {
|
||||
WriteULong(f);
|
||||
}
|
||||
|
||||
void FontOutputStream::WriteDateTime(int64_t date) {
|
||||
WriteULong((date >> 32) & 0xffffffff);
|
||||
WriteULong(date & 0xffffffff);
|
||||
}
|
||||
|
||||
void FontOutputStream::Flush() {
|
||||
if (stream_) {
|
||||
stream_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
void FontOutputStream::Close() {
|
||||
if (stream_) {
|
||||
stream_->Flush();
|
||||
stream_->Close();
|
||||
position_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/output_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// An output stream for writing font data.
|
||||
// The data types used are as listed:
|
||||
// BYTE 8-bit unsigned integer.
|
||||
// CHAR 8-bit signed integer.
|
||||
// USHORT 16-bit unsigned integer.
|
||||
// SHORT 16-bit signed integer.
|
||||
// UINT24 24-bit unsigned integer.
|
||||
// ULONG 32-bit unsigned integer.
|
||||
// LONG 32-bit signed integer.
|
||||
// Fixed 32-bit signed fixed-point number (16.16)
|
||||
// FUNIT Smallest measurable distance in the em space.
|
||||
// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
|
||||
// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
|
||||
// FUnits.
|
||||
// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
|
||||
// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
|
||||
// January 1, 1904. The value is represented as a signed 64-bit
|
||||
// integer.
|
||||
|
||||
// Note: The wrapped output stream is *NOT* reference counted (because it's
|
||||
// meaningless to ref-count an I/O stream).
|
||||
class FontOutputStream : public OutputStream {
|
||||
public:
|
||||
explicit FontOutputStream(OutputStream* os);
|
||||
virtual ~FontOutputStream();
|
||||
|
||||
virtual void Write(uint8_t b);
|
||||
virtual void Write(std::vector<uint8_t>* b);
|
||||
virtual void Write(std::vector<uint8_t>* b, int32_t off, int32_t len);
|
||||
virtual void Write(uint8_t* b, int32_t off, int32_t len);
|
||||
virtual void WriteChar(uint8_t c);
|
||||
virtual void WriteUShort(int32_t us);
|
||||
virtual void WriteShort(int32_t s);
|
||||
virtual void WriteUInt24(int32_t ui);
|
||||
virtual void WriteULong(int64_t ul);
|
||||
virtual void WriteLong(int64_t l);
|
||||
virtual void WriteFixed(int32_t l);
|
||||
virtual void WriteDateTime(int64_t date);
|
||||
|
||||
// Note: C++ port only.
|
||||
virtual void Flush();
|
||||
virtual void Close();
|
||||
|
||||
private:
|
||||
// Note: we do not use the variable name out as in Java because it has
|
||||
// special meaning in VC++ and will be very confusing.
|
||||
OutputStream* stream_;
|
||||
size_t position_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/growable_memory_byte_array.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
GrowableMemoryByteArray::GrowableMemoryByteArray()
|
||||
: ByteArray(0, INT_MAX, true) {
|
||||
// Note: We did not set an initial size of array like Java because STL
|
||||
// implementation will determine the best strategy.
|
||||
}
|
||||
|
||||
GrowableMemoryByteArray::~GrowableMemoryByteArray() {}
|
||||
|
||||
int32_t GrowableMemoryByteArray::CopyTo(OutputStream* os,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(os);
|
||||
os->Write(&b_, offset, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
void GrowableMemoryByteArray::InternalPut(int32_t index, uint8_t b) {
|
||||
if ((size_t)index >= b_.size()) {
|
||||
b_.resize((size_t)(index + 1));
|
||||
}
|
||||
b_[index] = b;
|
||||
}
|
||||
|
||||
int32_t GrowableMemoryByteArray::InternalPut(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
if ((size_t)index + length >= b_.size()) {
|
||||
// Note: We grow one byte more than Java version. VC debuggers shows
|
||||
// data better this way.
|
||||
b_.resize((size_t)(index + length + 1));
|
||||
}
|
||||
std::copy(b + offset, b + offset + length, b_.begin() + index);
|
||||
return length;
|
||||
}
|
||||
|
||||
uint8_t GrowableMemoryByteArray::InternalGet(int32_t index) {
|
||||
return b_[index];
|
||||
}
|
||||
|
||||
int32_t GrowableMemoryByteArray::InternalGet(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
memcpy(b + offset, &(b_[0]) + index, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
void GrowableMemoryByteArray::Close() {
|
||||
b_.clear();
|
||||
}
|
||||
|
||||
uint8_t* GrowableMemoryByteArray::Begin() {
|
||||
return &(b_[0]);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_
|
||||
|
||||
#include "sfntly/data/byte_array.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// Note: This is not really a port of Java version. Instead, this wraps a
|
||||
// std::vector inside and let it grow by calling resize().
|
||||
class GrowableMemoryByteArray : public ByteArray,
|
||||
public RefCounted<GrowableMemoryByteArray> {
|
||||
public:
|
||||
GrowableMemoryByteArray();
|
||||
virtual ~GrowableMemoryByteArray();
|
||||
virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
|
||||
|
||||
// Make gcc -Woverloaded-virtual happy.
|
||||
virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); }
|
||||
virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) {
|
||||
return ByteArray::CopyTo(array, offset, length);
|
||||
}
|
||||
virtual int32_t CopyTo(int32_t dst_offset,
|
||||
ByteArray* array,
|
||||
int32_t src_offset,
|
||||
int32_t length) {
|
||||
return ByteArray::CopyTo(dst_offset, array, src_offset, length);
|
||||
}
|
||||
virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); }
|
||||
|
||||
protected:
|
||||
virtual void InternalPut(int32_t index, uint8_t b);
|
||||
virtual int32_t InternalPut(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
virtual uint8_t InternalGet(int32_t index);
|
||||
virtual int32_t InternalGet(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
virtual void Close();
|
||||
virtual uint8_t* Begin();
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> b_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/memory_byte_array.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
MemoryByteArray::MemoryByteArray(int32_t length)
|
||||
: ByteArray(0, length), b_(NULL), allocated_(true) {
|
||||
}
|
||||
|
||||
MemoryByteArray::MemoryByteArray(uint8_t* b, int32_t filled_length)
|
||||
: ByteArray(filled_length, filled_length), b_(b), allocated_(false) {
|
||||
assert(b);
|
||||
}
|
||||
|
||||
MemoryByteArray::~MemoryByteArray() {
|
||||
Close();
|
||||
}
|
||||
|
||||
int32_t MemoryByteArray::CopyTo(OutputStream* os,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(os);
|
||||
os->Write(b_, offset, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
void MemoryByteArray::Init() {
|
||||
if (allocated_ && b_ == NULL) {
|
||||
b_ = new uint8_t[Size()];
|
||||
memset(b_, 0, Size());
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryByteArray::InternalPut(int32_t index, uint8_t b) {
|
||||
Init();
|
||||
b_[index] = b;
|
||||
}
|
||||
|
||||
int32_t MemoryByteArray::InternalPut(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(b);
|
||||
Init();
|
||||
memcpy(b_ + index, b + offset, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
uint8_t MemoryByteArray::InternalGet(int32_t index) {
|
||||
Init();
|
||||
return b_[index];
|
||||
}
|
||||
|
||||
int32_t MemoryByteArray::InternalGet(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(b);
|
||||
Init();
|
||||
memcpy(b + offset, b_ + index, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
void MemoryByteArray::Close() {
|
||||
if (allocated_ && b_) {
|
||||
delete[] b_;
|
||||
}
|
||||
b_ = NULL;
|
||||
}
|
||||
|
||||
uint8_t* MemoryByteArray::Begin() {
|
||||
Init();
|
||||
return b_;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_
|
||||
|
||||
#include "sfntly/data/byte_array.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class MemoryByteArray : public ByteArray, public RefCounted<MemoryByteArray> {
|
||||
public:
|
||||
// Construct a new MemoryByteArray with a new array of the size given. It is
|
||||
// assumed that none of the array is filled and readable.
|
||||
explicit MemoryByteArray(int32_t length);
|
||||
|
||||
// Note: not implemented due to dangerous operations in constructor.
|
||||
//explicit MemoryByteArray(std::vector<uint8_t>* b);
|
||||
|
||||
// Construct a new MemoryByteArray using byte array.
|
||||
// @param b the byte array that provides the actual storage
|
||||
// @param filled_length the index of the last byte in the array has data
|
||||
// Note: This is different from Java version, it does not take over the
|
||||
// ownership of b. Caller is responsible for handling the lifetime
|
||||
// of b. C++ port also assumes filled_length is buffer_length since
|
||||
// there is not a reliable way to identify the actual size of buffer.
|
||||
MemoryByteArray(uint8_t* b, int32_t filled_length);
|
||||
|
||||
virtual ~MemoryByteArray();
|
||||
virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
|
||||
|
||||
// Make gcc -Woverloaded-virtual happy.
|
||||
virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); }
|
||||
virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) {
|
||||
return ByteArray::CopyTo(array, offset, length);
|
||||
}
|
||||
virtual int32_t CopyTo(int32_t dst_offset,
|
||||
ByteArray* array,
|
||||
int32_t src_offset,
|
||||
int32_t length) {
|
||||
return ByteArray::CopyTo(dst_offset, array, src_offset, length);
|
||||
}
|
||||
virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); }
|
||||
|
||||
protected:
|
||||
virtual void InternalPut(int32_t index, uint8_t b);
|
||||
virtual int32_t InternalPut(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
virtual uint8_t InternalGet(int32_t index);
|
||||
virtual int32_t InternalGet(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
virtual void Close();
|
||||
virtual uint8_t* Begin();
|
||||
|
||||
private:
|
||||
void Init(); // C++ port only, used to allocate memory outside constructor.
|
||||
|
||||
uint8_t* b_;
|
||||
bool allocated_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/readable_font_data.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "sfntly/data/memory_byte_array.h"
|
||||
#include "sfntly/data/writable_font_data.h"
|
||||
#include "sfntly/port/exception_type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
ReadableFontData::ReadableFontData(ByteArray* array)
|
||||
: FontData(array),
|
||||
checksum_set_(false),
|
||||
checksum_(0) {
|
||||
}
|
||||
|
||||
ReadableFontData::~ReadableFontData() {}
|
||||
|
||||
// TODO(arthurhsu): re-investigate the memory model of this function. It's
|
||||
// not too useful without copying, but it's not performance
|
||||
// savvy to do copying.
|
||||
CALLER_ATTACH
|
||||
ReadableFontData* ReadableFontData::CreateReadableFontData(std::vector<uint8_t>* b) {
|
||||
assert(b);
|
||||
ByteArrayPtr ba = new MemoryByteArray(b->size());
|
||||
ba->Put(0, b);
|
||||
ReadableFontDataPtr wfd = new ReadableFontData(ba);
|
||||
return wfd.Detach();
|
||||
}
|
||||
|
||||
int64_t ReadableFontData::Checksum() {
|
||||
AutoLock lock(checksum_lock_);
|
||||
if (!checksum_set_) {
|
||||
ComputeChecksum();
|
||||
}
|
||||
return checksum_;
|
||||
}
|
||||
|
||||
void ReadableFontData::SetCheckSumRanges(const std::vector<int32_t>& ranges) {
|
||||
checksum_range_ = ranges;
|
||||
checksum_set_ = false; // UNIMPLEMENTED: atomicity
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadUByte(int32_t index) {
|
||||
int32_t b = array_->Get(BoundOffset(index));
|
||||
if (b < 0) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException(
|
||||
"Index attempted to be read from is out of bounds", index);
|
||||
#endif
|
||||
return kInvalidUnsigned;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadByte(int32_t index) {
|
||||
int32_t b = array_->Get(BoundOffset(index));
|
||||
if (b < 0) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException(
|
||||
"Index attempted to be read from is out of bounds", index);
|
||||
#endif
|
||||
return kInvalidByte;
|
||||
}
|
||||
return (b << 24) >> 24;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadBytes(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length));
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadChar(int32_t index) {
|
||||
return ReadUByte(index);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadUShort(int32_t index) {
|
||||
int32_t b1 = ReadUByte(index);
|
||||
if (b1 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidUnsigned;
|
||||
return 0xffff & (b1 << 8 | b2);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadShort(int32_t index) {
|
||||
int32_t b1 = ReadByte(index);
|
||||
if (b1 == kInvalidByte)
|
||||
return kInvalidShort;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidShort;
|
||||
|
||||
uint32_t result = static_cast<uint32_t>(b1) << 8 | b2;
|
||||
return static_cast<int32_t>(result << 16) >> 16;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadUInt24(int32_t index) {
|
||||
int32_t b1 = ReadUByte(index);
|
||||
if (b1 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b3 = ReadUByte(index + 2);
|
||||
if (b3 < 0)
|
||||
return kInvalidUnsigned;
|
||||
return 0xffffff & (b1 << 16 | b2 << 8 | b3);
|
||||
}
|
||||
|
||||
int64_t ReadableFontData::ReadULong(int32_t index) {
|
||||
int32_t b1 = ReadUByte(index);
|
||||
if (b1 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b3 = ReadUByte(index + 2);
|
||||
if (b3 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b4 = ReadUByte(index + 3);
|
||||
if (b4 < 0)
|
||||
return kInvalidUnsigned;
|
||||
return 0xffffffffL & (b1 << 24 | b2 << 16 | b3 << 8 | b4);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadULongAsInt(int32_t index) {
|
||||
int64_t ulong = ReadULong(index);
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
if ((ulong & 0x80000000) == 0x80000000) {
|
||||
throw ArithmeticException("Long value too large to fit into an integer.");
|
||||
}
|
||||
#endif
|
||||
return static_cast<int32_t>(ulong);
|
||||
}
|
||||
|
||||
int64_t ReadableFontData::ReadULongLE(int32_t index) {
|
||||
int32_t b1 = ReadUByte(index);
|
||||
if (b1 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b3 = ReadUByte(index + 2);
|
||||
if (b3 < 0)
|
||||
return kInvalidUnsigned;
|
||||
int32_t b4 = ReadUByte(index + 3);
|
||||
if (b4 < 0)
|
||||
return kInvalidUnsigned;
|
||||
return 0xffffffffL & (b1 | b2 << 8 | b3 << 16 | b4 << 24);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadLong(int32_t index) {
|
||||
int32_t b1 = ReadByte(index);
|
||||
if (b1 == kInvalidByte)
|
||||
return kInvalidLong;
|
||||
int32_t b2 = ReadUByte(index + 1);
|
||||
if (b2 < 0)
|
||||
return kInvalidLong;
|
||||
int32_t b3 = ReadUByte(index + 2);
|
||||
if (b3 < 0)
|
||||
return kInvalidLong;
|
||||
int32_t b4 = ReadUByte(index + 3);
|
||||
if (b4 < 0)
|
||||
return kInvalidLong;
|
||||
return static_cast<uint32_t>(b1) << 24 | b2 << 16 | b3 << 8 | b4;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadFixed(int32_t index) {
|
||||
return ReadLong(index);
|
||||
}
|
||||
|
||||
int64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) {
|
||||
int64_t high = ReadULong(index);
|
||||
if (high == kInvalidUnsigned)
|
||||
return kInvalidLongDateTime;
|
||||
int64_t low = ReadULong(index + 4);
|
||||
if (low == kInvalidUnsigned)
|
||||
return kInvalidLongDateTime;
|
||||
return high << 32 | low;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadFWord(int32_t index) {
|
||||
return ReadShort(index);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::ReadFUFWord(int32_t index) {
|
||||
return ReadUShort(index);
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::CopyTo(OutputStream* os) {
|
||||
return array_->CopyTo(os, BoundOffset(0), Length());
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::CopyTo(WritableFontData* wfd) {
|
||||
return array_->CopyTo(wfd->BoundOffset(0),
|
||||
wfd->array_,
|
||||
BoundOffset(0),
|
||||
Length());
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::CopyTo(ByteArray* ba) {
|
||||
return array_->CopyTo(ba, BoundOffset(0), Length());
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::SearchUShort(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t end_index,
|
||||
int32_t end_offset,
|
||||
int32_t length,
|
||||
int32_t key) {
|
||||
int32_t location = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = length;
|
||||
while (top != bottom) {
|
||||
location = (top + bottom) / 2;
|
||||
int32_t location_start = ReadUShort(start_index + location * start_offset);
|
||||
if (key < location_start) {
|
||||
// location is below current location
|
||||
top = location;
|
||||
} else {
|
||||
// is key below the upper bound?
|
||||
int32_t location_end = ReadUShort(end_index + location * end_offset);
|
||||
#if defined (SFNTLY_DEBUG_FONTDATA)
|
||||
fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end);
|
||||
#endif
|
||||
if (key <= location_end)
|
||||
return location;
|
||||
|
||||
// location is above the current location
|
||||
bottom = location + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::SearchUShort(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t key) {
|
||||
int32_t location = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = length;
|
||||
while (top != bottom) {
|
||||
location = (top + bottom) / 2;
|
||||
int32_t location_start = ReadUShort(start_index + location * start_offset);
|
||||
if (key == location_start)
|
||||
return location;
|
||||
|
||||
if (key < location_start) {
|
||||
// location is below current location
|
||||
top = location;
|
||||
} else {
|
||||
// location is above current location
|
||||
bottom = location + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ReadableFontData::SearchULong(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t end_index,
|
||||
int32_t end_offset,
|
||||
int32_t length,
|
||||
int32_t key) {
|
||||
int32_t location = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = length;
|
||||
while (top != bottom) {
|
||||
location = (top + bottom) / 2;
|
||||
int32_t location_start = ReadULongAsInt(start_index
|
||||
+ location * start_offset);
|
||||
if (key < location_start) {
|
||||
// location is below current location
|
||||
top = location;
|
||||
} else {
|
||||
// is key below the upper bound?
|
||||
int32_t location_end = ReadULongAsInt(end_index + location * end_offset);
|
||||
#if defined (SFNTLY_DEBUG_FONTDATA)
|
||||
fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end);
|
||||
#endif
|
||||
if (key <= location_end)
|
||||
return location;
|
||||
|
||||
// location is above the current location
|
||||
bottom = location + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset,
|
||||
int32_t length) {
|
||||
if (offset < 0 || length < 0 ||
|
||||
offset > std::numeric_limits<int32_t>::max() - length ||
|
||||
offset + length > Size()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundsException(
|
||||
"Attempt to bind data outside of its limits");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
FontDataPtr slice = new ReadableFontData(this, offset, length);
|
||||
return slice.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset) {
|
||||
if (offset < 0 || offset > Size()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundsException(
|
||||
"Attempt to bind data outside of its limits");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
FontDataPtr slice = new ReadableFontData(this, offset);
|
||||
return slice.Detach();
|
||||
}
|
||||
|
||||
ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset)
|
||||
: FontData(data, offset),
|
||||
checksum_set_(false),
|
||||
checksum_(0) {
|
||||
}
|
||||
|
||||
ReadableFontData::ReadableFontData(ReadableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t length)
|
||||
: FontData(data, offset, length),
|
||||
checksum_set_(false),
|
||||
checksum_(0) {
|
||||
}
|
||||
|
||||
void ReadableFontData::ComputeChecksum() {
|
||||
// TODO(arthurhsu): IMPLEMENT: synchronization/atomicity
|
||||
int64_t sum = 0;
|
||||
if (checksum_range_.empty()) {
|
||||
sum = ComputeCheckSum(0, Length());
|
||||
} else {
|
||||
for (uint32_t low_bound_index = 0; low_bound_index < checksum_range_.size();
|
||||
low_bound_index += 2) {
|
||||
int32_t low_bound = checksum_range_[low_bound_index];
|
||||
int32_t high_bound = (low_bound_index == checksum_range_.size() - 1) ?
|
||||
Length() :
|
||||
checksum_range_[low_bound_index + 1];
|
||||
sum += ComputeCheckSum(low_bound, high_bound);
|
||||
}
|
||||
}
|
||||
|
||||
checksum_ = sum & 0xffffffffL;
|
||||
checksum_set_ = true;
|
||||
}
|
||||
|
||||
int64_t ReadableFontData::ComputeCheckSum(int32_t low_bound,
|
||||
int32_t high_bound) {
|
||||
int64_t sum = 0;
|
||||
// Checksum all whole 4-byte chunks.
|
||||
for (int32_t i = low_bound; i <= high_bound - 4; i += 4) {
|
||||
sum += ReadULong(i);
|
||||
}
|
||||
|
||||
// Add last fragment if not 4-byte multiple
|
||||
int32_t off = high_bound & -4;
|
||||
if (off < high_bound) {
|
||||
int32_t b3 = ReadUByte(off);
|
||||
int32_t b2 = (off + 1 < high_bound) ? ReadUByte(off + 1) : 0;
|
||||
int32_t b1 = (off + 2 < high_bound) ? ReadUByte(off + 2) : 0;
|
||||
int32_t b0 = 0;
|
||||
sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,315 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
|
||||
|
||||
#include "sfntly/data/font_data.h"
|
||||
#include "sfntly/port/lock.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class OutputStream;
|
||||
class WritableFontData;
|
||||
|
||||
// Writable font data wrapper. Supports reading of data primitives in the
|
||||
// TrueType / OpenType spec.
|
||||
// The data types used are as listed:
|
||||
// BYTE 8-bit unsigned integer.
|
||||
// CHAR 8-bit signed integer.
|
||||
// USHORT 16-bit unsigned integer.
|
||||
// SHORT 16-bit signed integer.
|
||||
// UINT24 24-bit unsigned integer.
|
||||
// ULONG 32-bit unsigned integer.
|
||||
// LONG 32-bit signed integer.
|
||||
// Fixed 32-bit signed fixed-point number (16.16)
|
||||
// FUNIT Smallest measurable distance in the em space.
|
||||
// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
|
||||
// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
|
||||
// FUnits.
|
||||
// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
|
||||
// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
|
||||
// January 1, 1904. The value is represented as a signed 64-bit
|
||||
// integer.
|
||||
|
||||
class ReadableFontData : public FontData,
|
||||
public RefCounted<ReadableFontData> {
|
||||
public:
|
||||
explicit ReadableFontData(ByteArray* array);
|
||||
virtual ~ReadableFontData();
|
||||
|
||||
static const int32_t kInvalidByte = 128;
|
||||
static const int32_t kInvalidShort = 32768;
|
||||
static const int32_t kInvalidLong = 0xffffffff;
|
||||
static const int32_t kInvalidUnsigned = -1;
|
||||
static const int64_t kInvalidLongDateTime = -1;
|
||||
|
||||
static CALLER_ATTACH ReadableFontData* CreateReadableFontData(std::vector<uint8_t>* b);
|
||||
|
||||
// Gets a computed checksum for the data. This checksum uses the OpenType spec
|
||||
// calculation. Every ULong value (32 bit unsigned) in the data is summed and
|
||||
// the resulting value is truncated to 32 bits. If the data length in bytes is
|
||||
// not an integral multiple of 4 then any remaining bytes are treated as the
|
||||
// start of a 4 byte sequence whose remaining bytes are zero.
|
||||
// @return the checksum
|
||||
int64_t Checksum();
|
||||
|
||||
// Sets the bounds to use for computing the checksum. These bounds are in
|
||||
// begin and end pairs. If an odd number is given then the final range is
|
||||
// assumed to extend to the end of the data. The lengths of each range must be
|
||||
// a multiple of 4.
|
||||
// @param ranges the range bounds to use for the checksum
|
||||
void SetCheckSumRanges(const std::vector<int32_t>& ranges);
|
||||
|
||||
// Read the UBYTE at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the UBYTE; -1 if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadUByte(int32_t index);
|
||||
|
||||
// Read the BYTE at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the BYTE; |kInvalidByte| if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadByte(int32_t index);
|
||||
|
||||
// Read the bytes at the given index into the array.
|
||||
// @param index index into the font data
|
||||
// @param b the destination for the bytes read
|
||||
// @param offset offset in the byte array to place the bytes
|
||||
// @param length the length of bytes to read
|
||||
// @return the number of bytes actually read; -1 if the index is outside the
|
||||
// bounds of the font data
|
||||
virtual int32_t ReadBytes(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
|
||||
// Read the CHAR at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the CHAR; -1 if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadChar(int32_t index);
|
||||
|
||||
// Read the USHORT at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the USHORT; -1 if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadUShort(int32_t index);
|
||||
|
||||
// Read the SHORT at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the SHORT; |kInvalidShort| if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadShort(int32_t index);
|
||||
|
||||
// Read the UINT24 at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the UINT24; -1 if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadUInt24(int32_t index);
|
||||
|
||||
// Read the ULONG at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the ULONG; kInvalidUnsigned if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int64_t ReadULong(int32_t index);
|
||||
|
||||
// Read the ULONG at the given index as int32_t.
|
||||
// @param index index into the font data
|
||||
// @return the ULONG
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadULongAsInt(int32_t index);
|
||||
|
||||
// Read the ULONG at the given index, little-endian variant
|
||||
// @param index index into the font data
|
||||
// @return the ULONG
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int64_t ReadULongLE(int32_t index);
|
||||
|
||||
// Read the LONG at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the LONG; kInvalidLong if outside the bounds of the font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadLong(int32_t index);
|
||||
|
||||
// Read the Fixed at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the Fixed
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadFixed(int32_t index);
|
||||
|
||||
// Read the LONGDATETIME at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the LONGDATETIME; kInvalidLongDateTime if outside the bounds of the
|
||||
// font data
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int64_t ReadDateTimeAsLong(int32_t index);
|
||||
|
||||
// Read the FWORD at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the FWORD
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadFWord(int32_t index);
|
||||
|
||||
// Read the UFWORD at the given index.
|
||||
// @param index index into the font data
|
||||
// @return the UFWORD
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t ReadFUFWord(int32_t index);
|
||||
|
||||
// Note: Not ported because they just throw UnsupportedOperationException()
|
||||
// in Java.
|
||||
/*
|
||||
virtual int32_t ReadFUnit(int32_t index);
|
||||
virtual int64_t ReadF2Dot14(int32_t index);
|
||||
*/
|
||||
|
||||
// Copy the FontData to an OutputStream.
|
||||
// @param os the destination
|
||||
// @return number of bytes copied
|
||||
// @throws IOException
|
||||
virtual int32_t CopyTo(OutputStream* os);
|
||||
|
||||
// Copy the FontData to a WritableFontData.
|
||||
// @param wfd the destination
|
||||
// @return number of bytes copied
|
||||
// @throws IOException
|
||||
virtual int32_t CopyTo(WritableFontData* wfd);
|
||||
|
||||
// Make gcc -Woverloaded-virtual happy.
|
||||
virtual int32_t CopyTo(ByteArray* ba);
|
||||
|
||||
// Search for the key value in the range tables provided.
|
||||
// The search looks through the start-end pairs looking for the key value. It
|
||||
// is assumed that the start-end pairs are both represented by UShort values,
|
||||
// ranges do not overlap, and are monotonically increasing.
|
||||
// @param startIndex the position to read the first start value from
|
||||
// @param startOffset the offset between subsequent start values
|
||||
// @param endIndex the position to read the first end value from
|
||||
// @param endOffset the offset between subsequent end values
|
||||
// @param length the number of start-end pairs
|
||||
// @param key the value to search for
|
||||
// @return the index of the start-end pairs in which the key was found; -1
|
||||
// otherwise
|
||||
int32_t SearchUShort(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t end_index,
|
||||
int32_t end_offset,
|
||||
int32_t length,
|
||||
int32_t key);
|
||||
|
||||
// Search for the key value in the table provided.
|
||||
// The search looks through the values looking for the key value. It is
|
||||
// assumed that the are represented by UShort values and are monotonically
|
||||
// increasing.
|
||||
// @param startIndex the position to read the first start value from
|
||||
// @param startOffset the offset between subsequent start values
|
||||
// @param length the number of start-end pairs
|
||||
// @param key the value to search for
|
||||
// @return the index of the start-end pairs in which the key was found; -1
|
||||
// otherwise
|
||||
int32_t SearchUShort(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t key);
|
||||
|
||||
// Search for the key value in the range tables provided.
|
||||
// The search looks through the start-end pairs looking for the key value. It
|
||||
// is assumed that the start-end pairs are both represented by ULong values
|
||||
// that can be represented within 31 bits, ranges do not overlap, and are
|
||||
// monotonically increasing.
|
||||
// @param startIndex the position to read the first start value from
|
||||
// @param startOffset the offset between subsequent start values
|
||||
// @param endIndex the position to read the first end value from
|
||||
// @param endOffset the offset between subsequent end values
|
||||
// @param length the number of start-end pairs
|
||||
// @param key the value to search for
|
||||
// @return the index of the start-end pairs in which the key was found; -1
|
||||
// otherwise
|
||||
int32_t SearchULong(int32_t start_index,
|
||||
int32_t start_offset,
|
||||
int32_t end_index,
|
||||
int32_t end_offset,
|
||||
int32_t length,
|
||||
int32_t key);
|
||||
|
||||
|
||||
// TODO(arthurhsu): IMPLEMENT
|
||||
/*
|
||||
virtual int32_t ReadFUnit(int32_t index);
|
||||
virtual int64_t ReadF2Dot14(int32_t index);
|
||||
virtual int64_t ReadLongDateTime(int32_t index);
|
||||
*/
|
||||
|
||||
// Makes a slice of this FontData. The returned slice will share the data with
|
||||
// the original FontData.
|
||||
// @param offset the start of the slice
|
||||
// @param length the number of bytes in the slice
|
||||
// @return a slice of the original FontData
|
||||
// Note: C++ polymorphism requires return type to be consistent
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length);
|
||||
|
||||
// Makes a bottom bound only slice of this array. The returned slice will
|
||||
// share the data with the original FontData.
|
||||
// @param offset the start of the slice
|
||||
// @return a slice of the original FontData
|
||||
// Note: C++ polymorphism requires return type to be consistent
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset);
|
||||
|
||||
// Not Ported: toString()
|
||||
|
||||
protected:
|
||||
// Constructor. Creates a bounded wrapper of another ReadableFontData from the
|
||||
// given offset until the end of the original ReadableFontData.
|
||||
// @param data data to wrap
|
||||
// @param offset the start of this data's view of the original data
|
||||
ReadableFontData(ReadableFontData* data, int32_t offset);
|
||||
|
||||
// Constructor. Creates a bounded wrapper of another ReadableFontData from the
|
||||
// given offset until the end of the original ReadableFontData.
|
||||
// @param data data to wrap
|
||||
// @param offset the start of this data's view of the original data
|
||||
// @param length the length of the other FontData to use
|
||||
ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length);
|
||||
|
||||
private:
|
||||
// Compute the checksum for the font data using any ranges set for the
|
||||
// calculation.
|
||||
void ComputeChecksum();
|
||||
|
||||
// Do the actual computation of the checksum for a range using the
|
||||
// TrueType/OpenType checksum algorithm. The range used is from the low bound
|
||||
// to the high bound in steps of four bytes. If any of the bytes within that 4
|
||||
// byte segment are not readable then it will considered a zero for
|
||||
// calculation.
|
||||
// Only called from within a synchronized method so it does not need to be
|
||||
// synchronized itself.
|
||||
// @param lowBound first position to start a 4 byte segment on
|
||||
// @param highBound last possible position to start a 4 byte segment on
|
||||
// @return the checksum for the total range
|
||||
int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound);
|
||||
|
||||
Lock checksum_lock_;
|
||||
bool checksum_set_;
|
||||
int64_t checksum_;
|
||||
std::vector<int32_t> checksum_range_;
|
||||
};
|
||||
typedef Ptr<ReadableFontData> ReadableFontDataPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/data/writable_font_data.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "sfntly/data/memory_byte_array.h"
|
||||
#include "sfntly/data/growable_memory_byte_array.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) {
|
||||
}
|
||||
|
||||
WritableFontData::~WritableFontData() {}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH
|
||||
WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) {
|
||||
ByteArrayPtr ba;
|
||||
if (length > 0) {
|
||||
ba = new MemoryByteArray(length);
|
||||
ba->SetFilledLength(length);
|
||||
} else {
|
||||
ba = new GrowableMemoryByteArray();
|
||||
}
|
||||
WritableFontDataPtr wfd = new WritableFontData(ba);
|
||||
return wfd.Detach();
|
||||
}
|
||||
|
||||
// TODO(arthurhsu): re-investigate the memory model of this function. It's
|
||||
// not too useful without copying, but it's not performance
|
||||
// savvy to do copying.
|
||||
CALLER_ATTACH
|
||||
WritableFontData* WritableFontData::CreateWritableFontData(std::vector<uint8_t>* b) {
|
||||
ByteArrayPtr ba = new GrowableMemoryByteArray();
|
||||
ba->Put(0, b);
|
||||
WritableFontDataPtr wfd = new WritableFontData(ba);
|
||||
return wfd.Detach();
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteByte(int32_t index, uint8_t b) {
|
||||
array_->Put(BoundOffset(index), b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteBytes(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
return array_->Put(BoundOffset(index),
|
||||
b,
|
||||
offset,
|
||||
BoundLength(index, length));
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteBytes(int32_t index, std::vector<uint8_t>* b) {
|
||||
assert(b);
|
||||
return WriteBytes(index, &((*b)[0]), 0, b->size());
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteBytesPad(int32_t index,
|
||||
std::vector<uint8_t>* b,
|
||||
int32_t offset,
|
||||
int32_t length,
|
||||
uint8_t pad) {
|
||||
int32_t written =
|
||||
array_->Put(BoundOffset(index),
|
||||
&((*b)[0]),
|
||||
offset,
|
||||
BoundLength(index,
|
||||
std::min<int32_t>(length, b->size() - offset)));
|
||||
written += WritePadding(written + index, length - written, pad);
|
||||
return written;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WritePadding(int32_t index, int32_t count) {
|
||||
return WritePadding(index, count, (uint8_t)0);
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WritePadding(int32_t index, int32_t count,
|
||||
uint8_t pad) {
|
||||
for (int32_t i = 0; i < count; ++i) {
|
||||
array_->Put(index + i, pad);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteChar(int32_t index, uint8_t c) {
|
||||
return WriteByte(index, c);
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteUShort(int32_t index, int32_t us) {
|
||||
WriteByte(index, (uint8_t)((us >> 8) & 0xff));
|
||||
WriteByte(index + 1, (uint8_t)(us & 0xff));
|
||||
return 2;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteUShortLE(int32_t index, int32_t us) {
|
||||
WriteByte(index, (uint8_t)(us & 0xff));
|
||||
WriteByte(index + 1, (uint8_t)((us >> 8) & 0xff));
|
||||
return 2;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteShort(int32_t index, int32_t s) {
|
||||
return WriteUShort(index, s);
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteUInt24(int32_t index, int32_t ui) {
|
||||
WriteByte(index, (uint8_t)((ui >> 16) & 0xff));
|
||||
WriteByte(index + 1, (uint8_t)((ui >> 8) & 0xff));
|
||||
WriteByte(index + 2, (uint8_t)(ui & 0xff));
|
||||
return 3;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteULong(int32_t index, int64_t ul) {
|
||||
WriteByte(index, (uint8_t)((ul >> 24) & 0xff));
|
||||
WriteByte(index + 1, (uint8_t)((ul >> 16) & 0xff));
|
||||
WriteByte(index + 2, (uint8_t)((ul >> 8) & 0xff));
|
||||
WriteByte(index + 3, (uint8_t)(ul & 0xff));
|
||||
return 4;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteULongLE(int32_t index, int64_t ul) {
|
||||
WriteByte(index, (uint8_t)(ul & 0xff));
|
||||
WriteByte(index + 1, (uint8_t)((ul >> 8) & 0xff));
|
||||
WriteByte(index + 2, (uint8_t)((ul >> 16) & 0xff));
|
||||
WriteByte(index + 3, (uint8_t)((ul >> 24) & 0xff));
|
||||
return 4;
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteLong(int32_t index, int64_t l) {
|
||||
return WriteULong(index, l);
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteFixed(int32_t index, int32_t f) {
|
||||
return WriteLong(index, f);
|
||||
}
|
||||
|
||||
int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) {
|
||||
WriteULong(index, (date >> 32) & 0xffffffff);
|
||||
WriteULong(index + 4, date & 0xffffffff);
|
||||
return 8;
|
||||
}
|
||||
|
||||
void WritableFontData::CopyFrom(InputStream* is, int32_t length) {
|
||||
array_->CopyFrom(is, length);
|
||||
}
|
||||
|
||||
void WritableFontData::CopyFrom(InputStream* is) {
|
||||
array_->CopyFrom(is);
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset,
|
||||
int32_t length) {
|
||||
if (offset < 0 || length < 0 ||
|
||||
offset > std::numeric_limits<int32_t>::max() - length ||
|
||||
offset + length > Size()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundsException(
|
||||
"Attempt to bind data outside of its limits");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
FontDataPtr slice = new WritableFontData(this, offset, length);
|
||||
return slice.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) {
|
||||
if (offset < 0 || offset > Size()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundsException(
|
||||
"Attempt to bind data outside of its limits");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
FontDataPtr slice = new WritableFontData(this, offset);
|
||||
return slice.Detach();
|
||||
}
|
||||
|
||||
WritableFontData::WritableFontData(WritableFontData* data, int32_t offset)
|
||||
: ReadableFontData(data, offset) {
|
||||
}
|
||||
|
||||
WritableFontData::WritableFontData(WritableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t length)
|
||||
: ReadableFontData(data, offset, length) {
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_
|
||||
|
||||
#include "sfntly/data/readable_font_data.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// Writable font data wrapper. Supports writing of data primitives in the
|
||||
// TrueType / OpenType spec.
|
||||
class WritableFontData : public ReadableFontData {
|
||||
public:
|
||||
explicit WritableFontData(ByteArray* ba);
|
||||
virtual ~WritableFontData();
|
||||
|
||||
// Constructs a writable font data object. If the length is specified as
|
||||
// positive then a fixed size font data object will be created. If the length
|
||||
// is zero or less then a growable font data object will be created and the
|
||||
// size will be used as an estimate to help in allocating the original space.
|
||||
// @param length if length > 0 create a fixed length font data; otherwise
|
||||
// create a growable font data
|
||||
// @return a new writable font data
|
||||
static CALLER_ATTACH WritableFontData* CreateWritableFontData(int32_t length);
|
||||
|
||||
// Constructs a writable font data object. The new font data object will wrap
|
||||
// the bytes passed in to the factory and it will take make a copy of those
|
||||
// bytes.
|
||||
// @param b the byte vector to wrap
|
||||
// @return a new writable font data
|
||||
static CALLER_ATTACH WritableFontData* CreateWritableFontData(std::vector<uint8_t>* b);
|
||||
|
||||
// Write a byte at the given index.
|
||||
// @param index index into the font data
|
||||
// @param b the byte to write
|
||||
// @return the number of bytes written
|
||||
virtual int32_t WriteByte(int32_t index, uint8_t b);
|
||||
|
||||
// Write the bytes from the array.
|
||||
// @param index index into the font data
|
||||
// @param b the source for the bytes to be written
|
||||
// @param offset offset in the byte array
|
||||
// @param length the length of the bytes to be written
|
||||
// @return the number of bytes actually written; -1 if the index is outside
|
||||
// the FontData's range
|
||||
virtual int32_t WriteBytes(int32_t index,
|
||||
uint8_t* b,
|
||||
int32_t offset,
|
||||
int32_t length);
|
||||
|
||||
// Write the bytes from the array.
|
||||
// @param index index into the font data
|
||||
// @param b the source for the bytes to be written
|
||||
// @return the number of bytes actually written; -1 if the index is outside
|
||||
// the FontData's range
|
||||
virtual int32_t WriteBytes(int32_t index, std::vector<uint8_t>* b);
|
||||
|
||||
// Write the bytes from the array and pad if necessary.
|
||||
// Write to the length given using the byte array provided and if there are
|
||||
// not enough bytes in the array then pad to the requested length using the
|
||||
// pad byte specified.
|
||||
// @param index index into the font data
|
||||
// @param b the source for the bytes to be written
|
||||
// @param offset offset in the byte array
|
||||
// @param length the length of the bytes to be written
|
||||
// @param pad the padding byte to be used if necessary
|
||||
// @return the number of bytes actually written
|
||||
virtual int32_t WriteBytesPad(int32_t index,
|
||||
std::vector<uint8_t>* b,
|
||||
int32_t offset,
|
||||
int32_t length,
|
||||
uint8_t pad);
|
||||
|
||||
// Writes padding to the FontData. The padding byte written is 0x00.
|
||||
// @param index index into the font data
|
||||
// @param count the number of pad bytes to write
|
||||
// @return the number of pad bytes written
|
||||
virtual int32_t WritePadding(int32_t index, int32_t count);
|
||||
|
||||
// Writes padding to the FontData.
|
||||
// @param index index into the font data
|
||||
// @param count the number of pad bytes to write
|
||||
// @param pad the byte value to use as padding
|
||||
// @return the number of pad bytes written
|
||||
virtual int32_t WritePadding(int32_t index, int32_t count, uint8_t pad);
|
||||
|
||||
// Write the CHAR at the given index.
|
||||
// @param index index into the font data
|
||||
// @param c the CHAR
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteChar(int32_t index, uint8_t c);
|
||||
|
||||
// Write the USHORT at the given index.
|
||||
// @param index index into the font data
|
||||
// @param us the USHORT
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteUShort(int32_t index, int32_t us);
|
||||
|
||||
// Write the USHORT at the given index in little endian format.
|
||||
// @param index index into the font data
|
||||
// @param us the USHORT
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteUShortLE(int32_t index, int32_t us);
|
||||
|
||||
// Write the SHORT at the given index.
|
||||
// @param index index into the font data
|
||||
// @param s the SHORT
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteShort(int32_t index, int32_t s);
|
||||
|
||||
// Write the UINT24 at the given index.
|
||||
// @param index index into the font data
|
||||
// @param ui the UINT24
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteUInt24(int32_t index, int32_t ui);
|
||||
|
||||
// Write the ULONG at the given index.
|
||||
// @param index index into the font data
|
||||
// @param ul the ULONG
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteULong(int32_t index, int64_t ul);
|
||||
|
||||
// Write the ULONG at the given index in little endian format.
|
||||
// @param index index into the font data
|
||||
// @param ul the ULONG
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteULongLE(int32_t index, int64_t ul);
|
||||
|
||||
// Write the LONG at the given index.
|
||||
// @param index index into the font data
|
||||
// @param l the LONG
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteLong(int32_t index, int64_t l);
|
||||
|
||||
// Write the Fixed at the given index.
|
||||
// @param index index into the font data
|
||||
// @param f the Fixed
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteFixed(int32_t index, int32_t f);
|
||||
|
||||
// Write the LONGDATETIME at the given index.
|
||||
// @param index index into the font data
|
||||
// @param date the LONGDATETIME
|
||||
// @return the number of bytes actually written
|
||||
// @throws IndexOutOfBoundsException if index is outside the FontData's range
|
||||
virtual int32_t WriteDateTime(int32_t index, int64_t date);
|
||||
|
||||
// Copy from the InputStream into this FontData.
|
||||
// @param is the source
|
||||
// @param length the number of bytes to copy
|
||||
// @throws IOException
|
||||
virtual void CopyFrom(InputStream* is, int32_t length);
|
||||
|
||||
// Copy everything from the InputStream into this FontData.
|
||||
// @param is the source
|
||||
// @throws IOException
|
||||
virtual void CopyFrom(InputStream* is);
|
||||
|
||||
// Makes a slice of this FontData. The returned slice will share the data with
|
||||
// the original FontData.
|
||||
// @param offset the start of the slice
|
||||
// @param length the number of bytes in the slice
|
||||
// @return a slice of the original FontData
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length);
|
||||
|
||||
// Makes a bottom bound only slice of this array. The returned slice will
|
||||
// share the data with the original FontData.
|
||||
// @param offset the start of the slice
|
||||
// @return a slice of the original FontData
|
||||
virtual CALLER_ATTACH FontData* Slice(int32_t offset);
|
||||
|
||||
private:
|
||||
// Constructor with a lower bound.
|
||||
// @param data other WritableFontData object to share data with
|
||||
// @param offset offset from the other WritableFontData's data
|
||||
WritableFontData(WritableFontData* data, int32_t offset);
|
||||
|
||||
// Constructor with lower bound and a length bound.
|
||||
// @param data other WritableFontData object to share data with
|
||||
// @param offset offset from the other WritableFontData's data
|
||||
// @param length length of other WritableFontData's data to use
|
||||
WritableFontData(WritableFontData* data, int32_t offset, int32_t length);
|
||||
};
|
||||
typedef Ptr<WritableFontData> WritableFontDataPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_
|
|
@ -1,586 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/font.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "sfntly/data/font_input_stream.h"
|
||||
#include "sfntly/font_factory.h"
|
||||
#include "sfntly/math/fixed1616.h"
|
||||
#include "sfntly/math/font_math.h"
|
||||
#include "sfntly/port/exception_type.h"
|
||||
#include "sfntly/table/core/font_header_table.h"
|
||||
#include "sfntly/table/core/horizontal_device_metrics_table.h"
|
||||
#include "sfntly/table/core/horizontal_header_table.h"
|
||||
#include "sfntly/table/core/horizontal_metrics_table.h"
|
||||
#include "sfntly/table/core/maximum_profile_table.h"
|
||||
#include "sfntly/table/truetype/loca_table.h"
|
||||
#include "sfntly/tag.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
namespace {
|
||||
|
||||
const int32_t kSFNTVersionMajor = 1;
|
||||
const int32_t kSFNTVersionMinor = 0;
|
||||
|
||||
const int32_t kMaxTableSize = 200 * 1024 * 1024;
|
||||
|
||||
bool IsValidHeaderRegion(int32_t data_length, int32_t offset, int32_t length) {
|
||||
return offset >= 0 && length >= 0 &&
|
||||
offset <= std::numeric_limits<int32_t>::max() - length &&
|
||||
offset + length <= data_length;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/******************************************************************************
|
||||
* Font class
|
||||
******************************************************************************/
|
||||
Font::~Font() {}
|
||||
|
||||
bool Font::HasTable(int32_t tag) const {
|
||||
return tables_.find(tag) != tables_.end();
|
||||
}
|
||||
|
||||
Table* Font::GetTable(int32_t tag) {
|
||||
if (!HasTable(tag))
|
||||
return NULL;
|
||||
return tables_[tag];
|
||||
}
|
||||
|
||||
const TableMap* Font::GetTableMap() {
|
||||
return &tables_;
|
||||
}
|
||||
|
||||
void Font::Serialize(OutputStream* os, std::vector<int32_t>* table_ordering) {
|
||||
assert(table_ordering);
|
||||
std::vector<int32_t> final_table_ordering;
|
||||
GenerateTableOrdering(table_ordering, &final_table_ordering);
|
||||
TableHeaderList table_records;
|
||||
BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
|
||||
|
||||
FontOutputStream fos(os);
|
||||
SerializeHeader(&fos, &table_records);
|
||||
SerializeTables(&fos, &table_records);
|
||||
}
|
||||
|
||||
Font::Font(int32_t sfnt_version, std::vector<uint8_t>* digest)
|
||||
: sfnt_version_(sfnt_version) {
|
||||
// non-trivial assignments that makes debugging hard if placed in
|
||||
// initialization list
|
||||
digest_ = *digest;
|
||||
}
|
||||
|
||||
void Font::BuildTableHeadersForSerialization(std::vector<int32_t>* table_ordering,
|
||||
TableHeaderList* table_headers) {
|
||||
assert(table_headers);
|
||||
assert(table_ordering);
|
||||
|
||||
std::vector<int32_t> final_table_ordering;
|
||||
GenerateTableOrdering(table_ordering, &final_table_ordering);
|
||||
int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
|
||||
Offset::kTableRecordSize;
|
||||
for (size_t i = 0; i < final_table_ordering.size(); ++i) {
|
||||
int32_t tag = final_table_ordering[i];
|
||||
TablePtr table = GetTable(tag);
|
||||
if (table == NULL)
|
||||
continue;
|
||||
|
||||
HeaderPtr header = new Header(tag, table->CalculatedChecksum(),
|
||||
table_offset, table->header()->length());
|
||||
table_headers->push_back(header);
|
||||
table_offset += (table->DataLength() + 3) & ~3;
|
||||
}
|
||||
}
|
||||
|
||||
void Font::SerializeHeader(FontOutputStream* fos,
|
||||
TableHeaderList* table_headers) {
|
||||
fos->WriteFixed(sfnt_version_);
|
||||
fos->WriteUShort(table_headers->size());
|
||||
int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size());
|
||||
int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4);
|
||||
fos->WriteUShort(search_range);
|
||||
fos->WriteUShort(log2_of_max_power_of_2);
|
||||
fos->WriteUShort((table_headers->size() * 16) - search_range);
|
||||
|
||||
HeaderTagSortedSet sorted_headers;
|
||||
std::copy(table_headers->begin(),
|
||||
table_headers->end(),
|
||||
std::inserter(sorted_headers, sorted_headers.end()));
|
||||
|
||||
for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
|
||||
record_end = sorted_headers.end();
|
||||
record != record_end; ++record) {
|
||||
fos->WriteULong((*record)->tag());
|
||||
fos->WriteULong((int32_t)((*record)->checksum()));
|
||||
fos->WriteULong((*record)->offset());
|
||||
fos->WriteULong((*record)->length());
|
||||
}
|
||||
}
|
||||
|
||||
void Font::SerializeTables(FontOutputStream* fos,
|
||||
TableHeaderList* table_headers) {
|
||||
assert(fos);
|
||||
assert(table_headers);
|
||||
for (size_t i = 0; i < table_headers->size(); ++i) {
|
||||
const HeaderPtr& record = (*table_headers)[i];
|
||||
TablePtr target_table = GetTable(record->tag());
|
||||
if (target_table == NULL) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("Table out of sync with font header.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
int32_t table_size = target_table->Serialize(fos);
|
||||
assert(table_size == record->length());
|
||||
|
||||
int32_t filler_size = ((table_size + 3) & ~3) - table_size;
|
||||
for (int32_t i = 0; i < filler_size; ++i) {
|
||||
fos->Write(static_cast<uint8_t>(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Font::GenerateTableOrdering(std::vector<int32_t>* default_table_ordering,
|
||||
std::vector<int32_t>* table_ordering) {
|
||||
assert(default_table_ordering);
|
||||
assert(table_ordering);
|
||||
table_ordering->clear();
|
||||
if (default_table_ordering->empty()) {
|
||||
DefaultTableOrdering(default_table_ordering);
|
||||
}
|
||||
|
||||
typedef std::map<int32_t, bool> Int2Bool;
|
||||
typedef std::pair<int32_t, bool> Int2BoolEntry;
|
||||
Int2Bool tables_in_font;
|
||||
for (TableMap::iterator table = tables_.begin(), table_end = tables_.end();
|
||||
table != table_end; ++table) {
|
||||
tables_in_font.insert(Int2BoolEntry(table->first, false));
|
||||
}
|
||||
for (std::vector<int32_t>::iterator tag = default_table_ordering->begin(),
|
||||
tag_end = default_table_ordering->end();
|
||||
tag != tag_end; ++tag) {
|
||||
if (HasTable(*tag)) {
|
||||
table_ordering->push_back(*tag);
|
||||
tables_in_font[*tag] = true;
|
||||
}
|
||||
}
|
||||
for (Int2Bool::iterator table = tables_in_font.begin(),
|
||||
table_end = tables_in_font.end();
|
||||
table != table_end; ++table) {
|
||||
if (table->second == false)
|
||||
table_ordering->push_back(table->first);
|
||||
}
|
||||
}
|
||||
|
||||
void Font::DefaultTableOrdering(std::vector<int32_t>* default_table_ordering) {
|
||||
assert(default_table_ordering);
|
||||
default_table_ordering->clear();
|
||||
if (HasTable(Tag::CFF)) {
|
||||
default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE);
|
||||
std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE,
|
||||
default_table_ordering->begin());
|
||||
return;
|
||||
}
|
||||
default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE);
|
||||
std::copy(TRUE_TYPE_TABLE_ORDERING,
|
||||
TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE,
|
||||
default_table_ordering->begin());
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Font::Builder class
|
||||
******************************************************************************/
|
||||
Font::Builder::~Builder() {}
|
||||
|
||||
CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
|
||||
InputStream* is) {
|
||||
FontBuilderPtr builder = new Builder(factory);
|
||||
builder->LoadFont(is);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
|
||||
FontFactory* factory,
|
||||
WritableFontData* wfd,
|
||||
int32_t offset_to_offset_table) {
|
||||
FontBuilderPtr builder = new Builder(factory);
|
||||
builder->LoadFont(wfd, offset_to_offset_table);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
|
||||
FontFactory* factory) {
|
||||
FontBuilderPtr builder = new Builder(factory);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
bool Font::Builder::ReadyToBuild() {
|
||||
// just read in data with no manipulation
|
||||
if (table_builders_.empty() && !data_blocks_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(stuartg): font level checks - required tables etc?
|
||||
for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
|
||||
table_builder_end = table_builders_.end();
|
||||
table_builder != table_builder_end;
|
||||
++table_builder) {
|
||||
if (!table_builder->second->ReadyToBuild())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* Font::Builder::Build() {
|
||||
FontPtr font = new Font(sfnt_version_, &digest_);
|
||||
|
||||
if (!table_builders_.empty()) {
|
||||
// Note: Different from Java. Directly use font->tables_ here to avoid
|
||||
// STL container copying.
|
||||
BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
|
||||
}
|
||||
|
||||
table_builders_.clear();
|
||||
data_blocks_.clear();
|
||||
return font.Detach();
|
||||
}
|
||||
|
||||
void Font::Builder::SetDigest(std::vector<uint8_t>* digest) {
|
||||
digest_.clear();
|
||||
digest_ = *digest;
|
||||
}
|
||||
|
||||
void Font::Builder::ClearTableBuilders() {
|
||||
table_builders_.clear();
|
||||
}
|
||||
|
||||
bool Font::Builder::HasTableBuilder(int32_t tag) {
|
||||
return (table_builders_.find(tag) != table_builders_.end());
|
||||
}
|
||||
|
||||
Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) {
|
||||
if (HasTableBuilder(tag))
|
||||
return table_builders_[tag];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
|
||||
HeaderPtr header = new Header(tag);
|
||||
TableBuilderPtr builder;
|
||||
builder.Attach(Table::Builder::GetBuilder(header, NULL));
|
||||
table_builders_.insert(TableBuilderEntry(header->tag(), builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
Table::Builder* Font::Builder::NewTableBuilder(int32_t tag,
|
||||
ReadableFontData* src_data) {
|
||||
assert(src_data);
|
||||
WritableFontDataPtr data;
|
||||
data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
|
||||
// TODO(stuarg): take over original data instead?
|
||||
src_data->CopyTo(data);
|
||||
|
||||
HeaderPtr header = new Header(tag, data->Length());
|
||||
TableBuilderPtr builder;
|
||||
builder.Attach(Table::Builder::GetBuilder(header, data));
|
||||
table_builders_.insert(TableBuilderEntry(tag, builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
void Font::Builder::RemoveTableBuilder(int32_t tag) {
|
||||
table_builders_.erase(tag);
|
||||
}
|
||||
|
||||
Font::Builder::Builder(FontFactory* factory)
|
||||
: factory_(factory),
|
||||
sfnt_version_(Fixed1616::Fixed(kSFNTVersionMajor, kSFNTVersionMinor)) {
|
||||
}
|
||||
|
||||
void Font::Builder::LoadFont(InputStream* is) {
|
||||
// Note: we do not throw exception here for is. This is more of an assertion.
|
||||
assert(is);
|
||||
FontInputStream font_is(is);
|
||||
HeaderOffsetSortedSet records;
|
||||
ReadHeader(&font_is, &records);
|
||||
LoadTableData(&records, &font_is, &data_blocks_);
|
||||
BuildAllTableBuilders(&data_blocks_, &table_builders_);
|
||||
font_is.Close();
|
||||
}
|
||||
|
||||
void Font::Builder::LoadFont(WritableFontData* wfd,
|
||||
int32_t offset_to_offset_table) {
|
||||
// Note: we do not throw exception here for is. This is more of an assertion.
|
||||
assert(wfd);
|
||||
HeaderOffsetSortedSet records;
|
||||
ReadHeader(wfd, offset_to_offset_table, &records);
|
||||
LoadTableData(&records, wfd, &data_blocks_);
|
||||
BuildAllTableBuilders(&data_blocks_, &table_builders_);
|
||||
}
|
||||
|
||||
int32_t Font::Builder::SfntWrapperSize() {
|
||||
return Offset::kSfntHeaderSize +
|
||||
(Offset::kTableRecordSize * table_builders_.size());
|
||||
}
|
||||
|
||||
void Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data,
|
||||
TableBuilderMap* builder_map) {
|
||||
for (DataBlockMap::iterator record = table_data->begin(),
|
||||
record_end = table_data->end();
|
||||
record != record_end; ++record) {
|
||||
TableBuilderPtr builder;
|
||||
builder.Attach(GetTableBuilder(record->first.p_, record->second.p_));
|
||||
builder_map->insert(TableBuilderEntry(record->first->tag(), builder));
|
||||
}
|
||||
InterRelateBuilders(&table_builders_);
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
Table::Builder* Font::Builder::GetTableBuilder(Header* header,
|
||||
WritableFontData* data) {
|
||||
return Table::Builder::GetBuilder(header, data);
|
||||
}
|
||||
|
||||
void Font::Builder::BuildTablesFromBuilders(Font* font,
|
||||
TableBuilderMap* builder_map,
|
||||
TableMap* table_map) {
|
||||
UNREFERENCED_PARAMETER(font);
|
||||
InterRelateBuilders(builder_map);
|
||||
|
||||
// Now build all the tables.
|
||||
for (TableBuilderMap::iterator builder = builder_map->begin(),
|
||||
builder_end = builder_map->end();
|
||||
builder != builder_end; ++builder) {
|
||||
TablePtr table;
|
||||
if (builder->second && builder->second->ReadyToBuild()) {
|
||||
table.Attach(down_cast<Table*>(builder->second->Build()));
|
||||
}
|
||||
if (table == NULL) {
|
||||
table_map->clear();
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
std::string builder_string = "Unable to build table - ";
|
||||
char* table_name = TagToString(builder->first);
|
||||
builder_string += table_name;
|
||||
delete[] table_name;
|
||||
throw RuntimeException(builder_string.c_str());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
table_map->insert(TableMapEntry(table->header()->tag(), table));
|
||||
}
|
||||
}
|
||||
|
||||
static Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) {
|
||||
if (!builder_map)
|
||||
return NULL;
|
||||
|
||||
TableBuilderMap::iterator target = builder_map->find(tag);
|
||||
if (target == builder_map->end())
|
||||
return NULL;
|
||||
|
||||
return target->second.p_;
|
||||
}
|
||||
|
||||
// Like GetBuilder(), but the returned Builder must be able to support reads.
|
||||
static Table::Builder* GetReadBuilder(TableBuilderMap* builder_map, int32_t tag) {
|
||||
Table::Builder* builder = GetBuilder(builder_map, tag);
|
||||
if (!builder || !builder->InternalReadData())
|
||||
return NULL;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) {
|
||||
Table::Builder* raw_head_builder = GetReadBuilder(builder_map, Tag::head);
|
||||
FontHeaderTableBuilderPtr header_table_builder;
|
||||
if (raw_head_builder != NULL) {
|
||||
header_table_builder =
|
||||
down_cast<FontHeaderTable::Builder*>(raw_head_builder);
|
||||
}
|
||||
|
||||
Table::Builder* raw_hhea_builder = GetReadBuilder(builder_map, Tag::hhea);
|
||||
HorizontalHeaderTableBuilderPtr horizontal_header_builder;
|
||||
if (raw_head_builder != NULL) {
|
||||
horizontal_header_builder =
|
||||
down_cast<HorizontalHeaderTable::Builder*>(raw_hhea_builder);
|
||||
}
|
||||
|
||||
Table::Builder* raw_maxp_builder = GetReadBuilder(builder_map, Tag::maxp);
|
||||
MaximumProfileTableBuilderPtr max_profile_builder;
|
||||
if (raw_maxp_builder != NULL) {
|
||||
max_profile_builder =
|
||||
down_cast<MaximumProfileTable::Builder*>(raw_maxp_builder);
|
||||
}
|
||||
|
||||
Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca);
|
||||
LocaTableBuilderPtr loca_table_builder;
|
||||
if (raw_loca_builder != NULL) {
|
||||
loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder);
|
||||
}
|
||||
|
||||
Table::Builder* raw_hmtx_builder = GetReadBuilder(builder_map, Tag::hmtx);
|
||||
HorizontalMetricsTableBuilderPtr horizontal_metrics_builder;
|
||||
if (raw_hmtx_builder != NULL) {
|
||||
horizontal_metrics_builder =
|
||||
down_cast<HorizontalMetricsTable::Builder*>(raw_hmtx_builder);
|
||||
}
|
||||
|
||||
#if defined (SFNTLY_EXPERIMENTAL)
|
||||
Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx);
|
||||
HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder;
|
||||
if (raw_hdmx_builder != NULL) {
|
||||
hdmx_table_builder =
|
||||
down_cast<HorizontalDeviceMetricsTable::Builder*>(raw_hdmx_builder);
|
||||
}
|
||||
#endif
|
||||
|
||||
// set the inter table data required to build certain tables
|
||||
if (horizontal_metrics_builder != NULL) {
|
||||
if (max_profile_builder != NULL) {
|
||||
int32_t num_glyphs = max_profile_builder->NumGlyphs();
|
||||
if (num_glyphs >= 0)
|
||||
horizontal_metrics_builder->SetNumGlyphs(num_glyphs);
|
||||
}
|
||||
if (horizontal_header_builder != NULL) {
|
||||
int32_t num_hmetrics = horizontal_header_builder->NumberOfHMetrics();
|
||||
if (num_hmetrics >= 0)
|
||||
horizontal_metrics_builder->SetNumberOfHMetrics(num_hmetrics);
|
||||
}
|
||||
}
|
||||
|
||||
if (loca_table_builder != NULL) {
|
||||
if (max_profile_builder != NULL) {
|
||||
int32_t num_glyphs = max_profile_builder->NumGlyphs();
|
||||
if (num_glyphs >= 0)
|
||||
loca_table_builder->SetNumGlyphs(num_glyphs);
|
||||
}
|
||||
if (header_table_builder != NULL) {
|
||||
loca_table_builder->set_format_version(
|
||||
header_table_builder->IndexToLocFormat());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (SFNTLY_EXPERIMENTAL)
|
||||
// Note: In C++, hdmx_table_builder can be NULL in a subsetter.
|
||||
if (max_profile_builder != NULL && hdmx_table_builder != NULL) {
|
||||
hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Font::Builder::ReadHeader(FontInputStream* is,
|
||||
HeaderOffsetSortedSet* records) {
|
||||
assert(records);
|
||||
sfnt_version_ = is->ReadFixed();
|
||||
num_tables_ = is->ReadUShort();
|
||||
search_range_ = is->ReadUShort();
|
||||
entry_selector_ = is->ReadUShort();
|
||||
range_shift_ = is->ReadUShort();
|
||||
|
||||
for (int32_t table_number = 0; table_number < num_tables_; ++table_number) {
|
||||
// Need to use temporary vars here. C++ evaluates function parameters from
|
||||
// right to left and thus breaks the order of input stream.
|
||||
int32_t tag = is->ReadULongAsInt();
|
||||
int64_t checksum = is->ReadULong();
|
||||
int32_t offset = is->ReadULongAsInt();
|
||||
int32_t length = is->ReadULongAsInt();
|
||||
if (!IsValidHeaderRegion(is->Length(), offset, length))
|
||||
continue;
|
||||
|
||||
HeaderPtr table = new Header(tag, checksum, offset, length);
|
||||
records->insert(table);
|
||||
}
|
||||
}
|
||||
|
||||
void Font::Builder::ReadHeader(ReadableFontData* fd,
|
||||
int32_t offset,
|
||||
HeaderOffsetSortedSet* records) {
|
||||
assert(records);
|
||||
sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
|
||||
num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
|
||||
search_range_ = fd->ReadUShort(offset + Offset::kSearchRange);
|
||||
entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector);
|
||||
range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift);
|
||||
|
||||
if (num_tables_ > fd->Size() / Offset::kTableRecordSize)
|
||||
return;
|
||||
|
||||
int32_t table_offset = offset + Offset::kTableRecordBegin;
|
||||
for (int32_t table_number = 0;
|
||||
table_number < num_tables_;
|
||||
table_number++, table_offset += Offset::kTableRecordSize) {
|
||||
int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag);
|
||||
int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum);
|
||||
int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset);
|
||||
int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength);
|
||||
if (!IsValidHeaderRegion(fd->Size(), offset, length))
|
||||
continue;
|
||||
|
||||
HeaderPtr table = new Header(tag, checksum, offset, length);
|
||||
records->insert(table);
|
||||
}
|
||||
}
|
||||
|
||||
void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
|
||||
FontInputStream* is,
|
||||
DataBlockMap* table_data) {
|
||||
assert(table_data);
|
||||
for (HeaderOffsetSortedSet::iterator it = headers->begin(),
|
||||
table_end = headers->end();
|
||||
it != table_end;
|
||||
++it) {
|
||||
const Ptr<Header> header = *it;
|
||||
is->Skip(header->offset() - is->position());
|
||||
if (header->length() > kMaxTableSize)
|
||||
continue;
|
||||
|
||||
FontInputStream table_is(is, header->length());
|
||||
WritableFontDataPtr data;
|
||||
data.Attach(WritableFontData::CreateWritableFontData(header->length()));
|
||||
data->CopyFrom(&table_is, header->length());
|
||||
table_data->insert(DataBlockEntry(header, data));
|
||||
}
|
||||
}
|
||||
|
||||
void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
|
||||
WritableFontData* fd,
|
||||
DataBlockMap* table_data) {
|
||||
for (HeaderOffsetSortedSet::iterator it = headers->begin(),
|
||||
table_end = headers->end();
|
||||
it != table_end;
|
||||
++it) {
|
||||
const Ptr<Header> header = *it;
|
||||
if (header->length() > kMaxTableSize)
|
||||
continue;
|
||||
|
||||
FontDataPtr sliced_data;
|
||||
sliced_data.Attach(fd->Slice(header->offset(), header->length()));
|
||||
WritableFontDataPtr data = down_cast<WritableFontData*>(sliced_data.p_);
|
||||
table_data->insert(DataBlockEntry(header, data));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,352 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_FONT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/endian.h"
|
||||
#include "sfntly/data/font_input_stream.h"
|
||||
#include "sfntly/data/font_output_stream.h"
|
||||
#include "sfntly/data/writable_font_data.h"
|
||||
#include "sfntly/table/table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// Note: following constants are embedded in Font class in Java. They are
|
||||
// extracted out for easier reference from other classes. Offset is the
|
||||
// one that is kept within class.
|
||||
// Platform ids. These are used in a number of places within the font whenever
|
||||
// the platform needs to be specified.
|
||||
struct PlatformId {
|
||||
enum {
|
||||
kUnknown = -1,
|
||||
kUnicode = 0,
|
||||
kMacintosh = 1,
|
||||
kISO = 2,
|
||||
kWindows = 3,
|
||||
kCustom = 4
|
||||
};
|
||||
};
|
||||
|
||||
// Unicode encoding ids. These are used in a number of places within the font
|
||||
// whenever character encodings need to be specified.
|
||||
struct UnicodeEncodingId {
|
||||
enum {
|
||||
kUnknown = -1,
|
||||
kUnicode1_0 = 0,
|
||||
kUnicode1_1 = 1,
|
||||
kISO10646 = 2,
|
||||
kUnicode2_0_BMP = 3,
|
||||
kUnicode2_0 = 4,
|
||||
kUnicodeVariationSequences = 5
|
||||
};
|
||||
};
|
||||
|
||||
// Windows encoding ids. These are used in a number of places within the font
|
||||
// whenever character encodings need to be specified.
|
||||
struct WindowsEncodingId {
|
||||
enum {
|
||||
kUnknown = 0xffffffff,
|
||||
kSymbol = 0,
|
||||
kUnicodeUCS2 = 1,
|
||||
kShiftJIS = 2,
|
||||
kPRC = 3,
|
||||
kBig5 = 4,
|
||||
kWansung = 5,
|
||||
kJohab = 6,
|
||||
kUnicodeUCS4 = 10
|
||||
};
|
||||
};
|
||||
|
||||
// Macintosh encoding ids. These are used in a number of places within the
|
||||
// font whenever character encodings need to be specified.
|
||||
struct MacintoshEncodingId {
|
||||
// Macintosh Platform Encodings
|
||||
enum {
|
||||
kUnknown = -1,
|
||||
kRoman = 0,
|
||||
kJapanese = 1,
|
||||
kChineseTraditional = 2,
|
||||
kKorean = 3,
|
||||
kArabic = 4,
|
||||
kHebrew = 5,
|
||||
kGreek = 6,
|
||||
kRussian = 7,
|
||||
kRSymbol = 8,
|
||||
kDevanagari = 9,
|
||||
kGurmukhi = 10,
|
||||
kGujarati = 11,
|
||||
kOriya = 12,
|
||||
kBengali = 13,
|
||||
kTamil = 14,
|
||||
kTelugu = 15,
|
||||
kKannada = 16,
|
||||
kMalayalam = 17,
|
||||
kSinhalese = 18,
|
||||
kBurmese = 19,
|
||||
kKhmer = 20,
|
||||
kThai = 21,
|
||||
kLaotian = 22,
|
||||
kGeorgian = 23,
|
||||
kArmenian = 24,
|
||||
kChineseSimplified = 25,
|
||||
kTibetan = 26,
|
||||
kMongolian = 27,
|
||||
kGeez = 28,
|
||||
kSlavic = 29,
|
||||
kVietnamese = 30,
|
||||
kSindhi = 31,
|
||||
kUninterpreted = 32
|
||||
};
|
||||
};
|
||||
|
||||
class FontFactory;
|
||||
|
||||
// An sfnt container font object. This object is immutable and thread safe. To
|
||||
// construct one use an instance of Font::Builder.
|
||||
class Font : public RefCounted<Font> {
|
||||
public:
|
||||
// A builder for a font object. The builder allows the for the creation of
|
||||
// immutable Font objects. The builder is a one use non-thread safe object and
|
||||
// once the Font object has been created it is no longer usable. To create a
|
||||
// further Font object new builder will be required.
|
||||
class Builder : public RefCounted<Builder> {
|
||||
public:
|
||||
virtual ~Builder();
|
||||
|
||||
static CALLER_ATTACH Builder*
|
||||
GetOTFBuilder(FontFactory* factory, InputStream* is);
|
||||
static CALLER_ATTACH Builder*
|
||||
GetOTFBuilder(FontFactory* factory,
|
||||
WritableFontData* ba,
|
||||
int32_t offset_to_offset_table);
|
||||
static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory);
|
||||
|
||||
// Get the font factory that created this font builder.
|
||||
FontFactory* GetFontFactory() { return factory_; }
|
||||
|
||||
// Is the font ready to build?
|
||||
bool ReadyToBuild();
|
||||
|
||||
// Build the Font. After this call this builder will no longer be usable.
|
||||
CALLER_ATTACH Font* Build();
|
||||
|
||||
// Set a unique fingerprint for the font object.
|
||||
void SetDigest(std::vector<uint8_t>* digest);
|
||||
|
||||
// Clear all table builders.
|
||||
void ClearTableBuilders();
|
||||
|
||||
// Does this font builder have the specified table builder.
|
||||
bool HasTableBuilder(int32_t tag);
|
||||
|
||||
// Get the table builder for the given tag. If there is no builder for that
|
||||
// tag then return a null.
|
||||
Table::Builder* GetTableBuilder(int32_t tag);
|
||||
|
||||
// Creates a new table builder for the table type given by the table id tag.
|
||||
// This new table has been added to the font and will replace any existing
|
||||
// builder for that table.
|
||||
// @return new empty table of the type specified by tag; if tag is not known
|
||||
// then a generic OpenTypeTable is returned
|
||||
virtual Table::Builder* NewTableBuilder(int32_t tag);
|
||||
|
||||
// Creates a new table builder for the table type given by the table id tag.
|
||||
// It makes a copy of the data provided and uses that copy for the table.
|
||||
// This new table has been added to the font and will replace any existing
|
||||
// builder for that table.
|
||||
virtual Table::Builder* NewTableBuilder(int32_t tag,
|
||||
ReadableFontData* src_data);
|
||||
|
||||
// Get a map of the table builders in this font builder accessed by table
|
||||
// tag.
|
||||
virtual TableBuilderMap* table_builders() { return &table_builders_; }
|
||||
|
||||
// Remove the specified table builder from the font builder.
|
||||
// Note: different from Java: we don't return object in removeTableBuilder
|
||||
virtual void RemoveTableBuilder(int32_t tag);
|
||||
|
||||
// Get the number of table builders in the font builder.
|
||||
virtual int32_t number_of_table_builders() {
|
||||
return (int32_t)table_builders_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Builder(FontFactory* factory);
|
||||
virtual void LoadFont(InputStream* is);
|
||||
virtual void LoadFont(WritableFontData* wfd,
|
||||
int32_t offset_to_offset_table);
|
||||
int32_t SfntWrapperSize();
|
||||
void BuildAllTableBuilders(DataBlockMap* table_data,
|
||||
TableBuilderMap* builder_map);
|
||||
CALLER_ATTACH Table::Builder*
|
||||
GetTableBuilder(Header* header, WritableFontData* data);
|
||||
void BuildTablesFromBuilders(Font* font,
|
||||
TableBuilderMap* builder_map,
|
||||
TableMap* tables);
|
||||
static void InterRelateBuilders(TableBuilderMap* builder_map);
|
||||
|
||||
void ReadHeader(FontInputStream* is,
|
||||
HeaderOffsetSortedSet* records);
|
||||
|
||||
void ReadHeader(ReadableFontData* fd,
|
||||
int32_t offset,
|
||||
HeaderOffsetSortedSet* records);
|
||||
|
||||
void LoadTableData(HeaderOffsetSortedSet* headers,
|
||||
FontInputStream* is,
|
||||
DataBlockMap* table_data);
|
||||
|
||||
void LoadTableData(HeaderOffsetSortedSet* headers,
|
||||
WritableFontData* fd,
|
||||
DataBlockMap* table_data);
|
||||
|
||||
TableBuilderMap table_builders_;
|
||||
FontFactory* factory_; // dumb pointer, avoid circular refcounting
|
||||
int32_t sfnt_version_;
|
||||
int32_t num_tables_;
|
||||
int32_t search_range_;
|
||||
int32_t entry_selector_;
|
||||
int32_t range_shift_;
|
||||
DataBlockMap data_blocks_;
|
||||
std::vector<uint8_t> digest_;
|
||||
};
|
||||
|
||||
virtual ~Font();
|
||||
|
||||
// Gets the sfnt version set in the sfnt wrapper of the font.
|
||||
int32_t sfnt_version() { return sfnt_version_; }
|
||||
|
||||
// Gets a copy of the fonts digest that was created when the font was read. If
|
||||
// no digest was set at creation time then the return result will be null.
|
||||
std::vector<uint8_t>* digest() { return &digest_; }
|
||||
|
||||
// Get the checksum for this font.
|
||||
int64_t checksum() { return checksum_; }
|
||||
|
||||
// Get the number of tables in this font.
|
||||
int32_t num_tables() { return (int32_t)tables_.size(); }
|
||||
|
||||
// Whether the font has a particular table.
|
||||
bool HasTable(int32_t tag) const;
|
||||
|
||||
// UNIMPLEMENTED: public Iterator<? extends Table> iterator
|
||||
|
||||
// Get the table in this font with the specified id.
|
||||
// @param tag the identifier of the table
|
||||
// @return the table specified if it exists; null otherwise
|
||||
// C++ port: rename table() to GetTable()
|
||||
Table* GetTable(int32_t tag);
|
||||
|
||||
// Get a map of the tables in this font accessed by table tag.
|
||||
// @return an unmodifiable view of the tables in this font
|
||||
// Note: renamed tableMap() to GetTableMap()
|
||||
const TableMap* GetTableMap();
|
||||
|
||||
// UNIMPLEMENTED: toString()
|
||||
|
||||
// Serialize the font to the output stream.
|
||||
// @param os the destination for the font serialization
|
||||
// @param tableOrdering the table ordering to apply
|
||||
void Serialize(OutputStream* os, std::vector<int32_t>* table_ordering);
|
||||
|
||||
private:
|
||||
// Offsets to specific elements in the underlying data. These offsets are
|
||||
// relative to the start of the table or the start of sub-blocks within the
|
||||
// table.
|
||||
struct Offset {
|
||||
enum {
|
||||
// Offsets within the main directory
|
||||
kSfntVersion = 0,
|
||||
kNumTables = 4,
|
||||
kSearchRange = 6,
|
||||
kEntrySelector = 8,
|
||||
kRangeShift = 10,
|
||||
kTableRecordBegin = 12,
|
||||
kSfntHeaderSize = 12,
|
||||
|
||||
// Offsets within a specific table record
|
||||
kTableTag = 0,
|
||||
kTableCheckSum = 4,
|
||||
kTableOffset = 8,
|
||||
kTableLength = 12,
|
||||
kTableRecordSize = 16
|
||||
};
|
||||
};
|
||||
|
||||
// Note: the two constants are moved to tag.h to avoid VC++ bug.
|
||||
// static const int32_t CFF_TABLE_ORDERING[];
|
||||
// static const int32_t TRUE_TYPE_TABLE_ORDERING[];
|
||||
|
||||
// Constructor.
|
||||
// @param sfntVersion the sfnt version
|
||||
// @param digest the computed digest for the font; null if digest was not
|
||||
// computed
|
||||
// Note: Current C++ port does not support SHA digest validation.
|
||||
Font(int32_t sfnt_version, std::vector<uint8_t>* digest);
|
||||
|
||||
// Build the table headers to be used for serialization. These headers will be
|
||||
// filled out with the data required for serialization. The headers will be
|
||||
// sorted in the order specified and only those specified will have headers
|
||||
// generated.
|
||||
// @param tableOrdering the tables to generate headers for and the order to
|
||||
// sort them
|
||||
// @return a list of table headers ready for serialization
|
||||
void BuildTableHeadersForSerialization(std::vector<int32_t>* table_ordering,
|
||||
TableHeaderList* table_headers);
|
||||
|
||||
// Searialize the headers.
|
||||
// @param fos the destination stream for the headers
|
||||
// @param tableHeaders the headers to serialize
|
||||
// @throws IOException
|
||||
void SerializeHeader(FontOutputStream* fos, TableHeaderList* table_headers);
|
||||
|
||||
// Serialize the tables.
|
||||
// @param fos the destination stream for the headers
|
||||
// @param tableHeaders the headers for the tables to serialize
|
||||
// @throws IOException
|
||||
void SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers);
|
||||
|
||||
// Generate the full table ordering to used for serialization. The full
|
||||
// ordering uses the partial ordering as a seed and then adds all remaining
|
||||
// tables in the font in an undefined order.
|
||||
// @param defaultTableOrdering the partial ordering to be used as a seed for
|
||||
// the full ordering
|
||||
// @param (out) table_ordering the full ordering for serialization
|
||||
void GenerateTableOrdering(std::vector<int32_t>* default_table_ordering,
|
||||
std::vector<int32_t>* table_ordering);
|
||||
|
||||
// Get the default table ordering based on the type of the font.
|
||||
// @param (out) default_table_ordering the default table ordering
|
||||
void DefaultTableOrdering(std::vector<int32_t>* default_table_ordering);
|
||||
|
||||
int32_t sfnt_version_;
|
||||
std::vector<uint8_t> digest_;
|
||||
int64_t checksum_;
|
||||
TableMap tables_;
|
||||
};
|
||||
typedef Ptr<Font> FontPtr;
|
||||
typedef std::vector<FontPtr> FontArray;
|
||||
typedef Ptr<Font::Builder> FontBuilderPtr;
|
||||
typedef std::vector<FontBuilderPtr> FontBuilderArray;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_H_
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/font_factory.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sfntly/tag.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
FontFactory::~FontFactory() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontFactory* FontFactory::GetInstance() {
|
||||
FontFactoryPtr instance = new FontFactory();
|
||||
return instance.Detach();
|
||||
}
|
||||
|
||||
void FontFactory::FingerprintFont(bool fingerprint) {
|
||||
fingerprint_ = fingerprint;
|
||||
}
|
||||
|
||||
bool FontFactory::FingerprintFont() {
|
||||
return fingerprint_;
|
||||
}
|
||||
|
||||
void FontFactory::LoadFonts(InputStream* is, FontArray* output) {
|
||||
assert(output);
|
||||
PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
|
||||
if (IsCollection(pbis)) {
|
||||
LoadCollection(pbis, output);
|
||||
return;
|
||||
}
|
||||
FontPtr font;
|
||||
font.Attach(LoadSingleOTF(pbis));
|
||||
if (font) {
|
||||
output->push_back(font);
|
||||
}
|
||||
}
|
||||
|
||||
void FontFactory::LoadFonts(std::vector<uint8_t>* b, FontArray* output) {
|
||||
WritableFontDataPtr wfd;
|
||||
wfd.Attach(WritableFontData::CreateWritableFontData(b));
|
||||
if (IsCollection(wfd)) {
|
||||
LoadCollection(wfd, output);
|
||||
return;
|
||||
}
|
||||
FontPtr font;
|
||||
font.Attach(LoadSingleOTF(wfd));
|
||||
if (font) {
|
||||
output->push_back(font);
|
||||
}
|
||||
}
|
||||
|
||||
void FontFactory::LoadFontsForBuilding(InputStream* is,
|
||||
FontBuilderArray* output) {
|
||||
PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
|
||||
if (IsCollection(pbis)) {
|
||||
LoadCollectionForBuilding(pbis, output);
|
||||
return;
|
||||
}
|
||||
FontBuilderPtr builder;
|
||||
builder.Attach(LoadSingleOTFForBuilding(pbis));
|
||||
if (builder) {
|
||||
output->push_back(builder);
|
||||
}
|
||||
}
|
||||
|
||||
void FontFactory::LoadFontsForBuilding(std::vector<uint8_t>* b,
|
||||
FontBuilderArray* output) {
|
||||
WritableFontDataPtr wfd;
|
||||
wfd.Attach(WritableFontData::CreateWritableFontData(b));
|
||||
if (IsCollection(wfd)) {
|
||||
LoadCollectionForBuilding(wfd, output);
|
||||
return;
|
||||
}
|
||||
FontBuilderPtr builder;
|
||||
builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
|
||||
if (builder) {
|
||||
output->push_back(builder);
|
||||
}
|
||||
}
|
||||
|
||||
void FontFactory::SerializeFont(Font* font, OutputStream* os) {
|
||||
std::vector<int32_t> table_ordering;
|
||||
font->Serialize(os, &table_ordering);
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() {
|
||||
return Font::Builder::GetOTFBuilder(this);
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) {
|
||||
FontBuilderPtr builder;
|
||||
builder.Attach(LoadSingleOTFForBuilding(is));
|
||||
return builder->Build();
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
|
||||
FontBuilderPtr builder;
|
||||
builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
|
||||
return builder->Build();
|
||||
}
|
||||
|
||||
void FontFactory::LoadCollection(InputStream* is, FontArray* output) {
|
||||
FontBuilderArray ba;
|
||||
LoadCollectionForBuilding(is, &ba);
|
||||
output->reserve(ba.size());
|
||||
for (FontBuilderArray::iterator builder = ba.begin(), builders_end = ba.end();
|
||||
builder != builders_end; ++builder) {
|
||||
FontPtr font;
|
||||
font.Attach((*builder)->Build());
|
||||
output->push_back(font);
|
||||
}
|
||||
}
|
||||
|
||||
void FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) {
|
||||
FontBuilderArray builders;
|
||||
LoadCollectionForBuilding(wfd, &builders);
|
||||
output->reserve(builders.size());
|
||||
for (FontBuilderArray::iterator builder = builders.begin(),
|
||||
builders_end = builders.end();
|
||||
builder != builders_end; ++builder) {
|
||||
FontPtr font;
|
||||
font.Attach((*builder)->Build());
|
||||
output->push_back(font);
|
||||
}
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
Font::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) {
|
||||
// UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
|
||||
Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is);
|
||||
// UNIMPLEMENTED: setDigest
|
||||
return builder;
|
||||
}
|
||||
|
||||
CALLER_ATTACH Font::Builder*
|
||||
FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd,
|
||||
int32_t offset_to_offset_table) {
|
||||
// UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
|
||||
Font::Builder* builder =
|
||||
Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table);
|
||||
// UNIMPLEMENTED: setDigest
|
||||
return builder;
|
||||
}
|
||||
|
||||
void FontFactory::LoadCollectionForBuilding(InputStream* is,
|
||||
FontBuilderArray* builders) {
|
||||
assert(is);
|
||||
assert(builders);
|
||||
WritableFontDataPtr wfd;
|
||||
wfd.Attach(WritableFontData::CreateWritableFontData(is->Available()));
|
||||
wfd->CopyFrom(is);
|
||||
LoadCollectionForBuilding(wfd, builders);
|
||||
}
|
||||
|
||||
void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd,
|
||||
FontBuilderArray* builders) {
|
||||
int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag);
|
||||
UNREFERENCED_PARAMETER(ttc_tag);
|
||||
int32_t version = wfd->ReadFixed(Offset::kVersion);
|
||||
UNREFERENCED_PARAMETER(version);
|
||||
int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts);
|
||||
if (num_fonts < 0)
|
||||
return;
|
||||
if (num_fonts > wfd->Length() / 4)
|
||||
return;
|
||||
|
||||
builders->reserve(num_fonts);
|
||||
int32_t offset_table_offset = Offset::kOffsetTable;
|
||||
for (int32_t font_number = 0;
|
||||
font_number < num_fonts;
|
||||
font_number++, offset_table_offset += DataSize::kULONG) {
|
||||
int32_t offset = wfd->ReadULongAsInt(offset_table_offset);
|
||||
if (offset < 0 || offset >= wfd->Length())
|
||||
continue;
|
||||
|
||||
FontBuilderPtr builder;
|
||||
builder.Attach(LoadSingleOTFForBuilding(wfd, offset));
|
||||
builders->push_back(builder);
|
||||
}
|
||||
}
|
||||
|
||||
bool FontFactory::IsCollection(PushbackInputStream* pbis) {
|
||||
std::vector<uint8_t> tag(4);
|
||||
pbis->Read(&tag);
|
||||
pbis->Unread(&tag);
|
||||
return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]);
|
||||
}
|
||||
|
||||
bool FontFactory::IsCollection(ReadableFontData* rfd) {
|
||||
std::vector<uint8_t> tag(4);
|
||||
rfd->ReadBytes(0, &(tag[0]), 0, tag.size());
|
||||
return Tag::ttcf ==
|
||||
GenerateTag(tag[0], tag[1], tag[2], tag[3]);
|
||||
}
|
||||
|
||||
FontFactory::FontFactory()
|
||||
: fingerprint_(false) {
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sfntly/port/refcount.h"
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/font.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class FontFactory : public RefCounted<FontFactory> {
|
||||
public:
|
||||
virtual ~FontFactory();
|
||||
|
||||
// Factory method for the construction of a font factory.
|
||||
static CALLER_ATTACH FontFactory* GetInstance();
|
||||
|
||||
// Toggle whether fonts that are loaded are fingerprinted with a SHA-1 hash.
|
||||
// If a font is fingerprinted then a SHA-1 hash is generated at load time and
|
||||
// stored in the font. This is useful for uniquely identifying fonts. By
|
||||
// default this is turned on.
|
||||
// @param fingerprint whether fingerprinting should be turned on or off
|
||||
// TODO(arthurhsu): IMPLEMENT: C++ port currently don't do any SHA-1
|
||||
void FingerprintFont(bool fingerprint);
|
||||
bool FingerprintFont();
|
||||
|
||||
// Load the font(s) from the input stream. The current settings on the factory
|
||||
// are used during the loading process. One or more fonts are returned if the
|
||||
// stream contains valid font data. Some font container formats may have more
|
||||
// than one font and in this case multiple font objects will be returned. If
|
||||
// the data in the stream cannot be parsed or is invalid an array of size zero
|
||||
// will be returned.
|
||||
void LoadFonts(InputStream* is, FontArray* output);
|
||||
|
||||
// ByteArray font loading
|
||||
// Load the font(s) from the byte array. The current settings on the factory
|
||||
// are used during the loading process. One or more fonts are returned if the
|
||||
// stream contains valid font data. Some font container formats may have more
|
||||
// than one font and in this case multiple font objects will be returned. If
|
||||
// the data in the stream cannot be parsed or is invalid an array of size zero
|
||||
// will be returned.
|
||||
void LoadFonts(std::vector<uint8_t>* b, FontArray* output);
|
||||
|
||||
// Load the font(s) from the input stream into font builders. The current
|
||||
// settings on the factory are used during the loading process. One or more
|
||||
// font builders are returned if the stream contains valid font data. Some
|
||||
// font container formats may have more than one font and in this case
|
||||
// multiple font builder objects will be returned. If the data in the stream
|
||||
// cannot be parsed or is invalid an array of size zero will be returned.
|
||||
void LoadFontsForBuilding(InputStream* is, FontBuilderArray* output);
|
||||
|
||||
// Load the font(s) from the byte array into font builders. The current
|
||||
// settings on the factory are used during the loading process. One or more
|
||||
// font builders are returned if the stream contains valid font data. Some
|
||||
// font container formats may have more than one font and in this case
|
||||
// multiple font builder objects will be returned. If the data in the stream
|
||||
// cannot be parsed or is invalid an array of size zero will be returned.
|
||||
void LoadFontsForBuilding(std::vector<uint8_t>* b, FontBuilderArray* output);
|
||||
|
||||
// Font serialization
|
||||
// Serialize the font to the output stream.
|
||||
// NOTE: in this port we attempted not to implement I/O stream because dealing
|
||||
// with cross-platform I/O stream itself is big enough as a project.
|
||||
// Byte buffer it is.
|
||||
void SerializeFont(Font* font, OutputStream* os);
|
||||
|
||||
// Get an empty font builder for creating a new font from scratch.
|
||||
CALLER_ATTACH Font::Builder* NewFontBuilder();
|
||||
|
||||
private:
|
||||
// Offsets to specific elements in the underlying data. These offsets are
|
||||
// relative to the start of the table or the start of sub-blocks within the
|
||||
// table.
|
||||
struct Offset {
|
||||
enum {
|
||||
// Offsets within the main directory.
|
||||
kTTCTag = 0,
|
||||
kVersion = 4,
|
||||
kNumFonts = 8,
|
||||
kOffsetTable = 12,
|
||||
|
||||
// TTC Version 2.0 extensions.
|
||||
// Offsets from end of OffsetTable.
|
||||
kulDsigTag = 0,
|
||||
kulDsigLength = 4,
|
||||
kulDsigOffset = 8
|
||||
};
|
||||
};
|
||||
|
||||
FontFactory();
|
||||
|
||||
CALLER_ATTACH Font* LoadSingleOTF(InputStream* is);
|
||||
CALLER_ATTACH Font* LoadSingleOTF(WritableFontData* wfd);
|
||||
|
||||
void LoadCollection(InputStream* is, FontArray* output);
|
||||
void LoadCollection(WritableFontData* wfd, FontArray* output);
|
||||
|
||||
CALLER_ATTACH Font::Builder* LoadSingleOTFForBuilding(InputStream* is);
|
||||
CALLER_ATTACH Font::Builder*
|
||||
LoadSingleOTFForBuilding(WritableFontData* wfd,
|
||||
int32_t offset_to_offset_table);
|
||||
|
||||
void LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders);
|
||||
void LoadCollectionForBuilding(WritableFontData* ba,
|
||||
FontBuilderArray* builders);
|
||||
|
||||
static bool IsCollection(PushbackInputStream* pbis);
|
||||
static bool IsCollection(ReadableFontData* wfd);
|
||||
|
||||
bool fingerprint_;
|
||||
};
|
||||
typedef Ptr<FontFactory> FontFactoryPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class Fixed1616 {
|
||||
public:
|
||||
static inline int32_t Integral(int32_t fixed) {
|
||||
return (fixed >> 16);
|
||||
}
|
||||
|
||||
static inline int32_t Fractional(int32_t fixed) {
|
||||
return (fixed & 0xffff);
|
||||
}
|
||||
|
||||
static inline int32_t Fixed(int32_t integral, int32_t fractional) {
|
||||
return ((integral & 0xffff) << 16) | (fractional & 0xffff);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class FontMath {
|
||||
public:
|
||||
static int32_t Log2(int32_t a) {
|
||||
int r = 0; // r will be lg(a)
|
||||
while (a != 0) {
|
||||
a >>= 1;
|
||||
r++;
|
||||
}
|
||||
return r - 1;
|
||||
}
|
||||
|
||||
// Calculates the amount of padding needed. The values provided need to be in
|
||||
// the same units. So, if the size is given as the number of bytes then the
|
||||
// alignment size must also be specified as byte size to align to.
|
||||
// @param size the size of the data that may need padding
|
||||
// @param alignmentSize the number of units to align to
|
||||
// @return the number of units needing to be added for alignment
|
||||
static int32_t PaddingRequired(int32_t size, int32_t alignment_size) {
|
||||
int32_t padding = alignment_size - (size % alignment_size);
|
||||
return padding == alignment_size ? 0 : padding;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static inline size_t AtomicIncrement(size_t* address) {
|
||||
#if defined (_WIN64)
|
||||
return InterlockedIncrement64(reinterpret_cast<LONGLONG*>(address));
|
||||
#else
|
||||
return InterlockedIncrement(reinterpret_cast<LONG*>(address));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline size_t AtomicDecrement(size_t* address) {
|
||||
#if defined (_WIN64)
|
||||
return InterlockedDecrement64(reinterpret_cast<LONGLONG*>(address));
|
||||
#else
|
||||
return InterlockedDecrement(reinterpret_cast<LONG*>(address));
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined (__APPLE__)
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
static inline size_t AtomicIncrement(size_t* address) {
|
||||
return OSAtomicIncrement32Barrier(reinterpret_cast<int32_t*>(address));
|
||||
}
|
||||
|
||||
static inline size_t AtomicDecrement(size_t* address) {
|
||||
return OSAtomicDecrement32Barrier(reinterpret_cast<int32_t*>(address));
|
||||
}
|
||||
|
||||
// Originally we check __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4, however, there are
|
||||
// issues that clang not carring over this definition. Therefore we boldly
|
||||
// assume it's gcc or gcc-compatible here. Compilation shall still fail since
|
||||
// the intrinsics used are GCC-specific.
|
||||
|
||||
#else
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
static inline size_t AtomicIncrement(size_t* address) {
|
||||
return __sync_add_and_fetch(address, 1);
|
||||
}
|
||||
|
||||
static inline size_t AtomicDecrement(size_t* address) {
|
||||
return __sync_sub_and_fetch(address, 1);
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_
|
||||
|
||||
#if !defined(SFNTLY_BIG_ENDIAN) && !defined(SFNTLY_LITTLE_ENDIAN)
|
||||
#if defined (__ppc__) || defined (__ppc64__)
|
||||
#define SFNTLY_BIG_ENDIAN
|
||||
#else
|
||||
#define SFNTLY_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_
|
||||
|
||||
#include "sfntly/port/config.h"
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
static inline uint16_t EndianSwap16(uint16_t value) {
|
||||
return (uint16_t)((value >> 8) | (value << 8));
|
||||
}
|
||||
|
||||
static inline int32_t EndianSwap32(int32_t value) {
|
||||
return (((value & 0x000000ff) << 24) |
|
||||
((value & 0x0000ff00) << 8) |
|
||||
((value & 0x00ff0000) >> 8) |
|
||||
((value & 0xff000000) >> 24));
|
||||
}
|
||||
|
||||
static inline uint64_t EndianSwap64(uint64_t value) {
|
||||
return (((value & 0x00000000000000ffLL) << 56) |
|
||||
((value & 0x000000000000ff00LL) << 40) |
|
||||
((value & 0x0000000000ff0000LL) << 24) |
|
||||
((value & 0x00000000ff000000LL) << 8) |
|
||||
((value & 0x000000ff00000000LL) >> 8) |
|
||||
((value & 0x0000ff0000000000LL) >> 24) |
|
||||
((value & 0x00ff000000000000LL) >> 40) |
|
||||
((value & 0xff00000000000000LL) >> 56));
|
||||
}
|
||||
|
||||
#ifdef SFNTLY_LITTLE_ENDIAN
|
||||
#define ToBE16(n) EndianSwap16(n)
|
||||
#define ToBE32(n) EndianSwap32(n)
|
||||
#define ToBE64(n) EndianSwap64(n)
|
||||
#define ToLE16(n) (n)
|
||||
#define ToLE32(n) (n)
|
||||
#define ToLE64(n) (n)
|
||||
#define FromBE16(n) EndianSwap16(n)
|
||||
#define FromBE32(n) EndianSwap32(n)
|
||||
#define FromBE64(n) EndianSwap64(n)
|
||||
#define FromLE16(n) (n)
|
||||
#define FromLE32(n) (n)
|
||||
#define FromLE64(n) (n)
|
||||
#else // SFNTLY_BIG_ENDIAN
|
||||
#define ToBE16(n) (n)
|
||||
#define ToBE32(n) (n)
|
||||
#define ToBE64(n) (n)
|
||||
#define ToLE16(n) EndianSwap16(n)
|
||||
#define ToLE32(n) EndianSwap32(n)
|
||||
#define ToLE64(n) EndianSwap64(n)
|
||||
#define FromBE16(n) (n)
|
||||
#define FromBE32(n) (n)
|
||||
#define FromBE64(n) (n)
|
||||
#define FromLE16(n) EndianSwap16(n)
|
||||
#define FromLE32(n) EndianSwap32(n)
|
||||
#define FromLE64(n) EndianSwap64(n)
|
||||
#endif
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
// Exceptions used in sfntly
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_
|
||||
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class Exception : public std::exception {
|
||||
public:
|
||||
Exception() : what_("Unknown exception") {}
|
||||
explicit Exception(const char* message) throw() { SetMessage(message); }
|
||||
virtual ~Exception() throw() {}
|
||||
virtual const char* what() const throw() { return what_.c_str(); }
|
||||
|
||||
protected:
|
||||
void SetMessage(const char* message) throw() {
|
||||
try {
|
||||
what_ = message;
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string what_;
|
||||
};
|
||||
|
||||
class IndexOutOfBoundException : public Exception {
|
||||
public:
|
||||
IndexOutOfBoundException() throw() : Exception("Index out of bound") {}
|
||||
explicit IndexOutOfBoundException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
IndexOutOfBoundException(const char* message, int32_t index) throw() {
|
||||
try {
|
||||
std::ostringstream msg;
|
||||
msg << message;
|
||||
msg << ":";
|
||||
msg << index;
|
||||
SetMessage(msg.str().c_str());
|
||||
} catch (...) {}
|
||||
}
|
||||
virtual ~IndexOutOfBoundException() throw() {}
|
||||
};
|
||||
|
||||
class IOException : public Exception {
|
||||
public:
|
||||
IOException() throw() : Exception("I/O exception") {}
|
||||
explicit IOException(const char* message) throw() : Exception(message) {}
|
||||
virtual ~IOException() throw() {}
|
||||
};
|
||||
|
||||
class ArithmeticException : public Exception {
|
||||
public:
|
||||
ArithmeticException() throw() : Exception("Arithmetic exception") {}
|
||||
explicit ArithmeticException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~ArithmeticException() throw() {}
|
||||
};
|
||||
|
||||
class UnsupportedOperationException : public Exception {
|
||||
public:
|
||||
UnsupportedOperationException() throw() :
|
||||
Exception("Operation not supported") {}
|
||||
explicit UnsupportedOperationException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~UnsupportedOperationException() throw() {}
|
||||
};
|
||||
|
||||
class RuntimeException : public Exception {
|
||||
public:
|
||||
RuntimeException() throw() : Exception("Runtime exception") {}
|
||||
explicit RuntimeException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~RuntimeException() throw() {}
|
||||
};
|
||||
|
||||
class NoSuchElementException : public Exception {
|
||||
public:
|
||||
NoSuchElementException() throw() : Exception("No such element") {}
|
||||
explicit NoSuchElementException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~NoSuchElementException() throw() {}
|
||||
};
|
||||
|
||||
class IllegalArgumentException : public Exception {
|
||||
public:
|
||||
IllegalArgumentException() throw() : Exception("Illegal argument") {}
|
||||
explicit IllegalArgumentException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~IllegalArgumentException() throw() {}
|
||||
};
|
||||
|
||||
class IllegalStateException : public Exception {
|
||||
public:
|
||||
IllegalStateException() throw() : Exception("Illegal state") {}
|
||||
explicit IllegalStateException(const char* message) throw()
|
||||
: Exception(message) {}
|
||||
virtual ~IllegalStateException() throw() {}
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // #if !defined (SFNTLY_NO_EXCEPTION)
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_
|
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "sfntly/port/file_input_stream.h"
|
||||
#include "sfntly/port/exception_type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
FileInputStream::FileInputStream()
|
||||
: file_(NULL),
|
||||
position_(0),
|
||||
length_(0) {
|
||||
}
|
||||
|
||||
FileInputStream::~FileInputStream() {
|
||||
Close();
|
||||
}
|
||||
|
||||
int32_t FileInputStream::Length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
int32_t FileInputStream::Available() {
|
||||
return length_ - position_;
|
||||
}
|
||||
|
||||
void FileInputStream::Close() {
|
||||
if (file_) {
|
||||
fclose(file_);
|
||||
length_ = 0;
|
||||
position_ = 0;
|
||||
file_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FileInputStream::Mark(int32_t readlimit) {
|
||||
// NOP
|
||||
UNREFERENCED_PARAMETER(readlimit);
|
||||
}
|
||||
|
||||
bool FileInputStream::MarkSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t FileInputStream::Read() {
|
||||
if (!file_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no opened file");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (feof(file_)) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("eof reached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
uint8_t value = 0;
|
||||
size_t length = fread(&value, 1, 1, file_);
|
||||
position_ += length;
|
||||
return value;
|
||||
}
|
||||
|
||||
int32_t FileInputStream::Read(std::vector<uint8_t>* b) {
|
||||
return Read(b, 0, b->size());
|
||||
}
|
||||
|
||||
int32_t FileInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
|
||||
assert(b);
|
||||
if (!file_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no opened file");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (feof(file_)) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("eof reached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
size_t read_count = std::min<size_t>(length_ - position_, length);
|
||||
if (b->size() < (size_t)(offset + read_count)) {
|
||||
b->resize((size_t)(offset + read_count));
|
||||
}
|
||||
int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_);
|
||||
position_ += actual_read;
|
||||
return actual_read;
|
||||
}
|
||||
|
||||
void FileInputStream::Reset() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
int64_t FileInputStream::Skip(int64_t n) {
|
||||
if (!file_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no opened file");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int64_t skip_count = 0;
|
||||
if (n < 0) { // move backwards
|
||||
skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
|
||||
position_ -= (size_t)(0 - skip_count);
|
||||
fseek(file_, position_, SEEK_SET);
|
||||
} else {
|
||||
skip_count = std::min<size_t>(length_ - position_, (size_t)n);
|
||||
position_ += (size_t)skip_count;
|
||||
fseek(file_, (size_t)skip_count, SEEK_CUR);
|
||||
}
|
||||
return skip_count;
|
||||
}
|
||||
|
||||
void FileInputStream::Unread(std::vector<uint8_t>* b) {
|
||||
Unread(b, 0, b->size());
|
||||
}
|
||||
|
||||
void FileInputStream::Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
|
||||
assert(b);
|
||||
assert(b->size() >= size_t(offset + length));
|
||||
if (!file_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no opened file");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
size_t unread_count = std::min<size_t>(position_, length);
|
||||
fseek(file_, position_ - unread_count, SEEK_SET);
|
||||
position_ -= unread_count;
|
||||
Read(b, offset, length);
|
||||
fseek(file_, position_ - unread_count, SEEK_SET);
|
||||
position_ -= unread_count;
|
||||
}
|
||||
|
||||
bool FileInputStream::Open(const char* file_path) {
|
||||
assert(file_path);
|
||||
if (file_) {
|
||||
Close();
|
||||
}
|
||||
#if defined (WIN32)
|
||||
fopen_s(&file_, file_path, "rb");
|
||||
#else
|
||||
file_ = fopen(file_path, "rb");
|
||||
#endif
|
||||
if (file_ == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(file_, 0, SEEK_END);
|
||||
length_ = ftell(file_);
|
||||
fseek(file_, 0, SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sfntly/port/input_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class FileInputStream : public PushbackInputStream {
|
||||
public:
|
||||
FileInputStream();
|
||||
virtual ~FileInputStream();
|
||||
|
||||
// InputStream methods
|
||||
virtual int32_t Length();
|
||||
virtual int32_t Available();
|
||||
virtual void Close();
|
||||
virtual void Mark(int32_t readlimit);
|
||||
virtual bool MarkSupported();
|
||||
virtual int32_t Read();
|
||||
virtual int32_t Read(std::vector<uint8_t>* b);
|
||||
virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length);
|
||||
virtual void Reset();
|
||||
virtual int64_t Skip(int64_t n);
|
||||
|
||||
// PushbackInputStream methods
|
||||
virtual void Unread(std::vector<uint8_t>* b);
|
||||
virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length);
|
||||
|
||||
// Own methods
|
||||
virtual bool Open(const char* file_path);
|
||||
|
||||
private:
|
||||
FILE* file_;
|
||||
size_t position_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// C++ equivalent to Java's OutputStream class
|
||||
class InputStream {
|
||||
public:
|
||||
virtual int32_t Length() = 0;
|
||||
virtual int32_t Available() = 0;
|
||||
virtual void Close() = 0;
|
||||
virtual void Mark(int32_t readlimit) = 0;
|
||||
virtual bool MarkSupported() = 0;
|
||||
virtual int32_t Read() = 0;
|
||||
virtual int32_t Read(std::vector<uint8_t>* b) = 0;
|
||||
virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) = 0;
|
||||
virtual void Reset() = 0;
|
||||
virtual int64_t Skip(int64_t n) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~InputStream() {}
|
||||
};
|
||||
|
||||
class PushbackInputStream : public InputStream {
|
||||
public:
|
||||
virtual void Unread(std::vector<uint8_t>* b) = 0;
|
||||
virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) = 0;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_
|
||||
|
||||
#include "sfntly/port/refcount.h"
|
||||
|
||||
// Interface of Java iterator.
|
||||
// This is a forward read-only iterator that represents java.util.Iterator<E>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
template <typename ReturnType, typename ContainerBase>
|
||||
class Iterator : public virtual RefCount {
|
||||
public:
|
||||
virtual ~Iterator() {}
|
||||
virtual ContainerBase* container_base() = 0;
|
||||
|
||||
protected:
|
||||
Iterator() {}
|
||||
NO_COPY_AND_ASSIGN(Iterator);
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename Container,
|
||||
typename ContainerBase = Container>
|
||||
class PODIterator : public Iterator<ReturnType, ContainerBase>,
|
||||
public RefCounted< PODIterator<ReturnType, Container> > {
|
||||
public:
|
||||
explicit PODIterator(Container* container) : container_(container) {}
|
||||
virtual ~PODIterator() {}
|
||||
virtual ContainerBase* container_base() {
|
||||
return static_cast<ContainerBase*>(container_);
|
||||
}
|
||||
|
||||
virtual bool HasNext() = 0;
|
||||
virtual ReturnType Next() = 0;
|
||||
virtual void Remove() {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
// Default to no support.
|
||||
throw UnsupportedOperationException();
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
Container* container() { return container_; }
|
||||
|
||||
private:
|
||||
Container* container_; // Dumb pointer is used to avoid circular ref-counting
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename Container,
|
||||
typename ContainerBase = Container>
|
||||
class RefIterator : public Iterator<ReturnType, ContainerBase>,
|
||||
public RefCounted< RefIterator<ReturnType, Container> > {
|
||||
public:
|
||||
explicit RefIterator(Container* container) : container_(container) {}
|
||||
virtual ~RefIterator() {}
|
||||
virtual ContainerBase* container_base() {
|
||||
return static_cast<ContainerBase*>(container_);
|
||||
}
|
||||
|
||||
virtual bool HasNext() = 0;
|
||||
CALLER_ATTACH virtual ReturnType* Next() = 0;
|
||||
virtual void Remove() {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
// Default to no support.
|
||||
throw UnsupportedOperationException();
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
Container* container() { return container_; }
|
||||
|
||||
private:
|
||||
Container* container_; // Dumb pointer is used to avoid circular ref-counting
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/port/lock.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
Lock::Lock() {
|
||||
// The second parameter is the spin count, for short-held locks it avoid the
|
||||
// contending thread from going to sleep which helps performance greatly.
|
||||
::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000);
|
||||
}
|
||||
|
||||
Lock::~Lock() {
|
||||
::DeleteCriticalSection(&os_lock_);
|
||||
}
|
||||
|
||||
bool Lock::Try() {
|
||||
if (::TryEnterCriticalSection(&os_lock_) != FALSE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Lock::Acquire() {
|
||||
::EnterCriticalSection(&os_lock_);
|
||||
}
|
||||
|
||||
void Lock::Unlock() {
|
||||
::LeaveCriticalSection(&os_lock_);
|
||||
}
|
||||
|
||||
#else // We assume it's pthread
|
||||
|
||||
Lock::Lock() {
|
||||
pthread_mutex_init(&os_lock_, NULL);
|
||||
}
|
||||
|
||||
Lock::~Lock() {
|
||||
pthread_mutex_destroy(&os_lock_);
|
||||
}
|
||||
|
||||
bool Lock::Try() {
|
||||
return (pthread_mutex_trylock(&os_lock_) == 0);
|
||||
}
|
||||
|
||||
void Lock::Acquire() {
|
||||
pthread_mutex_lock(&os_lock_);
|
||||
}
|
||||
|
||||
void Lock::Unlock() {
|
||||
pthread_mutex_unlock(&os_lock_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <windows.h>
|
||||
#else // Assume pthread.
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
#if defined (WIN32)
|
||||
typedef CRITICAL_SECTION OSLockType;
|
||||
#else // Assume pthread.
|
||||
typedef pthread_mutex_t OSLockType;
|
||||
#endif
|
||||
|
||||
class Lock {
|
||||
public:
|
||||
Lock();
|
||||
~Lock();
|
||||
|
||||
// If the lock is not held, take it and return true. If the lock is already
|
||||
// held by something else, immediately return false.
|
||||
bool Try();
|
||||
|
||||
// Take the lock, blocking until it is available if necessary.
|
||||
void Acquire();
|
||||
|
||||
// Release the lock. This must only be called by the lock's holder: after
|
||||
// a successful call to Try, or a call to Lock.
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
OSLockType os_lock_;
|
||||
NO_COPY_AND_ASSIGN(Lock);
|
||||
};
|
||||
|
||||
// A helper class that acquires the given Lock while the AutoLock is in scope.
|
||||
class AutoLock {
|
||||
public:
|
||||
explicit AutoLock(Lock& lock) : lock_(lock) {
|
||||
lock_.Acquire();
|
||||
}
|
||||
|
||||
~AutoLock() {
|
||||
lock_.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Lock& lock_;
|
||||
NO_COPY_AND_ASSIGN(AutoLock);
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_LOGGING_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_LOGGING_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Cheap base/logging.h knock off.
|
||||
|
||||
#define CHECK(expr) \
|
||||
if (!(expr)) { \
|
||||
printf("CHECK failed\n"); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_LOGGING_H_
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "sfntly/port/memory_input_stream.h"
|
||||
#include "sfntly/port/exception_type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
MemoryInputStream::MemoryInputStream()
|
||||
: buffer_(NULL),
|
||||
position_(0),
|
||||
length_(0) {
|
||||
}
|
||||
|
||||
MemoryInputStream::~MemoryInputStream() {
|
||||
Close();
|
||||
}
|
||||
|
||||
int32_t MemoryInputStream::Length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
int32_t MemoryInputStream::Available() {
|
||||
return length_ - position_;
|
||||
}
|
||||
|
||||
void MemoryInputStream::Close() {
|
||||
}
|
||||
|
||||
void MemoryInputStream::Mark(int32_t readlimit) {
|
||||
// NOP
|
||||
UNREFERENCED_PARAMETER(readlimit);
|
||||
}
|
||||
|
||||
bool MemoryInputStream::MarkSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t MemoryInputStream::Read() {
|
||||
if (!buffer_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no memory attached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (position_ >= length_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("eof reached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
uint8_t value = buffer_[position_++];
|
||||
return value;
|
||||
}
|
||||
|
||||
int32_t MemoryInputStream::Read(std::vector<uint8_t>* b) {
|
||||
return Read(b, 0, b->size());
|
||||
}
|
||||
|
||||
int32_t MemoryInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
|
||||
assert(b);
|
||||
if (!buffer_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no memory attached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (position_ >= length_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("eof reached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
size_t read_count = std::min<size_t>(length_ - position_, length);
|
||||
if (b->size() < (size_t)(offset + read_count)) {
|
||||
b->resize((size_t)(offset + read_count));
|
||||
}
|
||||
memcpy(&((*b)[offset]), buffer_ + position_, read_count);
|
||||
position_ += read_count;
|
||||
return read_count;
|
||||
}
|
||||
|
||||
void MemoryInputStream::Reset() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
int64_t MemoryInputStream::Skip(int64_t n) {
|
||||
if (!buffer_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no memory attached");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int64_t skip_count = 0;
|
||||
if (n < 0) { // move backwards
|
||||
skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
|
||||
position_ -= (size_t)(0 - skip_count);
|
||||
} else {
|
||||
skip_count = std::min<size_t>(length_ - position_, (size_t)n);
|
||||
position_ += (size_t)skip_count;
|
||||
}
|
||||
return skip_count;
|
||||
}
|
||||
|
||||
void MemoryInputStream::Unread(std::vector<uint8_t>* b) {
|
||||
Unread(b, 0, b->size());
|
||||
}
|
||||
|
||||
void MemoryInputStream::Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
|
||||
assert(b);
|
||||
assert(b->size() >= size_t(offset + length));
|
||||
if (!buffer_) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IOException("no memory attached");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
size_t unread_count = std::min<size_t>(position_, length);
|
||||
position_ -= unread_count;
|
||||
Read(b, offset, length);
|
||||
position_ -= unread_count;
|
||||
}
|
||||
|
||||
bool MemoryInputStream::Attach(const uint8_t* buffer, size_t length) {
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
buffer_ = buffer;
|
||||
length_ = length;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sfntly/port/input_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class MemoryInputStream : public PushbackInputStream {
|
||||
public:
|
||||
MemoryInputStream();
|
||||
virtual ~MemoryInputStream();
|
||||
|
||||
// InputStream methods
|
||||
virtual int32_t Length();
|
||||
virtual int32_t Available();
|
||||
virtual void Close();
|
||||
virtual void Mark(int32_t readlimit);
|
||||
virtual bool MarkSupported();
|
||||
virtual int32_t Read();
|
||||
virtual int32_t Read(std::vector<uint8_t>* b);
|
||||
virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length);
|
||||
virtual void Reset();
|
||||
virtual int64_t Skip(int64_t n);
|
||||
|
||||
// PushbackInputStream methods
|
||||
virtual void Unread(std::vector<uint8_t>* b);
|
||||
virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length);
|
||||
|
||||
// Own methods
|
||||
virtual bool Attach(const uint8_t* buffer, size_t length);
|
||||
|
||||
private:
|
||||
const uint8_t* buffer_;
|
||||
size_t position_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/port/memory_output_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream() {
|
||||
}
|
||||
|
||||
MemoryOutputStream::~MemoryOutputStream() {
|
||||
}
|
||||
|
||||
void MemoryOutputStream::Write(std::vector<uint8_t>* buffer) {
|
||||
store_.insert(store_.end(), buffer->begin(), buffer->end());
|
||||
}
|
||||
|
||||
void MemoryOutputStream::Write(std::vector<uint8_t>* buffer,
|
||||
int32_t offset,
|
||||
int32_t length) {
|
||||
assert(buffer);
|
||||
if (offset >= 0 && length > 0) {
|
||||
store_.insert(store_.end(),
|
||||
buffer->begin() + offset,
|
||||
buffer->begin() + offset + length);
|
||||
} else {
|
||||
#if !defined(SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryOutputStream::Write(uint8_t* buffer, int32_t offset, int32_t length) {
|
||||
assert(buffer);
|
||||
if (offset >= 0 && length > 0) {
|
||||
store_.insert(store_.end(), buffer + offset, buffer + offset + length);
|
||||
} else {
|
||||
#if !defined(SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryOutputStream::Write(uint8_t b) {
|
||||
store_.push_back(b);
|
||||
}
|
||||
|
||||
uint8_t* MemoryOutputStream::Get() {
|
||||
if (store_.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return &(store_[0]);
|
||||
}
|
||||
|
||||
size_t MemoryOutputStream::Size() {
|
||||
return store_.size();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
#include "sfntly/port/output_stream.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// OutputStream backed by STL vector
|
||||
|
||||
class MemoryOutputStream : public OutputStream {
|
||||
public:
|
||||
MemoryOutputStream();
|
||||
virtual ~MemoryOutputStream();
|
||||
|
||||
virtual void Close() {} // no-op
|
||||
virtual void Flush() {} // no-op
|
||||
virtual void Write(std::vector<uint8_t>* buffer);
|
||||
virtual void Write(std::vector<uint8_t>* buffer, int32_t offset, int32_t length);
|
||||
virtual void Write(uint8_t* buffer, int32_t offset, int32_t length);
|
||||
virtual void Write(uint8_t b);
|
||||
|
||||
uint8_t* Get();
|
||||
size_t Size();
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> store_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_
|
||||
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// C++ equivalent to Java's OutputStream class
|
||||
class OutputStream {
|
||||
public:
|
||||
// Make gcc -Wnon-virtual-dtor happy.
|
||||
virtual ~OutputStream() {}
|
||||
|
||||
virtual void Close() = 0;
|
||||
virtual void Flush() = 0;
|
||||
virtual void Write(std::vector<uint8_t>* buffer) = 0;
|
||||
virtual void Write(uint8_t b) = 0;
|
||||
|
||||
// Note: C++ port offered both versions of Write() here. The first one is
|
||||
// better because it does check bounds. The second one is there for
|
||||
// performance concerns.
|
||||
virtual void Write(std::vector<uint8_t>* buffer, int32_t offset, int32_t length) = 0;
|
||||
|
||||
// Note: Caller is responsible for the boundary of buffer.
|
||||
virtual void Write(uint8_t* buffer, int32_t offset, int32_t length) = 0;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
// Object reference count and smart pointer implementation.
|
||||
|
||||
// Smart pointer usage in sfntly:
|
||||
//
|
||||
// sfntly carries a smart pointer implementation like COM. Ref-countable object
|
||||
// type inherits from RefCounted<>, which have AddRef and Release just like
|
||||
// IUnknown (but no QueryInterface). Use a Ptr<> based smart pointer to hold
|
||||
// the object so that the object ref count is handled correctly.
|
||||
//
|
||||
// class Foo : public RefCounted<Foo> {
|
||||
// public:
|
||||
// static Foo* CreateInstance() {
|
||||
// Ptr<Foo> obj = new Foo(); // ref count = 1
|
||||
// return obj.Detach();
|
||||
// }
|
||||
// };
|
||||
// typedef Ptr<Foo> FooPtr; // common short-hand notation
|
||||
// FooPtr obj;
|
||||
// obj.Attach(Foo::CreatedInstance()); // ref count = 1
|
||||
// {
|
||||
// FooPtr obj2 = obj; // ref count = 2
|
||||
// } // ref count = 1, obj2 out of scope
|
||||
// obj.Release(); // ref count = 0, object destroyed
|
||||
|
||||
// Notes on usage:
|
||||
// 1. Virtual inherit from RefCount interface in base class if smart pointers
|
||||
// are going to be defined.
|
||||
// 2. All RefCounted objects must be instantiated on the heap. Allocating the
|
||||
// object on stack will cause crash.
|
||||
// 3. Be careful when you have complex inheritance. For example,
|
||||
// class A : public RefCounted<A>;
|
||||
// class B : public A, public RefCounted<B>;
|
||||
// In this case the smart pointer is pretty dumb and don't count on it to
|
||||
// nicely destroy your objects as designed. Try refactor your code like
|
||||
// class I; // the common interface and implementations
|
||||
// class A : public I, public RefCounted<A>; // A specific implementation
|
||||
// class B : public I, public RefCounted<B>; // B specific implementation
|
||||
// 4. Smart pointers here are very bad candidates for function parameters. Use
|
||||
// dumb pointers in function parameter list.
|
||||
// 5. When down_cast is performed on a dangling pointer due to bugs in code,
|
||||
// VC++ will generate SEH which is not handled well in VC++ debugger. One
|
||||
// can use WinDBG to run it and get the faulting stack.
|
||||
// 6. Idioms for heap object as return value
|
||||
// Foo* createFoo() { FooPtr obj = new Foo(); return obj.Detach(); }
|
||||
// Foo* passthru() { FooPtr obj = createFoo(), return obj; }
|
||||
// FooPtr end_scope_pointer;
|
||||
// end_scope_pointer.Attach(passThrough);
|
||||
// If you are not passing that object back, you are the end of scope.
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_
|
||||
|
||||
#if !defined (NDEBUG)
|
||||
#define ENABLE_OBJECT_COUNTER
|
||||
// #define REF_COUNT_DEBUGGING
|
||||
#endif
|
||||
|
||||
#if defined (REF_COUNT_DEBUGGING)
|
||||
#include <stdio.h>
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include "sfntly/port/atomic.h"
|
||||
#include "sfntly/port/type.h"
|
||||
|
||||
// Special tag for functions that requires caller to attach instead of using
|
||||
// assignment operators.
|
||||
#define CALLER_ATTACH
|
||||
|
||||
#if defined (REF_COUNT_DEBUGGING)
|
||||
#define DEBUG_OUTPUT(a) \
|
||||
fprintf(stderr, "%s%s:oc=%d,oid=%d,rc=%d\n", a, \
|
||||
typeid(this).name(), object_counter_, object_id_, ref_count_)
|
||||
#else
|
||||
#define DEBUG_OUTPUT(a)
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
// VC 2008/2010 incorrectly gives this warning for pure virtual functions
|
||||
// in virtual inheritance. The only way to get around it is to disable it.
|
||||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
bool TestSmartPointer();
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
template <typename T>
|
||||
class Ptr;
|
||||
|
||||
class RefCount {
|
||||
public:
|
||||
// Make gcc -Wnon-virtual-dtor happy.
|
||||
virtual ~RefCount() {}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class Ptr;
|
||||
|
||||
virtual size_t AddRef() const = 0;
|
||||
virtual size_t Release() const = 0;
|
||||
};
|
||||
|
||||
template <typename TDerived>
|
||||
class RefCounted : virtual public RefCount {
|
||||
public:
|
||||
RefCounted() : ref_count_(0) {
|
||||
#if defined (ENABLE_OBJECT_COUNTER)
|
||||
object_id_ = AtomicIncrement(&next_id_);
|
||||
AtomicIncrement(&object_counter_);
|
||||
DEBUG_OUTPUT("C ");
|
||||
#endif
|
||||
}
|
||||
RefCounted(const RefCounted<TDerived>&) : ref_count_(0) {}
|
||||
virtual ~RefCounted() {
|
||||
#if defined (ENABLE_OBJECT_COUNTER)
|
||||
AtomicDecrement(&object_counter_);
|
||||
DEBUG_OUTPUT("D ");
|
||||
#endif
|
||||
}
|
||||
|
||||
RefCounted<TDerived>& operator=(const RefCounted<TDerived>&) {
|
||||
// Each object maintains own ref count, don't propagate.
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual size_t AddRef() const {
|
||||
size_t new_count = AtomicIncrement(&ref_count_);
|
||||
DEBUG_OUTPUT("A ");
|
||||
return new_count;
|
||||
}
|
||||
|
||||
virtual size_t Release() const {
|
||||
size_t new_ref_count = AtomicDecrement(&ref_count_);
|
||||
DEBUG_OUTPUT("R ");
|
||||
if (new_ref_count == 0) {
|
||||
// A C-style is used to cast away const-ness and to derived.
|
||||
// lint does not like this but this is how it works.
|
||||
delete (TDerived*)(this);
|
||||
}
|
||||
return new_ref_count;
|
||||
}
|
||||
|
||||
mutable size_t ref_count_; // reference count of current object
|
||||
friend bool ::TestSmartPointer();
|
||||
#if defined (ENABLE_OBJECT_COUNTER)
|
||||
static size_t object_counter_;
|
||||
static size_t next_id_;
|
||||
mutable size_t object_id_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined (ENABLE_OBJECT_COUNTER)
|
||||
template <typename TDerived> size_t RefCounted<TDerived>::object_counter_ = 0;
|
||||
template <typename TDerived> size_t RefCounted<TDerived>::next_id_ = 0;
|
||||
#endif
|
||||
|
||||
// semi-smart pointer for RefCount derived objects, similar to CComPtr
|
||||
template <typename T>
|
||||
class Ptr {
|
||||
public:
|
||||
Ptr() : p_(NULL) {
|
||||
}
|
||||
|
||||
// This constructor shall not be explicit.
|
||||
// lint does not like this but this is how it works.
|
||||
Ptr(T* pT) : p_(NULL) {
|
||||
*this = pT;
|
||||
}
|
||||
|
||||
Ptr(const Ptr<T>& p) : p_(NULL) {
|
||||
*this = p;
|
||||
}
|
||||
|
||||
~Ptr() {
|
||||
Release();
|
||||
}
|
||||
|
||||
T* operator=(T* pT) {
|
||||
if (p_ == pT) {
|
||||
return p_;
|
||||
}
|
||||
if (pT) {
|
||||
RefCount* p = static_cast<RefCount*>(pT);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p->AddRef(); // always AddRef() before Release()
|
||||
}
|
||||
Release();
|
||||
p_ = pT;
|
||||
return p_;
|
||||
}
|
||||
|
||||
T* operator=(const Ptr<T>& p) {
|
||||
if (p_ == p.p_) {
|
||||
return p_;
|
||||
}
|
||||
return operator=(p.p_);
|
||||
}
|
||||
|
||||
operator T*&() {
|
||||
return p_;
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
return *p_; // It can throw!
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
return p_; // It can throw!
|
||||
}
|
||||
|
||||
bool operator!() const {
|
||||
return (p_ == NULL);
|
||||
}
|
||||
|
||||
bool operator<(const Ptr<T>& p) const {
|
||||
return (p_ < p.p_);
|
||||
}
|
||||
|
||||
bool operator!=(T* pT) const {
|
||||
return !operator==(pT);
|
||||
}
|
||||
|
||||
bool operator==(T* pT) const {
|
||||
return (p_ == pT);
|
||||
}
|
||||
|
||||
size_t Release() const {
|
||||
size_t ref_count = 0;
|
||||
if (p_) {
|
||||
RefCount* p = static_cast<RefCount*>(p_);
|
||||
if (p) {
|
||||
ref_count = p->Release();
|
||||
}
|
||||
p_ = NULL;
|
||||
}
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
void Attach(T* pT) {
|
||||
if (p_ != pT) {
|
||||
Release();
|
||||
p_ = pT;
|
||||
}
|
||||
}
|
||||
|
||||
T* Detach() {
|
||||
T* pT = p_;
|
||||
p_ = NULL;
|
||||
return pT;
|
||||
}
|
||||
|
||||
mutable T* p_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// deprecated
|
||||
typedef uint8_t byte_t;
|
||||
typedef uint16_t word_t;
|
||||
typedef uint32_t dword_t;
|
||||
typedef uint64_t qword_t;
|
||||
typedef std::vector<uint8_t> ByteVector;
|
||||
typedef std::vector<int32_t> IntegerList;
|
||||
typedef std::set<int32_t> IntegerSet;
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions.
|
||||
// This should be used in the private: declarations for a class.
|
||||
#define NO_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
// Make google3 happy since it prohibits RTTI.
|
||||
template<typename To, typename From>
|
||||
inline To implicit_cast(From const &f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
||||
inline To down_cast(From* f) { // so we only accept pointers
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
#if defined (_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) // disable "conditional expression is constant"
|
||||
#endif
|
||||
if (false) {
|
||||
implicit_cast<From*, To>(0);
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// The following code is the only place for RTTI. It is done so to allow
|
||||
// additional type checking when SFNTLY_TYPE_VERIFICATION is defined.
|
||||
#if defined (SFNTLY_TYPE_VERIFICATION)
|
||||
assert(f == NULL || dynamic_cast<To>(f) != NULL);
|
||||
#endif
|
||||
return static_cast<To>(f);
|
||||
}
|
||||
|
||||
#if !defined(WIN32)
|
||||
#define UNREFERENCED_PARAMETER(p) do { (void)p; } while (0)
|
||||
#endif
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/big_glyph_metrics.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* BigGlyphMetrics class
|
||||
******************************************************************************/
|
||||
BigGlyphMetrics::BigGlyphMetrics(ReadableFontData* data)
|
||||
: GlyphMetrics(data) {
|
||||
}
|
||||
|
||||
BigGlyphMetrics::~BigGlyphMetrics() {
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Height() {
|
||||
return data_->ReadByte(Offset::kHeight);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Width() {
|
||||
return data_->ReadByte(Offset::kWidth);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::HoriBearingX() {
|
||||
return data_->ReadByte(Offset::kHoriBearingX);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::HoriBearingY() {
|
||||
return data_->ReadByte(Offset::kHoriBearingY);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::HoriAdvance() {
|
||||
return data_->ReadByte(Offset::kHoriAdvance);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::VertBearingX() {
|
||||
return data_->ReadByte(Offset::kVertBearingX);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::VertBearingY() {
|
||||
return data_->ReadByte(Offset::kVertBearingY);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::VertAdvance() {
|
||||
return data_->ReadByte(Offset::kVertAdvance);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* BigGlyphMetrics::Builder class
|
||||
******************************************************************************/
|
||||
BigGlyphMetrics::Builder::Builder(WritableFontData* data)
|
||||
: GlyphMetrics::Builder(data) {
|
||||
}
|
||||
|
||||
BigGlyphMetrics::Builder::Builder(ReadableFontData* data)
|
||||
: GlyphMetrics::Builder(data) {
|
||||
}
|
||||
|
||||
BigGlyphMetrics::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::Height() {
|
||||
return InternalReadData()->ReadByte(Offset::kHeight);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetHeight(uint8_t height) {
|
||||
InternalWriteData()->WriteByte(Offset::kHeight, height);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::Width() {
|
||||
return InternalReadData()->ReadByte(Offset::kWidth);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetWidth(uint8_t width) {
|
||||
InternalWriteData()->WriteByte(Offset::kWidth, width);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::HoriBearingX() {
|
||||
return InternalReadData()->ReadByte(Offset::kHoriBearingX);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetHoriBearingX(uint8_t bearing) {
|
||||
InternalWriteData()->WriteByte(Offset::kHoriBearingX, bearing);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::HoriBearingY() {
|
||||
return InternalReadData()->ReadByte(Offset::kHoriBearingY);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetHoriBearingY(uint8_t bearing) {
|
||||
InternalWriteData()->WriteByte(Offset::kHoriBearingY, bearing);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::HoriAdvance() {
|
||||
return InternalReadData()->ReadByte(Offset::kHoriAdvance);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetHoriAdvance(uint8_t advance) {
|
||||
InternalWriteData()->WriteByte(Offset::kHoriAdvance, advance);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::VertBearingX() {
|
||||
return InternalReadData()->ReadByte(Offset::kVertBearingX);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetVertBearingX(uint8_t bearing) {
|
||||
InternalWriteData()->WriteByte(Offset::kVertBearingX, bearing);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::VertBearingY() {
|
||||
return InternalReadData()->ReadByte(Offset::kVertBearingY);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetVertBearingY(uint8_t bearing) {
|
||||
InternalWriteData()->WriteByte(Offset::kVertBearingY, bearing);
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::VertAdvance() {
|
||||
return InternalReadData()->ReadByte(Offset::kVertAdvance);
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SetVertAdvance(uint8_t advance) {
|
||||
InternalWriteData()->WriteByte(Offset::kVertAdvance, advance);
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable*
|
||||
BigGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void BigGlyphMetrics::Builder::SubDataSet() {
|
||||
// NOP.
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::SubDataSizeToSerialize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BigGlyphMetrics::Builder::SubReadyToSerialize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t BigGlyphMetrics::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
return Data()->CopyTo(new_data);
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH
|
||||
BigGlyphMetrics::Builder* BigGlyphMetrics::Builder::CreateBuilder() {
|
||||
WritableFontDataPtr data;
|
||||
data.Attach(WritableFontData::CreateWritableFontData(Offset::kMetricsLength));
|
||||
BigGlyphMetricsBuilderPtr output = new BigGlyphMetrics::Builder(data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_
|
||||
|
||||
#include "sfntly/table/bitmap/glyph_metrics.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class BigGlyphMetrics : public GlyphMetrics,
|
||||
public RefCounted<BigGlyphMetrics> {
|
||||
public:
|
||||
struct Offset {
|
||||
enum {
|
||||
kMetricsLength = 8,
|
||||
|
||||
kHeight = 0,
|
||||
kWidth = 1,
|
||||
kHoriBearingX = 2,
|
||||
kHoriBearingY = 3,
|
||||
kHoriAdvance = 4,
|
||||
kVertBearingX = 5,
|
||||
kVertBearingY = 6,
|
||||
kVertAdvance = 7,
|
||||
};
|
||||
};
|
||||
|
||||
class Builder : public GlyphMetrics::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
// Constructor scope altered to public because C++ does not allow base
|
||||
// class to instantiate derived class with protected constructors.
|
||||
explicit Builder(WritableFontData* data);
|
||||
explicit Builder(ReadableFontData* data);
|
||||
|
||||
virtual ~Builder();
|
||||
|
||||
int32_t Height();
|
||||
void SetHeight(uint8_t height);
|
||||
int32_t Width();
|
||||
void SetWidth(uint8_t width);
|
||||
int32_t HoriBearingX();
|
||||
void SetHoriBearingX(uint8_t bearing);
|
||||
int32_t HoriBearingY();
|
||||
void SetHoriBearingY(uint8_t bearing);
|
||||
int32_t HoriAdvance();
|
||||
void SetHoriAdvance(uint8_t advance);
|
||||
int32_t VertBearingX();
|
||||
void SetVertBearingX(uint8_t bearing);
|
||||
int32_t VertBearingY();
|
||||
void SetVertBearingY(uint8_t bearing);
|
||||
int32_t VertAdvance();
|
||||
void SetVertAdvance(uint8_t advance);
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
// Static instantiation function.
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
};
|
||||
|
||||
explicit BigGlyphMetrics(ReadableFontData* data);
|
||||
virtual ~BigGlyphMetrics();
|
||||
|
||||
int32_t Height();
|
||||
int32_t Width();
|
||||
int32_t HoriBearingX();
|
||||
int32_t HoriBearingY();
|
||||
int32_t HoriAdvance();
|
||||
int32_t VertBearingX();
|
||||
int32_t VertBearingY();
|
||||
int32_t VertAdvance();
|
||||
};
|
||||
typedef Ptr<BigGlyphMetrics> BigGlyphMetricsPtr;
|
||||
typedef Ptr<BigGlyphMetrics::Builder> BigGlyphMetricsBuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/bitmap_glyph.h"
|
||||
#include "sfntly/table/bitmap/simple_bitmap_glyph.h"
|
||||
#include "sfntly/table/bitmap/composite_bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* BitmapGlyph class
|
||||
******************************************************************************/
|
||||
BitmapGlyph::~BitmapGlyph() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyph* BitmapGlyph::CreateGlyph(ReadableFontData* data,
|
||||
int32_t format) {
|
||||
BitmapGlyphPtr glyph;
|
||||
BitmapGlyphBuilderPtr builder;
|
||||
builder.Attach(Builder::CreateGlyphBuilder(data, format));
|
||||
if (builder) {
|
||||
glyph.Attach(down_cast<BitmapGlyph*>(builder->Build()));
|
||||
}
|
||||
return glyph;
|
||||
}
|
||||
|
||||
BitmapGlyph::BitmapGlyph(ReadableFontData* data, int32_t format)
|
||||
: SubTable(data), format_(format) {
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* BitmapGlyph::Builder class
|
||||
******************************************************************************/
|
||||
BitmapGlyph::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyph::Builder*
|
||||
BitmapGlyph::Builder::CreateGlyphBuilder(ReadableFontData* data,
|
||||
int32_t format) {
|
||||
BitmapGlyphBuilderPtr builder;
|
||||
switch (format) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
builder = new SimpleBitmapGlyph::Builder(data, format);
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
builder = new CompositeBitmapGlyph::Builder(data, format);
|
||||
break;
|
||||
}
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
BitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format)
|
||||
: SubTable::Builder(data), format_(format) {
|
||||
}
|
||||
|
||||
BitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format)
|
||||
: SubTable::Builder(data), format_(format) {
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
FontDataTable* BitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void BitmapGlyph::Builder::SubDataSet() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
int32_t BitmapGlyph::Builder::SubDataSizeToSerialize() {
|
||||
return InternalReadData()->Length();
|
||||
}
|
||||
|
||||
bool BitmapGlyph::Builder::SubReadyToSerialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t BitmapGlyph::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
return InternalReadData()->CopyTo(new_data);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "sfntly/table/subtable.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class BitmapGlyph : public SubTable {
|
||||
public:
|
||||
struct Offset {
|
||||
enum {
|
||||
// header
|
||||
kVersion = 0,
|
||||
|
||||
kSmallGlyphMetricsLength = 5,
|
||||
kBigGlyphMetricsLength = 8,
|
||||
// format 1
|
||||
kGlyphFormat1_imageData = kSmallGlyphMetricsLength,
|
||||
|
||||
// format 2
|
||||
kGlyphFormat2_imageData = kSmallGlyphMetricsLength,
|
||||
|
||||
// format 3
|
||||
|
||||
// format 4
|
||||
|
||||
// format 5
|
||||
kGlyphFormat5_imageData = 0,
|
||||
|
||||
// format 6
|
||||
kGlyphFormat6_imageData = kBigGlyphMetricsLength,
|
||||
|
||||
// format 7
|
||||
kGlyphFormat7_imageData = kBigGlyphMetricsLength,
|
||||
|
||||
// format 8
|
||||
kGlyphFormat8_numComponents = kSmallGlyphMetricsLength + 1,
|
||||
kGlyphFormat8_componentArray = kGlyphFormat8_numComponents +
|
||||
DataSize::kUSHORT,
|
||||
|
||||
// format 9
|
||||
kGlyphFormat9_numComponents = kBigGlyphMetricsLength,
|
||||
kGlyphFormat9_componentArray = kGlyphFormat9_numComponents +
|
||||
DataSize::kUSHORT,
|
||||
|
||||
// ebdtComponent
|
||||
kEbdtComponentLength = DataSize::kUSHORT + 2 * DataSize::kCHAR,
|
||||
kEbdtComponent_glyphCode = 0,
|
||||
kEbdtComponent_xOffset = 2,
|
||||
kEbdtComponent_yOffset = 3,
|
||||
};
|
||||
};
|
||||
|
||||
// TODO(stuartg): builder is not functional at all
|
||||
// - need to add subclasses for each type of bitmap glyph
|
||||
class Builder : public SubTable::Builder {
|
||||
public:
|
||||
virtual ~Builder();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
int32_t format() { return format_; }
|
||||
|
||||
static CALLER_ATTACH Builder* CreateGlyphBuilder(ReadableFontData* data,
|
||||
int32_t format);
|
||||
|
||||
protected:
|
||||
Builder(WritableFontData* data, int32_t format);
|
||||
Builder(ReadableFontData* data, int32_t format);
|
||||
|
||||
private:
|
||||
int32_t format_;
|
||||
};
|
||||
|
||||
virtual ~BitmapGlyph();
|
||||
|
||||
static CALLER_ATTACH BitmapGlyph* CreateGlyph(ReadableFontData* data,
|
||||
int32_t format);
|
||||
int32_t format() { return format_; }
|
||||
|
||||
// UNIMPLEMENTED: toString()
|
||||
|
||||
protected:
|
||||
BitmapGlyph(ReadableFontData* data, int32_t format);
|
||||
|
||||
private:
|
||||
int32_t format_;
|
||||
};
|
||||
typedef Ptr<BitmapGlyph> BitmapGlyphPtr;
|
||||
typedef Ptr<BitmapGlyph::Builder> BitmapGlyphBuilderPtr;
|
||||
typedef std::map<int32_t, BitmapGlyphBuilderPtr> BitmapGlyphBuilderMap;
|
||||
typedef std::vector<BitmapGlyphBuilderMap> BitmapGlyphBuilderList;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/bitmap_glyph_info.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
|
||||
int32_t block_offset,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t format)
|
||||
: glyph_id_(glyph_id),
|
||||
relative_(true),
|
||||
block_offset_(block_offset),
|
||||
start_offset_(start_offset),
|
||||
length_(length),
|
||||
format_(format) {
|
||||
}
|
||||
|
||||
BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t format)
|
||||
: glyph_id_(glyph_id),
|
||||
relative_(false),
|
||||
block_offset_(0),
|
||||
start_offset_(start_offset),
|
||||
length_(length),
|
||||
format_(format) {
|
||||
}
|
||||
|
||||
bool BitmapGlyphInfo::operator==(const BitmapGlyphInfo& rhs) const {
|
||||
return (format_ == rhs.format_ &&
|
||||
glyph_id_ == rhs.glyph_id_ &&
|
||||
length_ == rhs.length_ &&
|
||||
offset() == rhs.offset());
|
||||
}
|
||||
|
||||
bool BitmapGlyphInfo::operator==(BitmapGlyphInfo* rhs) {
|
||||
if (rhs == NULL) {
|
||||
return false; // Well defined C++ code's this is always not null.
|
||||
}
|
||||
return (format_ == rhs->format() &&
|
||||
glyph_id_ == rhs->glyph_id() &&
|
||||
length_ == rhs->length() &&
|
||||
offset() == rhs->offset());
|
||||
}
|
||||
|
||||
bool StartOffsetComparator::operator()(BitmapGlyphInfo* lhs,
|
||||
BitmapGlyphInfo* rhs) {
|
||||
return lhs->start_offset() > rhs->start_offset();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "sfntly/table/subtable.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
// An immutable class holding bitmap glyph information.
|
||||
class BitmapGlyphInfo : public RefCounted<BitmapGlyphInfo> {
|
||||
public:
|
||||
// Constructor for a relative located glyph. The glyph's position in the EBDT
|
||||
// table is a combination of it's block offset and it's own start offset.
|
||||
// @param glyphId the glyph id
|
||||
// @param blockOffset the offset of the block to which the glyph belongs
|
||||
// @param startOffset the offset of the glyph within the block
|
||||
// @param length the byte length
|
||||
// @param format the glyph image format
|
||||
BitmapGlyphInfo(int32_t glyph_id,
|
||||
int32_t block_offset,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t format);
|
||||
|
||||
// Constructor for an absolute located glyph. The glyph's position in the EBDT
|
||||
// table is only given by it's own start offset.
|
||||
// @param glyphId the glyph id
|
||||
// @param startOffset the offset of the glyph within the block
|
||||
// @param length the byte length
|
||||
// @param format the glyph image format
|
||||
BitmapGlyphInfo(int32_t glyph_id,
|
||||
int32_t start_offset,
|
||||
int32_t length,
|
||||
int32_t format);
|
||||
|
||||
int32_t glyph_id() const { return glyph_id_; }
|
||||
bool relative() const { return relative_; }
|
||||
int32_t block_offset() const { return block_offset_; }
|
||||
int32_t offset() const { return block_offset() + start_offset(); }
|
||||
int32_t start_offset() const { return start_offset_; }
|
||||
int32_t length() const { return length_; }
|
||||
int32_t format() const { return format_; }
|
||||
|
||||
// UNIMPLEMENTED: hashCode()
|
||||
bool operator==(const BitmapGlyphInfo& rhs) const;
|
||||
bool operator==(BitmapGlyphInfo* rhs);
|
||||
|
||||
private:
|
||||
int32_t glyph_id_;
|
||||
bool relative_;
|
||||
int32_t block_offset_;
|
||||
int32_t start_offset_;
|
||||
int32_t length_;
|
||||
int32_t format_;
|
||||
};
|
||||
typedef Ptr<BitmapGlyphInfo> BitmapGlyphInfoPtr;
|
||||
typedef std::map<int32_t, BitmapGlyphInfoPtr> BitmapGlyphInfoMap;
|
||||
typedef std::vector<BitmapGlyphInfoMap> BitmapLocaList;
|
||||
|
||||
class StartOffsetComparator {
|
||||
public:
|
||||
bool operator()(BitmapGlyphInfo* lhs, BitmapGlyphInfo* rhs);
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_
|
|
@ -1,604 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/bitmap_size_table.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sfntly/math/font_math.h"
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format1.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format2.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format3.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format4.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format5.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* BitmapSizeTable class
|
||||
******************************************************************************/
|
||||
BitmapSizeTable::~BitmapSizeTable() {
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::IndexSubTableArrayOffset() {
|
||||
return data_->ReadULongAsInt(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::IndexTableSize() {
|
||||
return data_->ReadULongAsInt(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexTableSize);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::NumberOfIndexSubTables() {
|
||||
return NumberOfIndexSubTables(data_, 0);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::ColorRef() {
|
||||
return data_->ReadULongAsInt(EblcTable::Offset::kBitmapSizeTable_colorRef);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::StartGlyphIndex() {
|
||||
return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_startGlyphIndex);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::EndGlyphIndex() {
|
||||
return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_endGlyphIndex);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::PpemX() {
|
||||
return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemX);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::PpemY() {
|
||||
return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemY);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::BitDepth() {
|
||||
return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_bitDepth);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::FlagsAsInt() {
|
||||
return data_->ReadChar(EblcTable::Offset::kBitmapSizeTable_flags);
|
||||
}
|
||||
|
||||
IndexSubTable* BitmapSizeTable::GetIndexSubTable(int32_t index) {
|
||||
IndexSubTableList* subtable_list = GetIndexSubTableList();
|
||||
if (index >= 0 && (size_t)index < subtable_list->size()) {
|
||||
return (*subtable_list)[index];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::GlyphOffset(int32_t glyph_id) {
|
||||
IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->GlyphOffset(glyph_id);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) {
|
||||
IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->GlyphLength(glyph_id);
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::GlyphInfo(int32_t glyph_id) {
|
||||
IndexSubTable* sub_table = SearchIndexSubTables(glyph_id);
|
||||
if (sub_table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return sub_table->GlyphInfo(glyph_id);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) {
|
||||
IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->image_format();
|
||||
}
|
||||
|
||||
BitmapSizeTable::BitmapSizeTable(ReadableFontData* data,
|
||||
ReadableFontData* master_data)
|
||||
: SubTable(data, master_data) {
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t BitmapSizeTable::NumberOfIndexSubTables(ReadableFontData* data,
|
||||
int32_t table_offset) {
|
||||
return data->ReadULongAsInt(table_offset +
|
||||
EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables);
|
||||
}
|
||||
|
||||
IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) {
|
||||
// would be faster to binary search but too many size tables don't have
|
||||
// sorted subtables
|
||||
#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH)
|
||||
return BinarySearchIndexSubTables(glyph_id);
|
||||
#else
|
||||
return LinearSearchIndexSubTables(glyph_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
IndexSubTable* BitmapSizeTable::LinearSearchIndexSubTables(int32_t glyph_id) {
|
||||
IndexSubTableList* subtable_list = GetIndexSubTableList();
|
||||
for (IndexSubTableList::iterator b = subtable_list->begin(),
|
||||
e = subtable_list->end(); b != e; b++) {
|
||||
if ((*b)->first_glyph_index() <= glyph_id &&
|
||||
(*b)->last_glyph_index() >= glyph_id) {
|
||||
return *b;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IndexSubTable* BitmapSizeTable::BinarySearchIndexSubTables(int32_t glyph_id) {
|
||||
IndexSubTableList* subtable_list = GetIndexSubTableList();
|
||||
int32_t index = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = subtable_list->size();
|
||||
while (top != bottom) {
|
||||
index = (top + bottom) / 2;
|
||||
IndexSubTable* subtable = (*subtable_list)[index];
|
||||
if (glyph_id < subtable->first_glyph_index()) {
|
||||
// Location beow current location
|
||||
top = index;
|
||||
} else {
|
||||
if (glyph_id <= subtable->last_glyph_index()) {
|
||||
return subtable;
|
||||
} else {
|
||||
bottom = index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) {
|
||||
return IndexSubTable::CreateIndexSubTable(master_read_data(),
|
||||
IndexSubTableArrayOffset(),
|
||||
index);
|
||||
}
|
||||
|
||||
IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() {
|
||||
AutoLock lock(index_subtables_lock_);
|
||||
if (index_subtables_.empty()) {
|
||||
for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) {
|
||||
IndexSubTablePtr table;
|
||||
table.Attach(CreateIndexSubTable(i));
|
||||
index_subtables_.push_back(table);
|
||||
}
|
||||
}
|
||||
return &index_subtables_;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* BitmapSizeTable::Builder class
|
||||
******************************************************************************/
|
||||
BitmapSizeTable::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
FontDataTable* BitmapSizeTable::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
BitmapSizeTablePtr output = new BitmapSizeTable(data, master_read_data());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() {
|
||||
IndexSubTableBuilderList* builders = IndexSubTableBuilders();
|
||||
if (builders->empty()) {
|
||||
return 0;
|
||||
}
|
||||
int32_t size = EblcTable::Offset::kBitmapSizeTableLength;
|
||||
bool variable = false;
|
||||
for (IndexSubTableBuilderList::iterator b = builders->begin(),
|
||||
e = builders->end(); b != e; b++) {
|
||||
size += EblcTable::Offset::kIndexSubTableEntryLength;
|
||||
int32_t sub_table_size = (*b)->SubDataSizeToSerialize();
|
||||
int32_t padding = FontMath::PaddingRequired(abs(sub_table_size),
|
||||
DataSize::kULONG);
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "subtable size=%d\n", sub_table_size);
|
||||
#endif
|
||||
variable = (sub_table_size > 0) ? variable : true;
|
||||
size += abs(sub_table_size) + padding;
|
||||
}
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size);
|
||||
#endif
|
||||
return variable ? -size : size;
|
||||
}
|
||||
|
||||
bool BitmapSizeTable::Builder::SubReadyToSerialize() {
|
||||
if (IndexSubTableBuilders()->empty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
SetNumberOfIndexSubTables(IndexSubTableBuilders()->size());
|
||||
int32_t size = InternalReadData()->CopyTo(new_data);
|
||||
return size;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapSizeTable::Builder*
|
||||
BitmapSizeTable::Builder::CreateBuilder(WritableFontData* data,
|
||||
ReadableFontData* master_data) {
|
||||
BitmapSizeTableBuilderPtr output =
|
||||
new BitmapSizeTable::Builder(data, master_data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapSizeTable::Builder*
|
||||
BitmapSizeTable::Builder::CreateBuilder(ReadableFontData* data,
|
||||
ReadableFontData* master_data) {
|
||||
BitmapSizeTableBuilderPtr output =
|
||||
new BitmapSizeTable::Builder(data, master_data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::IndexSubTableArrayOffset() {
|
||||
return InternalReadData()->ReadULongAsInt(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset);
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::SetIndexSubTableArrayOffset(int32_t offset) {
|
||||
InternalWriteData()->WriteULong(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset, offset);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::IndexTableSize() {
|
||||
return InternalReadData()->ReadULongAsInt(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexTableSize);
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::SetIndexTableSize(int32_t size) {
|
||||
InternalWriteData()->WriteULong(
|
||||
EblcTable::Offset::kBitmapSizeTable_indexTableSize, size);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::NumberOfIndexSubTables() {
|
||||
return GetIndexSubTableBuilders()->size();
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::ColorRef() {
|
||||
return InternalReadData()->ReadULongAsInt(
|
||||
EblcTable::Offset::kBitmapSizeTable_colorRef);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::StartGlyphIndex() {
|
||||
return InternalReadData()->ReadUShort(
|
||||
EblcTable::Offset::kBitmapSizeTable_startGlyphIndex);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::EndGlyphIndex() {
|
||||
return InternalReadData()->ReadUShort(
|
||||
EblcTable::Offset::kBitmapSizeTable_endGlyphIndex);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::PpemX() {
|
||||
return InternalReadData()->ReadByte(
|
||||
EblcTable::Offset::kBitmapSizeTable_ppemX);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::PpemY() {
|
||||
return InternalReadData()->ReadByte(
|
||||
EblcTable::Offset::kBitmapSizeTable_ppemY);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::BitDepth() {
|
||||
return InternalReadData()->ReadByte(
|
||||
EblcTable::Offset::kBitmapSizeTable_bitDepth);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::FlagsAsInt() {
|
||||
return InternalReadData()->ReadChar(
|
||||
EblcTable::Offset::kBitmapSizeTable_flags);
|
||||
}
|
||||
|
||||
IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder(
|
||||
int32_t index) {
|
||||
IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders();
|
||||
return sub_table_list->at(index);
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::Builder::GlyphInfo(
|
||||
int32_t glyph_id) {
|
||||
IndexSubTable::Builder* sub_table = SearchIndexSubTables(glyph_id);
|
||||
if (sub_table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return sub_table->GlyphInfo(glyph_id);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::GlyphOffset(int32_t glyph_id) {
|
||||
IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->GlyphOffset(glyph_id);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::GlyphLength(int32_t glyph_id) {
|
||||
IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->GlyphLength(glyph_id);
|
||||
}
|
||||
|
||||
int32_t BitmapSizeTable::Builder::GlyphFormat(int32_t glyph_id) {
|
||||
IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
|
||||
if (subtable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return subtable->image_format();
|
||||
}
|
||||
|
||||
IndexSubTableBuilderList* BitmapSizeTable::Builder::IndexSubTableBuilders() {
|
||||
return GetIndexSubTableBuilders();
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapSizeTable::Builder::BitmapGlyphInfoIterator*
|
||||
BitmapSizeTable::Builder::GetIterator() {
|
||||
Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> output =
|
||||
new BitmapSizeTable::Builder::BitmapGlyphInfoIterator(this);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::GenerateLocaMap(BitmapGlyphInfoMap* output) {
|
||||
assert(output);
|
||||
Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> it;
|
||||
it.Attach(GetIterator());
|
||||
while (it->HasNext()) {
|
||||
BitmapGlyphInfoPtr info;
|
||||
info.Attach(it->Next());
|
||||
(*output)[info->glyph_id()] = info;
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::Revert() {
|
||||
index_sub_tables_.clear();
|
||||
set_model_changed(false);
|
||||
}
|
||||
|
||||
BitmapSizeTable::Builder::Builder(WritableFontData* data,
|
||||
ReadableFontData* master_data)
|
||||
: SubTable::Builder(data, master_data) {
|
||||
}
|
||||
|
||||
BitmapSizeTable::Builder::Builder(ReadableFontData* data,
|
||||
ReadableFontData* master_data)
|
||||
: SubTable::Builder(data, master_data) {
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t count) {
|
||||
InternalWriteData()->WriteULong(
|
||||
EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables, count);
|
||||
}
|
||||
|
||||
IndexSubTable::Builder* BitmapSizeTable::Builder::SearchIndexSubTables(
|
||||
int32_t glyph_id) {
|
||||
// would be faster to binary search but too many size tables don't have
|
||||
// sorted subtables
|
||||
#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH)
|
||||
return BinarySearchIndexSubTables(glyph_id);
|
||||
#else
|
||||
return LinearSearchIndexSubTables(glyph_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
IndexSubTable::Builder* BitmapSizeTable::Builder::LinearSearchIndexSubTables(
|
||||
int32_t glyph_id) {
|
||||
IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders();
|
||||
for (IndexSubTableBuilderList::iterator b = subtable_list->begin(),
|
||||
e = subtable_list->end();
|
||||
b != e; b++) {
|
||||
if ((*b)->first_glyph_index() <= glyph_id &&
|
||||
(*b)->last_glyph_index() >= glyph_id) {
|
||||
return *b;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IndexSubTable::Builder* BitmapSizeTable::Builder::BinarySearchIndexSubTables(
|
||||
int32_t glyph_id) {
|
||||
IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders();
|
||||
int32_t index = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = subtable_list->size();
|
||||
while (top != bottom) {
|
||||
index = (top + bottom) / 2;
|
||||
IndexSubTable::Builder* subtable = subtable_list->at(index);
|
||||
if (glyph_id < subtable->first_glyph_index()) {
|
||||
// Location beow current location
|
||||
top = index;
|
||||
} else {
|
||||
if (glyph_id <= subtable->last_glyph_index()) {
|
||||
return subtable;
|
||||
} else {
|
||||
bottom = index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IndexSubTableBuilderList* BitmapSizeTable::Builder::GetIndexSubTableBuilders() {
|
||||
if (index_sub_tables_.empty()) {
|
||||
Initialize(InternalReadData());
|
||||
set_model_changed();
|
||||
}
|
||||
return &index_sub_tables_;
|
||||
}
|
||||
|
||||
void BitmapSizeTable::Builder::Initialize(ReadableFontData* data) {
|
||||
index_sub_tables_.clear();
|
||||
if (data) {
|
||||
int32_t number_of_index_subtables =
|
||||
BitmapSizeTable::NumberOfIndexSubTables(data, 0);
|
||||
index_sub_tables_.resize(number_of_index_subtables);
|
||||
for (int32_t i = 0; i < number_of_index_subtables; ++i) {
|
||||
index_sub_tables_[i].Attach(CreateIndexSubTableBuilder(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
BitmapSizeTable::Builder::CreateIndexSubTableBuilder(int32_t index) {
|
||||
return IndexSubTable::Builder::CreateBuilder(master_read_data(),
|
||||
IndexSubTableArrayOffset(),
|
||||
index);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* BitmapSizeTable::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
BitmapSizeTable::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
BitmapSizeTable::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, BitmapSizeTable::Builder>(container) {
|
||||
sub_table_iter_ = container->IndexSubTableBuilders()->begin();
|
||||
sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator());
|
||||
}
|
||||
|
||||
bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (sub_table_glyph_info_iter_ && HasNext(sub_table_glyph_info_iter_)) {
|
||||
return true;
|
||||
}
|
||||
while (++sub_table_iter_ != container()->IndexSubTableBuilders()->end()) {
|
||||
sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator());
|
||||
if (HasNext(sub_table_glyph_info_iter_)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
return Next(sub_table_glyph_info_iter_);
|
||||
}
|
||||
|
||||
bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext(
|
||||
BitmapGlyphInfoIter* iterator_base) {
|
||||
if (iterator_base) {
|
||||
switch (iterator_base->container_base()->index_format()) {
|
||||
case 1: {
|
||||
IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->HasNext();
|
||||
}
|
||||
|
||||
case 2: {
|
||||
IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->HasNext();
|
||||
}
|
||||
|
||||
case 3: {
|
||||
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->HasNext();
|
||||
}
|
||||
|
||||
case 4: {
|
||||
IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->HasNext();
|
||||
}
|
||||
|
||||
case 5: {
|
||||
IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->HasNext();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next(
|
||||
BitmapGlyphInfoIter* iterator_base) {
|
||||
if (iterator_base) {
|
||||
switch (iterator_base->container_base()->index_format()) {
|
||||
case 1: {
|
||||
IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->Next();
|
||||
}
|
||||
|
||||
case 2: {
|
||||
IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->Next();
|
||||
}
|
||||
|
||||
case 3: {
|
||||
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->Next();
|
||||
}
|
||||
|
||||
case 4: {
|
||||
IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->Next();
|
||||
}
|
||||
|
||||
case 5: {
|
||||
IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it =
|
||||
down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>(
|
||||
iterator_base);
|
||||
return it->Next();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_
|
||||
|
||||
#include "sfntly/port/lock.h"
|
||||
#include "sfntly/table/bitmap/bitmap_glyph_info.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
// Binary search would be faster but many fonts have index subtables that
|
||||
// aren't sorted.
|
||||
// Note: preprocessor define is used to avoid const expression warnings in C++
|
||||
// code.
|
||||
#define SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH 0
|
||||
|
||||
class BitmapSizeTable : public SubTable,
|
||||
public RefCounted<BitmapSizeTable> {
|
||||
public:
|
||||
class Builder : public SubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator :
|
||||
public RefIterator<BitmapGlyphInfo, Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
bool HasNext(BitmapGlyphInfoIter* iterator_base);
|
||||
CALLER_ATTACH BitmapGlyphInfo* Next(BitmapGlyphInfoIter* iterator_base);
|
||||
|
||||
IndexSubTableBuilderList::iterator sub_table_iter_;
|
||||
BitmapGlyphInfoIterPtr sub_table_glyph_info_iter_;
|
||||
};
|
||||
|
||||
virtual ~Builder();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
ReadableFontData* master_data);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
ReadableFontData* master_data);
|
||||
// Gets the subtable array offset as set in the original table as read from
|
||||
// the font file. This value cannot be explicitly set and will be generated
|
||||
// during table building.
|
||||
// @return the subtable array offset
|
||||
int32_t IndexSubTableArrayOffset();
|
||||
|
||||
// Sets the subtable array offset. This is used only during the building
|
||||
// process when the objects are being serialized.
|
||||
// @param offset the offset to the index subtable array
|
||||
void SetIndexSubTableArrayOffset(int32_t offset);
|
||||
|
||||
// Gets the subtable array size as set in the original table as read from
|
||||
// the font file. This value cannot be explicitly set and will be generated
|
||||
// during table building.
|
||||
// @return the subtable array size
|
||||
int32_t IndexTableSize();
|
||||
|
||||
// Sets the subtable size. This is used only during the building process
|
||||
// when the objects are being serialized.
|
||||
// @param size the offset to the index subtable array
|
||||
void SetIndexTableSize(int32_t size);
|
||||
|
||||
int32_t NumberOfIndexSubTables();
|
||||
int32_t ColorRef();
|
||||
// TODO(stuartg): SBitLineMetrics hori();
|
||||
// TODO(stuartg): SBitLineMetrics vert();
|
||||
int32_t StartGlyphIndex();
|
||||
int32_t EndGlyphIndex();
|
||||
int32_t PpemX();
|
||||
int32_t PpemY();
|
||||
int32_t BitDepth();
|
||||
int32_t FlagsAsInt();
|
||||
|
||||
IndexSubTable::Builder* IndexSubTableBuilder(int32_t index);
|
||||
CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id);
|
||||
int32_t GlyphOffset(int32_t glyph_id);
|
||||
int32_t GlyphLength(int32_t glyph_id);
|
||||
int32_t GlyphFormat(int32_t glyph_id);
|
||||
IndexSubTableBuilderList* IndexSubTableBuilders();
|
||||
// Note: renamed from iterator(), type is the derived type.
|
||||
CALLER_ATTACH BitmapGlyphInfoIterator* GetIterator();
|
||||
void GenerateLocaMap(BitmapGlyphInfoMap* output);
|
||||
|
||||
protected:
|
||||
void Revert();
|
||||
|
||||
private:
|
||||
Builder(WritableFontData* data, ReadableFontData* master_data);
|
||||
Builder(ReadableFontData* data, ReadableFontData* master_data);
|
||||
|
||||
void SetNumberOfIndexSubTables(int32_t count);
|
||||
IndexSubTable::Builder* SearchIndexSubTables(int32_t glyph_id);
|
||||
IndexSubTable::Builder* LinearSearchIndexSubTables(int32_t glyph_id);
|
||||
IndexSubTable::Builder* BinarySearchIndexSubTables(int32_t glyph_id);
|
||||
IndexSubTableBuilderList* GetIndexSubTableBuilders();
|
||||
void Initialize(ReadableFontData* data);
|
||||
CALLER_ATTACH IndexSubTable::Builder* CreateIndexSubTableBuilder(
|
||||
int32_t index);
|
||||
|
||||
IndexSubTableBuilderList index_sub_tables_;
|
||||
};
|
||||
|
||||
virtual ~BitmapSizeTable();
|
||||
|
||||
int32_t IndexSubTableArrayOffset();
|
||||
int32_t IndexTableSize();
|
||||
int32_t NumberOfIndexSubTables();
|
||||
int32_t ColorRef();
|
||||
// TODO(stuartg): SBitLineMetrics hori();
|
||||
// TODO(stuartg): SBitLineMetrics vert();
|
||||
int32_t StartGlyphIndex();
|
||||
int32_t EndGlyphIndex();
|
||||
int32_t PpemX();
|
||||
int32_t PpemY();
|
||||
int32_t BitDepth();
|
||||
int32_t FlagsAsInt();
|
||||
|
||||
// Note: renamed from indexSubTable()
|
||||
IndexSubTable* GetIndexSubTable(int32_t index);
|
||||
int32_t GlyphOffset(int32_t glyph_id);
|
||||
int32_t GlyphLength(int32_t glyph_id);
|
||||
CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id);
|
||||
int32_t GlyphFormat(int32_t glyph_id);
|
||||
|
||||
protected:
|
||||
BitmapSizeTable(ReadableFontData* data,
|
||||
ReadableFontData* master_data);
|
||||
|
||||
private:
|
||||
static int32_t NumberOfIndexSubTables(ReadableFontData* data,
|
||||
int32_t table_offset);
|
||||
IndexSubTable* SearchIndexSubTables(int32_t glyph_id);
|
||||
IndexSubTable* LinearSearchIndexSubTables(int32_t glyph_id);
|
||||
IndexSubTable* BinarySearchIndexSubTables(int32_t glyph_id);
|
||||
CALLER_ATTACH IndexSubTable* CreateIndexSubTable(int32_t index);
|
||||
IndexSubTableList* GetIndexSubTableList();
|
||||
|
||||
Lock index_subtables_lock_;
|
||||
IndexSubTableList index_subtables_;
|
||||
};
|
||||
typedef Ptr<BitmapSizeTable> BitmapSizeTablePtr;
|
||||
typedef std::vector<BitmapSizeTablePtr> BitmapSizeTableList;
|
||||
typedef Ptr<BitmapSizeTable::Builder> BitmapSizeTableBuilderPtr;
|
||||
typedef std::vector<BitmapSizeTableBuilderPtr> BitmapSizeTableBuilderList;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/composite_bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* CompositeBitmapGlyph class
|
||||
******************************************************************************/
|
||||
CompositeBitmapGlyph::CompositeBitmapGlyph(ReadableFontData* data,
|
||||
int32_t format)
|
||||
: BitmapGlyph(data, format) {
|
||||
Initialize(format);
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::~CompositeBitmapGlyph() {
|
||||
}
|
||||
|
||||
int32_t CompositeBitmapGlyph::NumComponents() {
|
||||
return data_->ReadUShort(num_components_offset_);
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::Component CompositeBitmapGlyph::GetComponent(
|
||||
int32_t component_num) const {
|
||||
int32_t component_offset = component_array_offset_ +
|
||||
component_num * Offset::kEbdtComponentLength;
|
||||
return CompositeBitmapGlyph::Component(
|
||||
data_->ReadUShort(component_offset + Offset::kEbdtComponent_glyphCode),
|
||||
data_->ReadChar(component_offset + Offset::kEbdtComponent_xOffset),
|
||||
data_->ReadChar(component_offset + Offset::kEbdtComponent_yOffset));
|
||||
}
|
||||
|
||||
void CompositeBitmapGlyph::Initialize(int32_t format) {
|
||||
if (format == 8) {
|
||||
num_components_offset_ = Offset::kGlyphFormat8_numComponents;
|
||||
component_array_offset_ = Offset::kGlyphFormat8_componentArray;
|
||||
} else if (format == 9) {
|
||||
num_components_offset_ = Offset::kGlyphFormat9_numComponents;
|
||||
component_array_offset_ = Offset::kGlyphFormat9_componentArray;
|
||||
} else {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IllegalStateException("Attempt to create a Composite Bitmap Glyph "
|
||||
"with a non-composite format.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CompositeBitmapGlyph::Component class
|
||||
******************************************************************************/
|
||||
CompositeBitmapGlyph::Component::Component(const Component& rhs)
|
||||
: glyph_code_(rhs.glyph_code_),
|
||||
x_offset_(rhs.x_offset_),
|
||||
y_offset_(rhs.y_offset_) {
|
||||
}
|
||||
|
||||
bool CompositeBitmapGlyph::Component::operator==(
|
||||
const CompositeBitmapGlyph::Component& rhs) {
|
||||
return glyph_code_ == rhs.glyph_code_;
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::Component& CompositeBitmapGlyph::Component::operator=(
|
||||
const CompositeBitmapGlyph::Component& rhs) {
|
||||
glyph_code_ = rhs.glyph_code_;
|
||||
x_offset_ = rhs.x_offset_;
|
||||
y_offset_ = rhs.y_offset_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::Component::Component(int32_t glyph_code,
|
||||
int32_t x_offset,
|
||||
int32_t y_offset)
|
||||
: glyph_code_(glyph_code), x_offset_(x_offset), y_offset_(y_offset) {
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CompositeBitmapGlyph::Builder class
|
||||
******************************************************************************/
|
||||
CompositeBitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format)
|
||||
: BitmapGlyph::Builder(data, format) {
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format)
|
||||
: BitmapGlyph::Builder(data, format) {
|
||||
}
|
||||
|
||||
CompositeBitmapGlyph::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable*
|
||||
CompositeBitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
Ptr<CompositeBitmapGlyph> glyph = new CompositeBitmapGlyph(data, format());
|
||||
return glyph.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_
|
||||
|
||||
#include "sfntly/table/bitmap/bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class CompositeBitmapGlyph : public BitmapGlyph,
|
||||
public RefCounted<CompositeBitmapGlyph> {
|
||||
public:
|
||||
class Component {
|
||||
public:
|
||||
Component(const Component& rhs);
|
||||
|
||||
int32_t glyph_code() { return glyph_code_; }
|
||||
int32_t x_offset() { return x_offset_; }
|
||||
int32_t y_offset() { return y_offset_; }
|
||||
|
||||
// UNIMPLEMENTED: int hashCode()
|
||||
bool operator==(const Component& rhs);
|
||||
Component& operator=(const Component& rhs);
|
||||
|
||||
protected:
|
||||
Component(int32_t glyph_code, int32_t x_offset, int32_t y_offset);
|
||||
|
||||
private:
|
||||
int32_t glyph_code_;
|
||||
int32_t x_offset_;
|
||||
int32_t y_offset_;
|
||||
|
||||
friend class CompositeBitmapGlyph;
|
||||
};
|
||||
|
||||
class Builder : public BitmapGlyph::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
Builder(WritableFontData* data, int32_t format);
|
||||
Builder(ReadableFontData* data, int32_t format);
|
||||
virtual ~Builder();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
};
|
||||
|
||||
CompositeBitmapGlyph(ReadableFontData* data, int32_t format);
|
||||
virtual ~CompositeBitmapGlyph();
|
||||
int32_t NumComponents();
|
||||
// Note: returned immutable object over stack.
|
||||
Component GetComponent(int32_t component_num) const;
|
||||
|
||||
private:
|
||||
void Initialize(int32_t format);
|
||||
|
||||
int32_t num_components_offset_;
|
||||
int32_t component_array_offset_;
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/ebdt_table.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sfntly/table/bitmap/composite_bitmap_glyph.h"
|
||||
#include "sfntly/table/bitmap/simple_bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* EbdtTable class
|
||||
******************************************************************************/
|
||||
EbdtTable::~EbdtTable() {
|
||||
}
|
||||
|
||||
int32_t EbdtTable::Version() {
|
||||
return data_->ReadFixed(Offset::kVersion);
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) {
|
||||
ReadableFontDataPtr glyph_data;
|
||||
glyph_data.Attach(down_cast<ReadableFontData*>(data_->Slice(offset, length)));
|
||||
return BitmapGlyph::CreateGlyph(glyph_data, format);
|
||||
}
|
||||
|
||||
EbdtTable::EbdtTable(Header* header, ReadableFontData* data)
|
||||
: SubTableContainerTable(header, data) {
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* EbdtTable::Builder class
|
||||
******************************************************************************/
|
||||
EbdtTable::Builder::Builder(Header* header, WritableFontData* data)
|
||||
: SubTableContainerTable::Builder(header, data) {
|
||||
}
|
||||
|
||||
EbdtTable::Builder::Builder(Header* header, ReadableFontData* data)
|
||||
: SubTableContainerTable::Builder(header, data) {
|
||||
}
|
||||
|
||||
EbdtTable::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable*
|
||||
EbdtTable::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
FontDataTablePtr table = new EbdtTable(header(), data);
|
||||
return table.Detach();
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t EbdtTable::Builder::SubDataSizeToSerialize() {
|
||||
if (glyph_builders_.empty()) {
|
||||
return 0;
|
||||
}
|
||||
bool fixed = true;
|
||||
int32_t size = Offset::kHeaderLength;
|
||||
for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
|
||||
builder_end = glyph_builders_.end();
|
||||
builder_map != builder_end;
|
||||
builder_map++) {
|
||||
for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
|
||||
glyph_entry_end = builder_map->end();
|
||||
glyph_entry != glyph_entry_end;
|
||||
glyph_entry++) {
|
||||
int32_t glyph_size = glyph_entry->second->SubDataSizeToSerialize();
|
||||
size += abs(glyph_size);
|
||||
fixed = (glyph_size <= 0) ? false : fixed;
|
||||
}
|
||||
}
|
||||
return (fixed ? 1 : -1) * size;
|
||||
}
|
||||
|
||||
bool EbdtTable::Builder::SubReadyToSerialize() {
|
||||
if (glyph_builders_.empty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
int32_t size = 0;
|
||||
size += new_data->WriteFixed(Offset::kVersion, kVersion);
|
||||
for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
|
||||
builder_end = glyph_builders_.end();
|
||||
builder_map != builder_end;
|
||||
builder_map++) {
|
||||
for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
|
||||
glyph_entry_end = builder_map->end();
|
||||
glyph_entry != glyph_entry_end;
|
||||
glyph_entry++) {
|
||||
WritableFontDataPtr slice;
|
||||
slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
|
||||
size += glyph_entry->second->SubSerialize(slice);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::SetLoca(BitmapLocaList* loca_list) {
|
||||
assert(loca_list);
|
||||
Revert();
|
||||
glyph_loca_.resize(loca_list->size());
|
||||
std::copy(loca_list->begin(), loca_list->end(), glyph_loca_.begin());
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::GenerateLocaList(BitmapLocaList* output) {
|
||||
assert(output);
|
||||
output->clear();
|
||||
|
||||
if (glyph_builders_.empty()) {
|
||||
if (glyph_loca_.empty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int start_offset = Offset::kHeaderLength;
|
||||
for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
|
||||
builder_end = glyph_builders_.end();
|
||||
builder_map != builder_end;
|
||||
builder_map++) {
|
||||
BitmapGlyphInfoMap new_loca_map;
|
||||
int32_t glyph_offset = 0;
|
||||
for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
|
||||
glyph_end = builder_map->end();
|
||||
glyph_entry != glyph_end;
|
||||
glyph_entry++) {
|
||||
BitmapGlyphBuilderPtr builder = glyph_entry->second;
|
||||
int32_t size = builder->SubDataSizeToSerialize();
|
||||
BitmapGlyphInfoPtr info = new BitmapGlyphInfo(glyph_entry->first,
|
||||
start_offset + glyph_offset, size, builder->format());
|
||||
new_loca_map[glyph_entry->first] = info;
|
||||
glyph_offset += size;
|
||||
}
|
||||
start_offset += glyph_offset;
|
||||
output->push_back(new_loca_map);
|
||||
}
|
||||
}
|
||||
|
||||
BitmapGlyphBuilderList* EbdtTable::Builder::GlyphBuilders() {
|
||||
return GetGlyphBuilders();
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::SetGlyphBuilders(
|
||||
BitmapGlyphBuilderList* glyph_builders) {
|
||||
glyph_builders_.clear();
|
||||
std::copy(glyph_builders->begin(), glyph_builders->end(),
|
||||
glyph_builders_.begin());
|
||||
set_model_changed();
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::Revert() {
|
||||
glyph_loca_.clear();
|
||||
glyph_builders_.clear();
|
||||
set_model_changed(false);
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header,
|
||||
WritableFontData* data) {
|
||||
Ptr<EbdtTable::Builder> builder;
|
||||
builder = new Builder(header, data);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header,
|
||||
ReadableFontData* data) {
|
||||
Ptr<EbdtTable::Builder> builder;
|
||||
builder = new Builder(header, data);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
BitmapGlyphBuilderList* EbdtTable::Builder::GetGlyphBuilders() {
|
||||
if (glyph_builders_.empty()) {
|
||||
if (glyph_loca_.empty()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IllegalStateException(
|
||||
"Loca values not set - unable to parse glyph data.");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
Initialize(InternalReadData(), &glyph_loca_, &glyph_builders_);
|
||||
set_model_changed();
|
||||
}
|
||||
return &glyph_builders_;
|
||||
}
|
||||
|
||||
void EbdtTable::Builder::Initialize(ReadableFontData* data,
|
||||
BitmapLocaList* loca_list,
|
||||
BitmapGlyphBuilderList* output) {
|
||||
assert(loca_list);
|
||||
assert(output);
|
||||
|
||||
output->clear();
|
||||
if (data) {
|
||||
for (BitmapLocaList::iterator loca_map = loca_list->begin(),
|
||||
loca_end = loca_list->end();
|
||||
loca_map != loca_end; loca_map++) {
|
||||
BitmapGlyphBuilderMap glyph_builder_map;
|
||||
for (BitmapGlyphInfoMap::iterator entry = loca_map->begin(),
|
||||
entry_end = loca_map->end();
|
||||
entry != entry_end; entry++) {
|
||||
BitmapGlyphInfoPtr info = entry->second;
|
||||
ReadableFontDataPtr slice;
|
||||
slice.Attach(down_cast<ReadableFontData*>(data->Slice(
|
||||
info->offset(), info->length())));
|
||||
BitmapGlyphBuilderPtr glyph_builder;
|
||||
glyph_builder.Attach(BitmapGlyph::Builder::CreateGlyphBuilder(
|
||||
slice, info->format()));
|
||||
glyph_builder_map[entry->first] = glyph_builder;
|
||||
}
|
||||
output->push_back(glyph_builder_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_
|
||||
|
||||
#include "sfntly/table/bitmap/bitmap_glyph.h"
|
||||
#include "sfntly/table/bitmap/bitmap_glyph_info.h"
|
||||
#include "sfntly/table/subtable_container_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class EbdtTable : public SubTableContainerTable,
|
||||
public RefCounted<EbdtTable> {
|
||||
public:
|
||||
struct Offset {
|
||||
enum {
|
||||
kVersion = 0,
|
||||
kHeaderLength = DataSize::kFixed,
|
||||
};
|
||||
};
|
||||
|
||||
class Builder : public SubTableContainerTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
// Constructor scope altered to public because C++ does not allow base
|
||||
// class to instantiate derived class with protected constructors.
|
||||
Builder(Header* header, WritableFontData* data);
|
||||
Builder(Header* header, ReadableFontData* data);
|
||||
virtual ~Builder();
|
||||
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual void SubDataSet();
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
|
||||
void SetLoca(BitmapLocaList* loca_list);
|
||||
void GenerateLocaList(BitmapLocaList* output);
|
||||
|
||||
// Gets the List of glyph builders for the glyph table builder. These may be
|
||||
// manipulated in any way by the caller and the changes will be reflected in
|
||||
// the final glyph table produced.
|
||||
// If there is no current data for the glyph builder or the glyph builders
|
||||
// have not been previously set then this will return an empty glyph builder
|
||||
// List. If there is current data (i.e. data read from an existing font) and
|
||||
// the loca list has not been set or is null, empty, or invalid, then an
|
||||
// empty glyph builder List will be returned.
|
||||
// @return the list of glyph builders
|
||||
BitmapGlyphBuilderList* GlyphBuilders();
|
||||
|
||||
// Replace the internal glyph builders with the one provided. The provided
|
||||
// list and all contained objects belong to this builder.
|
||||
// This call is only required if the entire set of glyphs in the glyph
|
||||
// table builder are being replaced. If the glyph builder list provided from
|
||||
// the {@link EbdtTable.Builder#glyphBuilders()} is being used and modified
|
||||
// then those changes will already be reflected in the glyph table builder.
|
||||
// @param glyphBuilders the new glyph builders
|
||||
void SetGlyphBuilders(BitmapGlyphBuilderList* glyph_builders);
|
||||
|
||||
void Revert();
|
||||
|
||||
// Create a new builder using the header information and data provided.
|
||||
// @param header the header information
|
||||
// @param data the data holding the table
|
||||
static CALLER_ATTACH Builder* CreateBuilder(Header* header,
|
||||
WritableFontData* data);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(Header* header,
|
||||
ReadableFontData* data);
|
||||
|
||||
private:
|
||||
BitmapGlyphBuilderList* GetGlyphBuilders();
|
||||
static void Initialize(ReadableFontData* data,
|
||||
BitmapLocaList* loca_list,
|
||||
BitmapGlyphBuilderList* output);
|
||||
|
||||
static const int32_t kVersion = 0x00020000; // TODO(stuartg): const/enum
|
||||
BitmapLocaList glyph_loca_;
|
||||
BitmapGlyphBuilderList glyph_builders_;
|
||||
};
|
||||
|
||||
virtual ~EbdtTable();
|
||||
int32_t Version();
|
||||
CALLER_ATTACH BitmapGlyph* Glyph(int32_t offset,
|
||||
int32_t length,
|
||||
int32_t format);
|
||||
protected:
|
||||
EbdtTable(Header* header, ReadableFontData* data);
|
||||
};
|
||||
typedef Ptr<EbdtTable> EbdtTablePtr;
|
||||
typedef Ptr<EbdtTable::Builder> EbdtTableBuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_
|
|
@ -1,317 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sfntly/math/font_math.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* EblcTable class
|
||||
******************************************************************************/
|
||||
int32_t EblcTable::Version() {
|
||||
return data_->ReadFixed(Offset::kVersion);
|
||||
}
|
||||
|
||||
int32_t EblcTable::NumSizes() {
|
||||
return data_->ReadULongAsInt(Offset::kNumSizes);
|
||||
}
|
||||
|
||||
BitmapSizeTable* EblcTable::GetBitmapSizeTable(int32_t index) {
|
||||
if (index < 0 || index > NumSizes()) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException(
|
||||
"Size table index is outside the range of tables.");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
BitmapSizeTableList* bitmap_size_table_list = GetBitmapSizeTableList();
|
||||
if (bitmap_size_table_list) {
|
||||
return (*bitmap_size_table_list)[index];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EblcTable::EblcTable(Header* header, ReadableFontData* data)
|
||||
: SubTableContainerTable(header, data) {
|
||||
}
|
||||
|
||||
BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() {
|
||||
AutoLock lock(bitmap_size_table_lock_);
|
||||
if (bitmap_size_table_.empty()) {
|
||||
CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_);
|
||||
}
|
||||
return &bitmap_size_table_;
|
||||
}
|
||||
|
||||
// static
|
||||
void EblcTable::CreateBitmapSizeTable(ReadableFontData* data,
|
||||
int32_t num_sizes,
|
||||
BitmapSizeTableList* output) {
|
||||
assert(data);
|
||||
assert(output);
|
||||
for (int32_t i = 0; i < num_sizes; ++i) {
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(Offset::kBitmapSizeTableArrayStart +
|
||||
i * Offset::kBitmapSizeTableLength,
|
||||
Offset::kBitmapSizeTableLength)));
|
||||
BitmapSizeTableBuilderPtr size_builder;
|
||||
size_builder.Attach(
|
||||
BitmapSizeTable::Builder::CreateBuilder(new_data, data));
|
||||
BitmapSizeTablePtr size;
|
||||
size.Attach(down_cast<BitmapSizeTable*>(size_builder->Build()));
|
||||
output->push_back(size);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* EblcTable::Builder class
|
||||
******************************************************************************/
|
||||
EblcTable::Builder::Builder(Header* header, WritableFontData* data)
|
||||
: SubTableContainerTable::Builder(header, data) {
|
||||
}
|
||||
|
||||
EblcTable::Builder::Builder(Header* header, ReadableFontData* data)
|
||||
: SubTableContainerTable::Builder(header, data) {
|
||||
}
|
||||
|
||||
EblcTable::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
// header
|
||||
int32_t size = new_data->WriteFixed(0, kVersion);
|
||||
size += new_data->WriteULong(size, size_table_builders_.size());
|
||||
|
||||
// calculate the offsets
|
||||
// offset to the start of the size table array
|
||||
int32_t size_table_start_offset = size;
|
||||
// walking offset in the size table array
|
||||
int32_t size_table_offset = size_table_start_offset;
|
||||
// offset to the start of the whole index subtable block
|
||||
int32_t sub_table_block_start_offset = size_table_offset +
|
||||
size_table_builders_.size() * Offset::kBitmapSizeTableLength;
|
||||
// walking offset in the index subtable
|
||||
// points to the start of the current subtable block
|
||||
int32_t current_sub_table_block_start_offset = sub_table_block_start_offset;
|
||||
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
int32_t size_index = 0;
|
||||
#endif
|
||||
for (BitmapSizeTableBuilderList::iterator
|
||||
size_builder = size_table_builders_.begin(),
|
||||
size_builder_end = size_table_builders_.end();
|
||||
size_builder != size_builder_end; size_builder++) {
|
||||
(*size_builder)->SetIndexSubTableArrayOffset(
|
||||
current_sub_table_block_start_offset);
|
||||
IndexSubTableBuilderList* index_sub_table_builder_list =
|
||||
(*size_builder)->IndexSubTableBuilders();
|
||||
|
||||
// walking offset within the current subTable array
|
||||
int32_t index_sub_table_array_offset = current_sub_table_block_start_offset;
|
||||
// walking offset within the subTable entries
|
||||
int32_t index_sub_table_offset = index_sub_table_array_offset +
|
||||
index_sub_table_builder_list->size() * Offset::kIndexSubHeaderLength;
|
||||
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ",
|
||||
size_index, size_table_offset,
|
||||
current_sub_table_block_start_offset);
|
||||
fprintf(stderr, "index subTableStart=%x\n", index_sub_table_offset);
|
||||
size_index++;
|
||||
int32_t sub_table_index = 0;
|
||||
#endif
|
||||
for (IndexSubTableBuilderList::iterator
|
||||
index_sub_table_builder = index_sub_table_builder_list->begin(),
|
||||
index_sub_table_builder_end = index_sub_table_builder_list->end();
|
||||
index_sub_table_builder != index_sub_table_builder_end;
|
||||
index_sub_table_builder++) {
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "\tsubTableIndex %d: format=%x, ", sub_table_index,
|
||||
(*index_sub_table_builder)->index_format());
|
||||
fprintf(stderr, "indexSubTableArrayOffset=%x, indexSubTableOffset=%x\n",
|
||||
index_sub_table_array_offset, index_sub_table_offset);
|
||||
sub_table_index++;
|
||||
#endif
|
||||
// array entry
|
||||
index_sub_table_array_offset += new_data->WriteUShort(
|
||||
index_sub_table_array_offset,
|
||||
(*index_sub_table_builder)->first_glyph_index());
|
||||
index_sub_table_array_offset += new_data->WriteUShort(
|
||||
index_sub_table_array_offset,
|
||||
(*index_sub_table_builder)->last_glyph_index());
|
||||
index_sub_table_array_offset += new_data->WriteULong(
|
||||
index_sub_table_array_offset,
|
||||
index_sub_table_offset - current_sub_table_block_start_offset);
|
||||
|
||||
// index sub table
|
||||
WritableFontDataPtr slice_index_sub_table;
|
||||
slice_index_sub_table.Attach(down_cast<WritableFontData*>(
|
||||
new_data->Slice(index_sub_table_offset)));
|
||||
int32_t current_sub_table_size =
|
||||
(*index_sub_table_builder)->SubSerialize(slice_index_sub_table);
|
||||
int32_t padding = FontMath::PaddingRequired(current_sub_table_size,
|
||||
DataSize::kULONG);
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "\t\tsubTableSize = %x, padding = %x\n",
|
||||
current_sub_table_size, padding);
|
||||
#endif
|
||||
index_sub_table_offset += current_sub_table_size;
|
||||
index_sub_table_offset +=
|
||||
new_data->WritePadding(index_sub_table_offset, padding);
|
||||
}
|
||||
|
||||
// serialize size table
|
||||
(*size_builder)->SetIndexTableSize(
|
||||
index_sub_table_offset - current_sub_table_block_start_offset);
|
||||
WritableFontDataPtr slice_size_table;
|
||||
slice_size_table.Attach(down_cast<WritableFontData*>(
|
||||
new_data->Slice(size_table_offset)));
|
||||
size_table_offset += (*size_builder)->SubSerialize(slice_size_table);
|
||||
|
||||
current_sub_table_block_start_offset = index_sub_table_offset;
|
||||
}
|
||||
return size + current_sub_table_block_start_offset;
|
||||
}
|
||||
|
||||
bool EblcTable::Builder::SubReadyToSerialize() {
|
||||
if (size_table_builders_.empty()) {
|
||||
return false;
|
||||
}
|
||||
for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
|
||||
e = size_table_builders_.end();
|
||||
b != e; b++) {
|
||||
if (!(*b)->SubReadyToSerialize()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t EblcTable::Builder::SubDataSizeToSerialize() {
|
||||
if (size_table_builders_.empty()) {
|
||||
return 0;
|
||||
}
|
||||
int32_t size = Offset::kHeaderLength;
|
||||
bool variable = false;
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
size_t size_index = 0;
|
||||
#endif
|
||||
for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
|
||||
e = size_table_builders_.end();
|
||||
b != e; b++) {
|
||||
int32_t size_builder_size = (*b)->SubDataSizeToSerialize();
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "sizeIndex = %d, sizeBuilderSize=0x%x (%d)\n",
|
||||
size_index++, size_builder_size, size_builder_size);
|
||||
#endif
|
||||
variable = size_builder_size > 0 ? variable : true;
|
||||
size += abs(size_builder_size);
|
||||
}
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "eblc size=%d\n", size);
|
||||
#endif
|
||||
return variable ? -size : size;
|
||||
}
|
||||
|
||||
void EblcTable::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
BitmapSizeTableBuilderList* EblcTable::Builder::BitmapSizeBuilders() {
|
||||
return GetSizeList();
|
||||
}
|
||||
|
||||
void EblcTable::Builder::Revert() {
|
||||
size_table_builders_.clear();
|
||||
set_model_changed(false);
|
||||
}
|
||||
|
||||
void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) {
|
||||
assert(output);
|
||||
BitmapSizeTableBuilderList* size_builder_list = GetSizeList();
|
||||
output->clear();
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
int32_t size_index = 0;
|
||||
#endif
|
||||
for (BitmapSizeTableBuilderList::iterator b = size_builder_list->begin(),
|
||||
e = size_builder_list->end();
|
||||
b != e; b++) {
|
||||
#if defined (SFNTLY_DEBUG_BITMAP)
|
||||
fprintf(stderr, "size table = %d\n", size_index++);
|
||||
#endif
|
||||
BitmapGlyphInfoMap loca_map;
|
||||
(*b)->GenerateLocaMap(&loca_map);
|
||||
output->push_back(loca_map);
|
||||
}
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
FontDataTable* EblcTable::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
Ptr<EblcTable> new_table = new EblcTable(header(), data);
|
||||
return new_table.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH EblcTable::Builder*
|
||||
EblcTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
|
||||
Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
|
||||
return new_builder.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH EblcTable::Builder*
|
||||
EblcTable::Builder::CreateBuilder(Header* header, ReadableFontData* data) {
|
||||
Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
|
||||
return new_builder.Detach();
|
||||
}
|
||||
|
||||
BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() {
|
||||
if (size_table_builders_.empty()) {
|
||||
Initialize(InternalReadData(), &size_table_builders_);
|
||||
set_model_changed();
|
||||
}
|
||||
return &size_table_builders_;
|
||||
}
|
||||
|
||||
void EblcTable::Builder::Initialize(ReadableFontData* data,
|
||||
BitmapSizeTableBuilderList* output) {
|
||||
assert(output);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes);
|
||||
if (num_sizes > data->Size() / Offset::kBitmapSizeTableLength)
|
||||
return;
|
||||
|
||||
for (int32_t i = 0; i < num_sizes; ++i) {
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(Offset::kBitmapSizeTableArrayStart +
|
||||
i * Offset::kBitmapSizeTableLength,
|
||||
Offset::kBitmapSizeTableLength)));
|
||||
BitmapSizeTableBuilderPtr size_builder;
|
||||
size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder(
|
||||
new_data, data));
|
||||
output->push_back(size_builder);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_
|
||||
|
||||
#include "sfntly/port/lock.h"
|
||||
#include "sfntly/table/bitmap/big_glyph_metrics.h"
|
||||
#include "sfntly/table/bitmap/bitmap_glyph.h"
|
||||
#include "sfntly/table/bitmap/bitmap_size_table.h"
|
||||
#include "sfntly/table/subtable_container_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class EblcTable : public SubTableContainerTable,
|
||||
public RefCounted<EblcTable> {
|
||||
public:
|
||||
struct Offset {
|
||||
enum {
|
||||
// header
|
||||
kVersion = 0,
|
||||
kNumSizes = 4,
|
||||
kHeaderLength = kNumSizes + DataSize::kULONG,
|
||||
|
||||
// bitmapSizeTable
|
||||
kBitmapSizeTableArrayStart = kHeaderLength,
|
||||
kBitmapSizeTableLength = 48,
|
||||
kBitmapSizeTable_indexSubTableArrayOffset = 0,
|
||||
kBitmapSizeTable_indexTableSize = 4,
|
||||
kBitmapSizeTable_numberOfIndexSubTables = 8,
|
||||
kBitmapSizeTable_colorRef = 12,
|
||||
kBitmapSizeTable_hori = 16,
|
||||
kBitmapSizeTable_vert = 28,
|
||||
kBitmapSizeTable_startGlyphIndex = 40,
|
||||
kBitmapSizeTable_endGlyphIndex = 42,
|
||||
kBitmapSizeTable_ppemX = 44,
|
||||
kBitmapSizeTable_ppemY = 45,
|
||||
kBitmapSizeTable_bitDepth = 46,
|
||||
kBitmapSizeTable_flags = 47,
|
||||
|
||||
// sbitLineMetrics
|
||||
kSbitLineMetricsLength = 12,
|
||||
kSbitLineMetrics_ascender = 0,
|
||||
kSbitLineMetrics_descender = 1,
|
||||
kSbitLineMetrics_widthMax = 2,
|
||||
kSbitLineMetrics_caretSlopeNumerator = 3,
|
||||
kSbitLineMetrics_caretSlopeDenominator = 4,
|
||||
kSbitLineMetrics_caretOffset = 5,
|
||||
kSbitLineMetrics_minOriginSB = 6,
|
||||
kSbitLineMetrics_minAdvanceSB = 7,
|
||||
kSbitLineMetrics_maxBeforeBL = 8,
|
||||
kSbitLineMetrics_minAfterBL = 9,
|
||||
kSbitLineMetrics_pad1 = 10,
|
||||
kSbitLineMetrics_pad2 = 11,
|
||||
|
||||
// indexSubTable
|
||||
kIndexSubTableEntryLength = 8,
|
||||
kIndexSubTableEntry_firstGlyphIndex = 0,
|
||||
kIndexSubTableEntry_lastGlyphIndex = 2,
|
||||
kIndexSubTableEntry_additionalOffsetToIndexSubTable = 4,
|
||||
|
||||
// indexSubHeader
|
||||
kIndexSubHeaderLength = 8,
|
||||
kIndexSubHeader_indexFormat = 0,
|
||||
kIndexSubHeader_imageFormat = 2,
|
||||
kIndexSubHeader_imageDataOffset = 4,
|
||||
|
||||
// indexSubTable - all offset relative to the subtable start
|
||||
|
||||
// indexSubTable1
|
||||
kIndexSubTable1_offsetArray = kIndexSubHeaderLength,
|
||||
kIndexSubTable1_builderDataSize = kIndexSubHeaderLength,
|
||||
|
||||
// kIndexSubTable2
|
||||
kIndexSubTable2Length = kIndexSubHeaderLength +
|
||||
DataSize::kULONG +
|
||||
BitmapGlyph::Offset::kBigGlyphMetricsLength,
|
||||
kIndexSubTable2_imageSize = kIndexSubHeaderLength,
|
||||
kIndexSubTable2_bigGlyphMetrics = kIndexSubTable2_imageSize +
|
||||
DataSize::kULONG,
|
||||
kIndexSubTable2_builderDataSize = kIndexSubTable2_bigGlyphMetrics +
|
||||
BigGlyphMetrics::Offset::kMetricsLength,
|
||||
|
||||
// kIndexSubTable3
|
||||
kIndexSubTable3_offsetArray = kIndexSubHeaderLength,
|
||||
kIndexSubTable3_builderDataSize = kIndexSubTable3_offsetArray,
|
||||
|
||||
// kIndexSubTable4
|
||||
kIndexSubTable4_numGlyphs = kIndexSubHeaderLength,
|
||||
kIndexSubTable4_glyphArray = kIndexSubTable4_numGlyphs +
|
||||
DataSize::kULONG,
|
||||
kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT,
|
||||
kIndexSubTable4_codeOffsetPair_glyphCode = 0,
|
||||
kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT,
|
||||
kIndexSubTable4_builderDataSize = kIndexSubTable4_glyphArray,
|
||||
|
||||
// kIndexSubTable5
|
||||
kIndexSubTable5_imageSize = kIndexSubHeaderLength,
|
||||
kIndexSubTable5_bigGlyphMetrics = kIndexSubTable5_imageSize +
|
||||
DataSize::kULONG,
|
||||
kIndexSubTable5_numGlyphs = kIndexSubTable5_bigGlyphMetrics +
|
||||
BitmapGlyph::Offset::kBigGlyphMetricsLength,
|
||||
kIndexSubTable5_glyphArray = kIndexSubTable5_numGlyphs +
|
||||
DataSize::kULONG,
|
||||
kIndexSubTable5_builderDataSize = kIndexSubTable5_glyphArray,
|
||||
|
||||
// codeOffsetPair
|
||||
kCodeOffsetPairLength = 2 * DataSize::kUSHORT,
|
||||
kCodeOffsetPair_glyphCode = 0,
|
||||
kCodeOffsetPair_offset = DataSize::kUSHORT,
|
||||
};
|
||||
};
|
||||
|
||||
class Builder : public SubTableContainerTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
// Constructor scope altered to public because C++ does not allow base
|
||||
// class to instantiate derived class with protected constructors.
|
||||
Builder(Header* header, WritableFontData* data);
|
||||
Builder(Header* header, ReadableFontData* data);
|
||||
virtual ~Builder();
|
||||
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual void SubDataSet();
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
|
||||
BitmapSizeTableBuilderList* BitmapSizeBuilders();
|
||||
void Revert();
|
||||
|
||||
// Generates the loca list for the EBDT table. The list is intended to be
|
||||
// used by the EBDT to allow it to parse the glyph data and generate glyph
|
||||
// objects. After returning from this method the list belongs to the caller.
|
||||
// The list entries are in the same order as the size table builders are at
|
||||
// the time of this call.
|
||||
// @return the list of loca maps with one for each size table builder
|
||||
void GenerateLocaList(BitmapLocaList* output);
|
||||
|
||||
// Create a new builder using the header information and data provided.
|
||||
// @param header the header information
|
||||
// @param data the data holding the table
|
||||
static CALLER_ATTACH Builder* CreateBuilder(Header* header,
|
||||
WritableFontData* data);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(Header* header,
|
||||
ReadableFontData* data);
|
||||
|
||||
private:
|
||||
BitmapSizeTableBuilderList* GetSizeList();
|
||||
void Initialize(ReadableFontData* data, BitmapSizeTableBuilderList* output);
|
||||
|
||||
static const int32_t kVersion = 0x00020000;
|
||||
BitmapSizeTableBuilderList size_table_builders_;
|
||||
};
|
||||
|
||||
int32_t Version();
|
||||
int32_t NumSizes();
|
||||
// UNIMPLEMENTED: toString()
|
||||
|
||||
BitmapSizeTable* GetBitmapSizeTable(int32_t index);
|
||||
|
||||
static const int32_t NOTDEF = -1;
|
||||
|
||||
protected:
|
||||
EblcTable(Header* header, ReadableFontData* data);
|
||||
|
||||
private:
|
||||
BitmapSizeTableList* GetBitmapSizeTableList();
|
||||
|
||||
static void CreateBitmapSizeTable(ReadableFontData* data,
|
||||
int32_t num_sizes,
|
||||
BitmapSizeTableList* output);
|
||||
|
||||
Lock bitmap_size_table_lock_;
|
||||
BitmapSizeTableList bitmap_size_table_;
|
||||
};
|
||||
typedef Ptr<EblcTable> EblcTablePtr;
|
||||
typedef Ptr<EblcTable::Builder> EblcTableBuilderPtr;
|
||||
}
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/ebsc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* EbscTable class
|
||||
******************************************************************************/
|
||||
EbscTable::~EbscTable() {
|
||||
}
|
||||
|
||||
int32_t EbscTable::Version() {
|
||||
return data_->ReadFixed(Offset::kVersion);
|
||||
}
|
||||
|
||||
int32_t EbscTable::NumSizes() {
|
||||
return data_->ReadULongAsInt(Offset::kNumSizes);
|
||||
}
|
||||
|
||||
EbscTable::EbscTable(Header* header, ReadableFontData* data)
|
||||
: Table(header, data) {
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* EbscTable::BitmapScaleTable class
|
||||
******************************************************************************/
|
||||
EbscTable::BitmapScaleTable::~BitmapScaleTable() {
|
||||
}
|
||||
|
||||
EbscTable::BitmapScaleTable::BitmapScaleTable(ReadableFontData* data)
|
||||
: SubTable(data) {
|
||||
}
|
||||
|
||||
int32_t EbscTable::BitmapScaleTable::PpemX() {
|
||||
return data_->ReadByte(Offset::kBitmapScaleTable_ppemX);
|
||||
}
|
||||
|
||||
int32_t EbscTable::BitmapScaleTable::PpemY() {
|
||||
return data_->ReadByte(Offset::kBitmapScaleTable_ppemY);
|
||||
}
|
||||
|
||||
int32_t EbscTable::BitmapScaleTable::SubstitutePpemX() {
|
||||
return data_->ReadByte(Offset::kBitmapScaleTable_substitutePpemX);
|
||||
}
|
||||
|
||||
int32_t EbscTable::BitmapScaleTable::SubstitutePpemY() {
|
||||
return data_->ReadByte(Offset::kBitmapScaleTable_substitutePpemY);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* EbscTable::Builder class
|
||||
******************************************************************************/
|
||||
EbscTable::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH EbscTable::Builder* EbscTable::Builder::CreateBuilder(
|
||||
Header* header, WritableFontData* data) {
|
||||
EbscTableBuilderPtr builder = new EbscTable::Builder(header, data);
|
||||
return builder.Detach();
|
||||
}
|
||||
|
||||
EbscTable::Builder::Builder(Header* header, WritableFontData* data)
|
||||
: Table::Builder(header, data) {
|
||||
}
|
||||
|
||||
EbscTable::Builder::Builder(Header* header, ReadableFontData* data)
|
||||
: Table::Builder(header, data) {
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
FontDataTable* EbscTable::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
EbscTablePtr output = new EbscTable(header(), data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void EbscTable::Builder::SubDataSet() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
int32_t EbscTable::Builder::SubDataSizeToSerialize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EbscTable::Builder::SubReadyToSerialize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t EbscTable::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
UNREFERENCED_PARAMETER(new_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class EbscTable : public Table,
|
||||
public RefCounted<EbscTable> {
|
||||
public:
|
||||
struct Offset {
|
||||
enum {
|
||||
// header
|
||||
kVersion = 0,
|
||||
kNumSizes = DataSize::kFixed,
|
||||
kHeaderLength = kNumSizes + DataSize::kULONG,
|
||||
kBitmapScaleTableStart = kHeaderLength,
|
||||
|
||||
// bitmapScaleTable
|
||||
kBitmapScaleTable_hori = 0,
|
||||
kBitmapScaleTable_vert = EblcTable::Offset::kSbitLineMetricsLength,
|
||||
kBitmapScaleTable_ppemX = kBitmapScaleTable_vert +
|
||||
EblcTable::Offset::kSbitLineMetricsLength,
|
||||
kBitmapScaleTable_ppemY = kBitmapScaleTable_ppemX + DataSize::kBYTE,
|
||||
kBitmapScaleTable_substitutePpemX = kBitmapScaleTable_ppemY +
|
||||
DataSize::kBYTE,
|
||||
kBitmapScaleTable_substitutePpemY = kBitmapScaleTable_substitutePpemX +
|
||||
DataSize::kBYTE,
|
||||
kBitmapScaleTableLength = kBitmapScaleTable_substitutePpemY +
|
||||
DataSize::kBYTE,
|
||||
};
|
||||
};
|
||||
|
||||
class BitmapScaleTable : public SubTable,
|
||||
public RefCounted<BitmapScaleTable> {
|
||||
public:
|
||||
virtual ~BitmapScaleTable();
|
||||
int32_t PpemX();
|
||||
int32_t PpemY();
|
||||
int32_t SubstitutePpemX();
|
||||
int32_t SubstitutePpemY();
|
||||
|
||||
protected:
|
||||
// Note: caller to do data->Slice(offset, Offset::kBitmapScaleTableLength)
|
||||
explicit BitmapScaleTable(ReadableFontData* data);
|
||||
};
|
||||
|
||||
// TODO(stuartg): currently the builder just builds from initial data
|
||||
// - need to make fully working but few if any examples to test with
|
||||
class Builder : public Table::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
virtual ~Builder();
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder(Header* header,
|
||||
WritableFontData* data);
|
||||
|
||||
protected:
|
||||
Builder(Header* header, WritableFontData* data);
|
||||
Builder(Header* header, ReadableFontData* data);
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
};
|
||||
|
||||
virtual ~EbscTable();
|
||||
|
||||
int32_t Version();
|
||||
int32_t NumSizes();
|
||||
// Note: renamed from bitmapScaleTable
|
||||
CALLER_ATTACH BitmapScaleTable* GetBitmapScaleTable(int32_t index);
|
||||
|
||||
private:
|
||||
EbscTable(Header* header, ReadableFontData* data);
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<EbscTable> EbscTablePtr;
|
||||
typedef Ptr<EbscTable::Builder> EbscTableBuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/glyph_metrics.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
GlyphMetrics::~GlyphMetrics() {
|
||||
}
|
||||
|
||||
GlyphMetrics::GlyphMetrics(ReadableFontData* data)
|
||||
: SubTable(data) {
|
||||
}
|
||||
|
||||
GlyphMetrics::Builder::~Builder() {
|
||||
}
|
||||
|
||||
GlyphMetrics::Builder::Builder(WritableFontData* data)
|
||||
: SubTable::Builder(data) {
|
||||
}
|
||||
|
||||
GlyphMetrics::Builder::Builder(ReadableFontData* data)
|
||||
: SubTable::Builder(data) {
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_
|
||||
|
||||
#include "sfntly/table/subtable.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class GlyphMetrics : public SubTable {
|
||||
public:
|
||||
virtual ~GlyphMetrics();
|
||||
|
||||
protected:
|
||||
class Builder : public SubTable::Builder {
|
||||
public:
|
||||
virtual ~Builder();
|
||||
|
||||
protected:
|
||||
explicit Builder(WritableFontData* data);
|
||||
explicit Builder(ReadableFontData* data);
|
||||
};
|
||||
|
||||
explicit GlyphMetrics(ReadableFontData* data);
|
||||
};
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_
|
|
@ -1,278 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format1.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format2.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format3.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format4.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table_format5.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTable class
|
||||
******************************************************************************/
|
||||
CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (GlyphStartOffset(glyph_id) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
BitmapGlyphInfoPtr output = new BitmapGlyphInfo(glyph_id,
|
||||
image_data_offset(),
|
||||
GlyphStartOffset(glyph_id),
|
||||
GlyphLength(glyph_id),
|
||||
image_format());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::GlyphOffset(int32_t glyph_id) {
|
||||
int32_t glyph_start_offset = GlyphStartOffset(glyph_id);
|
||||
if (glyph_start_offset == -1) {
|
||||
return -1;
|
||||
}
|
||||
return image_data_offset() + glyph_start_offset;
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTable*
|
||||
IndexSubTable::CreateIndexSubTable(ReadableFontData* data,
|
||||
int32_t offset_to_index_sub_table_array,
|
||||
int32_t array_index) {
|
||||
IndexSubTableBuilderPtr builder;
|
||||
builder.Attach(IndexSubTable::Builder::CreateBuilder(
|
||||
data, offset_to_index_sub_table_array, array_index));
|
||||
return down_cast<IndexSubTable*>(builder->Build());
|
||||
}
|
||||
|
||||
IndexSubTable::IndexSubTable(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: SubTable(data),
|
||||
first_glyph_index_(first_glyph_index),
|
||||
last_glyph_index_(last_glyph_index) {
|
||||
index_format_ =
|
||||
data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat);
|
||||
image_format_ =
|
||||
data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
|
||||
image_data_offset_ =
|
||||
data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id) {
|
||||
return CheckGlyphRange(glyph_id, first_glyph_index(), last_glyph_index());
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id,
|
||||
int32_t first_glyph_id,
|
||||
int32_t last_glyph_id) {
|
||||
if (glyph_id < first_glyph_id || glyph_id > last_glyph_id) {
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IndexOutOfBoundException("Glyph ID is outside of the allowed range.");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return glyph_id - first_glyph_id;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTable::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTable::Builder::~Builder() {
|
||||
}
|
||||
|
||||
void IndexSubTable::Builder::Revert() {
|
||||
set_model_changed(false);
|
||||
Initialize(InternalReadData());
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::Builder::GlyphInfo(
|
||||
int32_t glyph_id) {
|
||||
BitmapGlyphInfoPtr glyph_info =
|
||||
new BitmapGlyphInfo(glyph_id,
|
||||
image_data_offset(),
|
||||
GlyphStartOffset(glyph_id),
|
||||
GlyphLength(glyph_id),
|
||||
image_format());
|
||||
return glyph_info.Detach();
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) {
|
||||
return image_data_offset() + GlyphStartOffset(glyph_id);
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
IndexSubTable::Builder::CreateBuilder(int32_t index_format) {
|
||||
switch (index_format) {
|
||||
case Format::FORMAT_1:
|
||||
return IndexSubTableFormat1::Builder::CreateBuilder();
|
||||
case Format::FORMAT_2:
|
||||
return IndexSubTableFormat2::Builder::CreateBuilder();
|
||||
case Format::FORMAT_3:
|
||||
return IndexSubTableFormat3::Builder::CreateBuilder();
|
||||
case Format::FORMAT_4:
|
||||
return IndexSubTableFormat4::Builder::CreateBuilder();
|
||||
case Format::FORMAT_5:
|
||||
return IndexSubTableFormat5::Builder::CreateBuilder();
|
||||
default:
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IllegalArgumentException("Invalid index subtable format");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTable::Builder*
|
||||
IndexSubTable::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t offset_to_index_sub_table_array, int32_t array_index) {
|
||||
int32_t index_sub_table_entry_offset =
|
||||
offset_to_index_sub_table_array +
|
||||
array_index * EblcTable::Offset::kIndexSubTableEntryLength;
|
||||
int32_t first_glyph_index =
|
||||
data->ReadUShort(index_sub_table_entry_offset +
|
||||
EblcTable::Offset::kIndexSubTableEntry_firstGlyphIndex);
|
||||
int32_t last_glyph_index =
|
||||
data->ReadUShort(index_sub_table_entry_offset +
|
||||
EblcTable::Offset::kIndexSubTableEntry_lastGlyphIndex);
|
||||
int32_t additional_offset_to_index_subtable = data->ReadULongAsInt(
|
||||
index_sub_table_entry_offset +
|
||||
EblcTable::Offset::kIndexSubTableEntry_additionalOffsetToIndexSubTable);
|
||||
int32_t index_sub_table_offset = offset_to_index_sub_table_array +
|
||||
additional_offset_to_index_subtable;
|
||||
int32_t index_format = data->ReadUShort(index_sub_table_offset);
|
||||
switch (index_format) {
|
||||
case 1:
|
||||
return IndexSubTableFormat1::Builder::CreateBuilder(
|
||||
data, index_sub_table_offset, first_glyph_index, last_glyph_index);
|
||||
case 2:
|
||||
return IndexSubTableFormat2::Builder::CreateBuilder(
|
||||
data, index_sub_table_offset, first_glyph_index, last_glyph_index);
|
||||
case 3:
|
||||
return IndexSubTableFormat3::Builder::CreateBuilder(
|
||||
data, index_sub_table_offset, first_glyph_index, last_glyph_index);
|
||||
case 4:
|
||||
return IndexSubTableFormat4::Builder::CreateBuilder(
|
||||
data, index_sub_table_offset, first_glyph_index, last_glyph_index);
|
||||
case 5:
|
||||
return IndexSubTableFormat5::Builder::CreateBuilder(
|
||||
data, index_sub_table_offset, first_glyph_index, last_glyph_index);
|
||||
default:
|
||||
// Unknown format and unable to process.
|
||||
#if !defined (SFNTLY_NO_EXCEPTION)
|
||||
throw IllegalArgumentException("Invalid Index Subtable Format");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CALLER_ATTACH
|
||||
FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void IndexSubTable::Builder::SubDataSet() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::Builder::SubDataSizeToSerialize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IndexSubTable::Builder::SubReadyToSerialize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) {
|
||||
UNREFERENCED_PARAMETER(new_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format)
|
||||
: SubTable::Builder(data_size),
|
||||
first_glyph_index_(0),
|
||||
last_glyph_index_(0),
|
||||
index_format_(index_format),
|
||||
image_format_(0),
|
||||
image_data_offset_(0) {
|
||||
}
|
||||
|
||||
IndexSubTable::Builder::Builder(int32_t index_format,
|
||||
int32_t image_format,
|
||||
int32_t image_data_offset,
|
||||
int32_t data_size)
|
||||
: SubTable::Builder(data_size),
|
||||
first_glyph_index_(0),
|
||||
last_glyph_index_(0),
|
||||
index_format_(index_format),
|
||||
image_format_(image_format),
|
||||
image_data_offset_(image_data_offset) {
|
||||
}
|
||||
|
||||
IndexSubTable::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: SubTable::Builder(data),
|
||||
first_glyph_index_(first_glyph_index),
|
||||
last_glyph_index_(last_glyph_index) {
|
||||
Initialize(data);
|
||||
}
|
||||
|
||||
IndexSubTable::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: SubTable::Builder(data),
|
||||
first_glyph_index_(first_glyph_index),
|
||||
last_glyph_index_(last_glyph_index) {
|
||||
Initialize(data);
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) {
|
||||
return IndexSubTable::CheckGlyphRange(glyph_id,
|
||||
first_glyph_index(),
|
||||
last_glyph_index());
|
||||
}
|
||||
|
||||
int32_t IndexSubTable::Builder::SerializeIndexSubHeader(
|
||||
WritableFontData* data) {
|
||||
int32_t size =
|
||||
data->WriteUShort(EblcTable::Offset::kIndexSubHeader_indexFormat,
|
||||
index_format());
|
||||
size += data->WriteUShort(EblcTable::Offset::kIndexSubHeader_imageFormat,
|
||||
image_format());
|
||||
size += data->WriteULong(EblcTable::Offset::kIndexSubHeader_imageDataOffset,
|
||||
image_data_offset());
|
||||
return size;
|
||||
}
|
||||
|
||||
void IndexSubTable::Builder::Initialize(ReadableFontData* data) {
|
||||
index_format_ =
|
||||
data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat);
|
||||
image_format_ =
|
||||
data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
|
||||
image_data_offset_ =
|
||||
data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sfntly/port/java_iterator.h"
|
||||
#include "sfntly/table/subtable.h"
|
||||
#include "sfntly/table/bitmap/bitmap_glyph_info.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class IndexSubTable : public SubTable {
|
||||
public:
|
||||
struct Format {
|
||||
enum {
|
||||
FORMAT_1 = 1,
|
||||
FORMAT_2 = 2,
|
||||
FORMAT_3 = 3,
|
||||
FORMAT_4 = 4,
|
||||
FORMAT_5 = 5,
|
||||
};
|
||||
};
|
||||
|
||||
class Builder : public SubTable::Builder {
|
||||
public:
|
||||
virtual ~Builder();
|
||||
|
||||
void Revert();
|
||||
|
||||
int32_t index_format() { return index_format_; }
|
||||
int32_t first_glyph_index() { return first_glyph_index_; }
|
||||
void set_first_glyph_index(int32_t v) { first_glyph_index_ = v; }
|
||||
int32_t last_glyph_index() { return last_glyph_index_; }
|
||||
void set_last_glyph_index(int32_t v) { last_glyph_index_ = v; }
|
||||
int32_t image_format() { return image_format_; }
|
||||
void set_image_format(int32_t v) { image_format_ = v; }
|
||||
int32_t image_data_offset() { return image_data_offset_; }
|
||||
void set_image_data_offset(int32_t v) { image_data_offset_ = v; }
|
||||
|
||||
virtual int32_t NumGlyphs() = 0;
|
||||
|
||||
// Gets the glyph info for the specified glyph id.
|
||||
// @param glyphId the glyph id to look up
|
||||
// @return the glyph info
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* GlyphInfo(int32_t glyph_id);
|
||||
|
||||
// Gets the full offset of the glyph within the EBDT table.
|
||||
// @param glyphId the glyph id
|
||||
// @return the glyph offset
|
||||
virtual int32_t GlyphOffset(int32_t glyph_id);
|
||||
|
||||
// Gets the offset of the glyph relative to the block for this index
|
||||
// subtable.
|
||||
// @param glyphId the glyph id
|
||||
// @return the glyph offset
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id) = 0;
|
||||
|
||||
// Gets the length of the glyph within the EBDT table.
|
||||
// @param glyphId the glyph id
|
||||
// @return the glyph offset
|
||||
virtual int32_t GlyphLength(int32_t glyph_id) = 0;
|
||||
|
||||
// Note: renamed from java iterator()
|
||||
CALLER_ATTACH virtual Iterator<BitmapGlyphInfo, IndexSubTable::Builder>*
|
||||
GetIterator() = 0;
|
||||
|
||||
// Static instantiation function.
|
||||
static CALLER_ATTACH Builder* CreateBuilder(int32_t index_format);
|
||||
static CALLER_ATTACH Builder*
|
||||
CreateBuilder(ReadableFontData* data,
|
||||
int32_t offset_to_index_sub_table_array,
|
||||
int32_t array_index);
|
||||
|
||||
// The following methods will never be called but they need to be here to
|
||||
// allow the BitmapSizeTable to see these methods through an abstract
|
||||
// reference.
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
protected:
|
||||
Builder(int32_t data_size, int32_t index_format);
|
||||
Builder(int32_t index_format,
|
||||
int32_t image_format,
|
||||
int32_t image_data_offset,
|
||||
int32_t data_size);
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
// Checks that the glyph id is within the correct range. If it returns the
|
||||
// offset of the glyph id from the start of the range.
|
||||
// @param glyphId
|
||||
// @return the offset of the glyphId from the start of the glyph range
|
||||
// @throws IndexOutOfBoundsException if the glyph id is not within the
|
||||
// correct range
|
||||
int32_t CheckGlyphRange(int32_t glyph_id);
|
||||
int32_t SerializeIndexSubHeader(WritableFontData* data);
|
||||
|
||||
private:
|
||||
void Initialize(ReadableFontData* data);
|
||||
|
||||
int32_t first_glyph_index_;
|
||||
int32_t last_glyph_index_;
|
||||
int32_t index_format_;
|
||||
int32_t image_format_;
|
||||
int32_t image_data_offset_;
|
||||
};
|
||||
|
||||
int32_t index_format() { return index_format_; }
|
||||
int32_t first_glyph_index() { return first_glyph_index_; }
|
||||
int32_t last_glyph_index() { return last_glyph_index_; }
|
||||
int32_t image_format() { return image_format_; }
|
||||
int32_t image_data_offset() { return image_data_offset_; }
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id);
|
||||
virtual int32_t GlyphOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id) = 0;
|
||||
virtual int32_t GlyphLength(int32_t glyph_id) = 0;
|
||||
virtual int32_t NumGlyphs() = 0;
|
||||
|
||||
static CALLER_ATTACH IndexSubTable*
|
||||
CreateIndexSubTable(ReadableFontData* data,
|
||||
int32_t offset_to_index_sub_table_array,
|
||||
int32_t array_index);
|
||||
|
||||
protected:
|
||||
// Note: the constructor does not implement offset/length form provided in
|
||||
// Java to avoid heavy lifting in constructors. Callers to call
|
||||
// GetDataLength() static method of the derived class to get proper
|
||||
// length and slice ahead.
|
||||
IndexSubTable(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
int32_t CheckGlyphRange(int32_t glyph_id);
|
||||
static int32_t CheckGlyphRange(int32_t glyph_id,
|
||||
int32_t first_glyph_id,
|
||||
int32_t last_glyph_id);
|
||||
|
||||
private:
|
||||
int32_t first_glyph_index_;
|
||||
int32_t last_glyph_index_;
|
||||
int32_t index_format_;
|
||||
int32_t image_format_;
|
||||
int32_t image_data_offset_;
|
||||
};
|
||||
typedef Ptr<IndexSubTable> IndexSubTablePtr;
|
||||
typedef std::vector<IndexSubTablePtr> IndexSubTableList;
|
||||
typedef Ptr<IndexSubTable::Builder> IndexSubTableBuilderPtr;
|
||||
typedef std::vector<IndexSubTableBuilderPtr> IndexSubTableBuilderList;
|
||||
typedef Iterator<BitmapGlyphInfo, IndexSubTable::Builder> BitmapGlyphInfoIter;
|
||||
typedef Ptr<BitmapGlyphInfoIter> BitmapGlyphInfoIterPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_
|
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table_format1.h"
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat1 class
|
||||
******************************************************************************/
|
||||
// static
|
||||
int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t first,
|
||||
int32_t last) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(offset);
|
||||
return (last - first + 1 + 1) * DataSize::kULONG;
|
||||
}
|
||||
|
||||
IndexSubTableFormat1::~IndexSubTableFormat1() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::NumGlyphs() {
|
||||
return last_glyph_index() - first_glyph_index() + 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return Loca(loca);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return Loca(loca + 1) - Loca(loca);
|
||||
}
|
||||
|
||||
IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Loca(int32_t loca) {
|
||||
return image_data_offset() +
|
||||
data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable1_offsetArray +
|
||||
loca * DataSize::kULONG);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat1::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat1::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Builder::NumGlyphs() {
|
||||
return GetOffsetArray()->size() - 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Builder::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return 0;
|
||||
}
|
||||
std::vector<int32_t>* offset_array = GetOffsetArray();
|
||||
return offset_array->at(loca + 1) - offset_array->at(loca);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Builder::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return GetOffsetArray()->at(loca);
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*
|
||||
IndexSubTableFormat1::Builder::GetIterator() {
|
||||
Ptr<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator> it =
|
||||
new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this);
|
||||
return it.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat1::Builder*
|
||||
IndexSubTableFormat1::Builder::CreateBuilder() {
|
||||
IndexSubTableFormat1BuilderPtr output = new IndexSubTableFormat1::Builder();
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat1::Builder*
|
||||
IndexSubTableFormat1::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
if (new_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexSubTableFormat1BuilderPtr output =
|
||||
new IndexSubTableFormat1::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat1::Builder*
|
||||
IndexSubTableFormat1::Builder::CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
WritableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<WritableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
IndexSubTableFormat1BuilderPtr output =
|
||||
new IndexSubTableFormat1::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable* IndexSubTableFormat1::Builder::SubBuildTable(
|
||||
ReadableFontData* data) {
|
||||
IndexSubTableFormat1Ptr output = new IndexSubTableFormat1(
|
||||
data, first_glyph_index(), last_glyph_index());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat1::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() {
|
||||
if (offset_array_.empty()) {
|
||||
return InternalReadData()->Length();
|
||||
}
|
||||
return EblcTable::Offset::kIndexSubHeaderLength +
|
||||
offset_array_.size() * DataSize::kULONG;
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat1::Builder::SubReadyToSerialize() {
|
||||
if (!offset_array_.empty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat1::Builder::SubSerialize(
|
||||
WritableFontData* new_data) {
|
||||
int32_t size = SerializeIndexSubHeader(new_data);
|
||||
if (!model_changed()) {
|
||||
if (InternalReadData() == NULL) {
|
||||
return size;
|
||||
}
|
||||
ReadableFontDataPtr source;
|
||||
WritableFontDataPtr target;
|
||||
source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable1_offsetArray)));
|
||||
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
|
||||
EblcTable::Offset::kIndexSubTable1_offsetArray)));
|
||||
size += source->CopyTo(target);
|
||||
} else {
|
||||
for (std::vector<int32_t>::iterator b = GetOffsetArray()->begin(),
|
||||
e = GetOffsetArray()->end(); b != e; b++) {
|
||||
size += new_data->WriteLong(size, *b);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
std::vector<int32_t>* IndexSubTableFormat1::Builder::OffsetArray() {
|
||||
return GetOffsetArray();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat1::Builder::SetOffsetArray(
|
||||
const std::vector<int32_t>& offset_array) {
|
||||
offset_array_.clear();
|
||||
offset_array_ = offset_array;
|
||||
set_model_changed();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat1::Builder::Revert() {
|
||||
offset_array_.clear();
|
||||
IndexSubTable::Builder::Revert();
|
||||
}
|
||||
|
||||
IndexSubTableFormat1::Builder::Builder()
|
||||
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable1_builderDataSize,
|
||||
IndexSubTable::Format::FORMAT_1) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat1::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat1::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
std::vector<int32_t>* IndexSubTableFormat1::Builder::GetOffsetArray() {
|
||||
if (offset_array_.empty()) {
|
||||
Initialize(InternalReadData());
|
||||
set_model_changed();
|
||||
}
|
||||
return &offset_array_;
|
||||
}
|
||||
|
||||
void IndexSubTableFormat1::Builder::Initialize(ReadableFontData* data) {
|
||||
offset_array_.clear();
|
||||
if (data) {
|
||||
int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
|
||||
for (int32_t i = 0; i < num_offsets; ++i) {
|
||||
offset_array_.push_back(data->ReadULongAsInt(
|
||||
EblcTable::Offset::kIndexSubTable1_offsetArray +
|
||||
i * DataSize::kULONG));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat1::Builder::DataLength(
|
||||
ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(index_sub_table_offset);
|
||||
return EblcTable::Offset::kIndexSubHeaderLength +
|
||||
(last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kULONG;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
IndexSubTableFormat1::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat1::Builder,
|
||||
IndexSubTable::Builder>(container) {
|
||||
glyph_id_ = container->first_glyph_index();
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (glyph_id_ <= container()->last_glyph_index()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo*
|
||||
IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
BitmapGlyphInfoPtr output;
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
output = new BitmapGlyphInfo(glyph_id_,
|
||||
container()->image_data_offset(),
|
||||
container()->GlyphStartOffset(glyph_id_),
|
||||
container()->GlyphLength(glyph_id_),
|
||||
container()->image_format());
|
||||
glyph_id_++;
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_
|
||||
|
||||
#include "sfntly/port/java_iterator.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
// Format 1 Index Subtable Entry.
|
||||
class IndexSubTableFormat1 : public IndexSubTable,
|
||||
public RefCounted<IndexSubTableFormat1> {
|
||||
public:
|
||||
class Builder : public IndexSubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator
|
||||
: public RefIterator<BitmapGlyphInfo, Builder, IndexSubTable::Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
int32_t glyph_id_;
|
||||
};
|
||||
|
||||
virtual ~Builder();
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
std::vector<int32_t>* OffsetArray();
|
||||
void SetOffsetArray(const std::vector<int32_t>& offset_array);
|
||||
CALLER_ATTACH BitmapGlyphInfoIter* Iterator();
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
protected:
|
||||
void Revert();
|
||||
|
||||
private:
|
||||
Builder();
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
std::vector<int32_t>* GetOffsetArray();
|
||||
void Initialize(ReadableFontData* data);
|
||||
|
||||
static int32_t DataLength(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
std::vector<int32_t> offset_array_;
|
||||
};
|
||||
|
||||
virtual ~IndexSubTableFormat1();
|
||||
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
|
||||
static int32_t GetDataLength(ReadableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t first,
|
||||
int32_t last);
|
||||
|
||||
private:
|
||||
IndexSubTableFormat1(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
int32_t Loca(int32_t loca_index);
|
||||
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<IndexSubTableFormat1> IndexSubTableFormat1Ptr;
|
||||
typedef Ptr<IndexSubTableFormat1::Builder> IndexSubTableFormat1BuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_
|
|
@ -1,275 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table_format2.h"
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat2 class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat2::~IndexSubTableFormat2() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::ImageSize() {
|
||||
return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize);
|
||||
}
|
||||
|
||||
CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::BigMetrics() {
|
||||
ReadableFontDataPtr slice;
|
||||
slice.Attach(down_cast<ReadableFontData*>(
|
||||
data_->Slice(EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics,
|
||||
BigGlyphMetrics::Offset::kMetricsLength)));
|
||||
BigGlyphMetricsPtr output = new BigGlyphMetrics(slice);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::NumGlyphs() {
|
||||
return last_glyph_index() - first_glyph_index() + 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return loca * image_size_;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) {
|
||||
if (CheckGlyphRange(glyph_id) == -1) {
|
||||
return 0;
|
||||
}
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data,
|
||||
int32_t first,
|
||||
int32_t last)
|
||||
: IndexSubTable(data, first, last) {
|
||||
image_size_ =
|
||||
data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat2::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat2::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::NumGlyphs() {
|
||||
return last_glyph_index() - first_glyph_index() + 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return loca * ImageSize();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return 0;
|
||||
}
|
||||
return ImageSize();
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*
|
||||
IndexSubTableFormat2::Builder::GetIterator() {
|
||||
Ptr<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator> it =
|
||||
new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this);
|
||||
return it.Detach();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::ImageSize() {
|
||||
return InternalReadData()->ReadULongAsInt(
|
||||
EblcTable::Offset::kIndexSubTable2_imageSize);
|
||||
}
|
||||
|
||||
void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) {
|
||||
InternalWriteData()->WriteULong(EblcTable::Offset::kIndexSubTable2_imageSize,
|
||||
image_size);
|
||||
}
|
||||
|
||||
BigGlyphMetrics::Builder* IndexSubTableFormat2::Builder::BigMetrics() {
|
||||
if (metrics_ == NULL) {
|
||||
WritableFontDataPtr data;
|
||||
data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics,
|
||||
BigGlyphMetrics::Offset::kMetricsLength)));
|
||||
metrics_ = new BigGlyphMetrics::Builder(data);
|
||||
}
|
||||
return metrics_;
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat2::Builder*
|
||||
IndexSubTableFormat2::Builder::CreateBuilder() {
|
||||
IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder();
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat2::Builder*
|
||||
IndexSubTableFormat2::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
if (new_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexSubTableFormat2BuilderPtr output =
|
||||
new IndexSubTableFormat2::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat2::Builder*
|
||||
IndexSubTableFormat2::Builder::CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
WritableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<WritableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
IndexSubTableFormat2BuilderPtr output =
|
||||
new IndexSubTableFormat2::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable(
|
||||
ReadableFontData* data) {
|
||||
IndexSubTableFormat2Ptr output = new IndexSubTableFormat2(
|
||||
data, first_glyph_index(), last_glyph_index());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat2::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() {
|
||||
return EblcTable::Offset::kIndexSubTable2Length;
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat2::Builder::SubReadyToSerialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat2::Builder::SubSerialize(
|
||||
WritableFontData* new_data) {
|
||||
int32_t size = SerializeIndexSubHeader(new_data);
|
||||
if (metrics_ == NULL) {
|
||||
ReadableFontDataPtr source;
|
||||
WritableFontDataPtr target;
|
||||
source.Attach(down_cast<ReadableFontData*>(
|
||||
InternalReadData()->Slice(size)));
|
||||
target.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
|
||||
size += source->CopyTo(target);
|
||||
} else {
|
||||
WritableFontDataPtr slice;
|
||||
size += new_data->WriteLong(EblcTable::Offset::kIndexSubTable2_imageSize,
|
||||
ImageSize());
|
||||
slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
|
||||
size += metrics_->SubSerialize(slice);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
IndexSubTableFormat2::Builder::Builder()
|
||||
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize,
|
||||
IndexSubTable::Format::FORMAT_2) {
|
||||
metrics_.Attach(BigGlyphMetrics::Builder::CreateBuilder());
|
||||
}
|
||||
|
||||
IndexSubTableFormat2::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat2::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat2::Builder::DataLength(
|
||||
ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(index_sub_table_offset);
|
||||
UNREFERENCED_PARAMETER(first_glyph_index);
|
||||
UNREFERENCED_PARAMETER(last_glyph_index);
|
||||
return EblcTable::Offset::kIndexSubTable2Length;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
IndexSubTableFormat2::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat2::Builder,
|
||||
IndexSubTable::Builder>(container) {
|
||||
glyph_id_ = container->first_glyph_index();
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (glyph_id_ <= container()->last_glyph_index()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo*
|
||||
IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
BitmapGlyphInfoPtr output;
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
output = new BitmapGlyphInfo(glyph_id_,
|
||||
container()->image_data_offset(),
|
||||
container()->GlyphStartOffset(glyph_id_),
|
||||
container()->GlyphLength(glyph_id_),
|
||||
container()->image_format());
|
||||
glyph_id_++;
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT2_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT2_H_
|
||||
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
#include "sfntly/table/bitmap/big_glyph_metrics.h"
|
||||
|
||||
namespace sfntly {
|
||||
// Format 2 Index Subtable Entry.
|
||||
class IndexSubTableFormat2 : public IndexSubTable,
|
||||
public RefCounted<IndexSubTableFormat2> {
|
||||
public:
|
||||
class Builder : public IndexSubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator
|
||||
: public RefIterator<BitmapGlyphInfo, Builder, IndexSubTable::Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
int32_t glyph_id_;
|
||||
};
|
||||
|
||||
virtual ~Builder();
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
int32_t ImageSize();
|
||||
void SetImageSize(int32_t image_size);
|
||||
BigGlyphMetrics::Builder* BigMetrics();
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
private:
|
||||
Builder();
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
static int32_t DataLength(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
BigGlyphMetricsBuilderPtr metrics_;
|
||||
};
|
||||
|
||||
virtual ~IndexSubTableFormat2();
|
||||
|
||||
int32_t ImageSize();
|
||||
CALLER_ATTACH BigGlyphMetrics* BigMetrics();
|
||||
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
|
||||
private:
|
||||
IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last);
|
||||
|
||||
int32_t image_size_;
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<IndexSubTableFormat2> IndexSubTableFormat2Ptr;
|
||||
typedef Ptr<IndexSubTableFormat2::Builder> IndexSubTableFormat2BuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_
|
|
@ -1,298 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table_format3.h"
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat3 class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat3::~IndexSubTableFormat3() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::NumGlyphs() {
|
||||
return last_glyph_index() - first_glyph_index() + 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca != -1) {
|
||||
return Loca(loca);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca != -1) {
|
||||
return Loca(glyph_id + 1) - Loca(glyph_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t first,
|
||||
int32_t last) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(offset);
|
||||
return (last - first + 1 + 1) * DataSize::kUSHORT;
|
||||
}
|
||||
|
||||
IndexSubTableFormat3::IndexSubTableFormat3(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Loca(int32_t loca) {
|
||||
int32_t read_offset =
|
||||
data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray +
|
||||
loca * DataSize::kUSHORT);
|
||||
return read_offset;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat3::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat3::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Builder::NumGlyphs() {
|
||||
return GetOffsetArray()->size() - 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
return GetOffsetArray()->at(loca);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return 0;
|
||||
}
|
||||
std::vector<int32_t>* offset_array = GetOffsetArray();
|
||||
return offset_array->at(loca + 1) - offset_array->at(loca);
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*
|
||||
IndexSubTableFormat3::Builder::GetIterator() {
|
||||
Ptr<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator> it =
|
||||
new IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator(this);
|
||||
return it.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat3::Builder::Revert() {
|
||||
offset_array_.clear();
|
||||
IndexSubTable::Builder::Revert();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat3::Builder::SetOffsetArray(
|
||||
const std::vector<int32_t>& offset_array) {
|
||||
offset_array_.clear();
|
||||
offset_array_ = offset_array;
|
||||
set_model_changed();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat3::Builder*
|
||||
IndexSubTableFormat3::Builder::CreateBuilder() {
|
||||
IndexSubTableFormat3BuilderPtr output = new IndexSubTableFormat3::Builder();
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat3::Builder*
|
||||
IndexSubTableFormat3::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
if (new_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexSubTableFormat3BuilderPtr output =
|
||||
new IndexSubTableFormat3::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat3::Builder*
|
||||
IndexSubTableFormat3::Builder::CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
WritableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<WritableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
IndexSubTableFormat3BuilderPtr output =
|
||||
new IndexSubTableFormat3::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable* IndexSubTableFormat3::Builder::SubBuildTable(
|
||||
ReadableFontData* data) {
|
||||
IndexSubTableFormat3Ptr output = new IndexSubTableFormat3(
|
||||
data, first_glyph_index(), last_glyph_index());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat3::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() {
|
||||
if (offset_array_.empty()) {
|
||||
return InternalReadData()->Length();
|
||||
}
|
||||
return EblcTable::Offset::kIndexSubHeaderLength +
|
||||
offset_array_.size() * DataSize::kULONG;
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat3::Builder::SubReadyToSerialize() {
|
||||
if (!offset_array_.empty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat3::Builder::SubSerialize(
|
||||
WritableFontData* new_data) {
|
||||
int32_t size = SerializeIndexSubHeader(new_data);
|
||||
if (!model_changed()) {
|
||||
if (InternalReadData() == NULL) {
|
||||
return size;
|
||||
}
|
||||
ReadableFontDataPtr source;
|
||||
WritableFontDataPtr target;
|
||||
source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable3_offsetArray)));
|
||||
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
|
||||
EblcTable::Offset::kIndexSubTable3_offsetArray)));
|
||||
size += source->CopyTo(target);
|
||||
} else {
|
||||
for (std::vector<int32_t>::iterator b = GetOffsetArray()->begin(),
|
||||
e = GetOffsetArray()->end(); b != e; b++) {
|
||||
size += new_data->WriteUShort(size, *b);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
IndexSubTableFormat3::Builder::Builder()
|
||||
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize,
|
||||
IndexSubTable::Format::FORMAT_3) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat3::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat3::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
std::vector<int32_t>* IndexSubTableFormat3::Builder::GetOffsetArray() {
|
||||
if (offset_array_.empty()) {
|
||||
Initialize(InternalReadData());
|
||||
set_model_changed();
|
||||
}
|
||||
return &offset_array_;
|
||||
}
|
||||
|
||||
void IndexSubTableFormat3::Builder::Initialize(ReadableFontData* data) {
|
||||
offset_array_.clear();
|
||||
if (data) {
|
||||
int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
|
||||
for (int32_t i = 0; i < num_offsets; ++i) {
|
||||
offset_array_.push_back(data->ReadUShort(
|
||||
EblcTable::Offset::kIndexSubTable3_offsetArray +
|
||||
i * DataSize::kUSHORT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat3::Builder::DataLength(
|
||||
ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(index_sub_table_offset);
|
||||
return EblcTable::Offset::kIndexSubHeaderLength +
|
||||
(last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kUSHORT;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
IndexSubTableFormat3::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat3::Builder,
|
||||
IndexSubTable::Builder>(container) {
|
||||
glyph_id_ = container->first_glyph_index();
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (glyph_id_ <= container()->last_glyph_index()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo*
|
||||
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
BitmapGlyphInfoPtr output;
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
output = new BitmapGlyphInfo(glyph_id_,
|
||||
container()->image_data_offset(),
|
||||
container()->GlyphStartOffset(glyph_id_),
|
||||
container()->GlyphLength(glyph_id_),
|
||||
container()->image_format());
|
||||
glyph_id_++;
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_
|
||||
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
// Format 3 Index Subtable Entry.
|
||||
class IndexSubTableFormat3 : public IndexSubTable,
|
||||
public RefCounted<IndexSubTableFormat3> {
|
||||
public:
|
||||
class Builder : public IndexSubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator
|
||||
: public RefIterator<BitmapGlyphInfo, Builder, IndexSubTable::Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
int32_t glyph_id_;
|
||||
};
|
||||
|
||||
virtual ~Builder();
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
void SetOffsetArray(const std::vector<int32_t>& offset_array);
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
protected:
|
||||
void Revert();
|
||||
|
||||
private:
|
||||
Builder();
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
std::vector<int32_t>* GetOffsetArray();
|
||||
void Initialize(ReadableFontData* data);
|
||||
|
||||
static int32_t DataLength(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
std::vector<int32_t> offset_array_;
|
||||
};
|
||||
|
||||
virtual ~IndexSubTableFormat3();
|
||||
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
|
||||
static int32_t GetDataLength(ReadableFontData* data,
|
||||
int32_t offset,
|
||||
int32_t first,
|
||||
int32_t last);
|
||||
|
||||
private:
|
||||
IndexSubTableFormat3(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
int32_t Loca(int32_t loca_index);
|
||||
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<IndexSubTableFormat3> IndexSubTableFormat3Ptr;
|
||||
typedef Ptr<IndexSubTableFormat3::Builder> IndexSubTableFormat3BuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_
|
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table_format4.h"
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat4 class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat4::~IndexSubTableFormat4() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::NumGlyphs() {
|
||||
return IndexSubTableFormat4::NumGlyphs(data_, 0);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
int32_t pair_index = FindCodeOffsetPair(glyph_id);
|
||||
if (pair_index < 0) {
|
||||
return -1;
|
||||
}
|
||||
return data_->ReadUShort(EblcTable::Offset::kIndexSubTable4_glyphArray +
|
||||
pair_index *
|
||||
EblcTable::Offset::kCodeOffsetPairLength +
|
||||
EblcTable::Offset::kCodeOffsetPair_offset);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t pair_index = FindCodeOffsetPair(glyph_id);
|
||||
if (pair_index < 0) {
|
||||
return -1;
|
||||
}
|
||||
return data_->ReadUShort(
|
||||
EblcTable::Offset::kIndexSubTable4_glyphArray +
|
||||
(pair_index + 1) * EblcTable::Offset::kCodeOffsetPairLength +
|
||||
EblcTable::Offset::kCodeOffsetPair_offset) -
|
||||
data_->ReadUShort(
|
||||
EblcTable::Offset::kIndexSubTable4_glyphArray +
|
||||
(pair_index) * EblcTable::Offset::kCodeOffsetPairLength +
|
||||
EblcTable::Offset::kCodeOffsetPair_offset);
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data,
|
||||
int32_t first,
|
||||
int32_t last)
|
||||
: IndexSubTable(data, first, last) {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) {
|
||||
return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray,
|
||||
EblcTable::Offset::kCodeOffsetPairLength,
|
||||
NumGlyphs(),
|
||||
glyph_id);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::NumGlyphs(ReadableFontData* data,
|
||||
int32_t table_offset) {
|
||||
int32_t num_glyphs = data->ReadULongAsInt(table_offset +
|
||||
EblcTable::Offset::kIndexSubTable4_numGlyphs);
|
||||
return num_glyphs;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat4::CodeOffsetPair related class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat4::CodeOffsetPair::CodeOffsetPair(int32_t glyph_code,
|
||||
int32_t offset)
|
||||
: glyph_code_(glyph_code), offset_(offset) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder()
|
||||
: CodeOffsetPair(0, 0) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder(
|
||||
int32_t glyph_code, int32_t offset)
|
||||
: CodeOffsetPair(glyph_code, offset) {
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat4::CodeOffsetPairGlyphCodeComparator::operator()(
|
||||
const CodeOffsetPair& lhs, const CodeOffsetPair& rhs) {
|
||||
return lhs.glyph_code() < rhs.glyph_code();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat4::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat4::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::NumGlyphs() {
|
||||
return GetOffsetArray()->size() - 1;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::GlyphLength(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return 0;
|
||||
}
|
||||
int32_t pair_index = FindCodeOffsetPair(glyph_id);
|
||||
if (pair_index == -1) {
|
||||
return 0;
|
||||
}
|
||||
return GetOffsetArray()->at(pair_index + 1).offset() -
|
||||
GetOffsetArray()->at(pair_index).offset();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t loca = CheckGlyphRange(glyph_id);
|
||||
if (loca == -1) {
|
||||
return -1;
|
||||
}
|
||||
int32_t pair_index = FindCodeOffsetPair(glyph_id);
|
||||
if (pair_index == -1) {
|
||||
return -1;
|
||||
}
|
||||
return GetOffsetArray()->at(pair_index).offset();
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*
|
||||
IndexSubTableFormat4::Builder::GetIterator() {
|
||||
Ptr<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator> it =
|
||||
new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this);
|
||||
return it.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat4::Builder*
|
||||
IndexSubTableFormat4::Builder::CreateBuilder() {
|
||||
IndexSubTableFormat4BuilderPtr output = new IndexSubTableFormat4::Builder();
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat4::Builder*
|
||||
IndexSubTableFormat4::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
if (new_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexSubTableFormat4BuilderPtr output =
|
||||
new IndexSubTableFormat4::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat4::Builder*
|
||||
IndexSubTableFormat4::Builder::CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
WritableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<WritableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
IndexSubTableFormat4BuilderPtr output =
|
||||
new IndexSubTableFormat4::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable* IndexSubTableFormat4::Builder::SubBuildTable(
|
||||
ReadableFontData* data) {
|
||||
IndexSubTableFormat4Ptr output = new IndexSubTableFormat4(
|
||||
data, first_glyph_index(), last_glyph_index());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat4::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::SubDataSizeToSerialize() {
|
||||
if (offset_pair_array_.empty()) {
|
||||
return InternalReadData()->Length();
|
||||
}
|
||||
return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG +
|
||||
GetOffsetArray()->size() *
|
||||
EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength;
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat4::Builder::SubReadyToSerialize() {
|
||||
if (!offset_pair_array_.empty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::SubSerialize(
|
||||
WritableFontData* new_data) {
|
||||
int32_t size = SerializeIndexSubHeader(new_data);
|
||||
if (!model_changed()) {
|
||||
if (InternalReadData() == NULL) {
|
||||
return size;
|
||||
}
|
||||
ReadableFontDataPtr source;
|
||||
WritableFontDataPtr target;
|
||||
source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable4_glyphArray)));
|
||||
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
|
||||
EblcTable::Offset::kIndexSubTable4_glyphArray)));
|
||||
size += source->CopyTo(target);
|
||||
} else {
|
||||
size += new_data->WriteLong(size, offset_pair_array_.size() - 1);
|
||||
for (std::vector<CodeOffsetPairBuilder>::iterator
|
||||
b = GetOffsetArray()->begin(), e = GetOffsetArray()->end();
|
||||
b != e; b++) {
|
||||
size += new_data->WriteUShort(size, b->glyph_code());
|
||||
size += new_data->WriteUShort(size, b->offset());
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void IndexSubTableFormat4::Builder::Revert() {
|
||||
offset_pair_array_.clear();
|
||||
IndexSubTable::Builder::Revert();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat4::Builder::SetOffsetArray(
|
||||
const std::vector<CodeOffsetPairBuilder>& pair_array) {
|
||||
offset_pair_array_.clear();
|
||||
offset_pair_array_ = pair_array;
|
||||
set_model_changed();
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::Builder::Builder()
|
||||
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable4_builderDataSize,
|
||||
Format::FORMAT_4) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat4::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
std::vector<IndexSubTableFormat4::CodeOffsetPairBuilder>*
|
||||
IndexSubTableFormat4::Builder::GetOffsetArray() {
|
||||
if (offset_pair_array_.empty()) {
|
||||
Initialize(InternalReadData());
|
||||
set_model_changed();
|
||||
}
|
||||
return &offset_pair_array_;
|
||||
}
|
||||
|
||||
void IndexSubTableFormat4::Builder::Initialize(ReadableFontData* data) {
|
||||
offset_pair_array_.clear();
|
||||
if (data) {
|
||||
int32_t num_pairs = IndexSubTableFormat4::NumGlyphs(data, 0) + 1;
|
||||
int32_t offset = EblcTable::Offset::kIndexSubTable4_glyphArray;
|
||||
for (int32_t i = 0; i < num_pairs; ++i) {
|
||||
int32_t glyph_code = data->ReadUShort(offset +
|
||||
EblcTable::Offset::kIndexSubTable4_codeOffsetPair_glyphCode);
|
||||
int32_t glyph_offset = data->ReadUShort(offset +
|
||||
EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset);
|
||||
offset += EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength;
|
||||
CodeOffsetPairBuilder pair_builder(glyph_code, glyph_offset);
|
||||
offset_pair_array_.push_back(pair_builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat4::Builder::FindCodeOffsetPair(int32_t glyph_id) {
|
||||
std::vector<CodeOffsetPairBuilder>* pair_list = GetOffsetArray();
|
||||
int32_t location = 0;
|
||||
int32_t bottom = 0;
|
||||
int32_t top = pair_list->size();
|
||||
while (top != bottom) {
|
||||
location = (top + bottom) / 2;
|
||||
CodeOffsetPairBuilder* pair = &(pair_list->at(location));
|
||||
if (glyph_id < pair->glyph_code()) {
|
||||
// location is below current location
|
||||
top = location;
|
||||
} else if (glyph_id > pair->glyph_code()) {
|
||||
// location is above current location
|
||||
bottom = location + 1;
|
||||
} else {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat4::Builder::DataLength(
|
||||
ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t num_glyphs = IndexSubTableFormat4::NumGlyphs(data,
|
||||
index_sub_table_offset);
|
||||
UNREFERENCED_PARAMETER(first_glyph_index);
|
||||
UNREFERENCED_PARAMETER(last_glyph_index);
|
||||
return EblcTable::Offset::kIndexSubTable4_glyphArray +
|
||||
num_glyphs * EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
IndexSubTableFormat4::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat4::Builder,
|
||||
IndexSubTable::Builder>(container),
|
||||
code_offset_pair_index_(0) {
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (code_offset_pair_index_ <
|
||||
(int32_t)(container()->GetOffsetArray()->size() - 1)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo*
|
||||
IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
BitmapGlyphInfoPtr output;
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
std::vector<CodeOffsetPairBuilder>* offset_array =
|
||||
container()->GetOffsetArray();
|
||||
int32_t offset = offset_array->at(code_offset_pair_index_).offset();
|
||||
int32_t next_offset = offset_array->at(code_offset_pair_index_ + 1).offset();
|
||||
int32_t glyph_code = offset_array->at(code_offset_pair_index_).glyph_code();
|
||||
output = new BitmapGlyphInfo(glyph_code,
|
||||
container()->image_data_offset(),
|
||||
offset,
|
||||
next_offset - offset,
|
||||
container()->image_format());
|
||||
code_offset_pair_index_++;
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_
|
||||
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class IndexSubTableFormat4 : public IndexSubTable,
|
||||
public RefCounted<IndexSubTableFormat4> {
|
||||
public:
|
||||
class CodeOffsetPair {
|
||||
public:
|
||||
int32_t glyph_code() const { return glyph_code_; }
|
||||
int32_t offset() const { return offset_; }
|
||||
|
||||
protected:
|
||||
CodeOffsetPair(int32_t glyph_code, int32_t offset);
|
||||
|
||||
// TODO(arthurhsu): C++ style guide prohibits protected members.
|
||||
int32_t glyph_code_;
|
||||
int32_t offset_;
|
||||
};
|
||||
|
||||
class CodeOffsetPairBuilder : public CodeOffsetPair {
|
||||
public:
|
||||
CodeOffsetPairBuilder();
|
||||
CodeOffsetPairBuilder(int32_t glyph_code, int32_t offset);
|
||||
void set_glyph_code(int32_t v) { glyph_code_ = v; }
|
||||
void set_offset(int32_t v) { offset_ = v; }
|
||||
};
|
||||
|
||||
class CodeOffsetPairGlyphCodeComparator {
|
||||
public:
|
||||
bool operator()(const CodeOffsetPair& lhs, const CodeOffsetPair& rhs);
|
||||
};
|
||||
|
||||
class Builder : public IndexSubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator
|
||||
: public RefIterator<BitmapGlyphInfo, Builder, IndexSubTable::Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
int32_t code_offset_pair_index_;
|
||||
};
|
||||
|
||||
virtual ~Builder();
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
void Revert();
|
||||
void SetOffsetArray(const std::vector<CodeOffsetPairBuilder>& pair_array);
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
private:
|
||||
Builder();
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
std::vector<CodeOffsetPairBuilder>* GetOffsetArray();
|
||||
void Initialize(ReadableFontData* data);
|
||||
int32_t FindCodeOffsetPair(int32_t glyph_id);
|
||||
|
||||
static int32_t DataLength(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
std::vector<CodeOffsetPairBuilder> offset_pair_array_;
|
||||
};
|
||||
|
||||
virtual ~IndexSubTableFormat4();
|
||||
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
|
||||
private:
|
||||
IndexSubTableFormat4(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
int32_t FindCodeOffsetPair(int32_t glyph_id);
|
||||
static int32_t NumGlyphs(ReadableFontData* data, int32_t table_offset);
|
||||
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<IndexSubTableFormat4> IndexSubTableFormat4Ptr;
|
||||
typedef Ptr<IndexSubTableFormat4::Builder> IndexSubTableFormat4BuilderPtr;
|
||||
typedef std::vector<IndexSubTableFormat4::CodeOffsetPairBuilder>
|
||||
CodeOffsetPairBuilderList;
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_
|
|
@ -1,347 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/index_sub_table_format5.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "sfntly/table/bitmap/eblc_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat5 class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat5::~IndexSubTableFormat5() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::NumGlyphs() {
|
||||
return NumGlyphs(data_, 0);
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t check = CheckGlyphRange(glyph_id);
|
||||
if (check == -1) {
|
||||
return -1;
|
||||
}
|
||||
int32_t loca = ReadFontData()->SearchUShort(
|
||||
EblcTable::Offset::kIndexSubTable5_glyphArray,
|
||||
DataSize::kUSHORT,
|
||||
NumGlyphs(),
|
||||
glyph_id);
|
||||
if (loca == -1) {
|
||||
return loca;
|
||||
}
|
||||
return loca * ImageSize();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) {
|
||||
int32_t check = CheckGlyphRange(glyph_id);
|
||||
if (check == -1) {
|
||||
return 0;
|
||||
}
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::ImageSize() {
|
||||
return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize);
|
||||
}
|
||||
|
||||
CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat5::BigMetrics() {
|
||||
ReadableFontDataPtr data;
|
||||
data.Attach(down_cast<ReadableFontData*>(data_->Slice(
|
||||
EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics,
|
||||
BigGlyphMetrics::Offset::kMetricsLength)));
|
||||
BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable(data, first_glyph_index, last_glyph_index) {
|
||||
image_size_ = data_->ReadULongAsInt(
|
||||
EblcTable::Offset::kIndexSubTable5_imageSize);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data,
|
||||
int32_t table_offset) {
|
||||
int32_t num_glyphs = data->ReadULongAsInt(table_offset +
|
||||
EblcTable::Offset::kIndexSubTable5_numGlyphs);
|
||||
return num_glyphs;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat5::Builder class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat5::Builder::~Builder() {
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::NumGlyphs() {
|
||||
return GetGlyphArray()->size();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::GlyphLength(int32_t glyph_id) {
|
||||
UNREFERENCED_PARAMETER(glyph_id);
|
||||
return ImageSize();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::GlyphStartOffset(int32_t glyph_id) {
|
||||
int32_t check = CheckGlyphRange(glyph_id);
|
||||
if (check == -1) {
|
||||
return -1;
|
||||
}
|
||||
std::vector<int32_t>* glyph_array = GetGlyphArray();
|
||||
std::vector<int32_t>::iterator it = std::find(glyph_array->begin(),
|
||||
glyph_array->end(),
|
||||
glyph_id);
|
||||
if (it == glyph_array->end()) {
|
||||
return -1;
|
||||
}
|
||||
return (it - glyph_array->begin()) * ImageSize();
|
||||
}
|
||||
|
||||
CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*
|
||||
IndexSubTableFormat5::Builder::GetIterator() {
|
||||
Ptr<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator> it =
|
||||
new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this);
|
||||
return it.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat5::Builder*
|
||||
IndexSubTableFormat5::Builder::CreateBuilder() {
|
||||
IndexSubTableFormat5BuilderPtr output = new IndexSubTableFormat5::Builder();
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat5::Builder*
|
||||
IndexSubTableFormat5::Builder::CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
ReadableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<ReadableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
if (new_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexSubTableFormat5BuilderPtr output =
|
||||
new IndexSubTableFormat5::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
// static
|
||||
CALLER_ATTACH IndexSubTableFormat5::Builder*
|
||||
IndexSubTableFormat5::Builder::CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t length = Builder::DataLength(data,
|
||||
index_sub_table_offset,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
WritableFontDataPtr new_data;
|
||||
new_data.Attach(down_cast<WritableFontData*>(
|
||||
data->Slice(index_sub_table_offset, length)));
|
||||
IndexSubTableFormat5BuilderPtr output =
|
||||
new IndexSubTableFormat5::Builder(new_data,
|
||||
first_glyph_index,
|
||||
last_glyph_index);
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable* IndexSubTableFormat5::Builder::SubBuildTable(
|
||||
ReadableFontData* data) {
|
||||
IndexSubTableFormat5Ptr output = new IndexSubTableFormat5(
|
||||
data, first_glyph_index(), last_glyph_index());
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat5::Builder::SubDataSet() {
|
||||
Revert();
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() {
|
||||
if (glyph_array_.empty()) {
|
||||
return InternalReadData()->Length();
|
||||
}
|
||||
return EblcTable::Offset::kIndexSubTable5_builderDataSize +
|
||||
glyph_array_.size() * DataSize::kUSHORT;
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat5::Builder::SubReadyToSerialize() {
|
||||
if (!glyph_array_.empty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::SubSerialize(
|
||||
WritableFontData* new_data) {
|
||||
int32_t size = SerializeIndexSubHeader(new_data);
|
||||
if (!model_changed()) {
|
||||
ReadableFontDataPtr source;
|
||||
WritableFontDataPtr target;
|
||||
source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable5_imageSize)));
|
||||
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
|
||||
EblcTable::Offset::kIndexSubTable5_imageSize)));
|
||||
size += source->CopyTo(target);
|
||||
} else {
|
||||
size += new_data->WriteULong(EblcTable::Offset::kIndexSubTable5_imageSize,
|
||||
ImageSize());
|
||||
WritableFontDataPtr slice;
|
||||
slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
|
||||
size += BigMetrics()->SubSerialize(slice);
|
||||
size += new_data->WriteULong(size, glyph_array_.size());
|
||||
for (std::vector<int32_t>::iterator b = glyph_array_.begin(), e = glyph_array_.end();
|
||||
b != e; b++) {
|
||||
size += new_data->WriteUShort(size, *b);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t IndexSubTableFormat5::Builder::ImageSize() {
|
||||
return InternalReadData()->ReadULongAsInt(
|
||||
EblcTable::Offset::kIndexSubTable5_imageSize);
|
||||
}
|
||||
|
||||
void IndexSubTableFormat5::Builder::SetImageSize(int32_t image_size) {
|
||||
InternalWriteData()->WriteULong(
|
||||
EblcTable::Offset::kIndexSubTable5_imageSize, image_size);
|
||||
}
|
||||
|
||||
BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() {
|
||||
if (metrics_ == NULL) {
|
||||
WritableFontDataPtr data;
|
||||
data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice(
|
||||
EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics,
|
||||
BigGlyphMetrics::Offset::kMetricsLength)));
|
||||
metrics_ = new BigGlyphMetrics::Builder(data);
|
||||
set_model_changed();
|
||||
}
|
||||
return metrics_;
|
||||
}
|
||||
|
||||
std::vector<int32_t>* IndexSubTableFormat5::Builder::GlyphArray() {
|
||||
return GetGlyphArray();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat5::Builder::SetGlyphArray(const std::vector<int32_t>& v) {
|
||||
glyph_array_.clear();
|
||||
glyph_array_ = v;
|
||||
set_model_changed();
|
||||
}
|
||||
|
||||
void IndexSubTableFormat5::Builder::Revert() {
|
||||
glyph_array_.clear();
|
||||
IndexSubTable::Builder::Revert();
|
||||
}
|
||||
|
||||
IndexSubTableFormat5::Builder::Builder()
|
||||
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable5_builderDataSize,
|
||||
IndexSubTable::Format::FORMAT_5) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat5::Builder::Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
IndexSubTableFormat5::Builder::Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index)
|
||||
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
|
||||
}
|
||||
|
||||
std::vector<int32_t>* IndexSubTableFormat5::Builder::GetGlyphArray() {
|
||||
if (glyph_array_.empty()) {
|
||||
Initialize(InternalReadData());
|
||||
set_model_changed();
|
||||
}
|
||||
return &glyph_array_;
|
||||
}
|
||||
|
||||
void IndexSubTableFormat5::Builder::Initialize(ReadableFontData* data) {
|
||||
glyph_array_.clear();
|
||||
if (data) {
|
||||
int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data, 0);
|
||||
for (int32_t i = 0; i < num_glyphs; ++i) {
|
||||
glyph_array_.push_back(data->ReadUShort(
|
||||
EblcTable::Offset::kIndexSubTable5_glyphArray +
|
||||
i * DataSize::kUSHORT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t IndexSubTableFormat5::Builder::DataLength(
|
||||
ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index) {
|
||||
int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data,
|
||||
index_sub_table_offset);
|
||||
UNREFERENCED_PARAMETER(first_glyph_index);
|
||||
UNREFERENCED_PARAMETER(last_glyph_index);
|
||||
return EblcTable::Offset::kIndexSubTable5_glyphArray +
|
||||
num_glyphs * DataSize::kUSHORT;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator class
|
||||
******************************************************************************/
|
||||
IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
|
||||
IndexSubTableFormat5::Builder* container)
|
||||
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat5::Builder,
|
||||
IndexSubTable::Builder>(container),
|
||||
offset_index_(0) {
|
||||
}
|
||||
|
||||
bool IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::HasNext() {
|
||||
if (offset_index_ < (int32_t)(container()->GetGlyphArray()->size())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CALLER_ATTACH BitmapGlyphInfo*
|
||||
IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::Next() {
|
||||
BitmapGlyphInfoPtr output;
|
||||
if (!HasNext()) {
|
||||
// Note: In C++, we do not throw exception when there's no element.
|
||||
return NULL;
|
||||
}
|
||||
output = new BitmapGlyphInfo(container()->GetGlyphArray()->at(offset_index_),
|
||||
container()->image_data_offset(),
|
||||
offset_index_ * container()->ImageSize(),
|
||||
container()->ImageSize(),
|
||||
container()->image_format());
|
||||
offset_index_++;
|
||||
return output.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_
|
||||
|
||||
#include "sfntly/table/bitmap/big_glyph_metrics.h"
|
||||
#include "sfntly/table/bitmap/index_sub_table.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class IndexSubTableFormat5 : public IndexSubTable,
|
||||
public RefCounted<IndexSubTableFormat5> {
|
||||
public:
|
||||
class Builder : public IndexSubTable::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
class BitmapGlyphInfoIterator
|
||||
: public RefIterator<BitmapGlyphInfo, Builder, IndexSubTable::Builder> {
|
||||
public:
|
||||
explicit BitmapGlyphInfoIterator(Builder* container);
|
||||
virtual ~BitmapGlyphInfoIterator() {}
|
||||
|
||||
virtual bool HasNext();
|
||||
CALLER_ATTACH virtual BitmapGlyphInfo* Next();
|
||||
|
||||
private:
|
||||
int32_t offset_index_;
|
||||
};
|
||||
virtual ~Builder();
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
virtual void SubDataSet();
|
||||
virtual int32_t SubDataSizeToSerialize();
|
||||
virtual bool SubReadyToSerialize();
|
||||
virtual int32_t SubSerialize(WritableFontData* new_data);
|
||||
|
||||
int32_t ImageSize();
|
||||
void SetImageSize(int32_t image_size);
|
||||
BigGlyphMetrics::Builder* BigMetrics();
|
||||
std::vector<int32_t>* GlyphArray();
|
||||
void SetGlyphArray(const std::vector<int32_t>& v);
|
||||
|
||||
static CALLER_ATTACH Builder* CreateBuilder();
|
||||
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
protected:
|
||||
void Revert();
|
||||
|
||||
private:
|
||||
Builder();
|
||||
Builder(WritableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
Builder(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
std::vector<int32_t>* GetGlyphArray();
|
||||
void Initialize(ReadableFontData* data);
|
||||
|
||||
static int32_t DataLength(ReadableFontData* data,
|
||||
int32_t index_sub_table_offset,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
std::vector<int32_t> glyph_array_;
|
||||
BigGlyphMetricsBuilderPtr metrics_;
|
||||
};
|
||||
virtual ~IndexSubTableFormat5();
|
||||
|
||||
virtual int32_t NumGlyphs();
|
||||
virtual int32_t GlyphStartOffset(int32_t glyph_id);
|
||||
virtual int32_t GlyphLength(int32_t glyph_id);
|
||||
|
||||
int32_t ImageSize();
|
||||
CALLER_ATTACH BigGlyphMetrics* BigMetrics();
|
||||
|
||||
private:
|
||||
IndexSubTableFormat5(ReadableFontData* data,
|
||||
int32_t first_glyph_index,
|
||||
int32_t last_glyph_index);
|
||||
|
||||
static int32_t NumGlyphs(ReadableFontData* dta, int32_t table_offset);
|
||||
|
||||
int32_t image_size_;
|
||||
|
||||
friend class Builder;
|
||||
};
|
||||
typedef Ptr<IndexSubTableFormat5> IndexSubTableFormat5Ptr;
|
||||
typedef Ptr<IndexSubTableFormat5::Builder> IndexSubTableFormat5BuilderPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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 "sfntly/table/bitmap/simple_bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
SimpleBitmapGlyph::SimpleBitmapGlyph(ReadableFontData* data, int32_t format)
|
||||
: BitmapGlyph(data, format) {
|
||||
}
|
||||
|
||||
SimpleBitmapGlyph::~SimpleBitmapGlyph() {
|
||||
}
|
||||
|
||||
SimpleBitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format)
|
||||
: BitmapGlyph::Builder(data, format) {
|
||||
}
|
||||
|
||||
SimpleBitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format)
|
||||
: BitmapGlyph::Builder(data, format) {
|
||||
}
|
||||
|
||||
SimpleBitmapGlyph::Builder::~Builder() {
|
||||
}
|
||||
|
||||
CALLER_ATTACH FontDataTable*
|
||||
SimpleBitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) {
|
||||
Ptr<SimpleBitmapGlyph> glyph = new SimpleBitmapGlyph(data, format());
|
||||
return glyph.Detach();
|
||||
}
|
||||
|
||||
} // namespace sfntly
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 = the "License");
|
||||
* you may not use this file 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.
|
||||
*/
|
||||
|
||||
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_
|
||||
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_
|
||||
|
||||
#include "sfntly/table/bitmap/bitmap_glyph.h"
|
||||
|
||||
namespace sfntly {
|
||||
|
||||
class SimpleBitmapGlyph : public BitmapGlyph,
|
||||
public RefCounted<SimpleBitmapGlyph> {
|
||||
public:
|
||||
class Builder : public BitmapGlyph::Builder,
|
||||
public RefCounted<Builder> {
|
||||
public:
|
||||
Builder(WritableFontData* data, int32_t format);
|
||||
Builder(ReadableFontData* data, int32_t format);
|
||||
virtual ~Builder();
|
||||
|
||||
virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
|
||||
};
|
||||
|
||||
SimpleBitmapGlyph(ReadableFontData* data, int32_t format);
|
||||
virtual ~SimpleBitmapGlyph();
|
||||
};
|
||||
typedef Ptr<SimpleBitmapGlyph> SimpleBitmapGlyphPtr;
|
||||
|
||||
} // namespace sfntly
|
||||
|
||||
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче