diff --git a/swf/src/read.rs b/swf/src/read.rs index adb3aaae4..c1858d8d1 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -1143,6 +1143,9 @@ impl Reader { .by_ref() .take(name_len.into()) .read_to_string(&mut name)?; + // TODO: SWF19 states that the font name should not have a terminating null byte, + // but it often does (depends on Flash IDE version?) + // We should probably strip anything past the first null. let num_glyphs = self.read_u16()? as usize; let mut glyphs = Vec::with_capacity(num_glyphs); @@ -1156,42 +1159,56 @@ impl Reader { }, ); - // OffsetTable - // We are throwing these away. - for _ in &mut glyphs { + // SWF19 p. 164 doesn't make it super clear: If there are no glyphs, + // then the following tables are omitted. But the table offset values + // may or may not be written... (depending on Flash IDE version that was used?) + if num_glyphs == 0 { + // Try to read the CodeTableOffset. It may or may not be present, + // so just dump any error. + if has_wide_offsets { + let _ = self.read_u32(); + } else { + let _ = self.read_u16(); + } + } else { + // OffsetTable + // We are throwing these away. + for _ in &mut glyphs { + if has_wide_offsets { + self.read_u32()?; + } else { + u32::from(self.read_u16()?); + }; + } + + // CodeTableOffset if has_wide_offsets { self.read_u32()?; } else { u32::from(self.read_u16()?); - }; - } - - // CodeTableOffset - if has_wide_offsets { - self.read_u32()?; - } else { - u32::from(self.read_u16()?); - } - - // ShapeTable - for glyph in &mut glyphs { - self.num_fill_bits = self.read_ubits(4)? as u8; - self.num_line_bits = self.read_ubits(4)? as u8; - while let Some(record) = self.read_shape_record(1)? { - glyph.shape_records.push(record); } - self.byte_align(); - } - - // CodeTable - for glyph in &mut glyphs { - glyph.code = if has_wide_codes { - self.read_u16()? - } else { - u16::from(self.read_u8()?) - }; + + // ShapeTable + for glyph in &mut glyphs { + self.num_fill_bits = self.read_ubits(4)? as u8; + self.num_line_bits = self.read_ubits(4)? as u8; + while let Some(record) = self.read_shape_record(1)? { + glyph.shape_records.push(record); + } + self.byte_align(); + } + + // CodeTable + for glyph in &mut glyphs { + glyph.code = if has_wide_codes { + self.read_u16()? + } else { + u16::from(self.read_u8()?) + }; + } } + // TODO: Is it possible to have a layout when there are no glyphs? let layout = if has_layout { let ascent = self.read_u16()?; let descent = self.read_u16()?; diff --git a/swf/src/write.rs b/swf/src/write.rs index b393be096..540f2a813 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -2391,32 +2391,35 @@ impl Writer { writer.output.write_all(font.name.as_bytes())?; writer.write_u16(num_glyphs as u16)?; - // OffsetTable - for offset in offsets { - if has_wide_offsets { - writer.write_u32(offset as u32)?; - } else { - writer.write_u16(offset as u16)?; + // If there are no glyphs, then the following tables are omitted. + if num_glyphs > 0 { + // OffsetTable + for offset in offsets { + if has_wide_offsets { + writer.write_u32(offset as u32)?; + } else { + writer.write_u16(offset as u16)?; + } } - } - // CodeTableOffset - let code_table_offset = - (num_glyphs + 1) * if has_wide_offsets { 4 } else { 2 } + shape_buf.len(); - if has_wide_offsets { - writer.write_u32(code_table_offset as u32)?; - } else { - writer.write_u16(code_table_offset as u16)?; - } - - writer.output.write_all(&shape_buf)?; - - // CodeTable - for glyph in &font.glyphs { - if has_wide_codes { - writer.write_u16(glyph.code)?; + // CodeTableOffset + let code_table_offset = + (num_glyphs + 1) * if has_wide_offsets { 4 } else { 2 } + shape_buf.len(); + if has_wide_offsets { + writer.write_u32(code_table_offset as u32)?; } else { - writer.write_u8(glyph.code as u8)?; + writer.write_u16(code_table_offset as u16)?; + } + + writer.output.write_all(&shape_buf)?; + + // CodeTable + for glyph in &font.glyphs { + if has_wide_codes { + writer.write_u16(glyph.code)?; + } else { + writer.write_u8(glyph.code as u8)?; + } } }