RE: WOFF2 bug

Folks,

I am working on the spec to incorporate actions 143 and 147 (https://www.w3.org/Fonts/WG/track/actions/pendingreview), and I found one more discrepancy between the spec and the reference implementation.

The definition of the bboxStreamSize (see http://dev.w3.org/webfonts/WOFF2/spec/#glyf_table_format) says that this field represents the size of the bbox stream. However, the reference implementation (see my previous email below) writes the combined length of both bboxBitmap and bboxStream in this field.
Since the size of bboxBitmap[n] is fixed and depends only on numGlyphs, the only variable part here _is_ the bboxStream size. It may not seem to make sense to inflate the bboxStreamSize with the size of the bboxBitmap that can be calculated based on the numGlyphs value from another field; however since the two data chunks are now grouped together and written out sequentially - having their combined length recorded in the header doesn't hurt either.

Should I just make the needed changes in the field description for the sake of keeping the reference implementation intact?

Thank you,
Vlad


From: Levantovsky, Vladimir [mailto:Vladimir.Levantovsky@monotype.com]
Sent: Tuesday, September 02, 2014 1:52 PM
To: w3c-webfonts-wg (public-webfonts-wg@w3.org)
Subject: WOFF2 bug

Hello WG,

One of my colleagues brought up a question about the discrepancy between the draft WOFF2 spec vs. the reference implementation - I believe he is on to something real that was overlooked all along.

The spec description of the TransformedGlyfHeader says that:
"The transformed table consists of a header with the size of each of the substreams, followed by the substreams in sequence."

The very last field of the header (according to the spec) is bboxBitmap array, which [as one would guess] is to be followed by nContourStream, nPointsStream, flagStream, glyphStream, compositeStream, bboxStream and instructionStream.
(Note to editors: the spec is very light on the stream descriptions leaving developers to guess what they and their sequence are, some additional language needs to be added to address this).

However, looking at the reference implementation (https://code.google.com/p/font-compression-reference/source/browse/woff2/transform.cc):
  void GetTransformedGlyfBytes(std::vector<uint8_t>* result) {

    WriteLong(result, 0);  // version

    WriteUShort(result, n_glyphs_);

    WriteUShort(result, 0);  // index_format, will be set later

    WriteLong(result, n_contour_stream_.size());

    WriteLong(result, n_points_stream_.size());

    WriteLong(result, flag_byte_stream_.size());

    WriteLong(result, glyph_stream_.size());

    WriteLong(result, composite_stream_.size());

    WriteLong(result, bbox_bitmap_.size() + bbox_stream_.size());

    WriteLong(result, instruction_stream_.size());

    WriteBytes(result, n_contour_stream_);

    WriteBytes(result, n_points_stream_);

    WriteBytes(result, flag_byte_stream_);

    WriteBytes(result, glyph_stream_);

    WriteBytes(result, composite_stream_);

    WriteBytes(result, bbox_bitmap_);

    WriteBytes(result, bbox_stream_);

    WriteBytes(result, instruction_stream_);

  }



where the bbox_bitmap is written out much later in the process - in between compositeStream and bboxStream.

This definitely breaks compatibility between the code and the spec, but considering that the code has now been widely adopted by two publicly released browser version (Chrome and Opera) and that large number of fonts served over the web in WOFF2 format implemented the same stream sequence as reference implementation - I think it would be much less of a pain to simply edit the spec to reflect the current implementation status.

Let's discuss it during the telcon tomorrow.

Thank you,
Vlad

Received on Tuesday, 7 October 2014 15:49:09 UTC