summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarthurhsu@google.com <arthurhsu@google.com@672e30a5-4c29-85ac-ac6d-611c735e0a51>2011-11-28 18:20:03 +0000
committerarthurhsu@google.com <arthurhsu@google.com@672e30a5-4c29-85ac-ac6d-611c735e0a51>2011-11-28 18:20:03 +0000
commit53847b66af7e0c1af9928e4da2e978ed3b7c2a25 (patch)
tree831a0fcdfbfdfcd71d869d23f6d7579bcbdcc1d1
parent5768f5055c95f4fdd9dad479ac1f56604a29aba2 (diff)
downloadsrc-53847b66af7e0c1af9928e4da2e978ed3b7c2a25.tar.gz
Finish bitmap subsetting support
git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@107 672e30a5-4c29-85ac-ac6d-611c735e0a51
-rw-r--r--sfntly/data/writable_font_data.h14
-rw-r--r--sfntly/table/bitmap/big_glyph_metrics.cc21
-rw-r--r--sfntly/table/bitmap/big_glyph_metrics.h7
-rw-r--r--sfntly/table/bitmap/bitmap_size_table.cc16
-rw-r--r--sfntly/table/bitmap/bitmap_size_table.h3
-rw-r--r--sfntly/table/bitmap/ebdt_table.h15
-rw-r--r--sfntly/table/bitmap/eblc_table.cc18
-rw-r--r--sfntly/table/bitmap/eblc_table.h16
-rw-r--r--sfntly/table/bitmap/index_sub_table.cc45
-rw-r--r--sfntly/table/bitmap/index_sub_table.h19
-rw-r--r--sfntly/table/bitmap/index_sub_table_format1.cc27
-rw-r--r--sfntly/table/bitmap/index_sub_table_format1.h2
-rw-r--r--sfntly/table/bitmap/index_sub_table_format2.cc60
-rw-r--r--sfntly/table/bitmap/index_sub_table_format2.h9
-rw-r--r--sfntly/table/bitmap/index_sub_table_format3.cc27
-rw-r--r--sfntly/table/bitmap/index_sub_table_format3.h2
-rw-r--r--sfntly/table/bitmap/index_sub_table_format4.cc37
-rw-r--r--sfntly/table/bitmap/index_sub_table_format4.h6
-rw-r--r--sfntly/table/bitmap/index_sub_table_format5.cc64
-rw-r--r--sfntly/table/bitmap/index_sub_table_format5.h5
-rw-r--r--sfntly/table/font_data_table.cc7
-rw-r--r--sfntly/table/font_data_table.h8
-rw-r--r--sfntly/table/subtable.cc5
-rw-r--r--sfntly/table/subtable.h3
-rw-r--r--test/bitmap_table_test.cc112
-rwxr-xr-xtest/serialization_test.cc55
-rw-r--r--test/subsetter_impl.cc372
-rw-r--r--test/subsetter_impl.h7
-rw-r--r--test/test_data.cc7
-rw-r--r--test/test_data.h2
30 files changed, 694 insertions, 297 deletions
diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h
index f88a986..d2a049e 100644
--- a/sfntly/data/writable_font_data.h
+++ b/sfntly/data/writable_font_data.h
@@ -85,16 +85,16 @@ class WritableFontData : public ReadableFontData {
int32_t length,
byte_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
+ // 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
+ // 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, byte_t pad);
diff --git a/sfntly/table/bitmap/big_glyph_metrics.cc b/sfntly/table/bitmap/big_glyph_metrics.cc
index d2519cd..2a30829 100644
--- a/sfntly/table/bitmap/big_glyph_metrics.cc
+++ b/sfntly/table/bitmap/big_glyph_metrics.cc
@@ -137,6 +137,18 @@ void BigGlyphMetrics::Builder::SetVertAdvance(byte_t advance) {
InternalWriteData()->WriteByte(Offset::kVertAdvance, advance);
}
+// Note: C++ port only
+void BigGlyphMetrics::Builder::CopyFrom(BigGlyphMetrics::Builder* source) {
+ SetHeight(static_cast<byte_t>(source->Height()));
+ SetWidth(static_cast<byte_t>(source->Width()));
+ SetHoriBearingX(static_cast<byte_t>(source->HoriBearingX()));
+ SetHoriBearingY(static_cast<byte_t>(source->HoriBearingY()));
+ SetHoriAdvance(static_cast<byte_t>(source->HoriAdvance()));
+ SetVertBearingX(static_cast<byte_t>(source->VertBearingX()));
+ SetVertBearingY(static_cast<byte_t>(source->VertBearingY()));
+ SetVertAdvance(static_cast<byte_t>(source->VertAdvance()));
+}
+
CALLER_ATTACH FontDataTable*
BigGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) {
BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
@@ -159,4 +171,13 @@ 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
diff --git a/sfntly/table/bitmap/big_glyph_metrics.h b/sfntly/table/bitmap/big_glyph_metrics.h
index 55963b4..b62aada 100644
--- a/sfntly/table/bitmap/big_glyph_metrics.h
+++ b/sfntly/table/bitmap/big_glyph_metrics.h
@@ -46,6 +46,7 @@ class BigGlyphMetrics : public GlyphMetrics,
// class to instantiate derived class with protected constructors.
explicit Builder(WritableFontData* data);
explicit Builder(ReadableFontData* data);
+
virtual ~Builder();
int32_t Height();
@@ -65,11 +66,17 @@ class BigGlyphMetrics : public GlyphMetrics,
int32_t VertAdvance();
void SetVertAdvance(byte_t advance);
+ // Note: C++ port only
+ void CopyFrom(Builder* source);
+
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);
diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc
index bde903a..6c7d731 100644
--- a/sfntly/table/bitmap/bitmap_size_table.cc
+++ b/sfntly/table/bitmap/bitmap_size_table.cc
@@ -16,8 +16,10 @@
#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"
@@ -216,10 +218,18 @@ int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() {
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);
+ size += abs(sub_table_size) + padding;
}
- return size;
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size);
+#endif
+ return variable ? -size : size;
}
bool BitmapSizeTable::Builder::SubReadyToSerialize() {
@@ -310,7 +320,7 @@ int32_t BitmapSizeTable::Builder::FlagsAsInt() {
EblcTable::Offset::kBitmapSizeTable_flags);
}
-IndexSubTable::Builder* BitmapSizeTable::Builder::GetIndexSubTable(
+IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder(
int32_t index) {
IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders();
return sub_table_list->at(index);
diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h
index 4f4a961..6733e20 100644
--- a/sfntly/table/bitmap/bitmap_size_table.h
+++ b/sfntly/table/bitmap/bitmap_size_table.h
@@ -96,8 +96,7 @@ class BitmapSizeTable : public SubTable,
int32_t BitDepth();
int32_t FlagsAsInt();
- // Note: renamed from indexSubTable()
- IndexSubTable::Builder* GetIndexSubTable(int32_t index);
+ 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);
diff --git a/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h
index 79852c3..d138c14 100644
--- a/sfntly/table/bitmap/ebdt_table.h
+++ b/sfntly/table/bitmap/ebdt_table.h
@@ -26,6 +26,13 @@ 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:
@@ -90,15 +97,7 @@ class EbdtTable : public SubTableContainerTable,
CALLER_ATTACH BitmapGlyph* Glyph(int32_t offset,
int32_t length,
int32_t format);
-
protected:
- struct Offset {
- enum {
- kVersion = 0,
- kHeaderLength = DataSize::kFixed,
- };
- };
-
EbdtTable(Header* header, ReadableFontData* data);
};
typedef Ptr<EbdtTable> EbdtTablePtr;
diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc
index 6691b04..0ad2764 100644
--- a/sfntly/table/bitmap/eblc_table.cc
+++ b/sfntly/table/bitmap/eblc_table.cc
@@ -16,6 +16,7 @@
#include "sfntly/table/bitmap/eblc_table.h"
+#include <stdio.h>
#include <stdlib.h>
#include "sfntly/math/font_math.h"
@@ -131,7 +132,8 @@ int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
#if defined (SFNTLY_DEBUG_BITMAP)
fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ",
- size_index, size_table_offset);
+ 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;
@@ -209,16 +211,24 @@ int32_t EblcTable::Builder::SubDataSizeToSerialize() {
}
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);
}
- return -size;
- // TODO(stuartg): need to fix to get size calculated accurately
- // return variable ? -size : size;
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "eblc size=%d\n", size);
+#endif
+ return variable ? -size : size;
}
void EblcTable::Builder::SubDataSet() {
diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h
index 3a9b4c4..b04338a 100644
--- a/sfntly/table/bitmap/eblc_table.h
+++ b/sfntly/table/bitmap/eblc_table.h
@@ -18,6 +18,7 @@
#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"
@@ -81,16 +82,21 @@ class EblcTable : public SubTableContainerTable,
// indexSubTable1
kIndexSubTable1_offsetArray = kIndexSubHeaderLength,
+ kIndexSubTable1_builderDataSize = kIndexSubHeaderLength,
// kIndexSubTable2
kIndexSubTable2Length = kIndexSubHeaderLength +
DataSize::kULONG +
BitmapGlyph::Offset::kBigGlyphMetricsLength,
kIndexSubTable2_imageSize = kIndexSubHeaderLength,
- kIndexSubTable2_bigGlyphMetrics = kIndexSubTable2_imageSize + 4,
+ 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,
@@ -99,15 +105,17 @@ class EblcTable : public SubTableContainerTable,
kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT,
kIndexSubTable4_codeOffsetPair_glyphCode = 0,
kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT,
+ kIndexSubTable4_builderDataSize = kIndexSubTable4_glyphArray,
// kIndexSubTable5
kIndexSubTable5_imageSize = kIndexSubHeaderLength,
- kIndexSubTable5_bigMetrics = kIndexSubTable5_imageSize +
- DataSize::kULONG,
- kIndexSubTable5_numGlyphs = kIndexSubTable5_bigMetrics +
+ 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,
diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc
index 80c0ffe..d302aed 100644
--- a/sfntly/table/bitmap/index_sub_table.cc
+++ b/sfntly/table/bitmap/index_sub_table.cc
@@ -121,6 +121,28 @@ int32_t IndexSubTable::Builder::GlyphOffset(int32_t 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 =
@@ -171,6 +193,7 @@ FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) {
}
void IndexSubTable::Builder::SubDataSet() {
+ // NOP
}
int32_t IndexSubTable::Builder::SubDataSizeToSerialize() {
@@ -186,6 +209,20 @@ int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) {
return 0;
}
+IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format)
+ : SubTable::Builder(data_size), index_format_(index_format) {
+}
+
+IndexSubTable::Builder::Builder(int32_t index_format,
+ int32_t image_format,
+ int32_t image_data_offset,
+ int32_t data_size)
+ : SubTable::Builder(data_size),
+ 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)
@@ -204,14 +241,6 @@ IndexSubTable::Builder::Builder(ReadableFontData* data,
Initialize(data);
}
-IndexSubTable::Builder::Builder(int32_t index_format,
- int32_t image_format,
- int32_t image_data_offset)
- : index_format_(index_format),
- image_format_(image_format),
- image_data_offset_(image_data_offset) {
-}
-
int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) {
return IndexSubTable::CheckGlyphRange(glyph_id,
first_glyph_index(),
diff --git a/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h
index 0993e76..6d27129 100644
--- a/sfntly/table/bitmap/index_sub_table.h
+++ b/sfntly/table/bitmap/index_sub_table.h
@@ -27,6 +27,16 @@ 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();
@@ -71,6 +81,7 @@ class IndexSubTable : public SubTable {
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,
@@ -86,15 +97,17 @@ class IndexSubTable : public SubTable {
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);
- Builder(int32_t index_format,
- int32_t image_format,
- int32_t image_data_offset);
// 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.
diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc
index 634fbb0..db73723 100644
--- a/sfntly/table/bitmap/index_sub_table_format1.cc
+++ b/sfntly/table/bitmap/index_sub_table_format1.cc
@@ -103,6 +103,13 @@ CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*
// 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,
@@ -155,7 +162,7 @@ void IndexSubTableFormat1::Builder::SubDataSet() {
int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() {
if (offset_array_.empty()) {
- return 0;
+ return InternalReadData()->Length();
}
return EblcTable::Offset::kIndexSubHeaderLength +
offset_array_.size() * DataSize::kULONG;
@@ -172,6 +179,9 @@ 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(
@@ -179,11 +189,11 @@ int32_t IndexSubTableFormat1::Builder::SubSerialize(
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
EblcTable::Offset::kIndexSubTable1_offsetArray)));
size += source->CopyTo(target);
- return size;
- }
- for (IntegerList::iterator b = GetOffsetArray()->begin(),
- e = GetOffsetArray()->end(); b != e; b++) {
- size += new_data->WriteLong(size, *b);
+ } else {
+ for (IntegerList::iterator b = GetOffsetArray()->begin(),
+ e = GetOffsetArray()->end(); b != e; b++) {
+ size += new_data->WriteLong(size, *b);
+ }
}
return size;
}
@@ -204,6 +214,11 @@ void IndexSubTableFormat1::Builder::Revert() {
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)
diff --git a/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h
index 1078831..33171c1 100644
--- a/sfntly/table/bitmap/index_sub_table_format1.h
+++ b/sfntly/table/bitmap/index_sub_table_format1.h
@@ -57,6 +57,7 @@ class IndexSubTableFormat1 : public IndexSubTable,
void SetOffsetArray(const IntegerList& 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,
@@ -70,6 +71,7 @@ class IndexSubTableFormat1 : public IndexSubTable,
void Revert();
private:
+ Builder();
Builder(WritableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index);
diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc
index 58881f4..b3bffda 100644
--- a/sfntly/table/bitmap/index_sub_table_format2.cc
+++ b/sfntly/table/bitmap/index_sub_table_format2.cc
@@ -25,6 +25,19 @@ namespace sfntly {
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;
}
@@ -95,12 +108,21 @@ void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) {
image_size);
}
-CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::Builder::BigMetrics() {
- WritableFontDataPtr data;
- data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice(
- EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics,
- BigGlyphMetrics::Offset::kMetricsLength)));
- BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
+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();
}
@@ -152,6 +174,7 @@ CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable(
}
void IndexSubTableFormat2::Builder::SubDataSet() {
+ Revert();
}
int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() {
@@ -165,14 +188,29 @@ bool IndexSubTableFormat2::Builder::SubReadyToSerialize() {
int32_t IndexSubTableFormat2::Builder::SubSerialize(
WritableFontData* new_data) {
int32_t size = SerializeIndexSubHeader(new_data);
- 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);
+ 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)
diff --git a/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h
index 52a9ae0..784e8a3 100644
--- a/sfntly/table/bitmap/index_sub_table_format2.h
+++ b/sfntly/table/bitmap/index_sub_table_format2.h
@@ -55,8 +55,9 @@ class IndexSubTableFormat2 : public IndexSubTable,
int32_t ImageSize();
void SetImageSize(int32_t image_size);
- CALLER_ATTACH BigGlyphMetrics* BigMetrics();
+ 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,
@@ -66,6 +67,7 @@ class IndexSubTableFormat2 : public IndexSubTable,
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);
@@ -77,10 +79,15 @@ class IndexSubTableFormat2 : public IndexSubTable,
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);
diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc
index eedc500..b3e418f 100644
--- a/sfntly/table/bitmap/index_sub_table_format3.cc
+++ b/sfntly/table/bitmap/index_sub_table_format3.cc
@@ -116,6 +116,13 @@ void IndexSubTableFormat3::Builder::SetOffsetArray(
// 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,
@@ -167,7 +174,7 @@ void IndexSubTableFormat3::Builder::SubDataSet() {
int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() {
if (offset_array_.empty()) {
- return 0;
+ return InternalReadData()->Length();
}
return EblcTable::Offset::kIndexSubHeaderLength +
offset_array_.size() * DataSize::kULONG;
@@ -184,6 +191,9 @@ 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(
@@ -191,15 +201,20 @@ int32_t IndexSubTableFormat3::Builder::SubSerialize(
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
EblcTable::Offset::kIndexSubTable3_offsetArray)));
size += source->CopyTo(target);
- return size;
- }
- for (IntegerList::iterator b = GetOffsetArray()->begin(),
- e = GetOffsetArray()->end(); b != e; b++) {
- size += new_data->WriteUShort(size, *b);
+ } else {
+ for (IntegerList::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)
diff --git a/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h
index e9f1fa2..d71f857 100644
--- a/sfntly/table/bitmap/index_sub_table_format3.h
+++ b/sfntly/table/bitmap/index_sub_table_format3.h
@@ -54,6 +54,7 @@ class IndexSubTableFormat3 : public IndexSubTable,
void SetOffsetArray(const IntegerList& 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,
@@ -67,6 +68,7 @@ class IndexSubTableFormat3 : public IndexSubTable,
void Revert();
private:
+ Builder();
Builder(WritableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index);
diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc
index 898e288..23f3e47 100644
--- a/sfntly/table/bitmap/index_sub_table_format4.cc
+++ b/sfntly/table/bitmap/index_sub_table_format4.cc
@@ -150,6 +150,13 @@ CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*
// 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,
@@ -201,11 +208,11 @@ void IndexSubTableFormat4::Builder::SubDataSet() {
int32_t IndexSubTableFormat4::Builder::SubDataSizeToSerialize() {
if (offset_pair_array_.empty()) {
- return 0;
+ return InternalReadData()->Length();
}
return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG +
GetOffsetArray()->size() *
- EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset;
+ EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength;
}
bool IndexSubTableFormat4::Builder::SubReadyToSerialize() {
@@ -219,6 +226,9 @@ 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(
@@ -226,15 +236,14 @@ int32_t IndexSubTableFormat4::Builder::SubSerialize(
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
EblcTable::Offset::kIndexSubTable4_glyphArray)));
size += source->CopyTo(target);
- return size;
- }
-
- 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());
+ } 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;
}
@@ -251,6 +260,11 @@ void IndexSubTableFormat4::Builder::SetOffsetArray(
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)
@@ -282,6 +296,7 @@ void IndexSubTableFormat4::Builder::Initialize(ReadableFontData* data) {
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);
}
diff --git a/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h
index be96628..efd540f 100644
--- a/sfntly/table/bitmap/index_sub_table_format4.h
+++ b/sfntly/table/bitmap/index_sub_table_format4.h
@@ -37,16 +37,12 @@ class IndexSubTableFormat4 : public IndexSubTable,
int32_t offset_;
};
- class Builder;
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; }
-
- private:
- friend class Builder;
};
class CodeOffsetPairGlyphCodeComparator {
@@ -85,6 +81,7 @@ class IndexSubTableFormat4 : public IndexSubTable,
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,
@@ -94,6 +91,7 @@ class IndexSubTableFormat4 : public IndexSubTable,
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);
diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc
index 1ddce05..b4ab1b8 100644
--- a/sfntly/table/bitmap/index_sub_table_format5.cc
+++ b/sfntly/table/bitmap/index_sub_table_format5.cc
@@ -62,7 +62,7 @@ int32_t IndexSubTableFormat5::ImageSize() {
CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat5::BigMetrics() {
ReadableFontDataPtr data;
data.Attach(down_cast<ReadableFontData*>(data_->Slice(
- EblcTable::Offset::kIndexSubTable5_bigMetrics,
+ EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics,
BigGlyphMetrics::Offset::kMetricsLength)));
BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
return output.Detach();
@@ -123,6 +123,13 @@ CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*
// 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,
@@ -169,16 +176,14 @@ CALLER_ATTACH FontDataTable* IndexSubTableFormat5::Builder::SubBuildTable(
}
void IndexSubTableFormat5::Builder::SubDataSet() {
- if (model_changed()) {
- Initialize(InternalReadData());
- }
+ Revert();
}
int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() {
if (glyph_array_.empty()) {
- return 0;
+ return InternalReadData()->Length();
}
- return EblcTable::Offset::kIndexSubHeaderLength +
+ return EblcTable::Offset::kIndexSubTable5_builderDataSize +
glyph_array_.size() * DataSize::kUSHORT;
}
@@ -200,23 +205,17 @@ int32_t IndexSubTableFormat5::Builder::SubSerialize(
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
EblcTable::Offset::kIndexSubTable5_imageSize)));
size += source->CopyTo(target);
- return size;
} else {
- ReadableFontDataPtr source;
- WritableFontDataPtr target;
- source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
- EblcTable::Offset::kIndexSubTable5_imageSize,
- EblcTable::Offset::kIndexSubTable5_numGlyphs)));
- target.Attach(down_cast<WritableFontData*>(new_data->Slice(
- EblcTable::Offset::kIndexSubTable5_imageSize,
- EblcTable::Offset::kIndexSubTable5_numGlyphs)));
- size += source->CopyTo(target);
- }
-
- size += new_data->WriteLong(size, glyph_array_.size());
- for (IntegerList::iterator b = glyph_array_.begin(), e = glyph_array_.end();
- b != e; b++) {
- size += new_data->WriteUShort(size, *b);
+ 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 (IntegerList::iterator b = glyph_array_.begin(), e = glyph_array_.end();
+ b != e; b++) {
+ size += new_data->WriteUShort(size, *b);
+ }
}
return size;
}
@@ -231,14 +230,16 @@ void IndexSubTableFormat5::Builder::SetImageSize(int32_t image_size) {
EblcTable::Offset::kIndexSubTable5_imageSize, image_size);
}
-CALLER_ATTACH
BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() {
- WritableFontDataPtr data;
- data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice(
- EblcTable::Offset::kIndexSubTable5_bigMetrics,
- BigGlyphMetrics::Offset::kMetricsLength)));
- BigGlyphMetricsBuilderPtr output = new BigGlyphMetrics::Builder(data);
- return output.Detach();
+ 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_;
}
IntegerList* IndexSubTableFormat5::Builder::GlyphArray() {
@@ -256,6 +257,11 @@ void IndexSubTableFormat5::Builder::Revert() {
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)
diff --git a/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h
index 511f1fc..a39e88c 100644
--- a/sfntly/table/bitmap/index_sub_table_format5.h
+++ b/sfntly/table/bitmap/index_sub_table_format5.h
@@ -54,10 +54,11 @@ class IndexSubTableFormat5 : public IndexSubTable,
int32_t ImageSize();
void SetImageSize(int32_t image_size);
- CALLER_ATTACH BigGlyphMetrics::Builder* BigMetrics();
+ BigGlyphMetrics::Builder* BigMetrics();
IntegerList* GlyphArray();
void SetGlyphArray(const IntegerList& v);
+ static CALLER_ATTACH Builder* CreateBuilder();
static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data,
int32_t index_sub_table_offset,
int32_t first_glyph_index,
@@ -70,6 +71,7 @@ class IndexSubTableFormat5 : public IndexSubTable,
void Revert();
private:
+ Builder();
Builder(WritableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index);
@@ -86,6 +88,7 @@ class IndexSubTableFormat5 : public IndexSubTable,
int32_t last_glyph_index);
IntegerList glyph_array_;
+ BigGlyphMetricsBuilderPtr metrics_;
};
virtual ~IndexSubTableFormat5();
diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc
index 7953269..0e27f7a 100644
--- a/sfntly/table/font_data_table.cc
+++ b/sfntly/table/font_data_table.cc
@@ -141,6 +141,13 @@ FontDataTable::Builder::Builder()
data_changed_(false) {
}
+FontDataTable::Builder::Builder(int32_t data_size)
+ : model_changed_(false),
+ contained_model_changed_(false),
+ data_changed_(false) {
+ w_data_.Attach(WritableFontData::CreateWritableFontData(data_size));
+}
+
FontDataTable::Builder::Builder(WritableFontData* data)
: model_changed_(false),
contained_model_changed_(false),
diff --git a/sfntly/table/font_data_table.h b/sfntly/table/font_data_table.h
index ce5433b..5e437e2 100644
--- a/sfntly/table/font_data_table.h
+++ b/sfntly/table/font_data_table.h
@@ -64,6 +64,14 @@ class FontDataTable : virtual public RefCount {
protected:
explicit Builder();
+
+ // Construct a FontDataTable.Builder with a WritableFontData backing store
+ // of size given. A positive size will create a fixed size backing store and
+ // a 0 or less size is an estimate for a growable backing store with the
+ // estimate being the absolute of the size.
+ // @param dataSize if positive then a fixed size; if 0 or less then an
+ // estimate for a growable size
+ Builder(int32_t data_size);
Builder(WritableFontData* data);
Builder(ReadableFontData* data);
virtual ~Builder();
diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc
index b990c7c..e5b906f 100644
--- a/sfntly/table/subtable.cc
+++ b/sfntly/table/subtable.cc
@@ -34,10 +34,11 @@ SubTable::SubTable(ReadableFontData* data)
/******************************************************************************
* SubTable::Builder class
******************************************************************************/
-SubTable::Builder::Builder() {
+SubTable::Builder::~Builder() {
}
-SubTable::Builder::~Builder() {
+SubTable::Builder::Builder(int32_t data_size)
+ : FontDataTable::Builder(data_size) {
}
SubTable::Builder::Builder(WritableFontData* data,
diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h
index 902d281..fa6f4c6 100644
--- a/sfntly/table/subtable.h
+++ b/sfntly/table/subtable.h
@@ -29,13 +29,12 @@ class SubTable : public FontDataTable {
public:
class Builder : public FontDataTable::Builder {
public:
- // Creates a new empty sub-table.
- Builder();
virtual ~Builder();
protected:
// @param data the data for the subtable being built
// @param master_data the data for the full table
+ Builder(int32_t data_size);
Builder(WritableFontData* data, ReadableFontData* master_data);
Builder(ReadableFontData* data, ReadableFontData* master_data);
explicit Builder(WritableFontData* data);
diff --git a/test/bitmap_table_test.cc b/test/bitmap_table_test.cc
index d5d718d..df3ffc0 100644
--- a/test/bitmap_table_test.cc
+++ b/test/bitmap_table_test.cc
@@ -16,9 +16,13 @@
#include "gtest/gtest.h"
#include "sfntly/font.h"
+#include "sfntly/port/file_input_stream.h"
+#include "sfntly/port/memory_input_stream.h"
+#include "sfntly/port/memory_output_stream.h"
#include "sfntly/table/bitmap/ebdt_table.h"
#include "sfntly/table/bitmap/eblc_table.h"
#include "sfntly/table/bitmap/index_sub_table_format3.h"
+#include "sfntly/table/bitmap/index_sub_table_format4.h"
#include "test/test_data.h"
#include "test/test_font_utils.h"
@@ -45,12 +49,8 @@ const int32_t STRIKE4_SUB1_GLYPH_OFFSET[] = {
const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10;
const int32_t STRIKE4_SUB1_GLYPH2_LENGTH = 0x58a2 - 0x589d;
-bool TestReadingBitmapTable() {
- FontFactoryPtr factory;
- factory.Attach(FontFactory::GetInstance());
- FontArray font_array;
- LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array);
- FontPtr font = font_array[0];
+bool CommonReadingTest(Font* raw_font) {
+ FontPtr font = raw_font;
EblcTablePtr bitmap_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
EbdtTablePtr bitmap_table = down_cast<EbdtTable*>(font->GetTable(Tag::EBDT));
@@ -64,7 +64,6 @@ bool TestReadingBitmapTable() {
BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0);
EXPECT_FALSE(strike1 == NULL);
EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET);
- EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE);
EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES);
EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF);
EXPECT_EQ(strike1->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX);
@@ -82,7 +81,6 @@ bool TestReadingBitmapTable() {
EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX);
IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0);
EXPECT_FALSE(sub1 == NULL);
- EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT);
EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT);
EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX);
EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX);
@@ -91,6 +89,24 @@ bool TestReadingBitmapTable() {
for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) {
EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]);
}
+ return true;
+}
+
+bool TestReadingBitmapTable() {
+ FontFactoryPtr factory;
+ factory.Attach(FontFactory::GetInstance());
+ FontArray font_array;
+ LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array);
+ FontPtr font = font_array[0];
+ EXPECT_TRUE(CommonReadingTest(font));
+
+ EblcTablePtr bitmap_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
+ BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0);
+ BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3);
+ IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0);
+
+ EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE);
+ EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT);
// Strike 4 Index Sub Table 1 is a Format 3
IndexSubTableFormat3Ptr sub3 =
@@ -108,8 +124,86 @@ bool TestReadingBitmapTable() {
return true;
}
+// Function in subset_impl.cc
+extern
+void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca);
+
+bool TestIndexFormatConversion() {
+ FontFactoryPtr factory;
+ factory.Attach(FontFactory::GetInstance());
+ FontBuilderArray builder_array;
+ BuilderForFontFile(SAMPLE_BITMAP_FONT, factory, &builder_array);
+
+ FontBuilderPtr font_builder;
+ font_builder = builder_array[0];
+ EblcTableBuilderPtr eblc_builder =
+ down_cast<EblcTable::Builder*>(font_builder->GetTableBuilder(Tag::EBLC));
+ BitmapLocaList new_loca;
+ eblc_builder->GenerateLocaList(&new_loca);
+ SubsetEBLC(eblc_builder, new_loca); // Format 3 -> 4
+
+ FontPtr new_font;
+ new_font.Attach(font_builder->Build());
+
+ // Serialize and reload the serialized font.
+ MemoryOutputStream os;
+ factory->SerializeFont(new_font, &os);
+
+#if defined (SFNTLY_DEBUG_BITMAP)
+ SerializeToFile(&os, "anon-mod.ttf");
+#endif
+
+ MemoryInputStream is;
+ is.Attach(os.Get(), os.Size());
+ FontArray font_array;
+ factory->LoadFonts(&is, &font_array);
+ new_font = font_array[0];
+
+ EXPECT_TRUE(CommonReadingTest(new_font));
+
+ // Strike 4 Index Sub Table 1 is a Format 4
+ EblcTablePtr bitmap_loca =
+ down_cast<EblcTable*>(new_font->GetTable(Tag::EBLC));
+ BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3);
+ IndexSubTableFormat4Ptr sub4 =
+ down_cast<IndexSubTableFormat4*>(strike4->GetIndexSubTable(0));
+ EXPECT_FALSE(sub4 == NULL);
+
+ // And this subtable shall have exactly the same offset as original table
+ // since no subsetting happens.
+ FontArray original_font_array;
+ LoadFont(SAMPLE_BITMAP_FONT, factory, &original_font_array);
+ FontPtr font = original_font_array[0];
+ EXPECT_FALSE(font == NULL);
+ EblcTablePtr original_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
+ EXPECT_FALSE(original_loca == NULL);
+ BitmapSizeTablePtr original_strike4 = bitmap_loca->GetBitmapSizeTable(3);
+ EXPECT_FALSE(original_strike4 == NULL);
+ IndexSubTableFormat3Ptr sub3 =
+ down_cast<IndexSubTableFormat3*>(strike4->GetIndexSubTable(0));
+ EXPECT_FALSE(sub3 == NULL);
+ EXPECT_EQ(strike4->StartGlyphIndex(), original_strike4->StartGlyphIndex());
+ EXPECT_EQ(strike4->EndGlyphIndex(), original_strike4->EndGlyphIndex());
+ for (int32_t i = strike4->StartGlyphIndex();
+ i <= strike4->EndGlyphIndex(); ++i) {
+ BitmapGlyphInfoPtr info, original_info;
+ info.Attach(sub4->GlyphInfo(i));
+ original_info.Attach(sub3->GlyphInfo(i));
+ EXPECT_EQ(info->format(), original_info->format());
+ EXPECT_EQ(info->glyph_id(), original_info->glyph_id());
+ EXPECT_EQ(info->length(), original_info->length());
+ EXPECT_EQ(info->offset(), original_info->offset());
+ }
+
+ return true;
+}
+
} // namespace sfntly
-TEST(BitmapTable, All) {
+TEST(BitmapTable, Reading) {
ASSERT_TRUE(sfntly::TestReadingBitmapTable());
}
+
+TEST(BitmapTable, IndexFormatConversion) {
+ ASSERT_TRUE(sfntly::TestIndexFormatConversion());
+}
diff --git a/test/serialization_test.cc b/test/serialization_test.cc
index 3df6d95..0f2f489 100755
--- a/test/serialization_test.cc
+++ b/test/serialization_test.cc
@@ -91,8 +91,61 @@ bool TestSerialization() {
return true;
}
+bool TestSerializationBitmap() {
+ FontFactoryPtr factory1, factory2, factory3;
+ factory1.Attach(FontFactory::GetInstance());
+ FontArray font_array;
+ LoadFont(SAMPLE_BITMAP_FONT, factory1, &font_array);
+ FontPtr original = font_array[0];
+
+ factory2.Attach(FontFactory::GetInstance());
+ FontBuilderArray font_builder_array;
+ BuilderForFontFile(SAMPLE_BITMAP_FONT, factory2, &font_builder_array);
+ FontBuilderPtr font_builder = font_builder_array[0];
+
+ FontPtr intermediate;
+ intermediate.Attach(font_builder->Build());
+ MemoryOutputStream os;
+ factory2->SerializeFont(intermediate, &os);
+
+ factory3.Attach(FontFactory::GetInstance());
+ FontArray new_font_array;
+ MemoryInputStream is;
+ is.Attach(os.Get(), os.Size());
+ factory3->LoadFonts(&is, &new_font_array);
+ FontPtr serialized = new_font_array[0];
+
+ // Check number of tables
+ EXPECT_EQ(original->num_tables(), serialized->num_tables());
+
+ // Check if same set of tables
+ const TableMap* original_tables = original->GetTableMap();
+ const TableMap* serialized_tables = serialized->GetTableMap();
+ EXPECT_EQ(original_tables->size(), serialized_tables->size());
+ TableMap::const_iterator not_found = serialized_tables->end();
+ for (TableMap::const_iterator b = original_tables->begin(),
+ e = original_tables->end(); b != e; ++b) {
+ EXPECT_TRUE((serialized_tables->find(b->first) != not_found));
+ }
+
+ // Check checksum equivalence
+ for (size_t i = 0; i < SAMPLE_BITMAP_KNOWN_TAGS; ++i) {
+ TablePtr original_table = original->GetTable(BITMAP_KNOWN_TAGS[i]);
+ TablePtr serialized_table = serialized->GetTable(BITMAP_KNOWN_TAGS[i]);
+ EXPECT_EQ(original_table->CalculatedChecksum(),
+ serialized_table->CalculatedChecksum());
+ EXPECT_EQ(original_table->DataLength(), serialized_table->DataLength());
+ }
+
+ return true;
+}
+
} // namespace sfntly
-TEST(Serialization, All) {
+TEST(Serialization, Simple) {
ASSERT_TRUE(sfntly::TestSerialization());
}
+
+TEST(Serialization, Bitmap) {
+ ASSERT_TRUE(sfntly::TestSerializationBitmap());
+}
diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc
index 292e83f..f36fcd2 100644
--- a/test/subsetter_impl.cc
+++ b/test/subsetter_impl.cc
@@ -39,6 +39,14 @@
#include "sfntly/port/memory_input_stream.h"
#include "sfntly/port/memory_output_stream.h"
+
+namespace {
+
+// The bitmap tables must be greater than 16KB to trigger bitmap subsetter.
+static const int BITMAP_SIZE_THRESHOLD = 16384;
+
+}
+
namespace sfntly {
void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) {
@@ -278,10 +286,16 @@ bool SetupGlyfBuilders(Font::Builder* builder,
return true;
}
-bool HasOverlap(int32_t range1_begin, int32_t range1_end,
- int32_t range2_begin, int32_t range2_end) {
- return (range2_begin < range1_end && range2_begin > range1_begin) ||
- (range1_begin < range2_end && range1_begin > range2_begin);
+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();
+ } else if (range_end > range_begin) {
+ IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin);
+ IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end);
+ return right != left;
+ }
+ return false;
}
// Initialize builder, returns false if glyph_id subset is not covered.
@@ -296,13 +310,12 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc,
// 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 inproperly will result in creation of >100K objects that
- // will be destroyed immediately and result in significant slowness.
+ // 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.begin()), *(glyph_ids.rbegin()))) {
+ (*strikes)[i]->EndGlyphIndex(), glyph_ids)) {
removed_strikes.push_back(i);
continue;
}
@@ -310,22 +323,27 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc,
IndexSubTableBuilderList* index_builders =
(*strikes)[i]->IndexSubTableBuilders();
IntegerList removed_indexes;
+ BitmapGlyphInfoMap info_map;
for (size_t j = 0; j < index_builders->size(); ++j) {
- BitmapGlyphInfoMap info_map;
+ if (!HasOverlap((*index_builders)[j]->first_glyph_index(),
+ (*index_builders)[j]->last_glyph_index(), 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++) {
BitmapGlyphInfoPtr info;
info.Attach((*index_builders)[j]->GlyphInfo(*gid));
- if (info) {
+ 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_indexes.push_back(j);
- }
+ }
+ if (!info_map.empty()) {
+ loca_list.push_back(info_map);
+ } else {
+ removed_strikes.push_back(i); // Detected null entries.
}
// Remove unused index sub tables
@@ -342,7 +360,11 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc,
// Remove unused strikes
for (IntegerList::reverse_iterator j = removed_strikes.rbegin(),
e = removed_strikes.rend(); j != e; j++) {
- strikes->erase(strikes->begin() + *j);
+ strikes->erase(strikes->begin() + *j);
+ }
+
+ if (strikes->empty()) { // no glyph covered, can safely drop the builders.
+ return false;
}
ebdt_builder->SetLoca(&loca_list);
@@ -350,134 +372,134 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc,
return true;
}
-/******************************************************************************
- * EXPERIMENTAL CODE STARTS
- *
- * The following code is used for experiment. Will obsolete once we have
- * support to create format 4 and 5 index sub tables from scratch.
- *****************************************************************************/
-void GenerateOffsetArray(int32_t first_gid, int32_t last_gid,
- const BitmapGlyphInfoMap& loca,
- IntegerList* new_offsets) {
- int32_t offset = 0;
- int32_t length = 0;
- for (int32_t i = first_gid; i <= last_gid; ++i) {
- BitmapGlyphInfoMap::const_iterator it = loca.find(i);
- if (it != loca.end()) {
- offset = it->second->offset();
- length = it->second->length();
- new_offsets->push_back(offset);
- if (i == last_gid) {
- new_offsets->push_back(offset + length);
- }
- } else { // Glyph id is not in subset.
- offset += length;
- new_offsets->push_back(offset);
- length = 0;
+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();
+ bool lower_bound_reached = false;
+ bool upper_bound_reached = false;
+ int32_t last_gid = -1;
+ BitmapGlyphInfoMap::const_iterator last_element = loca.end();
+ --last_element;
+ for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end();
+ i != e; i++) {
+ int32_t gid = i->first;
+ if (gid < lower_bound) {
+ continue;
+ }
+ if (!lower_bound_reached) {
+ builder4->set_first_glyph_index(gid);
+ builder4->set_image_format(b->image_format());
+ builder4->set_image_data_offset(*image_data_offset);
+ last_gid = gid;
+ lower_bound_reached = true;
+ }
+ if (gid > upper_bound || i == last_element) {
+ upper_bound_reached = true;
+ }
+ if (!upper_bound_reached || i == last_element) {
+ offset_pairs.push_back(
+ IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset));
+ offset += i->second->length();
+ last_gid = gid;
+ }
+ if (upper_bound_reached) {
+ offset_pairs.push_back(
+ IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset));
+ builder4->set_last_glyph_index(last_gid);
+ *image_data_offset += offset;
+ break;
}
}
-}
-
-void SubsetIndexSubTableFormat1(IndexSubTable::Builder* b,
- const BitmapGlyphInfoMap& loca) {
- IndexSubTableFormat1BuilderPtr builder =
- down_cast<IndexSubTableFormat1::Builder*>(b);
- if (builder->first_glyph_index() < loca.begin()->first) {
- builder->set_first_glyph_index(loca.begin()->first);
- }
- if (builder->last_glyph_index() > loca.rbegin()->first) {
- builder->set_last_glyph_index(loca.rbegin()->first);
- }
- builder->set_image_data_offset(loca.begin()->second->block_offset());
-
- IntegerList new_offsets;
- GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(),
- loca, &new_offsets);
- builder->SetOffsetArray(new_offsets);
-}
-
-void SubsetIndexSubTableFormat2(IndexSubTable::Builder* b,
- const BitmapGlyphInfoMap& loca) {
- UNREFERENCED_PARAMETER(b);
- UNREFERENCED_PARAMETER(loca);
-}
-
-void SubsetIndexSubTableFormat3(IndexSubTable::Builder* b,
- const BitmapGlyphInfoMap& loca) {
- IndexSubTableFormat3BuilderPtr builder =
- down_cast<IndexSubTableFormat3::Builder*>(b);
- if (builder->first_glyph_index() < loca.begin()->first) {
- builder->set_first_glyph_index(loca.begin()->first);
- }
- if (builder->last_glyph_index() > loca.rbegin()->first) {
- builder->set_last_glyph_index(loca.rbegin()->first);
- }
- builder->set_image_data_offset(loca.begin()->second->block_offset());
+ builder4->SetOffsetArray(offset_pairs);
- IntegerList new_offsets;
- GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(),
- loca, &new_offsets);
- builder->SetOffsetArray(new_offsets);
+ return builder4.Detach();
}
-void SubsetIndexSubTableFormat4(IndexSubTable::Builder* b,
- const BitmapGlyphInfoMap& loca) {
- IndexSubTableFormat4BuilderPtr builder =
- down_cast<IndexSubTableFormat4::Builder*>(b);
- CodeOffsetPairBuilderList pairs;
- pairs.resize(loca.size());
- size_t index = 0;
+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);
+ new_builder->BigMetrics()->CopyFrom(builder2->BigMetrics());
+ image_size = builder2->ImageSize();
+ } else {
+ IndexSubTableFormat5BuilderPtr builder5 =
+ down_cast<IndexSubTableFormat5::Builder*>(b);
+ BigGlyphMetricsBuilderPtr metrics_builder;
+ new_builder->BigMetrics()->CopyFrom(builder5->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();
+ bool lower_bound_reached = false;
+ bool upper_bound_reached = false;
+ int32_t last_gid = -1;
+ BitmapGlyphInfoMap::const_iterator last_element = loca.end();
+ --last_element;
for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end();
i != e; i++) {
- pairs[index].set_glyph_code(i->first);
- pairs[index].set_offset(i->second->offset());
- index++;
- }
- builder->SetOffsetArray(pairs);
-}
-
-void SubsetIndexSubTableFormat5(IndexSubTable::Builder* b,
- const BitmapGlyphInfoMap& loca) {
- IndexSubTableFormat5BuilderPtr builder =
- down_cast<IndexSubTableFormat5::Builder*>(b);
- IntegerList* glyph_array = builder->GlyphArray();
- for (IntegerList::iterator i = glyph_array->begin(); i != glyph_array->end();
- i++) {
- if (loca.find(*i) == loca.end()) {
- glyph_array->erase(i);
+ int32_t gid = i->first;
+ if (gid < lower_bound) {
+ continue;
+ }
+ if (!lower_bound_reached) {
+ new_builder->set_first_glyph_index(gid);
+ new_builder->set_image_format(b->image_format());
+ new_builder->set_image_data_offset(*image_data_offset);
+ new_builder->SetImageSize(image_size);
+ last_gid = gid;
+ lower_bound_reached = true;
+ }
+ if (gid > upper_bound || i == last_element) {
+ upper_bound_reached = true;
+ }
+ if (!upper_bound_reached || i == last_element) {
+ glyph_array->push_back(gid);
+ offset += i->second->length();
+ last_gid = gid;
+ }
+ if (upper_bound_reached) {
+ new_builder->set_last_glyph_index(last_gid);
+ *image_data_offset += offset;
+ break;
}
}
- if (!glyph_array->empty()) {
- builder->set_first_glyph_index(*(glyph_array->begin()));
- builder->set_last_glyph_index(*(glyph_array->rbegin()));
- } else {
- builder->set_first_glyph_index(0);
- builder->set_last_glyph_index(0);
- }
+ return new_builder.Detach();
}
-void SubsetIndexSubTable(IndexSubTable::Builder* builder,
- const BitmapGlyphInfoMap& loca) {
+CALLER_ATTACH IndexSubTable::Builder*
+SubsetIndexSubTable(IndexSubTable::Builder* builder,
+ const BitmapGlyphInfoMap& loca,
+ int32_t* image_data_offset) {
switch (builder->index_format()) {
- case 1:
- SubsetIndexSubTableFormat1(builder, loca);
- break;
- case 2:
- SubsetIndexSubTableFormat2(builder, loca);
- break;
- case 3:
- SubsetIndexSubTableFormat3(builder, loca);
- break;
- case 4:
- SubsetIndexSubTableFormat4(builder, loca);
- break;
- case 5:
- SubsetIndexSubTableFormat5(builder, loca);
- break;
+ 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); // Shall not be here.
break;
}
+ return NULL;
}
void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) {
@@ -487,25 +509,20 @@ void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) {
return; // No valid EBLC.
}
+ 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();
- bool format4_processed = false;
for (size_t index = 0; index < index_builders->size(); ++index) {
- // Only one format 4 table per strike.
- if ((*index_builders)[index]->index_format() == 4 && format4_processed) {
- continue;
- }
- SubsetIndexSubTable((*index_builders)[index], new_loca[strike]);
- if ((*index_builders)[index]->index_format() == 4) {
- format4_processed = true;
+ 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);
}
}
}
}
-/******************************************************************************
- * EXPERIMENTAL CODE ENDS
- *****************************************************************************/
/******************************************************************************
Long background comments
@@ -542,34 +559,21 @@ Subsetting EBLC table:
reconstructed to either format 4 or 5.
*******************************************************************************/
bool SetupBitmapBuilders(Font* font, Font::Builder* builder,
- const IntegerSet& glyph_ids) {
+ const IntegerSet& glyph_ids, bool use_ebdt) {
if (!font || !builder) {
return false;
}
- // Check if bitmap table exists.
- bool use_ebdt = true;
- EbdtTablePtr ebdt_table = down_cast<EbdtTable*>(font->GetTable(Tag::EBDT));
- EblcTablePtr eblc_table = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
- if (ebdt_table == NULL && eblc_table == NULL) {
- use_ebdt = false;
- // Check BDAT variants.
- 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) {
- // There's no bitmap tables.
- return true;
- }
+ EbdtTablePtr ebdt_table =
+ down_cast<EbdtTable*>(font->GetTable(use_ebdt ? Tag::EBDT : Tag::bdat));
+ EblcTablePtr eblc_table =
+ down_cast<EblcTable*>(font->GetTable(use_ebdt ? Tag::EBLC : Tag::bloc));
// If the bitmap table's size is too small, skip subsetting.
- // TODO(arthurhsu): temporarily comment out to use smaller font for testing.
- /*
if (ebdt_table->DataLength() + eblc_table->DataLength() <
BITMAP_SIZE_THRESHOLD) {
return true;
}
- */
// Get the builders.
FontBuilderPtr font_builder = builder;
@@ -586,11 +590,9 @@ bool SetupBitmapBuilders(Font* font, Font::Builder* builder,
if (!ShallSubset(ebdt_table_builder, eblc_table_builder, glyph_ids)) {
// Bitmap tables do not cover the glyphs in our subset.
- ebdt_table_builder.Release();
- eblc_table_builder.Release();
- font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat);
font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc);
- return true;
+ font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat);
+ return false;
}
BitmapLocaList new_loca;
@@ -600,6 +602,30 @@ bool SetupBitmapBuilders(Font* font, Font::Builder* builder,
return true;
}
+enum BitmapDetection {
+ kNotFound,
+ kEBDTFound,
+ kOnlyBDATFound
+};
+
+// Some fonts have both EBDT/EBLC and bdat/bloc, we need only one set of them.
+int DetectBitmapBuilders(Font* font) {
+ // 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));
+ if (ebdt_table == NULL && eblc_table == NULL) {
+ // Check BDAT variants.
+ 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) {
+ // There's no bitmap tables.
+ return kNotFound;
+ }
+ return kOnlyBDATFound;
+ }
+ return kEBDTFound;
+}
+
SubsetterImpl::SubsetterImpl() {
}
@@ -735,13 +761,23 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) {
remove_tags.insert(Tag::glyf);
remove_tags.insert(Tag::loca);
}
- if (SetupBitmapBuilders(font_, font_builder, glyph_ids)) {
- remove_tags.insert(Tag::bdat);
- remove_tags.insert(Tag::bloc);
- remove_tags.insert(Tag::bhed);
- remove_tags.insert(Tag::EBDT);
- remove_tags.insert(Tag::EBLC);
- remove_tags.insert(Tag::EBSC);
+
+ int flag = DetectBitmapBuilders(font_);
+ if (flag != kNotFound) {
+ bool use_ebdt = (flag == kEBDTFound);
+ bool subset_success =
+ SetupBitmapBuilders(font_, font_builder, glyph_ids, use_ebdt);
+
+ if (use_ebdt || !subset_success) {
+ remove_tags.insert(Tag::bdat);
+ remove_tags.insert(Tag::bloc);
+ remove_tags.insert(Tag::bhed);
+ }
+ if (use_ebdt && !subset_success) {
+ remove_tags.insert(Tag::EBDT);
+ remove_tags.insert(Tag::EBLC);
+ remove_tags.insert(Tag::EBSC);
+ }
}
IntegerSet allowed_tags;
diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h
index abcc420..5e6debe 100644
--- a/test/subsetter_impl.h
+++ b/test/subsetter_impl.h
@@ -47,13 +47,6 @@ namespace sfntly {
// } // ref count = 1, obj2 out of scope
// obj.release(); // ref count = 0, object destroyed
-namespace {
-
-// The bitmap tables must be greater than 256KB to trigger bitmap subsetter.
-static const int BITMAP_SIZE_THRESHOLD = 262144;
-
-}
-
class SubsetterImpl {
public:
SubsetterImpl();
diff --git a/test/test_data.cc b/test/test_data.cc
index 6c26f0e..05bc759 100644
--- a/test/test_data.cc
+++ b/test/test_data.cc
@@ -31,6 +31,7 @@ const char* SAMPLE_BITMAP_FONT = "AnonymousPro-Regular.ttf";
const size_t SAMPLE_TTF_SIZE = 183936;
const size_t SAMPLE_TTF_TABLES = 17;
const size_t SAMPLE_TTF_KNOWN_TAGS = 16;
+const size_t SAMPLE_BITMAP_KNOWN_TAGS = 20;
const size_t SAMPLE_TTF_FEAT = 3;
const size_t SAMPLE_TTF_HEAD = 6;
const size_t SAMPLE_TTF_POST = 14;
@@ -41,6 +42,12 @@ const int32_t TTF_KNOWN_TAGS[] = {
Tag::loca, Tag::maxp, Tag::morx, Tag::name, Tag::post,
Tag::prop };
+const int32_t BITMAP_KNOWN_TAGS[] = {
+ Tag::EBDT, Tag::EBLC, Tag::EBSC, Tag::LTSH, Tag::OS_2,
+ Tag::VDMX, Tag::cmap, Tag::cvt, Tag::fpgm, Tag::gasp,
+ Tag::glyf, Tag::hdmx, Tag::head, Tag::hhea, Tag::hmtx,
+ Tag::loca, Tag::maxp, Tag::name, Tag::post, Tag::prep };
+
const int64_t TTF_CHECKSUM[] = {
0xD463FC48, 0x252028D1, 0x0065078A, 0xC01407B5, 0xFFFF0003,
0x9544342B, 0xFC8F16AD, 0x0EC30C7A, 0xA029CD5D, 0x32513087,
diff --git a/test/test_data.h b/test/test_data.h
index b6a5ed6..d5e576f 100644
--- a/test/test_data.h
+++ b/test/test_data.h
@@ -27,11 +27,13 @@ extern const char* SAMPLE_BITMAP_FONT;
extern const size_t SAMPLE_TTF_SIZE;
extern const size_t SAMPLE_TTF_TABLES;
extern const size_t SAMPLE_TTF_KNOWN_TAGS;
+extern const size_t SAMPLE_BITMAP_KNOWN_TAGS;
extern const size_t SAMPLE_TTF_FEAT;
extern const size_t SAMPLE_TTF_HEAD;
extern const size_t SAMPLE_TTF_POST;
extern const int32_t TTF_KNOWN_TAGS[];
+extern const int32_t BITMAP_KNOWN_TAGS[];
extern const int64_t TTF_CHECKSUM[];
extern const int64_t TTF_OFFSET[];
extern const int32_t TTF_LENGTH[];