[woff2] Copy un-transformed tables to sfnt stream. Copy un-transformed tables to the sfnt stream. * src/sfnt/sfwoff2.c: (WRITE_SFNT_BUF): New macro. (write_buf): New function. Extend memory of `dst' buffer and copy bytes from `src'. (compute_ULong_sum): New function. Calculate checksum of table. (reconstruct_font): Change `FT_Byte* sfnt' to `FT_Byte** sfnt_bytes'. This has been done because we reallocate memory to `sfnt' multiple times, which may change the pointer value of `sfnt'. This new pointer must be propogated back to the caller. Same reason for using a double pointer in `write_buf'. * src/sfnt/woff2tags.h (WOFF2_DEFAULT_MAX_SIZE): New macro used for overflow checking.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
diff --git a/ChangeLog b/ChangeLog
index 2baee36..01bde59 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+ [woff2] Copy un-transformed tables to sfnt stream.
+
+ Copy un-transformed tables to the sfnt stream.
+
+ * src/sfnt/sfwoff2.c: (WRITE_SFNT_BUF): New macro.
+ (write_buf): New function. Extend memory of `dst' buffer and copy
+ bytes from `src'.
+ (compute_ULong_sum): New function. Calculate checksum of table.
+ (reconstruct_font): Change `FT_Byte* sfnt' to `FT_Byte**
+ sfnt_bytes'. This has been done because we reallocate memory to
+ `sfnt' multiple times, which may change the pointer value of `sfnt'.
+ This new pointer must be propogated back to the caller. Same reason
+ for using a double pointer in `write_buf'.
+
+ * src/sfnt/woff2tags.h (WOFF2_DEFAULT_MAX_SIZE): New macro used for
+ overflow checking.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
[woff2] Create stream for uncompressed buffer.
Uncompressed buffer is now an `FT_Stream'.
diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c
index a44cd6f..cc6a4d1 100644
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -64,6 +64,8 @@
\
} while ( 0 )
+#define WRITE_SFNT_BUF( buf, s ) \
+ write_buf( &sfnt, &dest_offset, buf, s, memory )
static void
stream_close( FT_Stream stream )
@@ -182,6 +184,41 @@
}
+ static FT_Error
+ write_buf( FT_Byte** dst_bytes,
+ FT_ULong* offset,
+ FT_Byte* src,
+ FT_ULong size,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ /* We are reallocating memory for `dst', so its pointer may change. */
+ FT_Byte* dst = *dst_bytes;
+
+ /* Check if we are within limits. */
+ if( ( *offset + size ) > WOFF2_DEFAULT_MAX_SIZE )
+ return FT_THROW( Array_Too_Large );
+
+ /* DEBUG - Remove later */
+ FT_TRACE2(( "Reallocating %lu to %lu.\n", *offset, (*offset + size) ));
+ /* Reallocate `dst'. */
+ if ( FT_REALLOC( dst,
+ (FT_ULong)(*offset),
+ (FT_ULong)(*offset + size ) ) )
+ goto Exit;
+
+ /* Copy data. */
+ ft_memcpy( dst + *offset, src, size );
+
+ *offset += size;
+ /* Set pointer of `dst' to its correct value. */
+ *dst_bytes = dst;
+
+ Exit:
+ return error;
+ }
+
+
static FT_Offset
CollectionHeaderSize( FT_ULong header_version,
FT_UShort num_fonts )
@@ -216,6 +253,32 @@
return offset;
}
+ static FT_Long
+ compute_ULong_sum( FT_Byte* buf,
+ FT_ULong size )
+ {
+ FT_ULong checksum = 0;
+ FT_ULong aligned_size = size & ~3;
+ FT_ULong i;
+ FT_ULong v;
+
+ for( i = 0; i < aligned_size; i += 4 )
+ {
+ checksum += ( buf[i] << 24 ) | ( buf[i+1] << 16 ) |
+ ( buf[i+2] << 8 ) | ( buf[i+3] << 0 );
+ }
+
+ /* If size is not aligned to 4, treat as if it is padded with 0s */
+ if( size != aligned_size )
+ {
+ v = 0;
+ for( i = aligned_size ; i < size; ++i )
+ v |= buf[i] << ( 24 - 8 * ( i & 3 ) );
+ checksum += v;
+ }
+ return checksum;
+ }
+
static FT_Error
woff2_uncompress( FT_Byte* dst,
@@ -293,15 +356,17 @@
FT_ULong transformed_buf_size,
WOFF2_Table* indices,
WOFF2_Header woff2,
- FT_Byte* sfnt,
+ FT_Byte** sfnt_bytes,
FT_Memory memory )
{
FT_Error error = FT_Err_Ok;
FT_Stream stream = NULL;
+ FT_Byte* buf_cursor = NULL;
+ /* We are reallocating memory for `sfnt', so its pointer may change. */
+ FT_Byte* sfnt = *sfnt_bytes;
- /* We're writing only one face per call, so initial offset is fixed. */
- FT_ULong dst_offset = 12;
FT_UShort num_tables = woff2->num_tables;
+ FT_ULong dest_offset = 12 + num_tables * 16UL;
FT_ULong checksum = 0;
FT_ULong loca_checksum = 0;
@@ -333,7 +398,6 @@
}
}
- FT_UNUSED( dst_offset );
FT_UNUSED( loca_checksum );
FT_UNUSED( checksum );
@@ -351,12 +415,14 @@
WOFF2_TableRec table = *( indices[nn] );
/* DEBUG - Remove later */
- FT_TRACE2(( "Seeking to %d with table size %d.\n", table.src_offset, table.src_length ));
+ FT_TRACE2(( "Seeking to %d with table size %d.\n",
+ table.src_offset, table.src_length ));
FT_TRACE2(( "Table tag: %c%c%c%c.\n",
(FT_Char)( table.Tag >> 24 ),
(FT_Char)( table.Tag >> 16 ),
(FT_Char)( table.Tag >> 8 ),
(FT_Char)( table.Tag ) ));
+
if ( FT_STREAM_SEEK( table.src_offset ) )
return FT_THROW( Invalid_Table );
@@ -370,6 +436,7 @@
return FT_THROW( Invalid_Table );
}
+ checksum = 0;
if( ( table.flags & WOFF2_FLAGS_TRANSFORM ) != WOFF2_FLAGS_TRANSFORM )
{
/* Check if `head' is atleast 12 bytes. */
@@ -377,12 +444,30 @@
{
if( table.src_length < 12 )
return FT_THROW( Invalid_Table );
+ buf_cursor = transformed_buf + table.src_offset + 8;
+ WRITE_ULONG( buf_cursor, 0 );
}
+ table.dst_offset = dest_offset;
+ checksum = compute_ULong_sum( transformed_buf + table.src_offset,
+ table.src_length );
+ /* DEBUG - Remove later */
+ FT_TRACE2(( "Checksum = %u\n", checksum ));
+
+ if( WRITE_SFNT_BUF( transformed_buf + table.src_offset,
+ table.src_length ) )
+ return FT_THROW( Invalid_Table );
+ }
+ else{
+ /* DEBUG - Remove later */
+ FT_TRACE2(( "This table has xform.\n" ));
+
+ /* TODO reconstruct transformed font tables! */
}
}
- /* TODO reconstruct the font tables! */
+ /* Set pointer of sfnt stream to its correct value. */
+ *sfnt_bytes = sfnt;
return FT_Err_Ok;
}
@@ -793,7 +878,7 @@
/* TODO Write table entries. */
reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
- indices, &woff2, sfnt, memory );
+ indices, &woff2, &sfnt, memory );
error = FT_THROW( Unimplemented_Feature );
/* DEBUG - Remove later */
@@ -821,6 +906,7 @@
#undef ROUND4
#undef WRITE_USHORT
#undef WRITE_ULONG
+#undef WRITE_SFNT_BUF
/* END */
diff --git a/src/sfnt/woff2tags.h b/src/sfnt/woff2tags.h
index 6579b85..422567d 100644
--- a/src/sfnt/woff2tags.h
+++ b/src/sfnt/woff2tags.h
@@ -33,6 +33,9 @@ FT_BEGIN_HEADER
#define WOFF2_SFNT_HEADER_SIZE 12
#define WOFF2_SFNT_ENTRY_SIZE 16
+ /* Suggested max size for output. */
+#define WOFF2_DEFAULT_MAX_SIZE 30 * 1024 * 1024
+
FT_LOCAL( FT_ULong )
woff2_known_tags( FT_Byte index );