summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarthurhsu@google.com <arthurhsu@google.com@672e30a5-4c29-85ac-ac6d-611c735e0a51>2011-10-11 01:01:16 +0000
committerarthurhsu@google.com <arthurhsu@google.com@672e30a5-4c29-85ac-ac6d-611c735e0a51>2011-10-11 01:01:16 +0000
commit333edd91cb32d6acfd0307ba2ae8f60baed75ff4 (patch)
treee2cd71c762d6105ef3fb8dafa5b08a109fe01c7f
parentdc47db9a1c26e13a4e8be6185bd0ecf89c0d1f81 (diff)
downloadsrc-333edd91cb32d6acfd0307ba2ae8f60baed75ff4.tar.gz
Update to Sep 30 snapshot, include all current EBXX support.
Refine Iterator ports: all java-style Iterator objects are ref-counted and have automatic memory management now. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@100 672e30a5-4c29-85ac-ac6d-611c735e0a51
-rw-r--r--sfntly/data/byte_array.cc8
-rw-r--r--sfntly/data/font_data.cc6
-rw-r--r--sfntly/data/font_data.h7
-rw-r--r--sfntly/data/readable_font_data.cc7
-rw-r--r--sfntly/data/readable_font_data.h6
-rw-r--r--sfntly/data/writable_font_data.cc16
-rw-r--r--sfntly/data/writable_font_data.h13
-rw-r--r--sfntly/font.cc26
-rw-r--r--sfntly/math/font_math.h11
-rw-r--r--sfntly/port/java_iterator.h94
-rw-r--r--sfntly/table/bitmap/big_glyph_metrics.cc162
-rw-r--r--sfntly/table/bitmap/big_glyph_metrics.h92
-rw-r--r--sfntly/table/bitmap/bitmap_glyph.cc51
-rw-r--r--sfntly/table/bitmap/bitmap_glyph.h25
-rw-r--r--sfntly/table/bitmap/bitmap_glyph_info.cc68
-rw-r--r--sfntly/table/bitmap/bitmap_glyph_info.h85
-rw-r--r--sfntly/table/bitmap/bitmap_size_table.cc440
-rw-r--r--sfntly/table/bitmap/bitmap_size_table.h125
-rw-r--r--sfntly/table/bitmap/composite_bitmap_glyph.cc20
-rw-r--r--sfntly/table/bitmap/composite_bitmap_glyph.h10
-rw-r--r--sfntly/table/bitmap/ebdt_table.cc182
-rw-r--r--sfntly/table/bitmap/ebdt_table.h47
-rw-r--r--sfntly/table/bitmap/eblc_table.cc199
-rw-r--r--sfntly/table/bitmap/eblc_table.h32
-rw-r--r--sfntly/table/bitmap/ebsc_table.cc107
-rw-r--r--sfntly/table/bitmap/ebsc_table.h102
-rw-r--r--sfntly/table/bitmap/glyph_metrics.cc39
-rw-r--r--sfntly/table/bitmap/glyph_metrics.h43
-rw-r--r--sfntly/table/bitmap/index_sub_table.cc222
-rw-r--r--sfntly/table/bitmap/index_sub_table.h104
-rw-r--r--sfntly/table/bitmap/index_sub_table_format1.cc247
-rw-r--r--sfntly/table/bitmap/index_sub_table_format1.h86
-rw-r--r--sfntly/table/bitmap/index_sub_table_format2.cc210
-rw-r--r--sfntly/table/bitmap/index_sub_table_format2.h74
-rw-r--r--sfntly/table/bitmap/index_sub_table_format3.cc251
-rw-r--r--sfntly/table/bitmap/index_sub_table_format3.h84
-rw-r--r--sfntly/table/bitmap/index_sub_table_format4.cc358
-rw-r--r--sfntly/table/bitmap/index_sub_table_format4.h109
-rw-r--r--sfntly/table/bitmap/index_sub_table_format5.cc328
-rw-r--r--sfntly/table/bitmap/index_sub_table_format5.h91
-rw-r--r--sfntly/table/bitmap/simple_bitmap_glyph.cc17
-rw-r--r--sfntly/table/bitmap/simple_bitmap_glyph.h11
-rw-r--r--sfntly/table/bitmap/small_glyph_metrics.cc126
-rw-r--r--sfntly/table/bitmap/small_glyph_metrics.h79
-rw-r--r--sfntly/table/byte_array_table_builder.cc70
-rw-r--r--sfntly/table/byte_array_table_builder.h53
-rw-r--r--sfntly/table/core/name_table.cc61
-rw-r--r--sfntly/table/core/name_table.h14
-rw-r--r--sfntly/table/font_data_table.cc18
-rw-r--r--sfntly/table/generic_table_builder.cc49
-rw-r--r--sfntly/table/generic_table_builder.h42
-rw-r--r--sfntly/table/header.h16
-rw-r--r--sfntly/table/subtable.cc23
-rw-r--r--sfntly/table/subtable.h23
-rw-r--r--sfntly/table/table.cc1
-rw-r--r--sfntly/table/table_based_table_builder.cc24
-rw-r--r--sfntly/table/table_based_table_builder.h13
-rw-r--r--sfntly/table/truetype/glyph_table.cc11
-rw-r--r--sfntly/table/truetype/glyph_table.h19
-rw-r--r--sfntly/table/truetype/loca_table.cc59
-rw-r--r--sfntly/table/truetype/loca_table.h23
-rw-r--r--test/font_parsing_test.cc1
62 files changed, 4449 insertions, 491 deletions
diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc
index c820adc..915a40c 100644
--- a/sfntly/data/byte_array.cc
+++ b/sfntly/data/byte_array.cc
@@ -115,13 +115,7 @@ int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array,
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);
- if (bytes_written != bytes_read) {
-#if defined (SFNTLY_NO_EXCEPTION)
- return 0;
-#else
- throw IOException("Error writing bytes.");
-#endif
- }
+ UNREFERENCED_PARAMETER(bytes_written);
index += bytes_read;
remaining_length -= bytes_read;
buffer_length = std::min<int32_t>(b.size(), remaining_length);
diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc
index ccc2a19..d2b95ea 100644
--- a/sfntly/data/font_data.cc
+++ b/sfntly/data/font_data.cc
@@ -58,7 +58,9 @@ FontData::FontData(FontData* data, int32_t offset, int32_t length) {
FontData::FontData(FontData* data, int32_t offset) {
Init(data->array_);
- Bound(data->bound_offset_ + offset);
+ Bound(data->bound_offset_ + offset,
+ (data->bound_length_ == GROWABLE_SIZE)
+ ? GROWABLE_SIZE : data->bound_length_ - offset);
}
FontData::~FontData() {}
@@ -66,7 +68,7 @@ FontData::~FontData() {}
void FontData::Init(ByteArray* ba) {
array_ = ba;
bound_offset_ = 0;
- bound_length_ = INT_MAX;
+ bound_length_ = GROWABLE_SIZE;
}
int32_t FontData::BoundOffset(int32_t offset) {
diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h
index ec87c72..d02e8b7 100644
--- a/sfntly/data/font_data.h
+++ b/sfntly/data/font_data.h
@@ -17,6 +17,8 @@
#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_
#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_
+#include <limits.h>
+
#include <vector>
#include "sfntly/port/type.h"
@@ -110,12 +112,15 @@ class FontData : virtual public RefCount {
// @return the bound compensated offset
int32_t BoundOffset(int32_t offset);
- // Gets the length in the underlying data taking into account any bounds on the data.
+ // 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);
+ static const int32_t GROWABLE_SIZE = INT_MAX;
+
// TODO(arthurhsu): style guide violation: refactor this protected member
ByteArrayPtr array_;
diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc
index fb083cb..bb58c26 100644
--- a/sfntly/data/readable_font_data.cc
+++ b/sfntly/data/readable_font_data.cc
@@ -121,6 +121,13 @@ int32_t ReadableFontData::ReadULongAsInt(int32_t index) {
return static_cast<int32_t>(ulong);
}
+int64_t ReadableFontData::ReadULongLE(int32_t index) {
+ return 0xffffffffL & (ReadUByte(index) |
+ ReadUByte(index + 1) << 8 |
+ ReadUByte(index + 2) << 16 |
+ ReadUByte(index + 3) << 24);
+}
+
int32_t ReadableFontData::ReadLong(int32_t index) {
return ReadByte(index) << 24 |
ReadUByte(index + 1) << 16 |
diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h
index c5833e8..b43c626 100644
--- a/sfntly/data/readable_font_data.h
+++ b/sfntly/data/readable_font_data.h
@@ -128,6 +128,12 @@ class ReadableFontData : public FontData,
// @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
diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc
index 0b271a3..ace387c 100644
--- a/sfntly/data/writable_font_data.cc
+++ b/sfntly/data/writable_font_data.cc
@@ -82,12 +82,22 @@ int32_t WritableFontData::WriteBytesPad(int32_t index,
offset,
BoundLength(index,
std::min<int32_t>(length, b->size() - offset)));
- for (; written < length; written++) {
- array_->Put(written + index, pad);
- }
+ written += WritePadding(written + index, length - written, pad);
return written;
}
+int32_t WritableFontData::WritePadding(int32_t index, int32_t count) {
+ return WritePadding(index, count, (byte_t)0);
+}
+
+int32_t WritableFontData::WritePadding(int32_t index, int32_t count,
+ byte_t pad) {
+ for (int32_t i = 0; i < count; ++i) {
+ array_->Put(index + i, pad);
+ }
+ return count;
+}
+
int32_t WritableFontData::WriteChar(int32_t index, byte_t c) {
return WriteByte(index, c);
}
diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h
index 9a9bd7b..f88a986 100644
--- a/sfntly/data/writable_font_data.h
+++ b/sfntly/data/writable_font_data.h
@@ -85,6 +85,19 @@ 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
+ // @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, byte_t pad);
+
// Write the CHAR at the given index.
// @param index index into the font data
// @param c the CHAR
diff --git a/sfntly/font.cc b/sfntly/font.cc
index 524932b..3fa77b0 100644
--- a/sfntly/font.cc
+++ b/sfntly/font.cc
@@ -295,15 +295,9 @@ Table::Builder* Font::Builder::NewTableBuilder(int32_t tag,
assert(src_data);
WritableFontDataPtr data;
data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
-#if !defined (SFNTLY_NO_EXCEPTION)
- try {
-#endif
- src_data->CopyTo(data);
-#if !defined (SFNTLY_NO_EXCEPTION)
- } catch (IOException& e) {
- return NULL;
- }
-#endif
+ // 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));
@@ -378,19 +372,7 @@ void Font::Builder::BuildTablesFromBuilders(Font* font,
builder != builder_end; ++builder) {
TablePtr table;
if (builder->second && builder->second->ReadyToBuild()) {
-#if !defined (SFNTLY_NO_EXCEPTION)
- try {
-#endif
- table.Attach(down_cast<Table*>(builder->second->Build()));
-#if !defined (SFNTLY_NO_EXCEPTION)
- } catch(IOException& e) {
- 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
+ table.Attach(down_cast<Table*>(builder->second->Build()));
}
if (table == NULL) {
table_map->clear();
diff --git a/sfntly/math/font_math.h b/sfntly/math/font_math.h
index c469347..f1cd2d2 100644
--- a/sfntly/math/font_math.h
+++ b/sfntly/math/font_math.h
@@ -31,6 +31,17 @@ class FontMath {
}
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
diff --git a/sfntly/port/java_iterator.h b/sfntly/port/java_iterator.h
new file mode 100644
index 0000000..0a99bca
--- /dev/null
+++ b/sfntly/port/java_iterator.h
@@ -0,0 +1,94 @@
+/*
+ * 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_
diff --git a/sfntly/table/bitmap/big_glyph_metrics.cc b/sfntly/table/bitmap/big_glyph_metrics.cc
new file mode 100644
index 0000000..d2519cd
--- /dev/null
+++ b/sfntly/table/bitmap/big_glyph_metrics.cc
@@ -0,0 +1,162 @@
+/*
+ * 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(byte_t height) {
+ InternalWriteData()->WriteByte(Offset::kHeight, height);
+}
+
+int32_t BigGlyphMetrics::Builder::Width() {
+ return InternalReadData()->ReadByte(Offset::kWidth);
+}
+
+void BigGlyphMetrics::Builder::SetWidth(byte_t width) {
+ InternalWriteData()->WriteByte(Offset::kWidth, width);
+}
+
+int32_t BigGlyphMetrics::Builder::HoriBearingX() {
+ return InternalReadData()->ReadByte(Offset::kHoriBearingX);
+}
+
+void BigGlyphMetrics::Builder::SetHoriBearingX(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kHoriBearingX, bearing);
+}
+
+int32_t BigGlyphMetrics::Builder::HoriBearingY() {
+ return InternalReadData()->ReadByte(Offset::kHoriBearingY);
+}
+
+void BigGlyphMetrics::Builder::SetHoriBearingY(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kHoriBearingY, bearing);
+}
+
+int32_t BigGlyphMetrics::Builder::HoriAdvance() {
+ return InternalReadData()->ReadByte(Offset::kHoriAdvance);
+}
+
+void BigGlyphMetrics::Builder::SetHoriAdvance(byte_t advance) {
+ InternalWriteData()->WriteByte(Offset::kHoriAdvance, advance);
+}
+
+int32_t BigGlyphMetrics::Builder::VertBearingX() {
+ return InternalReadData()->ReadByte(Offset::kVertBearingX);
+}
+
+void BigGlyphMetrics::Builder::SetVertBearingX(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kVertBearingX, bearing);
+}
+
+int32_t BigGlyphMetrics::Builder::VertBearingY() {
+ return InternalReadData()->ReadByte(Offset::kVertBearingY);
+}
+
+void BigGlyphMetrics::Builder::SetVertBearingY(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kVertBearingY, bearing);
+}
+
+int32_t BigGlyphMetrics::Builder::VertAdvance() {
+ return InternalReadData()->ReadByte(Offset::kVertAdvance);
+}
+
+void BigGlyphMetrics::Builder::SetVertAdvance(byte_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);
+}
+
+} // namespace sfntly
diff --git a/sfntly/table/bitmap/big_glyph_metrics.h b/sfntly/table/bitmap/big_glyph_metrics.h
new file mode 100644
index 0000000..55963b4
--- /dev/null
+++ b/sfntly/table/bitmap/big_glyph_metrics.h
@@ -0,0 +1,92 @@
+/*
+ * 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(byte_t height);
+ int32_t Width();
+ void SetWidth(byte_t width);
+ int32_t HoriBearingX();
+ void SetHoriBearingX(byte_t bearing);
+ int32_t HoriBearingY();
+ void SetHoriBearingY(byte_t bearing);
+ int32_t HoriAdvance();
+ void SetHoriAdvance(byte_t advance);
+ int32_t VertBearingX();
+ void SetVertBearingX(byte_t bearing);
+ int32_t VertBearingY();
+ void SetVertBearingY(byte_t bearing);
+ int32_t VertAdvance();
+ void SetVertAdvance(byte_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);
+ };
+
+ 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_
diff --git a/sfntly/table/bitmap/bitmap_glyph.cc b/sfntly/table/bitmap/bitmap_glyph.cc
index 82d78b3..334a0c0 100644
--- a/sfntly/table/bitmap/bitmap_glyph.cc
+++ b/sfntly/table/bitmap/bitmap_glyph.cc
@@ -15,6 +15,8 @@
*/
#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 {
/******************************************************************************
@@ -23,6 +25,17 @@ namespace sfntly {
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) {
}
@@ -33,12 +46,34 @@ BitmapGlyph::BitmapGlyph(ReadableFontData* data, int32_t format)
BitmapGlyph::Builder::~Builder() {
}
-BitmapGlyph::Builder::Builder(WritableFontData* data)
- : SubTable::Builder(data) {
+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)
- : SubTable::Builder(data) {
+BitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format)
+ : SubTable::Builder(data), format_(format) {
}
CALLER_ATTACH
@@ -48,19 +83,19 @@ FontDataTable* BitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) {
}
void BitmapGlyph::Builder::SubDataSet() {
+ // NOP
}
int32_t BitmapGlyph::Builder::SubDataSizeToSerialize() {
- return 0;
+ return InternalReadData()->Length();
}
bool BitmapGlyph::Builder::SubReadyToSerialize() {
- return false;
+ return true;
}
int32_t BitmapGlyph::Builder::SubSerialize(WritableFontData* new_data) {
- UNREFERENCED_PARAMETER(new_data);
- return 0;
+ return InternalReadData()->CopyTo(new_data);
}
} // namespace sfntly
diff --git a/sfntly/table/bitmap/bitmap_glyph.h b/sfntly/table/bitmap/bitmap_glyph.h
index 47afbe1..2dd4c3a 100644
--- a/sfntly/table/bitmap/bitmap_glyph.h
+++ b/sfntly/table/bitmap/bitmap_glyph.h
@@ -17,6 +17,9 @@
#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 {
@@ -73,18 +76,29 @@ class BitmapGlyph : public SubTable {
public:
virtual ~Builder();
- protected:
- Builder(WritableFontData* data);
- Builder(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);
+
+ 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()
@@ -96,6 +110,9 @@ class BitmapGlyph : public SubTable {
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
diff --git a/sfntly/table/bitmap/bitmap_glyph_info.cc b/sfntly/table/bitmap/bitmap_glyph_info.cc
new file mode 100644
index 0000000..ab9953b
--- /dev/null
+++ b/sfntly/table/bitmap/bitmap_glyph_info.cc
@@ -0,0 +1,68 @@
+/*
+ * 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 this == 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
diff --git a/sfntly/table/bitmap/bitmap_glyph_info.h b/sfntly/table/bitmap/bitmap_glyph_info.h
new file mode 100644
index 0000000..9921d0d
--- /dev/null
+++ b/sfntly/table/bitmap/bitmap_glyph_info.h
@@ -0,0 +1,85 @@
+/*
+ * 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_
diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc
index 00488ea..93b8625 100644
--- a/sfntly/table/bitmap/bitmap_size_table.cc
+++ b/sfntly/table/bitmap/bitmap_size_table.cc
@@ -16,16 +16,19 @@
#include "sfntly/table/bitmap/bitmap_size_table.h"
+#include <stdlib.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::BitmapSizeTable(ReadableFontData* data,
- ReadableFontData* master_data)
- : SubTable(data) {
- master_data_ = master_data;
-}
-
+/******************************************************************************
+ * BitmapSizeTable class
+ ******************************************************************************/
BitmapSizeTable::~BitmapSizeTable() {
}
@@ -40,8 +43,7 @@ int32_t BitmapSizeTable::IndexTableSize() {
}
int32_t BitmapSizeTable::NumberOfIndexSubTables() {
- return data_->ReadULongAsInt(
- EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables);
+ return NumberOfIndexSubTables(data_, 0);
}
int32_t BitmapSizeTable::ColorRef() {
@@ -96,6 +98,14 @@ int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) {
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) {
@@ -104,7 +114,41 @@ int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) {
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;
@@ -128,21 +172,389 @@ IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) {
CALLER_ATTACH
IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) {
- return IndexSubTable::CreateIndexSubTable(master_data_,
+ return IndexSubTable::CreateIndexSubTable(master_read_data(),
IndexSubTableArrayOffset(),
index);
}
IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() {
- AutoLock lock(atomic_subtables_lock_);
- if (atomic_subtables.empty()) {
+ AutoLock lock(index_subtables_lock_);
+ if (index_subtables_.empty()) {
for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) {
IndexSubTablePtr table;
table.Attach(CreateIndexSubTable(i));
- atomic_subtables.push_back(table);
+ 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();
+ variable = (sub_table_size > 0) ? variable : true;
+ size += abs(sub_table_size);
+ }
+ return 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::GetIndexSubTable(
+ int32_t index) {
+ IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders();
+ return sub_table_list->at(index);
+}
+
+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) {
+ 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);
+ for (int32_t i = 0; i < number_of_index_subtables; ++i) {
+ index_sub_tables_[index_sub_tables_.size()].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 &atomic_subtables;
+ return NULL;
}
} // namespace sfntly
diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h
index ee58bca..2bc91da 100644
--- a/sfntly/table/bitmap/bitmap_size_table.h
+++ b/sfntly/table/bitmap/bitmap_size_table.h
@@ -17,28 +17,120 @@
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_
-#include <vector>
-
#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:
- // Note: C++ port take two ReadableFontData. The first is sliced data, and
- // the second is unsliced data. The second one is used to correctly
- // construct index sub tables since Java version calculate the offset
- // based on unsliced data.
- BitmapSizeTable(ReadableFontData* data,
- ReadableFontData* master_data);
+ 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();
+
+ // Note: renamed from indexSubTable()
+ IndexSubTable::Builder* GetIndexSubTable(int32_t index);
+ 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);
+ 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();
@@ -48,22 +140,31 @@ class BitmapSizeTable : public SubTable,
// 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();
- ReadableFontDataPtr master_data_;
- Lock atomic_subtables_lock_;
- IndexSubTableList atomic_subtables;
+ 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
diff --git a/sfntly/table/bitmap/composite_bitmap_glyph.cc b/sfntly/table/bitmap/composite_bitmap_glyph.cc
index bd680e4..ae7dc5a 100644
--- a/sfntly/table/bitmap/composite_bitmap_glyph.cc
+++ b/sfntly/table/bitmap/composite_bitmap_glyph.cc
@@ -86,4 +86,24 @@ CompositeBitmapGlyph::Component::Component(int32_t glyph_code,
: 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
diff --git a/sfntly/table/bitmap/composite_bitmap_glyph.h b/sfntly/table/bitmap/composite_bitmap_glyph.h
index 0521213..897db7e 100644
--- a/sfntly/table/bitmap/composite_bitmap_glyph.h
+++ b/sfntly/table/bitmap/composite_bitmap_glyph.h
@@ -47,6 +47,16 @@ class CompositeBitmapGlyph : public BitmapGlyph,
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();
diff --git a/sfntly/table/bitmap/ebdt_table.cc b/sfntly/table/bitmap/ebdt_table.cc
index a131f5a..75a5080 100644
--- a/sfntly/table/bitmap/ebdt_table.cc
+++ b/sfntly/table/bitmap/ebdt_table.cc
@@ -16,6 +16,8 @@
#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"
@@ -32,28 +34,9 @@ int32_t EbdtTable::Version() {
CALLER_ATTACH
BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) {
- ReadableFontDataPtr new_data;
- new_data.Attach(down_cast<ReadableFontData*>(data_->Slice(offset, length)));
- BitmapGlyphPtr glyph;
- switch (format) {
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- glyph = new SimpleBitmapGlyph(new_data, format);
- break;
- case 8:
- case 9:
- glyph = new CompositeBitmapGlyph(new_data, format);
- break;
- default:
- assert(false);
- break;
- }
- return glyph.Detach();
+ 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)
@@ -81,20 +64,113 @@ CALLER_ATTACH FontDataTable*
}
void EbdtTable::Builder::SubDataSet() {
- // NOP
+ Revert();
}
int32_t EbdtTable::Builder::SubDataSizeToSerialize() {
- return 0;
+ 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() {
- return false;
+ if (glyph_builders_.empty()) {
+ return false;
+ }
+ return true;
}
int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) {
- UNREFERENCED_PARAMETER(new_data);
- return 0;
+ 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();
+ 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;
+ }
+ }
+
+ output->resize(glyph_builders_.size());
+ 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
@@ -105,5 +181,57 @@ EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header,
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();
+ output->resize(loca_list->size());
+ 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->start_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
diff --git a/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h
index 998541e..723c3f9 100644
--- a/sfntly/table/bitmap/ebdt_table.h
+++ b/sfntly/table/bitmap/ebdt_table.h
@@ -18,6 +18,7 @@
#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 {
@@ -40,8 +41,48 @@ class EbdtTable : public SubTableContainerTable,
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();
@@ -51,14 +92,14 @@ class EbdtTable : public SubTableContainerTable,
int32_t format);
protected:
- EbdtTable(Header* header, ReadableFontData* data);
-
- private:
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 decbadf..bb36db0 100644
--- a/sfntly/table/bitmap/eblc_table.cc
+++ b/sfntly/table/bitmap/eblc_table.cc
@@ -16,6 +16,10 @@
#include "sfntly/table/bitmap/eblc_table.h"
+#include <stdlib.h>
+
+#include "sfntly/math/font_math.h"
+
namespace sfntly {
/******************************************************************************
* EblcTable class
@@ -67,8 +71,12 @@ void EblcTable::CreateBitmapSizeTable(ReadableFontData* data,
data->Slice(Offset::kBitmapSizeTableArrayStart +
i * Offset::kBitmapSizeTableLength,
Offset::kBitmapSizeTableLength)));
- BitmapSizeTablePtr new_table = new BitmapSizeTable(new_data, data);
- output->push_back(new_table);
+ 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);
}
}
@@ -87,20 +95,163 @@ EblcTable::Builder::~Builder() {
}
int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
- UNREFERENCED_PARAMETER(new_data);
- return 0;
+ // 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);
+ 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() {
- return false;
+ 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() {
- return 0;
+ if (size_table_builders_.empty()) {
+ return 0;
+ }
+ int32_t size = Offset::kHeaderLength;
+ bool variable = false;
+ for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
+ e = size_table_builders_.end();
+ b != e; b++) {
+ int32_t size_builder_size = (*b)->SubDataSizeToSerialize();
+ 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;
}
void EblcTable::Builder::SubDataSet() {
- // NOP
+ 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();
+ output->resize(size_builder_list->size());
+#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
@@ -116,4 +267,38 @@ CALLER_ATTACH EblcTable::Builder*
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) {
+ int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes);
+ 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
diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h
index 84831ef..f8f052d 100644
--- a/sfntly/table/bitmap/eblc_table.h
+++ b/sfntly/table/bitmap/eblc_table.h
@@ -32,9 +32,10 @@ class EblcTable : public SubTableContainerTable,
// header
kVersion = 0,
kNumSizes = 4,
+ kHeaderLength = kNumSizes + DataSize::kULONG,
// bitmapSizeTable
- kBitmapSizeTableArrayStart = 8,
+ kBitmapSizeTableArrayStart = kHeaderLength,
kBitmapSizeTableLength = 48,
kBitmapSizeTable_indexSubTableArrayOffset = 0,
kBitmapSizeTable_indexTableSize = 4,
@@ -95,6 +96,9 @@ class EblcTable : public SubTableContainerTable,
kIndexSubTable4_numGlyphs = kIndexSubHeaderLength,
kIndexSubTable4_glyphArray = kIndexSubTable4_numGlyphs +
DataSize::kULONG,
+ kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT,
+ kIndexSubTable4_codeOffsetPair_glyphCode = 0,
+ kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT,
// kIndexSubTable5
kIndexSubTable5_imageSize = kIndexSubHeaderLength,
@@ -127,8 +131,31 @@ class EblcTable : public SubTableContainerTable,
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();
@@ -137,11 +164,14 @@ class EblcTable : public SubTableContainerTable,
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);
diff --git a/sfntly/table/bitmap/ebsc_table.cc b/sfntly/table/bitmap/ebsc_table.cc
new file mode 100644
index 0000000..458c2d4
--- /dev/null
+++ b/sfntly/table/bitmap/ebsc_table.cc
@@ -0,0 +1,107 @@
+/*
+ * 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
diff --git a/sfntly/table/bitmap/ebsc_table.h b/sfntly/table/bitmap/ebsc_table.h
new file mode 100644
index 0000000..43088fd
--- /dev/null
+++ b/sfntly/table/bitmap/ebsc_table.h
@@ -0,0 +1,102 @@
+/*
+ * 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 is minimally functional
+ // -just builds from initial data
+ // - need to make fully working
+ 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_
diff --git a/sfntly/table/bitmap/glyph_metrics.cc b/sfntly/table/bitmap/glyph_metrics.cc
new file mode 100644
index 0000000..e91eb99
--- /dev/null
+++ b/sfntly/table/bitmap/glyph_metrics.cc
@@ -0,0 +1,39 @@
+/*
+ * 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
diff --git a/sfntly/table/bitmap/glyph_metrics.h b/sfntly/table/bitmap/glyph_metrics.h
new file mode 100644
index 0000000..5f16aaa
--- /dev/null
+++ b/sfntly/table/bitmap/glyph_metrics.h
@@ -0,0 +1,43 @@
+/*
+ * 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_
diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc
index 329179d..66d2d83 100644
--- a/sfntly/table/bitmap/index_sub_table.cc
+++ b/sfntly/table/bitmap/index_sub_table.cc
@@ -24,30 +24,31 @@
#include "sfntly/table/bitmap/index_sub_table_format5.h"
namespace sfntly {
-
-bool IndexSubTable::CheckGlyphRange(int32_t glyph_id) {
- if (glyph_id < first_glyph_index() || glyph_id > last_glyph_index()) {
-#if !defined (SFNTLY_NO_EXCEPTION)
- throw IndexOutOfBoundException("Glyph ID is outside of the allowed range");
-#endif
- return false;
+/******************************************************************************
+ * IndexSubTable class
+ ******************************************************************************/
+CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return NULL;
}
- return true;
+ 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();
}
-template <typename IndexSubTableType>
-static IndexSubTableType* CreateTable(ReadableFontData* data,
- int32_t index_sub_table_offset,
- int32_t first_glyph_index,
- int32_t last_glyph_index) {
- ReadableFontDataPtr new_data;
- new_data.Attach(down_cast<ReadableFontData*>(
- data->Slice(index_sub_table_offset,
- IndexSubTableType::GetDataLength(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index))));
- return new IndexSubTableType(new_data, first_glyph_index, last_glyph_index);
+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
@@ -55,10 +56,65 @@ 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());
+}
+
+int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) {
+ return image_data_offset() + GlyphStartOffset(glyph_id);
+}
+
+// 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);
@@ -68,49 +124,25 @@ CALLER_ATTACH IndexSubTable*
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);
- IndexSubTablePtr new_table;
- ReadableFontDataPtr new_data;
switch (index_format) {
case 1:
- new_table = CreateTable<IndexSubTableFormat1>(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index);
- break;
-
+ return IndexSubTableFormat1::Builder::CreateBuilder(
+ data, index_sub_table_offset, first_glyph_index, last_glyph_index);
case 2:
- new_table = CreateTable<IndexSubTableFormat2>(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index);
- break;
-
+ return IndexSubTableFormat2::Builder::CreateBuilder(
+ data, index_sub_table_offset, first_glyph_index, last_glyph_index);
case 3:
- new_table = CreateTable<IndexSubTableFormat3>(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index);
- break;
-
+ return IndexSubTableFormat3::Builder::CreateBuilder(
+ data, index_sub_table_offset, first_glyph_index, last_glyph_index);
case 4:
- new_table = CreateTable<IndexSubTableFormat4>(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index);
- break;
-
+ return IndexSubTableFormat4::Builder::CreateBuilder(
+ data, index_sub_table_offset, first_glyph_index, last_glyph_index);
case 5:
- new_table = CreateTable<IndexSubTableFormat5>(data,
- index_sub_table_offset,
- first_glyph_index,
- last_glyph_index);
- break;
-
+ 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)
@@ -118,20 +150,82 @@ CALLER_ATTACH IndexSubTable*
#endif
break;
}
+ return NULL;
+}
- return new_table.Detach();
+CALLER_ATTACH
+FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) {
+ UNREFERENCED_PARAMETER(data);
+ return NULL;
}
-IndexSubTable::IndexSubTable(ReadableFontData* data,
- int32_t first,
- int32_t last)
- : SubTable(data), first_glyph_index_(first), last_glyph_index_(last) {
+void IndexSubTable::Builder::SubDataSet() {
+}
+
+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(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);
+}
+
+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(),
+ 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);
+ data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat);
image_format_ =
- data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
+ data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
image_data_offset_ =
- data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
+ data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
}
} // namespace sfntly
diff --git a/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h
index 253f165..c2be7d1 100644
--- a/sfntly/table/bitmap/index_sub_table.h
+++ b/sfntly/table/bitmap/index_sub_table.h
@@ -19,18 +19,106 @@
#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:
+ 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 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(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(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.
+ // @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_; }
- virtual int32_t GlyphOffset(int32_t glyph_id) = 0;
+ 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;
@@ -44,10 +132,14 @@ class IndexSubTable : public SubTable {
// 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, int32_t last);
+ IndexSubTable(ReadableFontData* data,
+ int32_t first_glyph_index,
+ int32_t last_glyph_index);
- // Note: change return type to bool in C++ since we may not throw.
- bool CheckGlyphRange(int32_t glyph_id);
+ 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_;
@@ -58,6 +150,10 @@ class IndexSubTable : public SubTable {
};
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
diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc
index b98655a..809412d 100644
--- a/sfntly/table/bitmap/index_sub_table_format1.cc
+++ b/sfntly/table/bitmap/index_sub_table_format1.cc
@@ -19,7 +19,9 @@
#include "sfntly/table/bitmap/eblc_table.h"
namespace sfntly {
-
+/******************************************************************************
+ * IndexSubTableFormat1 class
+ ******************************************************************************/
// static
int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data,
int32_t offset,
@@ -30,12 +32,6 @@ int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data,
return (last - first + 1 + 1) * DataSize::kULONG;
}
-IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data,
- int32_t first,
- int32_t last)
- : IndexSubTable(data, first, last) {
-}
-
IndexSubTableFormat1::~IndexSubTableFormat1() {
}
@@ -43,25 +39,242 @@ int32_t IndexSubTableFormat1::NumGlyphs() {
return last_glyph_index() - first_glyph_index() + 1;
}
-int32_t IndexSubTableFormat1::GlyphOffset(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return Loca(glyph_id);
+int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return -1;
}
- return -1;
+ return Loca(loca);
}
int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return Loca(glyph_id + 1) - Loca(glyph_id);
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return -1;
}
- return -1;
+ return Loca(loca + 1) - Loca(loca);
}
-int32_t IndexSubTableFormat1::Loca(int32_t loca_index) {
+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_index - first_glyph_index()) *
- DataSize::kULONG);
+ 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;
+ }
+ IntegerList* 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
+BitmapGlyphInfoIter* IndexSubTableFormat1::Builder::GetIterator() {
+ Ptr<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator> it =
+ new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this);
+ return it.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)));
+ 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 0;
+ }
+ 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()) {
+ 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);
+ return size;
+ }
+ for (IntegerList::iterator b = GetOffsetArray()->begin(),
+ e = GetOffsetArray()->end(); b != e; b++) {
+ size += new_data->WriteLong(size, *b);
+ }
+ return size;
+}
+
+void IndexSubTableFormat1::Builder::SetOffsetArray(
+ const IntegerList& 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(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) {
+}
+
+IntegerList* 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
diff --git a/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h
index 3329bc9..c36bf18 100644
--- a/sfntly/table/bitmap/index_sub_table_format1.h
+++ b/sfntly/table/bitmap/index_sub_table_format1.h
@@ -17,32 +17,96 @@
#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:
- static int32_t GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last);
+ 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 BitmapGlyphInfoIter* 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 IntegerList& offset_array);
+ CALLER_ATTACH BitmapGlyphInfoIter* Iterator();
+
+ 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(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);
+ IntegerList* 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);
+
+ IntegerList offset_array_;
+ };
- // 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.
- IndexSubTableFormat1(ReadableFontData* data, int32_t first, int32_t last);
virtual ~IndexSubTableFormat1();
virtual int32_t NumGlyphs();
- virtual int32_t GlyphOffset(int32_t glyph_id);
+ 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
diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc
index 82deef3..e54481b 100644
--- a/sfntly/table/bitmap/index_sub_table_format2.cc
+++ b/sfntly/table/bitmap/index_sub_table_format2.cc
@@ -19,17 +19,29 @@
#include "sfntly/table/bitmap/eblc_table.h"
namespace sfntly {
+/******************************************************************************
+ * IndexSubTableFormat2 class
+ ******************************************************************************/
+IndexSubTableFormat2::~IndexSubTableFormat2() {
+}
-// static
-int32_t IndexSubTableFormat2::GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last) {
- UNREFERENCED_PARAMETER(data);
- UNREFERENCED_PARAMETER(offset);
- UNREFERENCED_PARAMETER(first);
- UNREFERENCED_PARAMETER(last);
- return EblcTable::Offset::kIndexSubTable2Length;
+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,
@@ -40,25 +52,183 @@ IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data,
data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize);
}
-IndexSubTableFormat2::~IndexSubTableFormat2() {
+/******************************************************************************
+ * IndexSubTableFormat2::Builder class
+ ******************************************************************************/
+IndexSubTableFormat2::Builder::~Builder() {
}
-int32_t IndexSubTableFormat2::NumGlyphs() {
+int32_t IndexSubTableFormat2::Builder::NumGlyphs() {
return last_glyph_index() - first_glyph_index() + 1;
}
-int32_t IndexSubTableFormat2::GlyphOffset(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return image_data_offset() + (glyph_id - first_glyph_index()) * image_size_;
+int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return -1;
}
- return -1;
+ return loca * ImageSize();
}
-int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return image_size_;
+int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return 0;
+ }
+ return ImageSize();
+}
+
+CALLER_ATTACH
+BitmapGlyphInfoIter* 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);
+}
+
+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);
+ 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)));
+ 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() {
+}
+
+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);
+ 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);
+ return size;
+}
+
+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;
}
- return -1;
+ 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
diff --git a/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h
index b325ccd..7b13d60 100644
--- a/sfntly/table/bitmap/index_sub_table_format2.h
+++ b/sfntly/table/bitmap/index_sub_table_format2.h
@@ -18,33 +18,81 @@
#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:
- static int32_t GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last);
-
- // 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.
- IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last);
+ 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 BitmapGlyphInfoIter* 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);
+ CALLER_ATTACH BigGlyphMetrics* BigMetrics();
+
+ 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(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);
+ };
+
virtual ~IndexSubTableFormat2();
virtual int32_t NumGlyphs();
- virtual int32_t GlyphOffset(int32_t glyph_id);
+ virtual int32_t GlyphStartOffset(int32_t glyph_id);
virtual int32_t GlyphLength(int32_t glyph_id);
private:
- int32_t Loca(int32_t loca_index);
+ 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
diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc
index 4fa529e..75ff14c 100644
--- a/sfntly/table/bitmap/index_sub_table_format3.cc
+++ b/sfntly/table/bitmap/index_sub_table_format3.cc
@@ -19,6 +19,31 @@
#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,
@@ -31,37 +56,225 @@ int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data,
}
IndexSubTableFormat3::IndexSubTableFormat3(ReadableFontData* data,
- int32_t first,
- int32_t last)
- : IndexSubTable(data, first, last) {
+ int32_t first_glyph_index,
+ int32_t last_glyph_index)
+ : IndexSubTable(data, first_glyph_index, last_glyph_index) {
}
-IndexSubTableFormat3::~IndexSubTableFormat3() {
+int32_t IndexSubTableFormat3::Loca(int32_t loca) {
+ int32_t read_offset =
+ data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray +
+ loca * DataSize::kUSHORT);
+ return read_offset;
}
-int32_t IndexSubTableFormat3::NumGlyphs() {
- return last_glyph_index() - first_glyph_index() + 1;
+/******************************************************************************
+ * IndexSubTableFormat3::Builder class
+ ******************************************************************************/
+IndexSubTableFormat3::Builder::~Builder() {
+}
+
+int32_t IndexSubTableFormat3::Builder::NumGlyphs() {
+ return GetOffsetArray()->size() - 1;
}
-int32_t IndexSubTableFormat3::GlyphOffset(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return Loca(glyph_id);
+int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return -1;
}
- return -1;
+ return GetOffsetArray()->at(loca);
}
-int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return Loca(glyph_id + 1) - Loca(glyph_id);
+int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) {
+ int32_t loca = CheckGlyphRange(glyph_id);
+ if (loca == -1) {
+ return 0;
}
- return -1;
+ IntegerList* offset_array = GetOffsetArray();
+ return offset_array->at(loca + 1) - offset_array->at(loca);
}
-int32_t IndexSubTableFormat3::Loca(int32_t loca_index) {
- int32_t read_offset =
- data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray +
- (loca_index - first_glyph_index()) * DataSize::kUSHORT);
- return image_data_offset() + read_offset;
+CALLER_ATTACH
+BitmapGlyphInfoIter* 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 IntegerList& offset_array) {
+ offset_array_.clear();
+ offset_array_ = offset_array;
+ set_model_changed();
+}
+
+// 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)));
+ 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 0;
+ }
+ 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()) {
+ 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);
+ return size;
+ }
+ for (IntegerList::iterator b = GetOffsetArray()->begin(),
+ e = GetOffsetArray()->end(); b != e; b++) {
+ size += new_data->WriteUShort(size, *b);
+ }
+ return size;
+}
+
+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) {
+}
+
+IntegerList* 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->ReadULongAsInt(
+ EblcTable::Offset::kIndexSubTable3_offsetArray +
+ i * DataSize::kULONG));
+ }
+ }
+}
+
+// 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
diff --git a/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h
index 1e45f23..2c4004c 100644
--- a/sfntly/table/bitmap/index_sub_table_format3.h
+++ b/sfntly/table/bitmap/index_sub_table_format3.h
@@ -20,29 +20,91 @@
#include "sfntly/table/bitmap/index_sub_table.h"
namespace sfntly {
-
+// Format 3 Index Subtable Entry.
class IndexSubTableFormat3 : public IndexSubTable,
public RefCounted<IndexSubTableFormat3> {
public:
- static int32_t GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last);
+ 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 BitmapGlyphInfoIter* 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 IntegerList& offset_array);
+
+ 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(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);
+ IntegerList* 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);
+
+ IntegerList offset_array_;
+ };
- // 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.
- IndexSubTableFormat3(ReadableFontData* data, int32_t first, int32_t last);
virtual ~IndexSubTableFormat3();
virtual int32_t NumGlyphs();
- virtual int32_t GlyphOffset(int32_t glyph_id);
+ 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
diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc
index 9ef681c..efa5f28 100644
--- a/sfntly/table/bitmap/index_sub_table_format4.cc
+++ b/sfntly/table/bitmap/index_sub_table_format4.cc
@@ -19,18 +19,49 @@
#include "sfntly/table/bitmap/eblc_table.h"
namespace sfntly {
+/******************************************************************************
+ * IndexSubTableFormat4 class
+ ******************************************************************************/
+IndexSubTableFormat4::~IndexSubTableFormat4() {
+}
-// static
-int32_t IndexSubTableFormat4::GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last) {
- UNREFERENCED_PARAMETER(first);
- UNREFERENCED_PARAMETER(last);
- assert(data);
- return data->ReadULongAsInt(offset +
- EblcTable::Offset::kIndexSubTable4_numGlyphs) *
- EblcTable::Offset::kCodeOffsetPairLength;
+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,
@@ -39,50 +70,293 @@ IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data,
: IndexSubTable(data, first, last) {
}
-IndexSubTableFormat4::~IndexSubTableFormat4() {
+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() {
- return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable4_numGlyphs);
+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(
+ 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
+BitmapGlyphInfoIter* IndexSubTableFormat4::Builder::GetIterator() {
+ Ptr<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator> it =
+ new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this);
+ return it.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)));
+ 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 0;
+ }
+ return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG +
+ GetOffsetArray()->size() *
+ EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset;
+}
+
+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()) {
+ 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);
+ 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());
+ }
+ 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(WritableFontData* data,
+ int32_t first_glyph_index,
+ int32_t last_glyph_index)
+ : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
}
-int32_t IndexSubTableFormat4::GlyphOffset(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- int32_t pair_index = FindCodeOffsetPair(glyph_id);
- if (pair_index < 0) {
- return -1;
+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);
+ CodeOffsetPairBuilder pair_builder(glyph_code, glyph_offset);
+ offset_pair_array_.push_back(pair_builder);
}
- return data_->ReadUShort(
- EblcTable::Offset::kIndexSubTable4_glyphArray +
- pair_index * EblcTable::Offset::kCodeOffsetPairLength +
- EblcTable::Offset::kCodeOffsetPair_offset);
}
- return -1;
}
-int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- int32_t pair_index = FindCodeOffsetPair(glyph_id);
- if (pair_index < 0) {
- return -1;
+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 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);
}
return -1;
}
-int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) {
- return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray,
- EblcTable::Offset::kCodeOffsetPairLength,
- NumGlyphs(),
- glyph_id);
+// 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
diff --git a/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h
index 821acca..258998d 100644
--- a/sfntly/table/bitmap/index_sub_table_format4.h
+++ b/sfntly/table/bitmap/index_sub_table_format4.h
@@ -24,25 +24,112 @@ namespace sfntly {
class IndexSubTableFormat4 : public IndexSubTable,
public RefCounted<IndexSubTableFormat4> {
public:
- static int32_t GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last);
-
- // 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.
- IndexSubTableFormat4(ReadableFontData* data, int32_t first, int32_t last);
+ 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 Builder;
+ class CodeOffsetPairBuilder : public CodeOffsetPair {
+ public:
+ void set_glyph_code(int32_t v) { glyph_code_ = v; }
+ void set_offset(int32_t v) { offset_ = v; }
+
+ private:
+ CodeOffsetPairBuilder(int32_t glyph_code, int32_t offset);
+
+ friend class Builder;
+ };
+
+ 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 BitmapGlyphInfoIter* 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(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(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 GlyphOffset(int32_t glyph_id);
+ 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;
} // namespace sfntly
diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc
index a2aed5c..7ba78ec 100644
--- a/sfntly/table/bitmap/index_sub_table_format5.cc
+++ b/sfntly/table/bitmap/index_sub_table_format5.cc
@@ -16,50 +16,324 @@
#include "sfntly/table/bitmap/index_sub_table_format5.h"
+#include <algorithm>
+
#include "sfntly/table/bitmap/eblc_table.h"
namespace sfntly {
+/******************************************************************************
+ * IndexSubTableFormat5 class
+ ******************************************************************************/
+IndexSubTableFormat5::~IndexSubTableFormat5() {
+}
-// static
-int32_t IndexSubTableFormat5::GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last) {
- UNREFERENCED_PARAMETER(first);
- UNREFERENCED_PARAMETER(last);
- assert(data);
- return data->ReadULongAsInt(offset +
- EblcTable::Offset::kIndexSubTable5_numGlyphs) *
- EblcTable::Offset::kCodeOffsetPairLength;
+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_bigMetrics,
+ BigGlyphMetrics::Offset::kMetricsLength)));
+ BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
+ return output.Detach();
}
IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data,
- int32_t first,
- int32_t last)
- : IndexSubTable(data, first, last) {
+ 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);
}
-IndexSubTableFormat5::~IndexSubTableFormat5() {
+// static
+int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data,
+ int32_t table_offset) {
+ UNREFERENCED_PARAMETER(table_offset);
+ int32_t num_glyphs = data->ReadULongAsInt(
+ EblcTable::Offset::kIndexSubTable5_numGlyphs);
+ return num_glyphs;
}
-int32_t IndexSubTableFormat5::NumGlyphs() {
- return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_numGlyphs);
+/******************************************************************************
+ * IndexSubTableFormat5::Builder class
+ ******************************************************************************/
+IndexSubTableFormat5::Builder::~Builder() {
}
-int32_t IndexSubTableFormat5::GlyphOffset(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return data_->ReadUShort(
- EblcTable::Offset::kIndexSubTable5_glyphArray +
- glyph_id * DataSize::kUSHORT);
+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;
+ }
+ IntegerList* glyph_array = GetGlyphArray();
+ IntegerList::iterator it = std::find(glyph_array->begin(),
+ glyph_array->end(),
+ glyph_id);
+ if (it == glyph_array->end()) {
+ return -1;
}
- return -1;
+ return (it - glyph_array->begin()) * ImageSize();
}
-int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) {
- if (CheckGlyphRange(glyph_id)) {
- return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize);
+CALLER_ATTACH
+BitmapGlyphInfoIter* IndexSubTableFormat5::Builder::GetIterator() {
+ Ptr<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator> it =
+ new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this);
+ return it.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)));
+ 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() {
+ if (model_changed()) {
+ Initialize(InternalReadData());
+ }
+}
+
+int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() {
+ if (glyph_array_.empty()) {
+ return 0;
+ }
+ return EblcTable::Offset::kIndexSubHeaderLength +
+ 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);
+ 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);
+ }
+ 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);
+}
+
+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();
+}
+
+IntegerList* IndexSubTableFormat5::Builder::GlyphArray() {
+ return GetGlyphArray();
+}
+
+void IndexSubTableFormat5::Builder::SetGlyphArray(const IntegerList& v) {
+ glyph_array_.clear();
+ glyph_array_ = v;
+ set_model_changed();
+}
+
+void IndexSubTableFormat5::Builder::Revert() {
+ glyph_array_.clear();
+ IndexSubTable::Builder::Revert();
+}
+
+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) {
+}
+
+IntegerList* 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->ReadULongAsInt(
+ 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;
}
- return -1;
+ 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
diff --git a/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h
index 354834e..c480fd8 100644
--- a/sfntly/table/bitmap/index_sub_table_format5.h
+++ b/sfntly/table/bitmap/index_sub_table_format5.h
@@ -17,6 +17,7 @@
#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 {
@@ -24,22 +25,90 @@ namespace sfntly {
class IndexSubTableFormat5 : public IndexSubTable,
public RefCounted<IndexSubTableFormat5> {
public:
- static int32_t GetDataLength(ReadableFontData* data,
- int32_t offset,
- int32_t first,
- int32_t last);
-
- // 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.
- IndexSubTableFormat5(ReadableFontData* data, int32_t first, int32_t last);
+ 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 BitmapGlyphInfoIter* 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);
+ CALLER_ATTACH BigGlyphMetrics::Builder* BigMetrics();
+ IntegerList* GlyphArray();
+ void SetGlyphArray(const IntegerList& v);
+
+ 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(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);
+
+ IntegerList* 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);
+
+ IntegerList glyph_array_;
+ };
virtual ~IndexSubTableFormat5();
virtual int32_t NumGlyphs();
- virtual int32_t GlyphOffset(int32_t glyph_id);
+ 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
diff --git a/sfntly/table/bitmap/simple_bitmap_glyph.cc b/sfntly/table/bitmap/simple_bitmap_glyph.cc
index 85364fd..87031a1 100644
--- a/sfntly/table/bitmap/simple_bitmap_glyph.cc
+++ b/sfntly/table/bitmap/simple_bitmap_glyph.cc
@@ -25,4 +25,21 @@ SimpleBitmapGlyph::SimpleBitmapGlyph(ReadableFontData* data, int32_t 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
diff --git a/sfntly/table/bitmap/simple_bitmap_glyph.h b/sfntly/table/bitmap/simple_bitmap_glyph.h
index 48bca98..56ede10 100644
--- a/sfntly/table/bitmap/simple_bitmap_glyph.h
+++ b/sfntly/table/bitmap/simple_bitmap_glyph.h
@@ -24,9 +24,20 @@ 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
diff --git a/sfntly/table/bitmap/small_glyph_metrics.cc b/sfntly/table/bitmap/small_glyph_metrics.cc
new file mode 100644
index 0000000..0f3c1e9
--- /dev/null
+++ b/sfntly/table/bitmap/small_glyph_metrics.cc
@@ -0,0 +1,126 @@
+/*
+ * 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/small_glyph_metrics.h"
+
+namespace sfntly {
+/******************************************************************************
+ * SmallGlyphMetrics class
+ ******************************************************************************/
+SmallGlyphMetrics::SmallGlyphMetrics(ReadableFontData* data)
+ : GlyphMetrics(data) {
+}
+
+SmallGlyphMetrics::~SmallGlyphMetrics() {
+}
+
+int32_t SmallGlyphMetrics::Height() {
+ return data_->ReadByte(Offset::kHeight);
+}
+
+int32_t SmallGlyphMetrics::Width() {
+ return data_->ReadByte(Offset::kWidth);
+}
+
+int32_t SmallGlyphMetrics::BearingX() {
+ return data_->ReadByte(Offset::kBearingX);
+}
+
+int32_t SmallGlyphMetrics::BearingY() {
+ return data_->ReadByte(Offset::kBearingY);
+}
+
+int32_t SmallGlyphMetrics::Advance() {
+ return data_->ReadByte(Offset::kAdvance);
+}
+
+/******************************************************************************
+ * SmallGlyphMetrics::Builder class
+ ******************************************************************************/
+SmallGlyphMetrics::Builder::Builder(WritableFontData* data)
+ : GlyphMetrics::Builder(data) {
+}
+
+SmallGlyphMetrics::Builder::Builder(ReadableFontData* data)
+ : GlyphMetrics::Builder(data) {
+}
+
+SmallGlyphMetrics::Builder::~Builder() {
+}
+
+int32_t SmallGlyphMetrics::Builder::Height() {
+ return InternalReadData()->ReadByte(Offset::kHeight);
+}
+
+void SmallGlyphMetrics::Builder::SetHeight(byte_t height) {
+ InternalWriteData()->WriteByte(Offset::kHeight, height);
+}
+
+int32_t SmallGlyphMetrics::Builder::Width() {
+ return InternalReadData()->ReadByte(Offset::kWidth);
+}
+
+void SmallGlyphMetrics::Builder::SetWidth(byte_t width) {
+ InternalWriteData()->WriteByte(Offset::kWidth, width);
+}
+
+int32_t SmallGlyphMetrics::Builder::BearingX() {
+ return InternalReadData()->ReadByte(Offset::kBearingX);
+}
+
+void SmallGlyphMetrics::Builder::SetBearingX(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kBearingX, bearing);
+}
+
+int32_t SmallGlyphMetrics::Builder::BearingY() {
+ return InternalReadData()->ReadByte(Offset::kBearingY);
+}
+
+void SmallGlyphMetrics::Builder::SetBearingY(byte_t bearing) {
+ InternalWriteData()->WriteByte(Offset::kBearingY, bearing);
+}
+
+int32_t SmallGlyphMetrics::Builder::Advance() {
+ return InternalReadData()->ReadByte(Offset::kAdvance);
+}
+
+void SmallGlyphMetrics::Builder::SetAdvance(byte_t advance) {
+ InternalWriteData()->WriteByte(Offset::kAdvance, advance);
+}
+
+CALLER_ATTACH FontDataTable*
+ SmallGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) {
+ SmallGlyphMetricsPtr output = new SmallGlyphMetrics(data);
+ return output.Detach();
+}
+
+void SmallGlyphMetrics::Builder::SubDataSet() {
+ // NOP.
+}
+
+int32_t SmallGlyphMetrics::Builder::SubDataSizeToSerialize() {
+ return 0;
+}
+
+bool SmallGlyphMetrics::Builder::SubReadyToSerialize() {
+ return false;
+}
+
+int32_t SmallGlyphMetrics::Builder::SubSerialize(WritableFontData* new_data) {
+ return Data()->CopyTo(new_data);
+}
+
+} // namespace sfntly
diff --git a/sfntly/table/bitmap/small_glyph_metrics.h b/sfntly/table/bitmap/small_glyph_metrics.h
new file mode 100644
index 0000000..ea13720
--- /dev/null
+++ b/sfntly/table/bitmap/small_glyph_metrics.h
@@ -0,0 +1,79 @@
+/*
+ * 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_SMALL_GLYPH_METRICS_H_
+#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SMALL_GLYPH_METRICS_H_
+
+#include "sfntly/port/refcount.h"
+#include "sfntly/table/bitmap/glyph_metrics.h"
+
+namespace sfntly {
+
+class SmallGlyphMetrics : public GlyphMetrics,
+ public RefCounted<SmallGlyphMetrics> {
+ public:
+ struct Offset {
+ enum {
+ kMetricsLength = 5,
+ kHeight = 0,
+ kWidth = 1,
+ kBearingX = 2,
+ kBearingY = 3,
+ kAdvance = 4,
+ };
+ };
+
+ 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(byte_t height);
+ int32_t Width();
+ void SetWidth(byte_t width);
+ int32_t BearingX();
+ void SetBearingX(byte_t bearing);
+ int32_t BearingY();
+ void SetBearingY(byte_t bearing);
+ int32_t Advance();
+ void SetAdvance(byte_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);
+ };
+
+ explicit SmallGlyphMetrics(ReadableFontData* data);
+ virtual ~SmallGlyphMetrics();
+
+ int32_t Height();
+ int32_t Width();
+ int32_t BearingX();
+ int32_t BearingY();
+ int32_t Advance();
+};
+typedef Ptr<SmallGlyphMetrics> SmallGlyphMetricsPtr;
+
+} // namespace sfntly
+
+#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SMALL_GLYPH_METRICS_H_
diff --git a/sfntly/table/byte_array_table_builder.cc b/sfntly/table/byte_array_table_builder.cc
new file mode 100644
index 0000000..631a05f
--- /dev/null
+++ b/sfntly/table/byte_array_table_builder.cc
@@ -0,0 +1,70 @@
+/*
+ * 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/byte_array_table_builder.h"
+
+namespace sfntly {
+
+ByteArrayTableBuilder::~ByteArrayTableBuilder() {}
+
+int32_t ByteArrayTableBuilder::ByteValue(int32_t index) {
+ ReadableFontDataPtr data = InternalReadData();
+ if (data == NULL) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IOException("No font data for the table");
+#endif
+ return -1;
+ }
+ return data->ReadByte(index);
+}
+
+void ByteArrayTableBuilder::SetByteValue(int32_t index, byte_t b) {
+ WritableFontDataPtr data = InternalWriteData();
+ if (data == NULL) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IOException("No font data for the table");
+#endif
+ return;
+ }
+ data->WriteByte(index, b);
+}
+
+int32_t ByteArrayTableBuilder::ByteCount() {
+ ReadableFontDataPtr data = InternalReadData();
+ if (data == NULL) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IOException("No font data for the table");
+#endif
+ return 0;
+ }
+ return data->Length();
+}
+
+ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header,
+ WritableFontData* data)
+ : TableBasedTableBuilder(header, data) {
+}
+
+ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header,
+ ReadableFontData* data)
+ : TableBasedTableBuilder(header, data) {
+}
+
+ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header)
+ : TableBasedTableBuilder(header) {
+}
+
+} // namespace sfntly
diff --git a/sfntly/table/byte_array_table_builder.h b/sfntly/table/byte_array_table_builder.h
new file mode 100644
index 0000000..42d27a8
--- /dev/null
+++ b/sfntly/table/byte_array_table_builder.h
@@ -0,0 +1,53 @@
+/*
+ * 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_BYTE_ARRAY_TABLE_BUILDER_H_
+#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_
+
+#include "sfntly/table/table_based_table_builder.h"
+
+namespace sfntly {
+
+// An abstract builder base for byte array based tables.
+class ByteArrayTableBuilder : public TableBasedTableBuilder {
+ public:
+ virtual ~ByteArrayTableBuilder();
+
+ // Get the byte value at the specified index. The index is relative to the
+ // start of the table.
+ // @param index index relative to the start of the table
+ // @return byte value at the given index
+ virtual int32_t ByteValue(int32_t index);
+
+ // Set the byte value at the specified index. The index is relative to the
+ // start of the table.
+ // @param index index relative to the start of the table
+ // @param b byte value to set
+ virtual void SetByteValue(int32_t index, byte_t b);
+
+ // Get the number of bytes set for this table. It may include padding bytes at
+ // the end.
+ virtual int32_t ByteCount();
+
+ protected:
+ ByteArrayTableBuilder(Header* header, WritableFontData* data);
+ ByteArrayTableBuilder(Header* header, ReadableFontData* data);
+ explicit ByteArrayTableBuilder(Header* header);
+};
+
+} // namespace sfntly
+
+#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_
diff --git a/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc
index 9853130..5f6d5a5 100644
--- a/sfntly/table/core/name_table.cc
+++ b/sfntly/table/core/name_table.cc
@@ -227,27 +227,31 @@ bool NameTable::NameEntryFilterInPlace::Accept(int32_t platform_id,
/******************************************************************************
* NameTable::NameEntryIterator class
******************************************************************************/
-NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) {
- Init(table, NULL);
+NameTable::NameEntryIterator::NameEntryIterator(NameTable* table)
+ : RefIterator<NameEntry, NameTable>(table),
+ name_index_(0),
+ filter_(NULL) {
}
NameTable::NameEntryIterator::NameEntryIterator(NameTable* table,
- NameEntryFilter* filter) {
- Init(table, filter);
+ NameEntryFilter* filter)
+ : RefIterator<NameEntry, NameTable>(table),
+ name_index_(0),
+ filter_(filter) {
}
bool NameTable::NameEntryIterator::HasNext() {
if (!filter_) {
- if (name_index_ < table_->NameCount()) {
+ if (name_index_ < container()->NameCount()) {
return true;
}
return false;
}
- for (; name_index_ < table_->NameCount(); ++name_index_) {
- if (filter_->Accept(table_->PlatformId(name_index_),
- table_->EncodingId(name_index_),
- table_->LanguageId(name_index_),
- table_->NameId(name_index_))) {
+ for (; name_index_ < container()->NameCount(); ++name_index_) {
+ if (filter_->Accept(container()->PlatformId(name_index_),
+ container()->EncodingId(name_index_),
+ container()->LanguageId(name_index_),
+ container()->NameId(name_index_))) {
return true;
}
}
@@ -257,21 +261,7 @@ bool NameTable::NameEntryIterator::HasNext() {
CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() {
if (!HasNext())
return NULL;
- return table_->GetNameEntry(name_index_++);
-}
-
-void NameTable::NameEntryIterator::Remove() {
-#if !defined (SFNTLY_NO_EXCEPTION)
- throw UnsupportedOperationException(
- "Cannot remove a name table from an existing font.");
-#endif
-}
-
-void NameTable::NameEntryIterator::Init(NameTable* table,
- NameEntryFilter* filter) {
- table_ = table;
- filter_ = filter;
- name_index_ = 0;
+ return container()->GetNameEntry(name_index_++);
}
/******************************************************************************
@@ -423,10 +413,11 @@ int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) {
void NameTable::Builder::Initialize(ReadableFontData* data) {
if (data) {
NameTablePtr table = new NameTable(header(), data);
- NameEntryIterator name_iter(table, NULL);
- while (name_iter.HasNext()) {
+ Ptr<NameEntryIterator> name_iter;
+ name_iter.Attach(table->Iterator());
+ while (name_iter->HasNext()) {
NameEntryPtr name_entry;
- name_entry.Attach(name_iter.Next());
+ name_entry.Attach(name_iter->Next());
NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry);
NameEntry* builder_entry = name_entry_builder->name_entry();
NameEntryId probe = builder_entry->name_entry_id();
@@ -532,21 +523,25 @@ CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t platform_id,
int32_t name_id) {
NameTable::NameEntryFilterInPlace
filter(platform_id, encoding_id, language_id, name_id);
- NameTable::NameEntryIterator* name_entry_iter = Iterator(&filter);
+ Ptr<NameTable::NameEntryIterator> name_entry_iter;
+ name_entry_iter.Attach(Iterator(&filter));
NameEntryPtr result;
if (name_entry_iter->HasNext()) {
result = name_entry_iter->Next();
}
- delete name_entry_iter;
return result;
}
-NameTable::NameEntryIterator* NameTable::Iterator() {
- return new NameTable::NameEntryIterator(this);
+CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator() {
+ Ptr<NameEntryIterator> output = new NameTable::NameEntryIterator(this);
+ return output.Detach();
}
+CALLER_ATTACH
NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) {
- return new NameTable::NameEntryIterator(this, filter);
+ Ptr<NameEntryIterator> output =
+ new NameTable::NameEntryIterator(this, filter);
+ return output.Detach();
}
NameTable::NameTable(Header* header, ReadableFontData* data)
diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h
index 0c657da..9c007a1 100644
--- a/sfntly/table/core/name_table.h
+++ b/sfntly/table/core/name_table.h
@@ -26,6 +26,7 @@
#include <map>
#include <utility>
+#include "sfntly/port/java_iterator.h"
#include "sfntly/table/subtable_container_table.h"
#if defined U_USING_ICU_NAMESPACE
@@ -555,23 +556,17 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> {
int32_t name_id_;
};
- // Mimic Java's iterator to iterate through the entries within the name table.
- class NameEntryIterator {
+ class NameEntryIterator : public RefIterator<NameEntry, NameTable> {
public:
// If filter is NULL, filter through all tables.
explicit NameEntryIterator(NameTable* table);
NameEntryIterator(NameTable* table, NameEntryFilter* filter);
- // Make gcc -Wnon-virtual-dtor happy.
virtual ~NameEntryIterator() {}
virtual bool HasNext();
virtual CALLER_ATTACH NameEntry* Next();
- virtual void Remove();
private:
- void Init(NameTable* table, NameEntryFilter* filter);
-
- NameTable* table_; // Use dumb pointer since it's a composition object.
int32_t name_index_;
NameEntryFilter* filter_;
};
@@ -686,9 +681,8 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> {
// virtual void names(std::set<NameEntryPtr>*);
// Get the iterator to iterate through all name entries.
- // Note: Caller delete the returned object.
- virtual NameEntryIterator* Iterator();
- virtual NameEntryIterator* Iterator(NameEntryFilter* filter);
+ virtual CALLER_ATTACH NameEntryIterator* Iterator();
+ virtual CALLER_ATTACH NameEntryIterator* Iterator(NameEntryFilter* filter);
private:
struct Offset {
diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc
index 0197bbd..7953269 100644
--- a/sfntly/table/font_data_table.cc
+++ b/sfntly/table/font_data_table.cc
@@ -53,6 +53,9 @@ CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() {
WritableFontDataPtr new_data;
if (model_changed_) {
if (!SubReadyToSerialize()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IOException("Table not ready to build.");
+#endif
return NULL;
}
int32_t size = SubDataSizeToSerialize();
@@ -80,6 +83,9 @@ CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() {
if (model_changed_) {
// Let subclass serialize from model.
if (!SubReadyToSerialize()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IOException("Table not ready to build.");
+#endif
return NULL;
}
int32_t size = SubDataSizeToSerialize();
@@ -113,9 +119,17 @@ WritableFontData* FontDataTable::Builder::InternalWriteData() {
WritableFontDataPtr new_data;
new_data.Attach(WritableFontData::CreateWritableFontData(
r_data_ == NULL ? 0 : r_data_->Length()));
- if (r_data_) {
- r_data_->CopyTo(new_data);
+#if !defined (SFNTLY_NO_EXCEPTION)
+ try {
+#endif
+ if (r_data_) {
+ r_data_->CopyTo(new_data);
+ }
+#if !defined (SFNTLY_NO_EXCEPTION)
+ } catch (IOException& e) {
+ // TODO(stuartg): fix when IOExceptions are cleaned up
}
+#endif
InternalSetData(new_data, false);
}
return w_data_.p_;
diff --git a/sfntly/table/generic_table_builder.cc b/sfntly/table/generic_table_builder.cc
new file mode 100644
index 0000000..78e6797
--- /dev/null
+++ b/sfntly/table/generic_table_builder.cc
@@ -0,0 +1,49 @@
+/*
+ * 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/generic_table_builder.h"
+
+namespace sfntly {
+
+GenericTableBuilder::~GenericTableBuilder() {}
+
+CALLER_ATTACH
+FontDataTable* GenericTableBuilder::SubBuildTable(ReadableFontData* data) {
+ // Note: In C++ port, we use GenericTable, the ref-counted version of Table
+ UNREFERENCED_PARAMETER(data);
+ Ptr<GenericTable> table = new GenericTable(header(), InternalReadData());
+ return table.Detach();
+}
+
+// static
+CALLER_ATTACH GenericTableBuilder*
+ GenericTableBuilder::CreateBuilder(Header* header, WritableFontData* data) {
+ Ptr<GenericTableBuilder> builder =
+ new GenericTableBuilder(header, data);
+ return builder.Detach();
+}
+
+GenericTableBuilder::GenericTableBuilder(Header* header,
+ WritableFontData* data)
+ : TableBasedTableBuilder(header, data) {
+}
+
+GenericTableBuilder::GenericTableBuilder(Header* header,
+ ReadableFontData* data)
+ : TableBasedTableBuilder(header, data) {
+}
+
+} // namespace sfntly
diff --git a/sfntly/table/generic_table_builder.h b/sfntly/table/generic_table_builder.h
new file mode 100644
index 0000000..a100ea0
--- /dev/null
+++ b/sfntly/table/generic_table_builder.h
@@ -0,0 +1,42 @@
+/*
+ * 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_GENERIC_TABLE_BUILDER_H_
+#define SFNTLY_CPP_SRC_SFNTLY_TABLE_GENERIC_TABLE_BUILDER_H_
+
+#include "sfntly/table/table_based_table_builder.h"
+
+namespace sfntly {
+
+// A table builder to do the minimal table building for an unknown table type.
+class GenericTableBuilder : public TableBasedTableBuilder,
+ public RefCounted<GenericTableBuilder> {
+ public:
+ virtual ~GenericTableBuilder();
+
+ virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
+
+ static CALLER_ATTACH GenericTableBuilder*
+ CreateBuilder(Header* header, WritableFontData* data);
+
+ private:
+ GenericTableBuilder(Header* header, WritableFontData* data);
+ GenericTableBuilder(Header* header, ReadableFontData* data);
+};
+
+} // namespace sfntly
+
+#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_
diff --git a/sfntly/table/header.h b/sfntly/table/header.h
index 117da95..280e556 100644
--- a/sfntly/table/header.h
+++ b/sfntly/table/header.h
@@ -22,7 +22,7 @@
namespace sfntly {
class Header : public RefCounted<Header> {
- public:
+ public:
// Make a partial header with only the basic info for an empty new table.
explicit Header(int32_t tag);
@@ -36,7 +36,10 @@ class Header : public RefCounted<Header> {
// Get the table tag.
int32_t tag() { return tag_; }
- // Get the table offset. The offset is from the start of the font file.
+ // Get the table offset. The offset is from the start of the font file. This
+ // offset value is what was read from the font file during construction of the
+ // font. It may not be meaningful if the font was maninpulated through the
+ // builders.
int32_t offset() { return offset_; }
// Is the offset in the header valid. The offset will not be valid if the
@@ -44,12 +47,15 @@ class Header : public RefCounted<Header> {
// font file.
bool offset_valid() { return offset_valid_; }
- // Get the length of the table as recorded in the table record header.
+ // Get the length of the table as recorded in the table record header. During
+ // building the header length will reflect the length that was initially read
+ // from the font file. This may not be consistent with the current state of
+ // the data.
int32_t length() { return length_; }
// Is the length in the header valid. The length will not be valid if the
// table was constructed during building and has no physical location in a
- // font file.
+ // font file until the table is built from the builder.
bool length_valid() { return length_valid_; }
// Get the checksum for the table as recorded in the table record header.
@@ -65,7 +71,7 @@ class Header : public RefCounted<Header> {
// int hashCode()
// string toString()
- private:
+ private:
int32_t tag_;
int32_t offset_;
bool offset_valid_;
diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc
index d70b18c..b990c7c 100644
--- a/sfntly/table/subtable.cc
+++ b/sfntly/table/subtable.cc
@@ -22,6 +22,11 @@ namespace sfntly {
******************************************************************************/
SubTable::~SubTable() {}
+SubTable::SubTable(ReadableFontData* data, ReadableFontData* master_data)
+ : FontDataTable(data), padding_(0) {
+ master_data_ = master_data;
+}
+
SubTable::SubTable(ReadableFontData* data)
: FontDataTable(data), padding_(0) {
}
@@ -29,7 +34,23 @@ SubTable::SubTable(ReadableFontData* data)
/******************************************************************************
* SubTable::Builder class
******************************************************************************/
-SubTable::Builder::~Builder() {}
+SubTable::Builder::Builder() {
+}
+
+SubTable::Builder::~Builder() {
+}
+
+SubTable::Builder::Builder(WritableFontData* data,
+ ReadableFontData* master_data)
+ : FontDataTable::Builder(data) {
+ master_data_ = master_data;
+}
+
+SubTable::Builder::Builder(ReadableFontData* data,
+ ReadableFontData* master_data)
+ : FontDataTable::Builder(data) {
+ master_data_ = master_data;
+}
SubTable::Builder::Builder(WritableFontData* data)
: FontDataTable::Builder(data) {
diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h
index e5ec748..fbfb4b0 100644
--- a/sfntly/table/subtable.h
+++ b/sfntly/table/subtable.h
@@ -29,24 +29,43 @@ class SubTable : public FontDataTable {
public:
class Builder : public FontDataTable::Builder {
public:
+ // Creates a new empty sub-table.
+ Builder();
virtual ~Builder();
protected:
- Builder(WritableFontData* data);
- Builder(ReadableFontData* data);
+ // @param data the data for the subtable being built
+ // @param master_data the data for the full table
+ Builder(WritableFontData* data, ReadableFontData* master_data);
+ Builder(ReadableFontData* data, ReadableFontData* master_data);
+ explicit Builder(WritableFontData* data);
+ explicit Builder(ReadableFontData* data);
+
+ ReadableFontData* master_read_data() { return master_data_; }
+
+ private:
+ ReadableFontDataPtr master_data_;
};
virtual ~SubTable();
int32_t padding() { return padding_; }
+ // Sets the amount of padding that is part of the data being used by this
+ // subtable.
void set_padding(int32_t padding) { padding_ = padding; }
protected:
+ SubTable(ReadableFontData* data, ReadableFontData* master_data);
+
// Note: constructor refactored in C++ to avoid heavy lifting.
// caller need to do data->Slice(offset, length) beforehand.
explicit SubTable(ReadableFontData* data);
+ ReadableFontData* master_read_data() { return master_data_; }
+
private:
+ // The data for the whole table in which this subtable is contained.
+ ReadableFontDataPtr master_data_;
int32_t padding_;
};
diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc
index 6cfe1f8..f1ff63d 100644
--- a/sfntly/table/table.cc
+++ b/sfntly/table/table.cc
@@ -31,6 +31,7 @@
#include "sfntly/table/core/maximum_profile_table.h"
#include "sfntly/table/core/name_table.h"
#include "sfntly/table/core/os2_table.h"
+#include "sfntly/table/generic_table_builder.h"
#include "sfntly/table/table_based_table_builder.h"
#include "sfntly/table/truetype/glyph_table.h"
#include "sfntly/table/truetype/loca_table.h"
diff --git a/sfntly/table/table_based_table_builder.cc b/sfntly/table/table_based_table_builder.cc
index 6e6a46a..b505704 100644
--- a/sfntly/table/table_based_table_builder.cc
+++ b/sfntly/table/table_based_table_builder.cc
@@ -18,7 +18,6 @@
namespace sfntly {
-
/******************************************************************************
* TableBasedTableBuilder class
******************************************************************************/
@@ -67,27 +66,4 @@ Table* TableBasedTableBuilder::GetTable() {
return table_;
}
-/******************************************************************************
- * GenericTableBuilder class
- ******************************************************************************/
-GenericTableBuilder::GenericTableBuilder(Header* header,
- WritableFontData* data)
- : TableBasedTableBuilder(header, data) {
-}
-
-CALLER_ATTACH FontDataTable*
- GenericTableBuilder::SubBuildTable(ReadableFontData* data) {
- // Note: In C++ port, we use GenericTable, the ref-counted version of Table
- UNREFERENCED_PARAMETER(data);
- FontDataTablePtr table = new GenericTable(this->header(), InternalReadData());
- return table.Detach();
-}
-
-CALLER_ATTACH GenericTableBuilder*
- GenericTableBuilder::CreateBuilder(Header* header, WritableFontData* data) {
- Ptr<GenericTableBuilder> builder =
- new GenericTableBuilder(header, data);
- return builder.Detach();
-}
-
} // namespace sfntly
diff --git a/sfntly/table/table_based_table_builder.h b/sfntly/table/table_based_table_builder.h
index 3868d46..d88eefd 100644
--- a/sfntly/table/table_based_table_builder.h
+++ b/sfntly/table/table_based_table_builder.h
@@ -34,7 +34,7 @@ class TableBasedTableBuilder : public Table::Builder {
protected:
TableBasedTableBuilder(Header* header, WritableFontData* data);
TableBasedTableBuilder(Header* header, ReadableFontData* data);
- TableBasedTableBuilder(Header* header);
+ explicit TableBasedTableBuilder(Header* header);
// C++ port: renamed table() to GetTable()
virtual Table* GetTable();
@@ -43,17 +43,6 @@ class TableBasedTableBuilder : public Table::Builder {
TablePtr table_;
};
-class GenericTableBuilder : public TableBasedTableBuilder,
- public RefCounted<GenericTableBuilder> {
- public:
- GenericTableBuilder(Header* header, WritableFontData* data);
- virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
-
- static CALLER_ATTACH
- GenericTableBuilder* CreateBuilder(Header* header,
- WritableFontData* data);
-};
-
} // namespace sfntly
#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_
diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc
index dc1163a..bec9c89 100644
--- a/sfntly/table/truetype/glyph_table.cc
+++ b/sfntly/table/truetype/glyph_table.cc
@@ -162,10 +162,6 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data,
const IntegerList& loca) {
if (data != NULL) {
if (loca_.empty()) {
-#if !defined (SFNTLY_NO_EXCEPTION)
- throw IllegalStateException(
- "Loca values not set - unable to parse glyph data.");
-#endif
return;
}
int32_t loca_value;
@@ -186,6 +182,13 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data,
GlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() {
if (glyph_builders_.empty()) {
+ if (InternalReadData() && !loca_.empty()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IllegalStateException(
+ "Loca values not set - unable to parse glyph data.");
+#endif
+ return NULL;
+ }
Initialize(InternalReadData(), loca_);
set_model_changed();
}
diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h
index 3ba9cac..f8a7c33 100644
--- a/sfntly/table/truetype/glyph_table.h
+++ b/sfntly/table/truetype/glyph_table.h
@@ -53,8 +53,8 @@ class GlyphTable : public SubTableContainerTable,
// Incoming table_builder is GlyphTable::Builder*.
// Note: constructor refactored in C++ to avoid heavy lifting.
// caller need to do data->Slice(offset, length) beforehand.
- Builder(WritableFontData* data);
- Builder(ReadableFontData* data);
+ explicit Builder(WritableFontData* data);
+ explicit Builder(ReadableFontData* data);
static CALLER_ATTACH Builder*
GetBuilder(GlyphTable::Builder* table_builder,
@@ -128,7 +128,12 @@ class GlyphTable : public SubTableContainerTable,
// invalid, then an empty glyph builder List will be returned.
GlyphBuilderList* GlyphBuilders();
- // Replace the internal glyph builders with the one provided.
+ // 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 GlyphTable.Builder::GlyphBuilders() is being used and modified
+ // then those changes will already be reflected in the glyph table builder.
void SetGlyphBuilders(GlyphBuilderList* glyph_builders);
// Glyph builder factories
@@ -173,8 +178,8 @@ class GlyphTable : public SubTableContainerTable,
protected:
// Note: constructor refactored in C++ to avoid heavy lifting.
// caller need to do data->Slice(offset, length) beforehand.
- SimpleGlyphBuilder(WritableFontData* data);
- SimpleGlyphBuilder(ReadableFontData* data);
+ explicit SimpleGlyphBuilder(WritableFontData* data);
+ explicit SimpleGlyphBuilder(ReadableFontData* data);
virtual CALLER_ATTACH FontDataTable*
SubBuildTable(ReadableFontData* data);
@@ -244,8 +249,8 @@ class GlyphTable : public SubTableContainerTable,
protected:
// Note: constructor refactored in C++ to avoid heavy lifting.
// caller need to do data->Slice(offset, length) beforehand.
- CompositeGlyphBuilder(WritableFontData* data);
- CompositeGlyphBuilder(ReadableFontData* data);
+ explicit CompositeGlyphBuilder(WritableFontData* data);
+ explicit CompositeGlyphBuilder(ReadableFontData* data);
virtual CALLER_ATTACH FontDataTable*
SubBuildTable(ReadableFontData* data);
diff --git a/sfntly/table/truetype/loca_table.cc b/sfntly/table/truetype/loca_table.cc
index 0a579ae..c692155 100644
--- a/sfntly/table/truetype/loca_table.cc
+++ b/sfntly/table/truetype/loca_table.cc
@@ -73,16 +73,15 @@ LocaTable::LocaTable(Header* header,
* LocaTable::Iterator class
******************************************************************************/
LocaTable::LocaIterator::LocaIterator(LocaTable* table)
- : index_(-1) {
- table_ = table;
+ : PODIterator<int32_t, LocaTable>(table), index_(-1) {
}
bool LocaTable::LocaIterator::HasNext() {
- return index_ <= table_->num_glyphs_;
+ return index_ <= container()->num_glyphs_;
}
int32_t LocaTable::LocaIterator::Next() {
- return table_->Loca(index_++);
+ return container()->Loca(index_++);
}
/******************************************************************************
@@ -118,29 +117,22 @@ void LocaTable::Builder::SetLocaList(IntegerList* list) {
loca_.clear();
if (list) {
loca_ = *list;
- num_glyphs_ = loca_.size();
set_model_changed();
}
}
int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) {
- if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) {
-#if !defined (SFNTLY_NO_EXCEPTION)
- throw IndexOutOfBoundException("Glyph ID is out of bounds.");
-#endif
+ if (CheckGlyphRange(glyph_id) == -1) {
return 0;
}
- return Loca(glyph_id);
+ return GetLocaList()->at(glyph_id);
}
int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) {
- if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) {
-#if !defined (SFNTLY_NO_EXCEPTION)
- throw IndexOutOfBoundException("Glyph ID is out of bounds.");
-#endif
+ if (CheckGlyphRange(glyph_id) == -1) {
return 0;
}
- return Loca(glyph_id + 1) - Loca(glyph_id);
+ return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id);
}
void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) {
@@ -148,10 +140,7 @@ void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) {
}
int32_t LocaTable::Builder::NumGlyphs() {
- if (!loca_.empty()) {
- return loca_.size() - 1;
- }
- return num_glyphs_;
+ return LastGlyphIndex() - 1;
}
void LocaTable::Builder::Revert() {
@@ -202,10 +191,12 @@ int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) {
size += new_data->WriteUShort(size, *l / 2);
}
}
- return 0;
+ num_glyphs_ = loca_.size() - 1;
+ return size;
}
void LocaTable::Builder::Initialize(ReadableFontData* data) {
+ ClearLoca(false);
if (data) {
if (NumGlyphs() < 0) {
#if !defined (SFNTLY_NO_EXCEPTION)
@@ -215,13 +206,28 @@ void LocaTable::Builder::Initialize(ReadableFontData* data) {
}
LocaTablePtr table =
new LocaTable(header(), data, format_version_, num_glyphs_);
- LocaTable::LocaIterator loca_iter(table);
- while (loca_iter.HasNext()) {
- loca_.push_back(loca_iter.Next());
+ Ptr<LocaTable::LocaIterator> loca_iter =
+ new LocaTable::LocaIterator(table);
+ while (loca_iter->HasNext()) {
+ loca_.push_back(loca_iter->Next());
}
}
}
+int32_t LocaTable::Builder::CheckGlyphRange(int32_t glyph_id) {
+ if (glyph_id < 0 || glyph_id > LastGlyphIndex()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundsException("Glyph ID is outside of the allowed range");
+#endif
+ return -1;
+ }
+ return glyph_id;
+}
+
+int32_t LocaTable::Builder::LastGlyphIndex() {
+ return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1;
+}
+
IntegerList* LocaTable::Builder::GetLocaList() {
if (loca_.empty()) {
Initialize(InternalReadData());
@@ -230,4 +236,11 @@ IntegerList* LocaTable::Builder::GetLocaList() {
return &loca_;
}
+void LocaTable::Builder::ClearLoca(bool nullify) {
+ // Note: in C++ port, nullify is not used at all.
+ UNREFERENCED_PARAMETER(nullify);
+ loca_.clear();
+ set_model_changed(false);
+}
+
} // namespace sfntly
diff --git a/sfntly/table/truetype/loca_table.h b/sfntly/table/truetype/loca_table.h
index 0ec13bd..67c5749 100644
--- a/sfntly/table/truetype/loca_table.h
+++ b/sfntly/table/truetype/loca_table.h
@@ -17,6 +17,7 @@
#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_LOCA_TABLE_H_
#define SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_LOCA_TABLE_H_
+#include "sfntly/port/java_iterator.h"
#include "sfntly/table/table.h"
#include "sfntly/table/core/font_header_table.h"
@@ -25,17 +26,16 @@ namespace sfntly {
// A Loca table - 'loca'.
class LocaTable : public Table, public RefCounted<LocaTable> {
public:
- // Note: different implementation than Java, caller to instantiate this class
- // object directly from stack instead of calling LocaTable::iterator().
- class LocaIterator {
+ class LocaIterator : public PODIterator<int32_t, LocaTable> {
public:
explicit LocaIterator(LocaTable* table);
- bool HasNext();
- int32_t Next();
+ virtual ~LocaIterator() {}
+
+ virtual bool HasNext();
+ virtual int32_t Next();
private:
int32_t index_;
- LocaTable* table_; // use dumb pointer since it's a composition object
};
class Builder : public Table::Builder, public RefCounted<Builder> {
@@ -83,7 +83,8 @@ class LocaTable : public Table, public RefCounted<LocaTable> {
// This method sets the number of glyphs that the builder will attempt to
// parse location data for from the raw binary data. This method only needs
// to be called (and <b>must</b> be) when the raw data for this builder has
- // been changed.
+ // been changed. It does not by itself reset the data or clear any set loca
+ // list.
void SetNumGlyphs(int32_t num_glyphs);
// Get the number of glyphs that this builder has support for.
@@ -119,11 +120,19 @@ class LocaTable : public Table, public RefCounted<LocaTable> {
// @param data the data to initialize from
void Initialize(ReadableFontData* data);
+ // Checks that the glyph id is within the correct range.
+ // @return glyph_id if correct, -1 otherwise.
+ int32_t CheckGlyphRange(int32_t glyph_id);
+
+ int32_t LastGlyphIndex();
+
// Internal method to get the loca list if already generated and if not to
// initialize the state of the builder.
// @return the loca list
IntegerList* GetLocaList();
+ void ClearLoca(bool nullify);
+
int32_t format_version_; // Note: IndexToLocFormat
int32_t num_glyphs_;
IntegerList loca_;
diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc
index 60c5524..6fd5c3b 100644
--- a/test/font_parsing_test.cc
+++ b/test/font_parsing_test.cc
@@ -22,6 +22,7 @@
#include "sfntly/font_factory.h"
#include "sfntly/table/core/font_header_table.h"
#include "sfntly/table/table.h"
+#include "sfntly/table/generic_table_builder.h"
#include "sfntly/table/table_based_table_builder.h"
#include "sfntly/tag.h"
#include "sfntly/port/file_input_stream.h"