# OpenType SVG font support to FreeType ## Week 3 Report ### Brief chronological overview Upon running the tool `ftview` on OT-SVG fonts it, I realized that the Glyph Management API of FreeType needs to support OT-SVG fonts. When I tried to do that I ran into issues as discussed in the [list](https://lists.nongnu.org/archive/html/freetype-devel/2019-06/msg00092.html). As Alexei suggested, I reverted my decision to store the document data in `TT_GlyphSlotRec`. See it [here](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=3e0cd54dd90b925c68cee00b7e5dcda49944e586). Having done that, I created a new public structure `FT_SVG_DocumentRec` (also its handle `FT_SVG_Document`) to store all the SVG document data and referenced this structure in `slot->other`. See it [here](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=dd5312cddf7de7141727fc0a4d71531be9036591). This structure evolved over time. So, I will discuss it in a below. Having done that, I focused on making the Glyph Management API support OT-SVG. For that, I created a new structure `FT_SvgGlyphRec` that inherits from `FT_OutlineGlyphRec`. See it [here](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=864ea569ab8c7db6729557d62d7a87fead7f7669). I created a new Glyph class for SVG glyphs and wrote most of the functions except `transform` and `bbox`. Simultaneously, I started working on making the FreeType demo tool `ftview` work with OT-SVG fonts. The most troublesome part for me was understanding its Makefile and linking it with my `resvg` port. After two days of debugging everything worked. [This](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=8e4177ac538c98d544ccee6d8a788fb6660a55dd) and [this](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=27672b0a0e1b9ad088c3fecd45cc5f6a99d0fb93) are some of the things I had to do. **Note** that the commits might seem sequential however the actual work was all going in parallel. After this, I did some changes in my `resvg` based rendering port to support those glyphs where the viewbox's `width` and `height` are different from the EM square. These require transformations to be applied on the SVG coordinate system. See the in-file comments [here](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=05e4953863488651ca9efbbf21dbe374c5b99454). I used the FreeType memory debugger to identify and fix most of the memory leaks. Some are still remaining that I need to tackle. See [this](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=438ece4e79692469c4458927af6df0508ed7c9c4) and [this](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=9cc52601605be88c5587a44c243c3f31499ac912). I modified `FT_SvgGlyphRec` and `FT_SVG_DocumentRec` so that the glyph range for each document can be seen by the rendering port. Thus allowing the port to implement a caching mechanism if it wants to do so. ### Discussion on the design of `FT_SvgGlyphRec` and `FT_SVG_DocumentRec` ATM, `FT_SVG_DocumentRec` has the following stuff in it: 1. A pointer to the document string. 2. Document's length 3. The size metrics object. (to be explained in a moment). 4. The units per EM. (to be explained in a moment). 5. The start glyph ID of the glyph range covered by this document. 6. The end glyph ID of the glyph range covered by this document. I have designed `FT_SvgGlyphRec` to inherit from `FT_OutlineGlyphRec`. The rest of the fields are exactly the same as `FT_SVG_DocumentRec` only one extra field `glyph_index`. First of all, let me justify the existence of all of the fields in `FT_SvgGlyphRec` and then I will also justify their existence in `FT_SVG_DocumentRec`. What I have understood is that a `FT_Glyph` object is supposed to be totally disconnected from the rest of the library and should on-its-own completely describe the glyph without needing anything else. To make this true for SVG Glyphs too, I had to: * Inherit this from `FT_OutlineGlyphRec` because I need the outlines to ultimately let the rendering port calculate its bounding box and thus render it properly. * Store the size information in the `metrics` object. This is necessary because we need to know exactly how big or small to render the glyph. Outline glyphs have scaled outlines which encapsulate the sizing information. (I think). * Store `units_per_EM`. Read [this](https://docs.microsoft.com/en-us/typography/opentype/spec/svg#coordinate-systems-and-glyph-metrics). In case if the viewbox width and height are different from the units per EM, a scaling transformation needs to be applied in the SVG coordinate system. Thus, the units per EM are required to properly render the SVG glyph. * Store `start_glyph_ID` and `end_glyph_ID` to allow the rendering port to perform caching if it wants to. Now let me justify why `units_per_EM` and `metrics` are stored inside the `FT_SVG_DocumentRec` structure too. The way the function `FT_Glyph_To_Bitmap` works is that it takes an `FT_Glyph` as an argument and creates a dummy `FT_GlyphSlotRec`, then passes it to `FT_Render_Glyph_Interenal` which ultimately renders it. In order to render an SVG glyph properly, the rendering port needs the `metrics` and `units_per_EM`, both of these can be grabbed from `slot->face`, but, this dummy slot can't have a `face` because `FT_Glyph_To_Bitmap` doesn't (and probably shouldn't) have access to the `face` object. Thus, the solution is, store these in an `FT_SVG_DocumentRec` which you reference in `dummy.other`. Hopefully the explanation is understandable, if not, ask me and I will elaborate it more. Wanted to keep it brief here. If there are better ways to do this, let me know! :) ### Discussion on the method of memory freeing I have employed #### Freeing `FT_SVG_DocumentRec` referenced in `slot->other` * I created a flag `FT_FACE_FLAG_SVG` that is set only if the `face` has an `SVG` table. [See](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?h=GSoC-2019-moazin&id=438ece4e79692469c4458927af6df0508ed7c9c4). * If this flag is set, in `ft_glyphslot_init` allocate the memory for a `FT_SVG_DocumentRec` and store the pointer in `slot->other`. * Modify `ft_glyphslot_clear` so that the `slot->other` doesn't get set to NULL if the font has an SVG table. * Modify `ft_glyphslot_done` to free the memory pointed by `slot->other` if the font has an SVG table. #### Freeing the memory allocated in `tt_face_load_svg_doc` to store the uncompressed document string of a GZIP compressed document If the document is in plaintext, the pointer can simply point to the file stream. However, if it's GZIP compressed, we need to uncompress it and then store it in separately allocated memory. This needs to be properly freed too. I did it by: * Creating a flag `FT_GLYPH_OWN_GZIP_SVG` that can be set in `slot->internal->flags` to indicate that the current slot has a GZIP uncompressed document that needs to be freed. * Set this flag from `tt_face_load_svg_doc` in case the document is GZIP compressed. * If this flag is set, free this memory in `ft_glyphslot_done` as well as `ft_glyphslot_clear`.