Port files under /data to Aug 11 version.
ReadableFontData.Search*() not ported since they're already in another CL under review.
git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@55 672e30a5-4c29-85ac-ac6d-611c735e0a51
diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc
index 5502185..c820adc 100644
--- a/sfntly/data/byte_array.cc
+++ b/sfntly/data/byte_array.cc
@@ -34,51 +34,57 @@
return filled_length_;
}
-byte_t ByteArray::Get(int32_t index) {
- return InternalGet(index);
+int32_t ByteArray::Get(int32_t index) {
+ return InternalGet(index) & 0xff;
}
int32_t ByteArray::Get(int32_t index, ByteVector* b) {
assert(b);
- return Get(index, b, 0, b->size());
+ return Get(index, &((*b)[0]), 0, b->size());
}
int32_t ByteArray::Get(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
assert(b);
if (index < 0 || index >= filled_length_) {
- return -1;
+ return 0;
}
int32_t actual_length = std::min<int32_t>(length, filled_length_ - index);
- if (actual_length < 0) {
- return -1;
- }
return InternalGet(index, b, offset, actual_length);
}
-bool ByteArray::Put(int32_t index, byte_t b) {
+void ByteArray::Put(int32_t index, byte_t b) {
if (index < 0 || index >= Size()) {
- return false;
+#if defined (SFNTLY_NO_EXCEPTION)
+ return;
+#else
+ throw IndexOutOfBoundException(
+ "Attempt to write outside the bounds of the data");
+#endif
}
- bool result = InternalPut(index, b);
+ InternalPut(index, b);
filled_length_ = std::max<int32_t>(filled_length_, index + 1);
- return result;
}
int32_t ByteArray::Put(int index, ByteVector* b) {
assert(b);
- return Put(index, b, 0, b->size());
+ return Put(index, &((*b)[0]), 0, b->size());
}
int32_t ByteArray::Put(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
assert(b);
if (index < 0 || index >= Size()) {
+#if defined (SFNTLY_NO_EXCEPTION)
return 0;
+#else
+ throw IndexOutOfBoundException(
+ "Attempt to write outside the bounds of the data");
+#endif
}
int32_t actual_length = std::min<int32_t>(length, Size() - index);
int32_t bytes_written = InternalPut(index, b, offset, actual_length);
@@ -106,8 +112,9 @@
int32_t index = 0;
int32_t remaining_length = length;
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
- while ((bytes_read = Get(index + src_offset, &b, 0, buffer_length)) > 0) {
- int bytes_written = array->Put(index + dst_offset, &b, 0, bytes_read);
+ 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;
@@ -131,7 +138,7 @@
int32_t bytes_read = 0;
int32_t index = 0;
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
- while ((bytes_read = Get(index + offset, &b, 0, buffer_length)) > 0) {
+ while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) {
os->Write(&b, 0, bytes_read);
index += bytes_read;
buffer_length = std::min<int32_t>(b.size(), length - index);
@@ -145,7 +152,7 @@
int32_t index = 0;
int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
- if (Put(index, &b, 0, bytes_read) != bytes_read) {
+ if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) {
#if defined (SFNTLY_NO_EXCEPTION)
return 0;
#else
@@ -165,7 +172,7 @@
int32_t index = 0;
int32_t buffer_length = COPY_BUFFER_SIZE;
while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
- if (Put(index, &b, 0, bytes_read) != bytes_read) {
+ if (Put(index, &b[0], 0, bytes_read) != bytes_read) {
#if defined (SFNTLY_NO_EXCEPTION)
return 0;
#else
diff --git a/sfntly/data/byte_array.h b/sfntly/data/byte_array.h
index 9ac56c0..3375244 100644
--- a/sfntly/data/byte_array.h
+++ b/sfntly/data/byte_array.h
@@ -24,56 +24,62 @@
namespace sfntly {
-// An interface abstraction to a byte array. Can be implemented to map to
-// various types of data storage.
+// An abstraction to a contiguous array of bytes.
// C++ port of this class assumes that the data are stored in a linear region
// like std::vector.
class ByteArray : virtual public RefCount {
public:
virtual ~ByteArray();
- // Get the current filled and readable length of the array.
+ // Gets the current filled and readable length of the array.
int32_t Length();
- // Get the maximum size of the array. This is the maximum number of bytes that
+ // Gets the maximum size of the array. This is the maximum number of bytes that
// the array can hold and all of it may not be filled with data or even fully
// allocated yet.
int32_t Size();
+ // Determines whether or not this array is growable or of fixed size.
bool growable() { return growable_; }
+
int32_t SetFilledLength(int32_t filled_length);
- // Get the byte from the given index.
- virtual byte_t Get(int32_t index);
+ // Gets the byte from the given index.
+ // @param index the index into the byte array
+ // @return the byte or -1 if reading beyond the bounds of the data
+ virtual int32_t Get(int32_t index);
- // Get the bytes from the given index and fill the buffer with them. As many
+ // Gets the bytes from the given index and fill the buffer with them. As many
// bytes as will fit into the buffer are read unless that would go past the
// end of the array.
+ // @param index the index into the byte array
+ // @param b the buffer to put the bytes read into
+ // @return the number of bytes read from the buffer
virtual int32_t Get(int32_t index, ByteVector* b);
- // Get the bytes from the given index and fill the buffer with them starting
+ // Gets the bytes from the given index and fill the buffer with them starting
// at the offset given. As many bytes as the specified length are read unless
// that would go past the end of the array.
// @param index the index into the byte array
// @param b the buffer to put the bytes read into
// @param offset the location in the buffer to start putting the bytes
// @param length the number of bytes to put into the buffer
- // @return the number of bytes put into the buffer
+ // @return the number of bytes read from the buffer
virtual int32_t Get(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
- // Put the specified byte into the array at the given index unless that would
+ // Puts the specified byte into the array at the given index unless that would
// be beyond the length of the array and it isn't growable.
- virtual bool Put(int32_t index, byte_t b);
+ virtual void Put(int32_t index, byte_t b);
- // Put the specified bytes into the array at the given index. The entire
+ // Puts the specified bytes into the array at the given index. The entire
// buffer is put into the array unless that would extend beyond the length and
// the array isn't growable.
virtual int32_t Put(int32_t index, ByteVector* b);
- // Put the specified bytes into the array at the given index. All of the bytes
+ // Puts the specified bytes into the array at the given index. All of the bytes
// specified are put into the array unless that would extend beyond the length
// and the array isn't growable. The bytes to be put into the array are those
// in the buffer from the given offset and for the given length.
@@ -83,22 +89,22 @@
// @param length the number of bytes to copy into the array
// @return the number of bytes actually written
virtual int32_t Put(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
- // Fully copy this ByteArray to another ByteArray to the extent that the
+ // Fully copies this ByteArray to another ByteArray to the extent that the
// destination array has storage for the data copied.
virtual int32_t CopyTo(ByteArray* array);
- // Copy a segment of this ByteArray to another ByteArray.
+ // Copies a segment of this ByteArray to another ByteArray.
// @param array the destination
// @param offset the offset in this ByteArray to start copying from
// @param length the maximum length in bytes to copy
// @return the number of bytes copied
virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length);
- // Copy this ByteArray to another ByteArray.
+ // Copies this ByteArray to another ByteArray.
// @param dstOffset the offset in the destination array to start copying to
// @param array the destination
// @param srcOffset the offset in this ByteArray to start copying from
@@ -109,9 +115,25 @@
int32_t src_offset,
int32_t length);
+ // Copies this ByteArray to an OutputStream.
+ // @param os the destination
+ // @return the number of bytes copied
virtual int32_t CopyTo(OutputStream* os);
+
+ // Copies this ByteArray to an OutputStream.
+ // @param os the destination
+ // @param offset
+ // @param length
+ // @return the number of bytes copied
virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
+
+ // Copies from the InputStream into this ByteArray.
+ // @param is the source
+ // @param length the number of bytes to copy
virtual bool CopyFrom(InputStream* is, int32_t length);
+
+ // Copies everything from the InputStream into this ByteArray.
+ // @param is the source
virtual bool CopyFrom(InputStream* is);
protected:
@@ -122,24 +144,52 @@
ByteArray(int32_t filled_length, int32_t storage_length);
void Init(int32_t filled_length, int32_t storage_length, bool growable);
- virtual bool InternalPut(int32_t index, byte_t b) = 0;
+ // Internal subclass API
+
+ // Stores the byte at the index given.
+ // @param index the location to store at
+ // @param b the byte to store
+ virtual void InternalPut(int32_t index, byte_t b) = 0;
+
+ // Stores the array of bytes at the given index.
+ // @param index the location to store at
+ // @param b the bytes to store
+ // @param offset the offset to start from in the byte array
+ // @param length the length of the byte array to store from the offset
+ // @return the number of bytes actually stored
virtual int32_t InternalPut(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) = 0;
+
+ // Gets the byte at the index given.
+ // @param index the location to get from
+ // @return the byte stored at the index
virtual byte_t InternalGet(int32_t index) = 0;
+
+ // Gets the bytes at the index given of the given length.
+ // @param index the location to start getting from
+ // @param b the array to put the bytes into
+ // @param offset the offset in the array to put the bytes into
+ // @param length the length of bytes to read
+ // @return the number of bytes actually ready
virtual int32_t InternalGet(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) = 0;
+
+ // Close this instance of the ByteArray.
virtual void Close() = 0;
// C++ port only, raw pointer to the first element of storage.
virtual byte_t* Begin() = 0;
+ // Java toString() not ported.
+
static const int32_t COPY_BUFFER_SIZE;
private:
+ //bool bound_; // unused, comment out
int32_t filled_length_;
int32_t storage_length_;
bool growable_;
diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc
index 437a810..ccc2a19 100644
--- a/sfntly/data/font_data.cc
+++ b/sfntly/data/font_data.cc
@@ -58,7 +58,7 @@
FontData::FontData(FontData* data, int32_t offset) {
Init(data->array_);
- Bound(offset);
+ Bound(data->bound_offset_ + offset);
}
FontData::~FontData() {}
diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h
index ab5cf54..6ac4d5d 100644
--- a/sfntly/data/font_data.h
+++ b/sfntly/data/font_data.h
@@ -48,13 +48,14 @@
class FontData : virtual public RefCount {
public:
- // Get the maximum size of the FontData. This is the maximum number of bytes
+ // Gets the maximum size of the FontData. This is the maximum number of bytes
// that the font data can hold and all of it may not be filled with data or
// even fully allocated yet.
- // @return the size of this array
+ // @return the maximum size of this font data
virtual int32_t Size() const;
- // Sets limits on the size of the FontData. The font data is
+ // Sets limits on the size of the FontData. The FontData is then only
+ // visible within the bounds set.
// @param offset the start of the new bounds
// @param length the number of bytes in the bounded array
// @return true if the bounding range was successful; false otherwise
@@ -69,19 +70,19 @@
virtual bool Bound(int32_t offset);
// Makes a slice of this FontData. The returned slice will share the data with
- // the original FontData.
+ // the original <code>FontData</code>.
// @param offset the start of the slice
// @param length the number of bytes in the slice
// @return a slice of the original FontData
virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length) = 0;
// Makes a bottom bound only slice of this array. The returned slice will
- // share the data with the original FontData.
+ // share the data with the original <code>FontData</code>.
// @param offset the start of the slice
// @return a slice of the original FontData
virtual CALLER_ATTACH FontData* Slice(int32_t offset) = 0;
- // Get the length of the data.
+ // Gets the length of the data.
virtual int32_t Length() const;
protected:
@@ -102,7 +103,17 @@
virtual ~FontData();
void Init(ByteArray* ba);
+
+ // Gets the offset in the underlying data taking into account any bounds on
+ // the data.
+ // @param offset the offset to get the bound compensated offset for
+ // @return the bound compensated offset
int32_t BoundOffset(int32_t offset);
+
+ // 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);
// TODO(arthurhsu): style guide violation: refactor this protected member
diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc
index a1fbe44..dcf8be3 100644
--- a/sfntly/data/font_input_stream.cc
+++ b/sfntly/data/font_input_stream.cc
@@ -25,7 +25,7 @@
}
FontInputStream::FontInputStream(InputStream* is, size_t length)
- : stream_(is), position_(0), length_(length), bounded_(false) {
+ : stream_(is), position_(0), length_(length), bounded_(true) {
}
FontInputStream::~FontInputStream() {
diff --git a/sfntly/data/font_input_stream.h b/sfntly/data/font_input_stream.h
index 7404825..5d9959d 100644
--- a/sfntly/data/font_input_stream.h
+++ b/sfntly/data/font_input_stream.h
@@ -22,6 +22,25 @@
namespace sfntly {
+// An input stream for reading font data.
+// The data types used are as listed:
+// BYTE 8-bit unsigned integer.
+// CHAR 8-bit signed integer.
+// USHORT 16-bit unsigned integer.
+// SHORT 16-bit signed integer.
+// UINT24 24-bit unsigned integer.
+// ULONG 32-bit unsigned integer.
+// LONG 32-bit signed integer.
+// Fixed 32-bit signed fixed-point number (16.16)
+// FUNIT Smallest measurable distance in the em space.
+// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
+// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
+// FUnits.
+// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
+// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
+// January 1, 1904. The value is represented as a signed 64-bit
+// integer.
+
// Note: Original class inherits from Java's FilterOutputStream, which wraps
// an InputStream within. In C++, we directly do the wrapping without
// defining another layer of abstraction. The wrapped output stream is
@@ -29,10 +48,18 @@
// stream).
class FontInputStream : public InputStream {
public:
+ // Constructor.
+ // @param is input stream to wrap
explicit FontInputStream(InputStream* is);
+
+ // Constructor for a bounded font input stream.
+ // @param is input stream to wrap
+ // @param length the maximum length of bytes to read
FontInputStream(InputStream* is, size_t length);
+
virtual ~FontInputStream();
+
virtual int32_t Available();
virtual void Close();
virtual void Mark(int32_t readlimit);
@@ -43,6 +70,8 @@
virtual int32_t Read(ByteVector* buffer);
virtual int32_t Read(ByteVector* buffer, int32_t offset, int32_t length);
+ // Get the current position in the stream in bytes.
+ // @return the current position in bytes
virtual int64_t position() { return position_; }
virtual int32_t ReadChar();
diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc
index a88a29e..3422a22 100644
--- a/sfntly/data/font_output_stream.cc
+++ b/sfntly/data/font_output_stream.cc
@@ -43,11 +43,35 @@
}
}
-void FontOutputStream::Write(ByteVector* b, int32_t offset, int32_t length) {
- if (stream_ && b) {
- stream_->Write(b, offset, length);
- position_ += length;
+void FontOutputStream::Write(ByteVector* b, int32_t off, int32_t len) {
+ assert(b);
+ assert(stream_);
+ if (off < 0 || len < 0 || off + len < 0 ||
+ static_cast<size_t>(off + len) > b->size()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundException();
+#else
+ return;
+#endif
}
+
+ stream_->Write(b, off, len);
+ position_ += len;
+}
+
+void FontOutputStream::Write(byte_t* b, int32_t off, int32_t len) {
+ assert(b);
+ assert(stream_);
+ if (off < 0 || len < 0 || off + len < 0) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundException();
+#else
+ return;
+#endif
+ }
+
+ stream_->Write(b, off, len);
+ position_ += len;
}
void FontOutputStream::WriteChar(byte_t c) {
diff --git a/sfntly/data/font_output_stream.h b/sfntly/data/font_output_stream.h
index 6938b66..f420af4 100644
--- a/sfntly/data/font_output_stream.h
+++ b/sfntly/data/font_output_stream.h
@@ -22,11 +22,27 @@
namespace sfntly {
-// Note: Original class inherits from Java's FilterOutputStream, which wraps
-// an InputStream within. In C++, we directly do the wrapping without
-// defining another layer of abstraction. The wrapped output stream is
-// *NOT* reference counted (because it's meaningless to ref-count an I/O
-// stream).
+// An output stream for writing font data.
+// The data types used are as listed:
+// BYTE 8-bit unsigned integer.
+// CHAR 8-bit signed integer.
+// USHORT 16-bit unsigned integer.
+// SHORT 16-bit signed integer.
+// UINT24 24-bit unsigned integer.
+// ULONG 32-bit unsigned integer.
+// LONG 32-bit signed integer.
+// Fixed 32-bit signed fixed-point number (16.16)
+// FUNIT Smallest measurable distance in the em space.
+// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
+// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
+// FUnits.
+// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
+// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
+// January 1, 1904. The value is represented as a signed 64-bit
+// integer.
+
+// Note: The wrapped output stream is *NOT* reference counted (because it's
+// meaningless to ref-count an I/O stream).
class FontOutputStream : public OutputStream {
public:
explicit FontOutputStream(OutputStream* os);
@@ -36,7 +52,8 @@
virtual void Write(byte_t b);
virtual void Write(ByteVector* b);
- virtual void Write(ByteVector* b, int32_t offset, int32_t len);
+ virtual void Write(ByteVector* b, int32_t off, int32_t len);
+ virtual void Write(byte_t* b, int32_t off, int32_t len);
virtual void WriteChar(byte_t c);
virtual void WriteUShort(int32_t us);
virtual void WriteShort(int32_t s);
@@ -46,10 +63,13 @@
virtual void WriteFixed(int32_t l);
virtual void WriteDateTime(int64_t date);
+ // Note: C++ port only.
virtual void Flush();
virtual void Close();
private:
+ // Note: we do not use the variable name out as in Java because it has
+ // special meaning in VC++ and will be very confusing.
OutputStream* stream_;
size_t position_;
};
diff --git a/sfntly/data/growable_memory_byte_array.cc b/sfntly/data/growable_memory_byte_array.cc
index 9e1a043..c335614 100644
--- a/sfntly/data/growable_memory_byte_array.cc
+++ b/sfntly/data/growable_memory_byte_array.cc
@@ -17,6 +17,7 @@
#include "sfntly/data/growable_memory_byte_array.h"
#include <limits.h>
+#include <string.h>
#include <algorithm>
@@ -24,28 +25,37 @@
GrowableMemoryByteArray::GrowableMemoryByteArray()
: ByteArray(0, INT_MAX, true) {
+ // Note: We did not set an initial size of array like Java because STL
+ // implementation will determine the best strategy.
}
GrowableMemoryByteArray::~GrowableMemoryByteArray() {}
-bool GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) {
- if ((size_t)index >= b_.capacity()) {
- b_.resize((size_t)(index + 1) << 2); // Grow exponentially.
+int32_t GrowableMemoryByteArray::CopyTo(OutputStream* os,
+ int32_t offset,
+ int32_t length) {
+ assert(os);
+ os->Write(&b_, offset, length);
+ return length;
+}
+
+void GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) {
+ if ((size_t)index >= b_.size()) {
+ b_.resize((size_t)(index + 1));
}
b_[index] = b;
- return true;
}
int32_t GrowableMemoryByteArray::InternalPut(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
- if ((size_t)index + length >= b_.capacity()) {
- b_.resize((size_t)(index + length + 1) << 2);
+ if ((size_t)index + length >= b_.size()) {
+ // Note: We grow one byte more than Java version. VC debuggers shows
+ // data better this way.
+ b_.resize((size_t)(index + length + 1));
}
- std::copy(b->begin() + offset,
- b->begin() + (offset + length),
- b_.begin() + index);
+ std::copy(b + offset, b + offset + length, b_.begin() + index);
return length;
}
@@ -54,12 +64,10 @@
}
int32_t GrowableMemoryByteArray::InternalGet(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
- std::copy(b_.begin() + index,
- b_.begin() + (index + length),
- b->begin() + offset);
+ memcpy(b + offset, &(b_[0]) + index, length);
return length;
}
diff --git a/sfntly/data/growable_memory_byte_array.h b/sfntly/data/growable_memory_byte_array.h
index dc59f62..0e35de6 100644
--- a/sfntly/data/growable_memory_byte_array.h
+++ b/sfntly/data/growable_memory_byte_array.h
@@ -21,23 +21,37 @@
namespace sfntly {
-// Note: this is not really a port of Java version. Instead, this wraps a
-// std::vector inside and let it grow by calling resize()
+// Note: This is not really a port of Java version. Instead, this wraps a
+// std::vector inside and let it grow by calling resize().
class GrowableMemoryByteArray : public ByteArray,
public RefCounted<GrowableMemoryByteArray> {
public:
GrowableMemoryByteArray();
virtual ~GrowableMemoryByteArray();
+ virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
+
+ // Make gcc -Woverloaded-virtual happy.
+ virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); }
+ virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) {
+ return ByteArray::CopyTo(array, offset, length);
+ }
+ virtual int32_t CopyTo(int32_t dst_offset,
+ ByteArray* array,
+ int32_t src_offset,
+ int32_t length) {
+ return ByteArray::CopyTo(dst_offset, array, src_offset, length);
+ }
+ virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); }
protected:
- virtual bool InternalPut(int32_t index, byte_t b);
+ virtual void InternalPut(int32_t index, byte_t b);
virtual int32_t InternalPut(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
virtual byte_t InternalGet(int32_t index);
virtual int32_t InternalGet(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
virtual void Close();
diff --git a/sfntly/data/memory_byte_array.cc b/sfntly/data/memory_byte_array.cc
index 0138b21..d6c9c48 100644
--- a/sfntly/data/memory_byte_array.cc
+++ b/sfntly/data/memory_byte_array.cc
@@ -20,25 +20,27 @@
namespace sfntly {
-// Note: this constructor can fail under low-memory situation.
MemoryByteArray::MemoryByteArray(int32_t length)
: ByteArray(0, length), b_(NULL), allocated_(true) {
}
-MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length)
- : ByteArray(buffer_length, buffer_length), b_(b), allocated_(false) {
-}
-
-MemoryByteArray::MemoryByteArray(byte_t* b,
- int32_t buffer_length,
- int32_t filled_length)
- : ByteArray(filled_length, buffer_length), b_(b), allocated_(false) {
+MemoryByteArray::MemoryByteArray(byte_t* b, int32_t filled_length)
+ : ByteArray(filled_length, filled_length), b_(b), allocated_(false) {
+ assert(b);
}
MemoryByteArray::~MemoryByteArray() {
Close();
}
+int32_t MemoryByteArray::CopyTo(OutputStream* os,
+ int32_t offset,
+ int32_t length) {
+ assert(os);
+ os->Write(b_, offset, length);
+ return length;
+}
+
void MemoryByteArray::Init() {
if (allocated_ && b_ == NULL) {
b_ = new byte_t[Size()];
@@ -46,18 +48,18 @@
}
}
-bool MemoryByteArray::InternalPut(int32_t index, byte_t b) {
+void MemoryByteArray::InternalPut(int32_t index, byte_t b) {
Init();
b_[index] = b;
- return true;
}
int32_t MemoryByteArray::InternalPut(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
+ assert(b);
Init();
- memcpy(b_ + index, &((*b)[offset]), length);
+ memcpy(b_ + index, b + offset, length);
return length;
}
@@ -67,11 +69,12 @@
}
int32_t MemoryByteArray::InternalGet(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
+ assert(b);
Init();
- memcpy(&((*b)[offset]), b_ + index, length);
+ memcpy(b + offset, b_ + index, length);
return length;
}
diff --git a/sfntly/data/memory_byte_array.h b/sfntly/data/memory_byte_array.h
index 171dcc7..9de5230 100644
--- a/sfntly/data/memory_byte_array.h
+++ b/sfntly/data/memory_byte_array.h
@@ -23,20 +23,47 @@
class MemoryByteArray : public ByteArray, public RefCounted<MemoryByteArray> {
public:
+ // Construct a new MemoryByteArray with a new array of the size given. It is
+ // assumed that none of the array is filled and readable.
explicit MemoryByteArray(int32_t length);
- MemoryByteArray(byte_t* b, int32_t buffer_length);
- MemoryByteArray(byte_t* b, int32_t buffer_length, int32_t filled_length);
+
+ // Note: not implemented due to dangerous operations in constructor.
+ //explicit MemoryByteArray(ByteVector* b);
+
+ // Construct a new MemoryByteArray using byte array.
+ // @param b the byte array that provides the actual storage
+ // @param filled_length the index of the last byte in the array has data
+ // Note: This is different from Java version, it does not take over the
+ // ownership of b. Caller is responsible for handling the lifetime
+ // of b. C++ port also assumes filled_length is buffer_length since
+ // there is not a reliable way to identify the actual size of buffer.
+ MemoryByteArray(byte_t* b, int32_t filled_length);
+
virtual ~MemoryByteArray();
+ virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length);
+
+ // Make gcc -Woverloaded-virtual happy.
+ virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); }
+ virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) {
+ return ByteArray::CopyTo(array, offset, length);
+ }
+ virtual int32_t CopyTo(int32_t dst_offset,
+ ByteArray* array,
+ int32_t src_offset,
+ int32_t length) {
+ return ByteArray::CopyTo(dst_offset, array, src_offset, length);
+ }
+ virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); }
protected:
- virtual bool InternalPut(int32_t index, byte_t b);
+ virtual void InternalPut(int32_t index, byte_t b);
virtual int32_t InternalPut(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
virtual byte_t InternalGet(int32_t index);
virtual int32_t InternalGet(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length);
virtual void Close();
diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc
index 904e7db..8f43575 100644
--- a/sfntly/data/readable_font_data.cc
+++ b/sfntly/data/readable_font_data.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "sfntly/data/memory_byte_array.h"
#include "sfntly/data/readable_font_data.h"
#include "sfntly/data/writable_font_data.h"
#include "sfntly/port/exception_type.h"
@@ -28,6 +29,18 @@
ReadableFontData::~ReadableFontData() {}
+// TODO(arthurhsu): re-investigate the memory model of this function. It's
+// not too useful without copying, but it's not performance
+// savvy to do copying.
+CALLER_ATTACH
+ReadableFontData* ReadableFontData::CreateReadableFontData(ByteVector* b) {
+ assert(b);
+ ByteArrayPtr ba = new MemoryByteArray(b->size());
+ ba->Put(0, b);
+ ReadableFontDataPtr wfd = new ReadableFontData(ba);
+ return wfd.Detach();
+}
+
int64_t ReadableFontData::Checksum() {
// TODO(arthurhsu): IMPLEMENT: atomicity
if (!checksum_set_) {
@@ -42,15 +55,29 @@
}
int32_t ReadableFontData::ReadUByte(int32_t index) {
- return 0xff & array_->Get(BoundOffset(index));
+ int32_t b = array_->Get(BoundOffset(index));
+#if !defined (SFNTLY_NO_EXCEPTION)
+ if (b < 0) {
+ throw IndexOutOfBoundException(
+ "Index attempted to be read from is out of bounds", index);
+ }
+#endif
+ return b;
}
int32_t ReadableFontData::ReadByte(int32_t index) {
- return (array_->Get(BoundOffset(index)) << 24) >> 24;
+ int32_t b = array_->Get(BoundOffset(index));
+#if !defined (SFNTLY_NO_EXCEPTION)
+ if (b < 0) {
+ throw IndexOutOfBoundException(
+ "Index attempted to be read from is out of bounds", index);
+ }
+#endif
+ return (b << 24) >> 24;
}
int32_t ReadableFontData::ReadBytes(int32_t index,
- ByteVector* b,
+ byte_t* b,
int32_t offset,
int32_t length) {
return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length));
@@ -88,7 +115,7 @@
throw ArithmeticException("Long value too large to fit into an integer.");
}
#endif
- return ((int32_t)ulong) & ~0x80000000;
+ return static_cast<int32_t>(ulong);
}
int32_t ReadableFontData::ReadLong(int32_t index) {
@@ -164,17 +191,6 @@
checksum_(0) {
}
-/* OpenType checksum
-ULONG
-CalcTableChecksum(ULONG *Table, ULONG Length)
-{
-ULONG Sum = 0L;
-ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG);
-while (Table < EndPtr)
- Sum += *Table++;
-return Sum;
-}
-*/
void ReadableFontData::ComputeChecksum() {
// TODO(arthurhsu): IMPLEMENT: synchronization/atomicity
int64_t sum = 0;
diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h
index b1ca846..e7b3170 100644
--- a/sfntly/data/readable_font_data.h
+++ b/sfntly/data/readable_font_data.h
@@ -24,13 +24,36 @@
class WritableFontData;
class OutputStream;
+
+// Writable font data wrapper. Supports reading of data primitives in the
+// TrueType / OpenType spec.
+// The data types used are as listed:
+// BYTE 8-bit unsigned integer.
+// CHAR 8-bit signed integer.
+// USHORT 16-bit unsigned integer.
+// SHORT 16-bit signed integer.
+// UINT24 24-bit unsigned integer.
+// ULONG 32-bit unsigned integer.
+// LONG 32-bit signed integer.
+// Fixed 32-bit signed fixed-point number (16.16)
+// FUNIT Smallest measurable distance in the em space.
+// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits.
+// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in
+// FUnits.
+// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14)
+// LONGDATETIME Date represented in number of seconds since 12:00 midnight,
+// January 1, 1904. The value is represented as a signed 64-bit
+// integer.
+
class ReadableFontData : public FontData,
public RefCounted<ReadableFontData> {
public:
explicit ReadableFontData(ByteArray* array);
virtual ~ReadableFontData();
- // Get a computed checksum for the data. This checksum uses the OpenType spec
+ static CALLER_ATTACH ReadableFontData* CreateReadableFontData(ByteVector* b);
+
+ // Gets a computed checksum for the data. This checksum uses the OpenType spec
// calculation. Every ULong value (32 bit unsigned) in the data is summed and
// the resulting value is truncated to 32 bits. If the data length in bytes is
// not an integral multiple of 4 then any remaining bytes are treated as the
@@ -45,32 +68,120 @@
// @param ranges the range bounds to use for the checksum
void SetCheckSumRanges(const IntegerList& ranges);
+ // Read the UBYTE at the given index.
+ // @param index index into the font data
+ // @return the UBYTE; -1 if outside the bounds of the font data
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadUByte(int32_t index);
+
+ // Read the BYTE at the given index.
+ // @param index index into the font data
+ // @return the BYTE
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadByte(int32_t index);
- virtual int32_t ReadBytes(int32_t index, ByteVector* b, int32_t offset,
+
+ // Read the bytes at the given index into the array.
+ // @param index index into the font data
+ // @param b the destination for the bytes read
+ // @param offset offset in the byte array to place the bytes
+ // @param length the length of bytes to read
+ // @return the number of bytes actually read; -1 if the index is outside the
+ // bounds of the font data
+ virtual int32_t ReadBytes(int32_t index,
+ byte_t* b,
+ int32_t offset,
int32_t length);
+
+ // Read the CHAR at the given index.
+ // @param index index into the font data
+ // @return the CHAR
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadChar(int32_t index);
+
+ // Read the USHORT at the given index.
+ // @param index index into the font data
+ // @return the USHORT
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadUShort(int32_t index);
+
+ // Read the SHORT at the given index.
+ // @param index index into the font data
+ // @return the SHORT
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadShort(int32_t index);
+
+ // Read the UINT24 at the given index.
+ // @param index index into the font data
+ // @return the UINT24
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadUInt24(int32_t index);
+
+ // Read the ULONG at the given index.
+ // @param index index into the font data
+ // @return the ULONG
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int64_t ReadULong(int32_t index);
+
+ // Read the ULONG at the given index as int32_t.
+ // @param index index into the font data
+ // @return the ULONG
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadULongAsInt(int32_t index);
+
+ // Read the LONG at the given index.
+ // @param index index into the font data
+ // @return the LONG
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadLong(int32_t index);
+
+ // Read the Fixed at the given index.
+ // @param index index into the font data
+ // @return the Fixed
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadFixed(int32_t index);
+
+ // Read the LONGDATETIME at the given index.
+ // @param index index into the font data
+ // @return the LONGDATETIME
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int64_t ReadDateTimeAsLong(int32_t index);
+ // Read the FWORD at the given index.
+ // @param index index into the font data
+ // @return the FWORD
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadFWord(int32_t index);
+
+ // Read the UFWORD at the given index.
+ // @param index index into the font data
+ // @return the UFWORD
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t ReadFUFWord(int32_t index);
- virtual int32_t CopyTo(OutputStream* os);
- virtual int32_t CopyTo(WritableFontData* wfd);
- virtual int32_t CopyTo(ByteArray* ba);
-
- // TODO(arthurhsu): IMPLEMENT
+ // Note: Not ported because they just throw UnsupportedOperationException()
+ // in Java.
/*
virtual int32_t ReadFUnit(int32_t index);
virtual int64_t ReadF2Dot14(int32_t index);
- virtual int64_t ReadLongDateTime(int32_t index);
+ */
+
+ // Copy the FontData to an OutputStream.
+ // @param os the destination
+ // @return number of bytes copied
+ // @throws IOException
+ virtual int32_t CopyTo(OutputStream* os);
+
+ // Copy the FontData to a WritableFontData.
+ // @param wfd the destination
+ // @return number of bytes copied
+ // @throws IOException
+ virtual int32_t CopyTo(WritableFontData* wfd);
+
+ // Make gcc -Woverloaded-virtual happy.
+ virtual int32_t CopyTo(ByteArray* ba);
+
+ // TODO(dfilimon): Implementation of following in review, need to merge.
+ /*
virtual int32_t SearchUShort(int32_t start, int32_t length, int32_t key);
virtual int32_t SearchUShort(int32_t start_index, int32_t start_offset,
int32_t count_index, int32_t count_offset,
@@ -85,14 +196,18 @@
// @param offset the start of the slice
// @param length the number of bytes in the slice
// @return a slice of the original FontData
+ // Note: C++ polymorphism requires return type to be consistent
virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length);
// Makes a bottom bound only slice of this array. The returned slice will
// share the data with the original FontData.
// @param offset the start of the slice
// @return a slice of the original FontData
+ // Note: C++ polymorphism requires return type to be consistent
virtual CALLER_ATTACH FontData* Slice(int32_t offset);
+ // Not Ported: toString()
+
protected:
// Constructor. Creates a bounded wrapper of another ReadableFontData from the
// given offset until the end of the original ReadableFontData.
@@ -104,10 +219,24 @@
// given offset until the end of the original ReadableFontData.
// @param data data to wrap
// @param offset the start of this data's view of the original data
+ // @param length the length of the other FontData to use
ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length);
private:
+ // Compute the checksum for the font data using any ranges set for the
+ // calculation.
void ComputeChecksum();
+
+ // Do the actual computation of the checksum for a range using the
+ // TrueType/OpenType checksum algorithm. The range used is from the low bound
+ // to the high bound in steps of four bytes. If any of the bytes within that 4
+ // byte segment are not readable then it will considered a zero for
+ // calculation.
+ // Only called from within a synchronized method so it does not need to be
+ // synchronized itself.
+ // @param lowBound first position to start a 4 byte segment on
+ // @param highBound last possible position to start a 4 byte segment on
+ // @return the checksum for the total range
int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound);
bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically.
diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc
index 5f694be..c690956 100644
--- a/sfntly/data/writable_font_data.cc
+++ b/sfntly/data/writable_font_data.cc
@@ -40,7 +40,9 @@
return wfd.Detach();
}
-// static
+// TODO(arthurhsu): re-investigate the memory model of this function. It's
+// not too useful without copying, but it's not performance
+// savvy to do copying.
CALLER_ATTACH
WritableFontData* WritableFontData::CreateWritableFontData(ByteVector* b) {
ByteArrayPtr ba = new GrowableMemoryByteArray();
@@ -54,18 +56,19 @@
return 1;
}
-int32_t WritableFontData::WriteBytes(int32_t offset,
- ByteVector* b,
- int32_t index,
+int32_t WritableFontData::WriteBytes(int32_t index,
+ byte_t* b,
+ int32_t offset,
int32_t length) {
- return array_->Put(BoundOffset(offset),
+ return array_->Put(BoundOffset(index),
b,
- index,
- BoundLength(offset, length));
+ offset,
+ BoundLength(index, length));
}
int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) {
- return WriteBytes(index, b, 0, b->size());
+ assert(b);
+ return WriteBytes(index, &((*b)[0]), 0, b->size());
}
int32_t WritableFontData::WriteChar(int32_t index, byte_t c) {
@@ -115,8 +118,8 @@
return WriteULong(index, l);
}
-int32_t WritableFontData::WriteFixed(int32_t index, int32_t l) {
- return WriteLong(index, l);
+int32_t WritableFontData::WriteFixed(int32_t index, int32_t f) {
+ return WriteLong(index, f);
}
int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) {
diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h
index ceefb30..f674ae1 100644
--- a/sfntly/data/writable_font_data.h
+++ b/sfntly/data/writable_font_data.h
@@ -21,6 +21,8 @@
namespace sfntly {
+// Writable font data wrapper. Supports writing of data primitives in the
+// TrueType / OpenType spec.
class WritableFontData : public ReadableFontData {
public:
explicit WritableFontData(ByteArray* ba);
@@ -30,7 +32,6 @@
// positive then a fixed size font data object will be created. If the length
// is zero or less then a growable font data object will be created and the
// size will be used as an estimate to help in allocating the original space.
- //
// @param length if length > 0 create a fixed length font data; otherwise
// create a growable font data
// @return a new writable font data
@@ -39,29 +40,114 @@
// Constructs a writable font data object. The new font data object will wrap
// the bytes passed in to the factory and it will take make a copy of those
// bytes.
- //
// @param b the byte vector to wrap
// @return a new writable font data
static CALLER_ATTACH WritableFontData* CreateWritableFontData(ByteVector* b);
+ // Write a byte at the given index.
+ // @param index index into the font data
+ // @param b the byte to write
+ // @return the number of bytes written
virtual int32_t WriteByte(int32_t index, byte_t b);
- virtual int32_t WriteBytes(int32_t offset,
- ByteVector* b,
- int32_t index,
+
+ // Write the bytes from the array.
+ // @param index index into the font data
+ // @param b the source for the bytes to be written
+ // @param offset offset in the byte array
+ // @param length the length of the bytes to be written
+ // @return the number of bytes actually written; -1 if the index is outside
+ // the FontData's range
+ virtual int32_t WriteBytes(int32_t index,
+ byte_t* b,
+ int32_t offset,
int32_t length);
+
+ // Write the bytes from the array.
+ // @param index index into the font data
+ // @param b the source for the bytes to be written
+ // @return the number of bytes actually written; -1 if the index is outside
+ // the FontData's range
virtual int32_t WriteBytes(int32_t index, ByteVector* b);
+
+ // Write the CHAR at the given index.
+ // @param index index into the font data
+ // @param c the CHAR
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteChar(int32_t index, byte_t c);
+
+ // Write the USHORT at the given index.
+ // @param index index into the font data
+ // @param us the USHORT
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteUShort(int32_t index, int32_t us);
+
+ // Write the USHORT at the given index in little endian format.
+ // @param index index into the font data
+ // @param us the USHORT
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteUShortLE(int32_t index, int32_t us);
+
+ // Write the SHORT at the given index.
+ // @param index index into the font data
+ // @param s the SHORT
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteShort(int32_t index, int32_t s);
+
+ // Write the UINT24 at the given index.
+ // @param index index into the font data
+ // @param ui the UINT24
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteUInt24(int32_t index, int32_t ui);
+
+ // Write the ULONG at the given index.
+ // @param index index into the font data
+ // @param ul the ULONG
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteULong(int32_t index, int64_t ul);
+
+ // Write the ULONG at the given index in little endian format.
+ // @param index index into the font data
+ // @param ul the ULONG
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteULongLE(int32_t index, int64_t ul);
+
+ // Write the LONG at the given index.
+ // @param index index into the font data
+ // @param l the LONG
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteLong(int32_t index, int64_t l);
- virtual int32_t WriteFixed(int32_t index, int32_t l);
+
+ // Write the Fixed at the given index.
+ // @param index index into the font data
+ // @param f the Fixed
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
+ virtual int32_t WriteFixed(int32_t index, int32_t f);
+
+ // Write the LONGDATETIME at the given index.
+ // @param index index into the font data
+ // @param date the LONGDATETIME
+ // @return the number of bytes actually written
+ // @throws IndexOutOfBoundsException if index is outside the FontData's range
virtual int32_t WriteDateTime(int32_t index, int64_t date);
+ // Copy from the InputStream into this FontData.
+ // @param is the source
+ // @param length the number of bytes to copy
+ // @throws IOException
virtual void CopyFrom(InputStream* is, int32_t length);
+
+ // Copy everything from the InputStream into this FontData.
+ // @param is the source
+ // @throws IOException
virtual void CopyFrom(InputStream* is);
// Makes a slice of this FontData. The returned slice will share the data with
@@ -78,7 +164,15 @@
virtual CALLER_ATTACH FontData* Slice(int32_t offset);
private:
+ // Constructor with a lower bound.
+ // @param data other WritableFontData object to share data with
+ // @param offset offset from the other WritableFontData's data
WritableFontData(WritableFontData* data, int32_t offset);
+
+ // Constructor with lower bound and a length bound.
+ // @param data other WritableFontData object to share data with
+ // @param offset offset from the other WritableFontData's data
+ // @param length length of other WritableFontData's data to use
WritableFontData(WritableFontData* data, int32_t offset, int32_t length);
};
typedef Ptr<WritableFontData> WritableFontDataPtr;
diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc
index 99e7c06..79c10dd 100644
--- a/sfntly/glyph_table.cc
+++ b/sfntly/glyph_table.cc
@@ -593,7 +593,7 @@
}
int32_t tsize = TransformationSize(contour);
transformation->resize(tsize);
- data_->ReadBytes(index, transformation, 0, tsize);
+ data_->ReadBytes(index, &((*transformation)[0]), 0, tsize);
}
int32_t GlyphTable::CompositeGlyph::InstructionSize() {
diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc
index d65f251..649baed 100644
--- a/sfntly/name_table.cc
+++ b/sfntly/name_table.cc
@@ -477,7 +477,7 @@
int32_t length = NameLength(index);
b->clear();
b->resize(length);
- data_->ReadBytes(NameOffset(index), b, 0, length);
+ data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length);
}
void NameTable::NameAsBytes(int32_t platform_id,
diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc
index 5b6181d..24ef4e9 100644
--- a/sfntly/os2_table.cc
+++ b/sfntly/os2_table.cc
@@ -167,7 +167,7 @@
void OS2Table::Panose(ByteVector* value) {
value->clear();
value->resize(10);
- data_->ReadBytes(Offset::kPanose, value, 0, 10);
+ data_->ReadBytes(Offset::kPanose, &((*value)[0]), 0, 10);
}
int64_t OS2Table::UlUnicodeRange1() {
@@ -189,7 +189,7 @@
void OS2Table::AchVendId(ByteVector* b) {
b->clear();
b->resize(4);
- data_->ReadBytes(Offset::kAchVendId, b, 0, 4);
+ data_->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4);
}
int32_t OS2Table::FsSelection() {
diff --git a/sfntly/port/exception_type.h b/sfntly/port/exception_type.h
index 2ba199a..ddeb95b 100644
--- a/sfntly/port/exception_type.h
+++ b/sfntly/port/exception_type.h
@@ -23,18 +23,23 @@
#include <exception>
#include <string>
+#include <sstream>
namespace sfntly {
class Exception : public std::exception {
public:
- explicit Exception(const char* message) throw() {
+ Exception() : what_("Unknown exception") {}
+ explicit Exception(const char* message) throw() { SetMessage(message); }
+ virtual ~Exception() throw() {}
+ virtual const char* what() const throw() { return what_.c_str(); }
+
+ protected:
+ void SetMessage(const char* message) throw() {
try {
what_ = message;
} catch (...) {}
}
- virtual ~Exception() throw() {}
- virtual const char* what() const throw() { return what_.c_str(); }
private:
std::string what_;
@@ -45,6 +50,15 @@
IndexOutOfBoundException() throw() : Exception("Index out of bound") {}
explicit IndexOutOfBoundException(const char* message) throw()
: Exception(message) {}
+ IndexOutOfBoundException(const char* message, int32_t index) throw() {
+ try {
+ std::ostringstream msg;
+ msg << message;
+ msg << ":";
+ msg << index;
+ SetMessage(msg.str().c_str());
+ } catch (...) {}
+ }
virtual ~IndexOutOfBoundException() throw() {}
};
diff --git a/sfntly/port/memory_output_stream.cc b/sfntly/port/memory_output_stream.cc
index 5ddeec2..f2ff2e3 100644
--- a/sfntly/port/memory_output_stream.cc
+++ b/sfntly/port/memory_output_stream.cc
@@ -31,9 +31,27 @@
void MemoryOutputStream::Write(ByteVector* buffer,
int32_t offset,
int32_t length) {
- store_.insert(store_.end(),
- buffer->begin() + offset,
- buffer->begin() + offset + length);
+ assert(buffer);
+ if (offset >= 0 && length > 0) {
+ store_.insert(store_.end(),
+ buffer->begin() + offset,
+ buffer->begin() + offset + length);
+ } else {
+#if !defined(SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundException();
+#endif
+ }
+}
+
+void MemoryOutputStream::Write(byte_t* buffer, int32_t offset, int32_t length) {
+ assert(buffer);
+ if (offset >= 0 && length > 0) {
+ store_.insert(store_.end(), buffer + offset, buffer + offset + length);
+ } else {
+#if !defined(SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundException();
+#endif
+ }
}
void MemoryOutputStream::Write(byte_t b) {
@@ -41,6 +59,9 @@
}
byte_t* MemoryOutputStream::Get() {
+ if (store_.empty()) {
+ return NULL;
+ }
return &(store_[0]);
}
diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h
index a0befea..8983ab0 100644
--- a/sfntly/port/memory_output_stream.h
+++ b/sfntly/port/memory_output_stream.h
@@ -36,6 +36,7 @@
virtual void Flush() {} // no-op
virtual void Write(ByteVector* buffer);
virtual void Write(ByteVector* buffer, int32_t offset, int32_t length);
+ virtual void Write(byte_t* buffer, int32_t offset, int32_t length);
virtual void Write(byte_t b);
byte_t* Get();
diff --git a/sfntly/port/output_stream.h b/sfntly/port/output_stream.h
index c5d71cf..d813333 100644
--- a/sfntly/port/output_stream.h
+++ b/sfntly/port/output_stream.h
@@ -30,8 +30,15 @@
virtual void Close() = 0;
virtual void Flush() = 0;
virtual void Write(ByteVector* buffer) = 0;
- virtual void Write(ByteVector* buffer, int32_t offset, int32_t length) = 0;
virtual void Write(byte_t b) = 0;
+
+ // Note: C++ port offered both versions of Write() here. The first one is
+ // better because it does check bounds. The second one is there for
+ // performance concerns.
+ virtual void Write(ByteVector* buffer, int32_t offset, int32_t length) = 0;
+
+ // Note: Caller is responsible for the boundary of buffer.
+ virtual void Write(byte_t* buffer, int32_t offset, int32_t length) = 0;
};
} // namespace sfntly
diff --git a/sfntly/tag.h b/sfntly/tag.h
index d802351..9a548f6 100644
--- a/sfntly/tag.h
+++ b/sfntly/tag.h
@@ -83,11 +83,8 @@
};
// Create integer tag value for human readable tag name.
-inline int32_t GenerateTag(char a, char b, char c, char d) {
- return (((int32_t)(a) << 24) |
- ((int32_t)(b) << 16) |
- ((int32_t)(c) << 8) |
- (int32_t)(d));
+inline int32_t GenerateTag(int32_t a, int32_t b, int32_t c, int32_t d) {
+ return (a << 24) | (b << 16) | (c << 8) | d;
}
// Translate tag to human readable string.
diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc
index 74b5290..40a6489 100644
--- a/test/byte_array_test.cc
+++ b/test/byte_array_test.cc
@@ -51,7 +51,7 @@
while (index < ba->Length()) {
actual_window_size =
std::min<int32_t>(actual_window_size, b->size() - index);
- int32_t bytes_read = ba->Get(index, b, index, actual_window_size);
+ int32_t bytes_read = ba->Get(index, &((*b)[0]), index, actual_window_size);
index += bytes_read;
}
}
diff --git a/test/font_data_test.cc b/test/font_data_test.cc
index 5a80fb3..4de6fff 100644
--- a/test/font_data_test.cc
+++ b/test/font_data_test.cc
@@ -48,7 +48,7 @@
int32_t index = 0;
while (index < rfd->Length()) {
- int32_t bytes_read = rfd->ReadBytes(index, &buffer, 0, buffer.size());
+ int32_t bytes_read = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size());
EXPECT_GE(bytes_read, 0);
std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index);
index += bytes_read;
@@ -62,7 +62,8 @@
while (index < rfd->Length()) {
int32_t actual_window_size =
std::min<int32_t>(window_size, b->size() - index);
- int32_t bytes_read = rfd->ReadBytes(index, b, index, actual_window_size);
+ int32_t bytes_read =
+ rfd->ReadBytes(index, &((*b)[0]), index, actual_window_size);
EXPECT_GE(bytes_read, 0);
index += bytes_read;
}
@@ -81,8 +82,8 @@
ByteVector buffer(buffer_size);
int32_t index = 0;
while (index < rfd->Length()) {
- int32_t bytesRead = rfd->ReadBytes(index, &buffer, 0, buffer.size());
- wfd->WriteBytes(index, &buffer, 0, buffer.size());
+ int32_t bytesRead = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size());
+ wfd->WriteBytes(index, &(buffer[0]), 0, buffer.size());
index += bytesRead;
}
}
@@ -94,8 +95,8 @@
int32_t index = 0;
while (index < rfd->Length()) {
int32_t sliding_size = std::min<int32_t>(window_size, b.size() - index);
- int32_t bytes_read = rfd->ReadBytes(index, &b, index, sliding_size);
- wfd->WriteBytes(index, &b, index, sliding_size);
+ int32_t bytes_read = rfd->ReadBytes(index, &(b[0]), index, sliding_size);
+ wfd->WriteBytes(index, &(b[0]), index, sliding_size);
index += bytes_read;
}
}
diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc
index ee794d1..3dcbda2 100644
--- a/test/font_parsing_test.cc
+++ b/test/font_parsing_test.cc
@@ -65,7 +65,7 @@
wfd.Attach(gdef_builder->Data());
ByteVector b;
b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]);
- wfd->ReadBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]);
+ wfd->ReadBytes(0, &(b[0]), 0, TTF_LENGTH[SAMPLE_TTF_GDEF]);
EXPECT_EQ(memcmp(&(b[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0);
// Header table
@@ -91,8 +91,8 @@
wfd1.Attach(builder1->Data());
WritableFontDataPtr wfd2;
wfd2.Attach(builder2->Data());
- wfd1->ReadBytes(0, &b1, 0, TTF_LENGTH[i]);
- wfd2->ReadBytes(0, &b2, 0, TTF_LENGTH[i]);
+ wfd1->ReadBytes(0, &(b1[0]), 0, TTF_LENGTH[i]);
+ wfd2->ReadBytes(0, &(b2[0]), 0, TTF_LENGTH[i]);
EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), TTF_LENGTH[i]), 0);
}