├── .gitignore ├── AUTHORS.txt ├── LICENSE ├── README.md ├── _config.yml ├── _includes ├── footer.html ├── header-masthead.html ├── html-end.html └── html-start.html ├── _layouts ├── bookpage.html └── homepage.html ├── assets ├── images │ ├── body-bg.jpg │ ├── download-button.png │ ├── github-button.png │ ├── header-bg.jpg │ ├── highlight-bg.jpg │ └── sidebar-bg.jpg └── stylesheets │ ├── print.css │ └── stylesheet.css ├── en-US-weightlist.md ├── en-US ├── Adobe_Glyph_List.md ├── Background_Knowledge.md ├── Browsers as a font test platform.md ├── Characters_and_Glyphs.md ├── Composite_Glyphs.md ├── Composite_Tools.md ├── Copyright_and_Licensing.md ├── Design_Metrics.md ├── Encoding.md ├── Environments.md ├── Font_Metadata.md ├── Font_Naming.md ├── Glyph_Construction.md ├── Glyph_Encoding_below_0020.md ├── Glyph_Metadata.md ├── Glyph_Naming.md ├── Introduction.md ├── Line_Metrics.md ├── OpenType.md ├── Optimization.md ├── Production_and_Distribution.md ├── Python-based_tools.md ├── Referencing_Guidelines.md ├── Script_Specific.md ├── Shaping_and_Rendering.md ├── Source_Formats.md ├── Style_Guidelines.md ├── Testing.md ├── Tools.md ├── UFO.md ├── Unicode_Ranges.md ├── User_Interface_Strings.md ├── Versioning.md ├── images │ ├── EncodedCRinScribus.png │ ├── EncodingBelow0020_FLFontInfo.png │ ├── EncodingBelow0020_FLTTGen.png │ ├── FireFox-font-inspector.jpg │ ├── Firefox-OTSanitizer-error.png │ └── UI-strings-in-use.png └── index.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | .sass-cache/ -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | # This file lists authors 2 | 3 | Bobby de Vos 4 | Victor Gaultney 5 | Bob Hallissy 6 | David Rowe 7 | Alan Ward 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | License 2 | 3 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 4 | 5 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 6 | 7 | 1. Definitions 8 | 9 | "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. 10 | 11 | "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License. 12 | 13 | "Creative Commons Compatible License" means a license that is listed at https://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License. 14 | 15 | "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. 16 | 17 | "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike. 18 | 19 | "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. 20 | 21 | "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. 22 | 23 | "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. 24 | 25 | "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. 26 | 27 | "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. 28 | 29 | "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. 30 | 31 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. 32 | 33 | 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: 34 | 35 | to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; 36 | 37 | to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; 38 | 39 | to Distribute and Publicly Perform the Work including as incorporated in Collections; and, 40 | 41 | to Distribute and Publicly Perform Adaptations. 42 | 43 | For the avoidance of doubt: 44 | 45 | Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; 46 | 47 | Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, 48 | 49 | Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. 50 | 51 | The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. 52 | 53 | 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: 54 | 55 | You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested. 56 | 57 | You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. 58 | 59 | If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. 60 | 61 | Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. 62 | 63 | 5. Representations, Warranties and Disclaimer 64 | 65 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 66 | 67 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 68 | 69 | 7. Termination 70 | 71 | This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. 72 | 73 | Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 74 | 75 | 8. Miscellaneous 76 | 77 | Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. 78 | 79 | Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. 80 | 81 | If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 82 | 83 | No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. 84 | 85 | This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. 86 | 87 | The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FDBP 2 | Font Development Best Practice documentation 3 | 4 | ## General Info 5 | - The anticipated content of the book can be found in the https://github.com/silnrsi/FDBP/blob/gh-pages/en-US-weightlist.md document. 6 | - Each page is written in GitHub Flavored Markdown (GFM) and begins with Jekyll front matter which specifies the title, category, weight (page sort order), outline level (similar to the weight, but showing the hierarchy), published status, and layout (page template - bookpage is currently used by all pages). 7 | - The GFM pages are in the en-US folder. 8 | - Some of the current pages are placeholders which need to be filled out and/or replaced by several pages. New pages probably aren’t needed for topics below the top level -- at least not until a higher level page gets too full. 9 | 10 | ## Contributing 11 | 12 | To contribute, edit the GitHub Flavored Markdown pages in the en-US folder. 13 | This can be done several ways: 14 | - Clone the repo, then edit the files with a text editor and push them. (See [Previewing your changes locally] (https://github.com/silnrsi/FDBP#previewing-your-changes-locally) for previewing the site or consider a markdown editor such as [Geany] for previewing content) 15 | - Use the GitHub web editor. 16 | - Use [prose.io/#silnrsi/FDBP](http://prose.io/#silnrsi/FDBP), which provides a GUI-like interface for GFM. 17 | You will need to use the prose.io interface to add that service as an authorized app on your GitHub account. 18 | 19 | A page can be added by adding a file to the en-US directory. 20 | - Do not use spaces in the file name. 21 | - Copy the front matter (between the triple hyphens) from another file and update the 22 | weight, title, and possibly category. 23 | - New pages will generally use a category that’s already in use. 24 | - Add the page title and weight to en-US-weightlist.md. 25 | 26 | If you contribute, add your name to AUTHORS.txt. 27 | 28 | ## Previewing your changes locally 29 | To see your working copy of the site served locally in your browser, start a command window, change to the directory containing the repository (using the `cd` command) and start the jekyll server. For example: 30 | ``` 31 | cd /home/hyde/FDBP 32 | jekyll serve 33 | ``` 34 | then point your browser at the URL which jekyll prints out (something like http://127.0.0.1:4000/FDBP/, for example). 35 | You may be able to substitute 'localhost' for '127.0.0.1' in the URL. 36 | 37 | This assumes you have jekyll installed already. 38 | 39 | ### Installing jekyll 40 | 41 | **Windows:** This guide explains how to [Easily install Jekyll on Windows] 42 | **Linux:** Install the jekyll package using your package manager, for example on Debian based operating systems 43 | 44 | `sudo apt-get install jekyll` 45 | 46 | Ensure that you have jekyll version 2 or later. 47 | 48 | ## Acknowledgements 49 | We gratefully acknowledge this site is modeled on [Design With FontForge] on [GitHub]. 50 | 51 | [Design With FontForge]: http://designwithfontforge.com 52 | [GitHub]: https://github.com/fontforge/designwithfontforge.com 53 | [Easily install Jekyll on Windows]: https://davidburela.wordpress.com/2015/11/28/easily-install-jekyll-on-windows-with-3-command-prompt-entries-and-chocolatey/ 54 | [Geany]: https://www.geany.org/ 55 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | markdown: kramdown 2 | highlighter: null 3 | permalink: none 4 | exclude: ["en-US/images/precompressed/", "node_modules", "Gruntfile.js", "package.json"] 5 | url: http://silnrsi.github.io/FDBP 6 | baseurl: /FDBP 7 | repourl: //github.com/silnrsi/FDBP 8 | title: Font Development Best Practices 9 | subtitle: Technical guidance regarding font development and production 10 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /_includes/header-masthead.html: -------------------------------------------------------------------------------- 1 | {% assign urlList = site.pages | map: 'url' %} 2 | 3 |
4 |
5 |

{{ site.title }}

6 |

{{ site.subtitle }}

7 | View project onGitHub 8 |
9 |
10 | -------------------------------------------------------------------------------- /_includes/html-end.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_includes/html-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | {% if page.title == site.title %} 15 | {{ site.title }} 16 | {% else %} 17 | {{ site.title }}: {{ page.title }} 18 | {% endif %} 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /_layouts/bookpage.html: -------------------------------------------------------------------------------- 1 | {% include html-start.html %} 2 | 3 | {% include header-masthead.html %} 4 | 5 | {% assign pageList = site.pages | sort: 'weight' %} 6 | 7 |
8 |
9 |
10 |

{{page.outlevel}} {{ page.title }}

11 | {{ content }} 12 | 61 |
62 | 63 | 87 |
88 |
89 | 90 | {% include footer.html %} 91 | 92 | {% include html-end.html %} -------------------------------------------------------------------------------- /_layouts/homepage.html: -------------------------------------------------------------------------------- 1 | {% include html-start.html %} 2 | 3 | {% include header-masthead.html %} 4 | 5 | 6 |
7 |
8 |
9 | 10 |

{{ content }}

11 |
12 | 13 | 17 | 18 |
19 |
20 | 21 | {% include footer.html %} 22 | 23 | {% include html-end.html %} 24 | -------------------------------------------------------------------------------- /assets/images/body-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/body-bg.jpg -------------------------------------------------------------------------------- /assets/images/download-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/download-button.png -------------------------------------------------------------------------------- /assets/images/github-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/github-button.png -------------------------------------------------------------------------------- /assets/images/header-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/header-bg.jpg -------------------------------------------------------------------------------- /assets/images/highlight-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/highlight-bg.jpg -------------------------------------------------------------------------------- /assets/images/sidebar-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/assets/images/sidebar-bg.jpg -------------------------------------------------------------------------------- /assets/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, iframe, 2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 3 | a, abbr, acronym, address, big, cite, code, 4 | del, dfn, em, img, ins, kbd, q, s, samp, 5 | small, strike, strong, sub, sup, tt, var, 6 | b, u, i, center, 7 | dl, dt, dd, ol, ul, li, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td, 10 | article, aside, canvas, details, embed, 11 | figure, figcaption, footer, header, hgroup, 12 | menu, nav, output, ruby, section, summary, 13 | time, mark, audio, video { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-size: 100%; 18 | font: inherit; 19 | vertical-align: baseline; 20 | } 21 | /* HTML5 display-role reset for older browsers */ 22 | article, aside, details, figcaption, figure, 23 | footer, header, hgroup, menu, nav, section { 24 | display: block; 25 | } 26 | body { 27 | line-height: 1; 28 | } 29 | ol, ul { 30 | list-style: none; 31 | } 32 | blockquote, q { 33 | quotes: none; 34 | } 35 | blockquote:before, blockquote:after, 36 | q:before, q:after { 37 | content: ''; 38 | content: none; 39 | } 40 | table { 41 | border-collapse: collapse; 42 | border-spacing: 0; 43 | } 44 | body { 45 | font-size: 13px; 46 | line-height: 1.5; 47 | font-family: 'Helvetica Neue', Helvetica, Arial, serif; 48 | color: #000; 49 | } 50 | 51 | a { 52 | color: #d5000d; 53 | font-weight: bold; 54 | } 55 | 56 | header { 57 | padding-top: 35px; 58 | padding-bottom: 10px; 59 | } 60 | 61 | header h1 { 62 | font-weight: bold; 63 | letter-spacing: -1px; 64 | font-size: 48px; 65 | color: #303030; 66 | line-height: 1.2; 67 | } 68 | 69 | header h2 { 70 | letter-spacing: -1px; 71 | font-size: 24px; 72 | color: #aaa; 73 | font-weight: normal; 74 | line-height: 1.3; 75 | } 76 | #downloads { 77 | display: none; 78 | } 79 | #main_content { 80 | padding-top: 20px; 81 | } 82 | 83 | code, pre { 84 | font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; 85 | color: #222; 86 | margin-bottom: 30px; 87 | font-size: 12px; 88 | } 89 | 90 | code { 91 | padding: 0 3px; 92 | } 93 | 94 | pre { 95 | border: solid 1px #ddd; 96 | padding: 20px; 97 | overflow: auto; 98 | } 99 | pre code { 100 | padding: 0; 101 | } 102 | 103 | ul, ol, dl { 104 | margin-bottom: 20px; 105 | } 106 | 107 | 108 | /* COMMON STYLES */ 109 | 110 | table { 111 | width: 100%; 112 | border: 1px solid #ebebeb; 113 | } 114 | 115 | th { 116 | font-weight: 500; 117 | } 118 | 119 | td { 120 | border: 1px solid #ebebeb; 121 | text-align: center; 122 | font-weight: 300; 123 | } 124 | 125 | form { 126 | background: #f2f2f2; 127 | padding: 20px; 128 | 129 | } 130 | 131 | 132 | /* GENERAL ELEMENT TYPE STYLES */ 133 | 134 | h1 { 135 | font-size: 2.8em; 136 | } 137 | 138 | h2 { 139 | font-size: 22px; 140 | font-weight: bold; 141 | color: #303030; 142 | margin-bottom: 8px; 143 | } 144 | 145 | h3 { 146 | color: #d5000d; 147 | font-size: 18px; 148 | font-weight: bold; 149 | margin-bottom: 8px; 150 | } 151 | 152 | h4 { 153 | font-size: 16px; 154 | color: #303030; 155 | font-weight: bold; 156 | } 157 | 158 | h5 { 159 | font-size: 1em; 160 | color: #303030; 161 | } 162 | 163 | h6 { 164 | font-size: .8em; 165 | color: #303030; 166 | } 167 | 168 | p { 169 | font-weight: 300; 170 | margin-bottom: 20px; 171 | } 172 | 173 | a { 174 | text-decoration: none; 175 | } 176 | 177 | p a { 178 | font-weight: 400; 179 | } 180 | 181 | blockquote { 182 | font-size: 1.6em; 183 | border-left: 10px solid #e9e9e9; 184 | margin-bottom: 20px; 185 | padding: 0 0 0 30px; 186 | } 187 | 188 | ul li { 189 | list-style: disc inside; 190 | padding-left: 20px; 191 | } 192 | 193 | ol li { 194 | list-style: decimal inside; 195 | padding-left: 3px; 196 | } 197 | 198 | dl dd { 199 | font-style: italic; 200 | font-weight: 100; 201 | } 202 | 203 | footer { 204 | margin-top: 40px; 205 | padding-top: 20px; 206 | padding-bottom: 30px; 207 | font-size: 13px; 208 | color: #aaa; 209 | } 210 | 211 | footer a { 212 | color: #666; 213 | } 214 | 215 | /* MISC */ 216 | .clearfix:after { 217 | clear: both; 218 | content: '.'; 219 | display: block; 220 | visibility: hidden; 221 | height: 0; 222 | } 223 | 224 | .clearfix {display: inline-block;} 225 | * html .clearfix {height: 1%;} 226 | .clearfix {display: block;} -------------------------------------------------------------------------------- /assets/stylesheets/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* This stylesheet started out as the GitHub Pages 2 | Architect theme by @jasonlong" 3 | 4 | http://meyerweb.com/eric/tools/css/reset/ 5 | v2.0 | 20110126 6 | License: none (public domain) 7 | */ 8 | html, body, div, span, applet, object, iframe, 9 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 10 | a, abbr, acronym, address, big, cite, code, 11 | del, dfn, em, img, ins, kbd, q, s, samp, 12 | small, strike, strong, sub, sup, tt, var, 13 | b, u, i, center, 14 | dl, dt, dd, ol, ul, li, 15 | fieldset, form, label, legend, 16 | table, caption, tbody, tfoot, thead, tr, th, td, 17 | article, aside, canvas, details, embed, 18 | figure, figcaption, footer, header, hgroup, 19 | menu, nav, output, ruby, section, summary, 20 | time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | /* HTML5 display-role reset for older browsers */ 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | body { 34 | line-height: 1; 35 | } 36 | ol, ul { 37 | list-style: none; 38 | } 39 | blockquote, q { 40 | quotes: none; 41 | } 42 | blockquote:before, blockquote:after, 43 | q:before, q:after { 44 | content: ''; 45 | content: none; 46 | } 47 | table { 48 | border-collapse: collapse; 49 | border-spacing: 0; 50 | } 51 | 52 | /* LAYOUT STYLES */ 53 | body { 54 | font-size: 15px; 55 | line-height: 1.5; 56 | background: #FAFAFA url(../images/body-bg.jpg) 0 0 repeat; 57 | font-family: 'Merriweather', serif; 58 | font-weight: 400; 59 | color: #333333; 60 | margin-bottom: 40px; 61 | } 62 | 63 | body > div, footer { 64 | -webkit-font-smoothing: antialiased; 65 | -moz-osx-font-smoothing: grayscale; 66 | } 67 | 68 | @media (min-width: 1170px) { 69 | body { 70 | font-size: 15px; 71 | } 72 | } 73 | 74 | #main-content h1, #main-content h2, h3, h4, h5, h6, #sidebar { 75 | font-family: 'Source Sans Pro', sans-serif; 76 | font-weight: 700; 77 | } 78 | #sidebar { 79 | font-weight: 400; 80 | } 81 | 82 | a, #main-content a h3 { 83 | color: #2879d0; 84 | } 85 | a:hover, #main-content a:hover h3 { 86 | color: #2268b2; 87 | } 88 | 89 | header { 90 | padding-top: 10px; 91 | padding-bottom: 10px; 92 | font-family: 'Julius Sans One', 'Helvetica Neue', Helvetica, Arial, serif; 93 | background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x; 94 | border-bottom: solid 1px #275da1; 95 | font-size: 26px; 96 | } 97 | 98 | header h1 { 99 | font-size: 26px; 100 | color: #fff; 101 | line-height: 1.1; 102 | margin-bottom: 0.1em; 103 | margin-top: 0em; 104 | width: 540px; 105 | } 106 | 107 | header h1 a { 108 | color: #fff; 109 | } 110 | 111 | header h1 a:hover { 112 | color: #9ddcff; 113 | } 114 | 115 | header h2 { 116 | font-size: 18px; 117 | color: #9ddcff; 118 | font-weight: normal; 119 | line-height: 1.3; 120 | width: 540px; 121 | letter-spacing: 0; 122 | text-transform: capitalize; 123 | } 124 | 125 | .inner { 126 | position: relative; 127 | width: 940px; 128 | margin: 0.67em auto; 129 | } 130 | 131 | @media (min-width: 1170px) { 132 | .inner { 133 | width: 1100px; 134 | } 135 | } 136 | 137 | #content-wrapper { 138 | border-top: solid 1px #fff; 139 | padding-top: 30px; 140 | } 141 | 142 | #main-content { 143 | width: 690px; 144 | float: left; 145 | } 146 | @media (min-width: 1170px) { 147 | #main-content { 148 | width: 850px; 149 | } 150 | } 151 | 152 | #main-content img { 153 | max-width: 100%; 154 | } 155 | 156 | nav#post-nav { 157 | width: 100%; 158 | margin-top: 5em; 159 | } 160 | 161 | nav#post-nav a { 162 | display: block; 163 | width: 45%; 164 | float: left; 165 | } 166 | nav#post-nav a h3 { 167 | margin: 0; 168 | } 169 | nav#post-nav a h3:before { 170 | content: ""; 171 | padding-right: 0; 172 | margin: 0; 173 | } 174 | @media (max-width: 767px) { 175 | nav#post-nav a { 176 | width: 73%; 177 | margin: 0 auto; 178 | float: none; 179 | text-align: center; 180 | padding: 15px; 181 | background: #2e78cd; 182 | } 183 | nav#post-nav h3 { 184 | margin: 0; 185 | color: #fff; 186 | } 187 | nav#post-nav a:hover h3, nav#post-nav span { 188 | color: #fff; 189 | } 190 | } 191 | 192 | nav#post-nav span { 193 | display: block; 194 | margin-bottom: .5em; 195 | } 196 | 197 | nav#post-nav span:last-child { 198 | margin-bottom: 0; 199 | } 200 | 201 | nav#post-nav .prev { 202 | margin-right: 10%; 203 | } 204 | @media (max-width: 767px) { 205 | nav#post-nav .prev { 206 | margin-right: auto; 207 | margin-bottom: 1em; 208 | } 209 | } 210 | 211 | nav#post-nav .next { 212 | margin-left: 55%; 213 | text-align: right; 214 | } 215 | @media (max-width: 767px) { 216 | nav#post-nav .next { 217 | margin-left: auto; 218 | text-align: center; 219 | } 220 | } 221 | 222 | nav#post-nav .prev + .next { 223 | margin-left: 0; 224 | } 225 | @media (max-width: 767px) { 226 | nav#post-nav .prev + .next { 227 | margin-left: auto; 228 | } 229 | } 230 | 231 | aside#sidebar { 232 | /* width: 200px; */ 233 | width: 220px; 234 | padding-left: 20px; 235 | min-height: 504px; 236 | float: right; 237 | background: transparent url(../images/sidebar-bg.jpg) 0 0 no-repeat; 238 | /* font-size: .62em; */ 239 | font-size: .9em; 240 | /* line-height: 1.3; */ 241 | line-height: 1.0; 242 | font-weight: 400; 243 | } 244 | 245 | aside#sidebar p.repo-owner, 246 | aside#sidebar p.repo-owner a { 247 | font-weight: 700; 248 | } 249 | 250 | #downloads { 251 | margin-bottom: 40px; 252 | } 253 | 254 | a.button { 255 | width: 134px; 256 | height: 58px; 257 | /* line-height: 1.2; */ 258 | line-height: 1; 259 | font-size: 23px; 260 | color: #fff; 261 | padding-left: 68px; 262 | padding-top: 22px; 263 | font-family: 'Julius Sans One', 'Helvetica Neue', Helvetica, Arial, serif; 264 | } 265 | a.button small { 266 | display: block; 267 | font-size: 11px; 268 | } 269 | header a.button { 270 | position: absolute; 271 | right: 0; 272 | top: -5px; 273 | background: transparent url(../images/github-button.png) 0 0 no-repeat; 274 | } 275 | aside a.button { 276 | width: 138px; 277 | padding-left: 64px; 278 | display: block; 279 | background: transparent url(../images/download-button.png) 0 0 no-repeat; 280 | margin-bottom: 20px; 281 | font-size: 21px; 282 | } 283 | 284 | code, pre { 285 | font-family: 'Source Code Pro', monospace; 286 | background-color: #e6edf0; 287 | overflow: auto; 288 | text-shadow: none; 289 | padding: 4px; 290 | border-radius: 5px; 291 | font-size: 0.85em; 292 | white-space: pre; 293 | max-width: 100%; 294 | } 295 | 296 | pre { 297 | display: inline-block; 298 | margin-bottom: 20px; 299 | } 300 | 301 | 302 | pre code { 303 | padding: 0; 304 | font-size: 1em; 305 | margin-bottom: 0; 306 | } 307 | 308 | ul, ol, dl { 309 | margin-bottom: 1em; 310 | } 311 | 312 | 313 | /* COMMON STYLES */ 314 | 315 | hr { 316 | height: 1px; 317 | line-height: 1px; 318 | margin-top: 1em; 319 | padding-bottom: 1em; 320 | border: none; 321 | /*background: transparent url('../images/hr.png') 0 0 no-repeat;*/ 322 | } 323 | 324 | table { 325 | width: 100%; 326 | border: 1px solid #ebebeb; 327 | font-size: 0.8em; 328 | margin-bottom: 1em; 329 | } 330 | 331 | th { 332 | font-weight: 700; 333 | } 334 | 335 | td { 336 | border: 1px solid #ebebeb; 337 | text-align: left; 338 | font-weight: 400; 339 | } 340 | 341 | form { 342 | background: #f2f2f2; 343 | padding: 20px; 344 | 345 | } 346 | 347 | em, i { 348 | font-style: italic; 349 | } 350 | 351 | b, strong { 352 | font-weight: bold; 353 | } 354 | .underline { 355 | text-decoration: underline; 356 | } 357 | 358 | /* GENERAL ELEMENT TYPE STYLES */ 359 | 360 | #main-content h1 { 361 | font-size: 1.6em; 362 | letter-spacing: 0px; 363 | margin-bottom: .375em; 364 | margin-top: 0em; 365 | color: #2879d0; 366 | } 367 | 368 | #main-content h1:before { 369 | content: "»"; 370 | color: #9ddcff; 371 | padding-right: 0.3em; 372 | margin-left: -.8em; 373 | } 374 | 375 | #main-content h2 { 376 | font-size: 1.3em; 377 | margin-bottom: .6em; 378 | margin-top: 1em; 379 | color: #2879d0; 380 | } 381 | #main-content h2:before { 382 | content: "»"; 383 | color: #9ddcff; 384 | padding-right: 0.3em; 385 | margin-left: -.8em; 386 | } 387 | 388 | #main-content h3 { 389 | font-size: 1.1em; 390 | margin-top: 1em; 391 | margin-bottom: .6em; 392 | color: #2879d0; 393 | } 394 | 395 | /* 396 | #main-content h3:before { 397 | content: "»"; 398 | color: #30B5FF; 399 | padding-right: 0.3em; 400 | margin-left: -1.25em; 401 | } 402 | */ 403 | 404 | #main-content h4 { 405 | font-size: 1em; 406 | margin-bottom: .4em; 407 | color: #2879d0; 408 | margin-top: 2.5em; 409 | } 410 | 411 | /* 412 | h4:not(.quiet):before { 413 | content: "////"; 414 | color: #9ddcff; 415 | padding-right: 0.3em; 416 | margin-left: -2em; 417 | } 418 | */ 419 | 420 | #main-content h5 { 421 | font-size: 14px; 422 | color: #2879d0; 423 | } 424 | /* 425 | h5:before { 426 | content: "/////"; 427 | color: #9ddcff; 428 | padding-right: 0.3em; 429 | margin-left: -3.2em; 430 | } 431 | */ 432 | 433 | #main-content h6 { 434 | font-size: .8em; 435 | color: #2879d0; 436 | } 437 | /* 438 | h6:before { 439 | content: "//////"; 440 | color: #9ddcff; 441 | padding-right: 0.3em; 442 | margin-left: -3.7em; 443 | } 444 | */ 445 | 446 | .note { 447 | background-color: #F2F7F9; 448 | border-top: .1em solid #E5EEF2; 449 | border-bottom: .1em solid #E5EEF2; 450 | padding: 1em .6em; 451 | } 452 | .warn { 453 | background-color: #F9F9EE; 454 | border-top: .1em solid #DDC; 455 | border-bottom: .1em solid #DDC; 456 | padding: 1em .6em; 457 | } 458 | div.note, div.warn { 459 | margin-bottom: 1em; 460 | } 461 | div.note ul, div.note p:last-child, div.warn ul, div.warn p:last-child { 462 | margin-bottom: 0; 463 | } 464 | 465 | .imagebox { 466 | background-color:#fff; 467 | padding:5px; 468 | border:solid 1px #ddd; 469 | } 470 | 471 | p { 472 | margin-bottom: 1em; 473 | } 474 | 475 | a { 476 | text-decoration: none; 477 | } 478 | 479 | p a { 480 | font-weight: 400; 481 | } 482 | 483 | .navi { 484 | background-color: #ccc; 485 | color: white; 486 | } 487 | 488 | blockquote { 489 | font-size: 0.85em; 490 | border-left: 10px solid #e9e9e9; 491 | margin-bottom: 20px; 492 | padding: 0 0 0 20px; 493 | } 494 | 495 | img { 496 | margin: .5em 0; 497 | } 498 | 499 | ul { 500 | padding-left: 20px; 501 | } 502 | 503 | ul li { 504 | list-style: disc inside; 505 | } 506 | 507 | ol li { 508 | list-style: decimal inside; 509 | padding-left: 3px; 510 | } 511 | 512 | dl dd { 513 | font-style: italic; 514 | font-weight: 100; 515 | } 516 | 517 | footer { 518 | /*background: transparent url('../images/hr.png') 0 0 no-repeat;*/ 519 | margin-top: 40px; 520 | padding-top: 20px; 521 | padding-bottom: 30px; 522 | font-size: .62em; 523 | color: #aaa; 524 | font-weight: 400; 525 | } 526 | 527 | footer p { 528 | margin: 0; 529 | } 530 | footer a { 531 | opacity: 0.5; 532 | } 533 | /* MISC */ 534 | .clearfix:after { 535 | clear: both; 536 | content: '.'; 537 | display: block; 538 | visibility: hidden; 539 | height: 0; 540 | } 541 | 542 | .clearfix {display: inline-block;} 543 | * html .clearfix {height: 1%;} 544 | .clearfix {display: block;} 545 | 546 | /* #Media Queries 547 | ================================================== */ 548 | 549 | /* Tablet Portrait size to standard 960 (devices and browsers) */ 550 | @media only screen and (min-width: 768px) and (max-width: 959px) { 551 | .inner { 552 | width: 740px; 553 | } 554 | header h1, header h2 { 555 | width: 340px; 556 | } 557 | header h1 { 558 | font-size: 36px; 559 | } 560 | header h2 { 561 | font-size: 24px; 562 | } 563 | #main-content { 564 | width: 490px; 565 | } 566 | #main-content h1:before, 567 | #main-content h2:before, 568 | #main-content h3:before, 569 | #main-content h4:before, 570 | #main-content h5:before, 571 | #main-content h6:before { 572 | content: none; 573 | padding-right: 0; 574 | margin-left: 0; 575 | } 576 | } 577 | 578 | /* All Mobile Sizes (devices and browser) */ 579 | @media only screen and (max-width: 767px) { 580 | .inner { 581 | width: 93%; 582 | } 583 | header { 584 | padding: 20px 0; 585 | } 586 | header .inner { 587 | position: relative; 588 | } 589 | header h1, header h2 { 590 | width: 100%; 591 | } 592 | header h1 { 593 | font-size: 43.5px; 594 | } 595 | header h2 { 596 | font-size: 24px; 597 | } 598 | header a.button { 599 | background-image: none; 600 | width: auto; 601 | height: auto; 602 | display: inline-block; 603 | margin-top: 15px; 604 | padding: 5px 10px; 605 | position: relative; 606 | text-align: center; 607 | font-size: 13px; 608 | line-height: 1; 609 | background-color: #9ddcff; 610 | color: #2879d0; 611 | border-radius: 5px; 612 | } 613 | header a.button small { 614 | font-size: 13px; 615 | display: inline; 616 | margin-right: 5px; 617 | } 618 | #main-content, 619 | aside#sidebar { 620 | float: none; 621 | width: 100% ! important; 622 | } 623 | aside#sidebar { 624 | background-image: none; 625 | margin-top: 20px; 626 | border-top: solid 1px #ddd; 627 | padding: 20px 0; 628 | min-height: 0; 629 | } 630 | aside#sidebar a.button { 631 | display: none; 632 | } 633 | #main-content h1:before, 634 | #main-content h2:before, 635 | #main-content h3:before, 636 | #main-content h4:before, 637 | #main-content h5:before, 638 | #main-content h6:before { 639 | content: none; 640 | padding-right: 0; 641 | margin-left: 0; 642 | } 643 | } 644 | 645 | @media (min-width: 768px) { 646 | .navi { 647 | margin-top: 10px; 648 | } 649 | } 650 | 651 | ul.breadcrumb li { 652 | display: inline; 653 | border: 0; 654 | margin: 0; 655 | padding: 0; 656 | text-transform: capitalize; 657 | font-weight: 400; 658 | } 659 | 660 | /* Rectangle List style from 661 | http://www.red-team-design.com/css3-ordered-list-styles */ 662 | 663 | ol.rectangle-list li { 664 | list-style: none; 665 | /* height: 2em; */ 666 | height: 1em; 667 | margin-bottom: 1em; 668 | } 669 | 670 | .rectangle-list { 671 | counter-reset: li; 672 | list-style: none; 673 | *list-style: decimal; 674 | padding: 0; 675 | margin-bottom: .4em; 676 | } 677 | 678 | ol.rectangle-list ol { 679 | margin: 0 0 0 2em; 680 | line-height: 1em; 681 | } 682 | 683 | ol.rectangle-list a { 684 | position: relative; 685 | display: block; 686 | padding: .4em .4em .4em .8em; 687 | *padding: .4em; 688 | margin: .5em 0 .5em 2.5em; 689 | background: #d6dce0; 690 | color: #222; 691 | text-decoration: none; 692 | -webkit-transition: all .3s ease-out; 693 | transition: all .3s ease-out; 694 | } 695 | 696 | ol.rectangle-list a.active, 697 | ol.rectangle-list a:hover { 698 | background: #2e78cc; 699 | color: #fff; 700 | } 701 | 702 | ol.rectangle-list a:before{ 703 | /* content: counter(li); */ 704 | counter-increment: li; 705 | position: absolute; 706 | left: -2.5em; 707 | top: 50%; 708 | margin-top: -1em; 709 | background: #2e78cd; 710 | color: #fff; 711 | /* height: 2em; */ 712 | height: 1em; 713 | width: 2em; 714 | /* line-height: 2em; */ 715 | text-align: center; 716 | } 717 | 718 | ol.rectangle-list a:after{ 719 | position: absolute; 720 | content: ''; 721 | border: .5em solid transparent; 722 | left: -1em; 723 | top: 50%; 724 | margin-top: -.5em; 725 | -webkit-transition: all .3s ease-out; 726 | transition: all .3s ease-out; 727 | } 728 | 729 | ol.rectangle-list a:hover:after{ 730 | left: -.5em; 731 | border-left-color: #2e78cd; 732 | } 733 | th, td { 734 | padding: 0.5em; 735 | } 736 | 737 | .outlevel { 738 | color: #000000; 739 | display: block; 740 | padding: .4em .4em .4em 0em; 741 | float: left; 742 | clear: left; 743 | width: 20px; 744 | height: 1em; 745 | } 746 | 747 | -------------------------------------------------------------------------------- /en-US-weightlist.md: -------------------------------------------------------------------------------- 1 | This table contains the anticipated content. Please **update** it if new pages are added. 2 | There is no automatic link between this page and the front matter weight variables on the pages. 3 | 4 | Page names proceeded by --- are anticipated future additions. 5 | 6 | | Weight |Outline| Page | 7 | |--------|-------|--------------------------------------------| 8 | | 0 | | Index | 9 | | 1 |1 | Introduction | 10 | | 2 |1.1 | Referencing Guidelines | 11 | | 3 |1.2 | Style Guidelines | 12 | | 4 |1.3 | Background Knowledge | 13 | | 10 |2 | Source Formats | 14 | | 20 |2.1 | --- Source Repository Structures | 15 | | 30 |2.2 | UFO | 16 | | 40 |2.3 | --- Information External to UFOs | 17 | | 50 |2.4 | --- Shaping & Rendering Data Formats | 18 | | 51 |2.4.1 | --- AAT | 19 | | 52 |2.4.2 | --- Graphite | 20 | | 53 |2.4.3 | --- .fea | 21 | | 60 |2.5 | --- .sfd (FontForge) | 22 | | 80 |2.6 | --- Other Application Formats | 23 | | 90 |2.7 | --- Other open formats (svg) | 24 | | 100 |3 | Font Metadata | 25 | | 110 |3.1 | Font Naming | 26 | | 120 |3.2 | Versioning | 27 | | 130 |3.3 | Design Metrics | 28 | | 140 |3.4 | Line Metrics | 29 | | 180 |3.5 | --- PANOSE | 30 | | 190 |3.6 | --- Unicode Ranges | 31 | | 200 |4 | Glyph Metadata | 32 | | 210 |4.1 | Character & Glyph Inventory | 33 | | 220 |4.2 | Encoding for Glyphs below U+0020 | 34 | | 230 |4.3 | Glyph Naming | 35 | | 230.3 |4.4 | Adobe Glyph Name Standards | 36 | | 240 |4.5 | --- Glyph Order | 37 | | 250 |4.6 | Encoding | 38 | | 300 |5 | Glyph Construction | 39 | | 310 |5.1 | --- Outlines | 40 | | 311 |5.1.1 | --- Principles for good outlines | 41 | | 315 |5.2 | --- Managing overlap | 42 | | 330 |5.3 | --- Interpolation | 43 | | 340 |5.4 | Composite Glyphs | 44 | | 348 |5.4.8 | Composite Tools | 45 | | 370 |5.5 | --- Anchors | 46 | | 378 |5.5.1 | --- Anchor data formats and conversion | 47 | | 400 |6 | Shaping and Rendering | 48 | | 410 |6.1 | --- AAT | 49 | | 420 |6.2 | --- Graphite | 50 | | 430 |6.3 | OpenType | 51 | | 480 |6.4 | --- Universal Shaping Engine | 52 | | 490 |6.5 | User Interface String | 53 | | 500 |7 | Optimization | 54 | | 510 |7.1 | --- Hinting | 55 | | 513 |7.1.1 | --- Setting FL autohint parameters | 56 | | 515 |7.1.2 | --- Procedure for hinting in FL | 57 | | 517 |7.1.3 | --- ttfautohint | 58 | | 520 |7.2 | --- Compression | 59 | | 530 |7.3 | --- Subsetting | 60 | | 540 |7.4 | --- Tuning | 61 | | 550 |7.5 | --- Metrics | 62 | | 600 |8 | Testing | 63 | | 610 |8.1 | --- Testing font inventory | 64 | | 620 |8.2 | --- Testing design | 65 | | 630 |8.3 | --- Testing metrics, spacing and kerning | 66 | | 640 |8.4 | --- Testing shaping and rendering | 67 | | 650 |8.5 | --- Testing font integrity | 68 | | 660 |8.6 | --- Testing web fonts | 69 | | 680 |8.7 | --- Test sources | 70 | | 682 |8.7.1 | --- Test texts | 71 | | 685 |8.7.2 | --- FTML | 72 | | 690 |8.8 | --- Testing tools | 73 | | 691 |8.8.1 | --- MSFV, OTS, etc | 74 | | 692 |8.8.2 | Browsers as test platforms | 75 | | 700 |9 | Production and Distribution | 76 | | 710 |9.1 | --- Source Management | 77 | | 720 |9.2 | --- Release Package Structures | 78 | | 740 |9.3 | --- Building Fonts & Packages | 79 | | 750 |9.4 | --- Building Debian Packages | 80 | | 790 |9.9 | Copyright & Licensing | 81 | | 800 |10 | Environments | 82 | | 810 |10.1 | --- Windows | 83 | | 820 |10.2 | --- Linux | 84 | | 830 |10.3 | --- Mac OS X | 85 | | 840 |10.4 | --- iOS | 86 | | 850 |10.5 | --- Android | 87 | | 860 |10.6 | --- Other Mobile Environments | 88 | | 870 |10.7 | --- Web Fonts | 89 | | 900 |11 | Tools | 90 | | 910 |11.1 | --- FontLab | 91 | | 920 |11.2 | --- Glyphs | 92 | | 930 |11.3 | --- FontForge | 93 | | 940 |11.4 | --- UFO-based Design Tools | 94 | | 941 |11.4.1 | --- Robofab | 95 | | 942 |11.4.2 | --- Robofont | 96 | | 945 |11.4.3 | --- Trufont | 97 | | 950 |11.5 | --- Python-based Tools | 98 | | 960 |11.6 | --- ADFKO | 99 | | 970 |11.7 | --- Other Tools | 100 | | 980 |11.8 | --- FontUtils | 101 | | 1000 |12 | --- Script-Specific Issues | 102 | | 9900 | | --- Appendices | 103 | | 9990 | | --- Back Matter | 104 | -------------------------------------------------------------------------------- /en-US/Adobe_Glyph_List.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 230.3 5 | outlevel: 4.4 6 | category: Glyph Metadata 7 | title: Adobe Glyph List 8 | --- 9 | 10 | In the [previous article](Glyph_Naming.html) we recommended that glyphs should be named in accordance with the standard set and maintained by Adobe. What is this standard and how does it work? 11 | 12 | ## Adobe Glyph List 13 | 14 | Adobe maintains this standard in two public GitHub repositories under their [adobe-type-tools] umbrella: 15 | 16 | - [Adobe Glyph List Specification][AGL] 17 | - [AGL & AGLFN][agl-aglfn] 18 | 19 | The various files in these two repos work together and should be thought of as one standard — and that standard is often called, simply, **the AGL**. 20 | 21 | ## How does it work? 22 | There are actually number of components involved, specifying: 23 | 24 | - allowed form for glyph names, including 25 | + what letters are allowed 26 | + permitted length 27 | - a complete list of names that PostScript® interpreters/engines are guaranteed to recognize. 28 | - a subset of the above that is recommended for new fonts. 29 | - a general mechanism to generate names for every character that is, or ever will be, in the Unicode standard. 30 | - how to combine names to denote ligatures 31 | - how to denote glyph variants (swash, small caps, etc) 32 | 33 | ## Requirements for all glyph names 34 | At the minimum, to conform to AGL requirements, a glyph name: 35 | 36 | - can be no longer than 31 characters, and 37 | - must consist only of characters from the following set: 38 | + A–Z 39 | + a–z 40 | + 0–9 41 | + . (period, U+002E FULL STOP) 42 | + _ (underscore, U+005F LOW LINE) 43 | 44 | In a font project, _working glyph names_ should at least meet these two minimum requirements. 45 | 46 | ### General format 47 | Glyph names can be thought of as having two parts, which we will call _basename_ and _suffix_. These parts are identified as follows: 48 | 49 | - If the glyph name does not contain a period (`.`) then the entire name is the basename. 50 | - If the glyph name contains at least one period (`.`), then the _first_ period is the separator: everything before it is the basename and everything after it is the suffix. 51 | 52 | #### Suffix 53 | The suffix can be about anything — its purpose is to identify variant glyphs. For example a `.swsh` suffix might be used to indicate a swash variant and `.smcp` used to indicate small cap. 54 | 55 | NB: Some modern tools such as the GlyphsApp font editor understand commonly used suffixes and will automatically build font smarts for them. 56 | 57 | #### Basename 58 | For working names the basename can be about anything. For production names, however, it is essential that the basename be constructed so that it identifies the Unicode character(s) that the glyph represents. This mapping, from glyph name to Unicode character sequence, is the essence of the [AGL] specification. 59 | 60 | Historically, in its own fonts, Adobe has used a lot of names that are no longer recommended. For this reason there are several different glyph lists in the AGL. For new fonts, we recommend using only the names that are in the [Adobe GLyph List for New Fonts \[AGLFN\]][aglfn]. 61 | 62 | #### Basename for arbitrary Unicode character(s) 63 | What if a needed basename is not included in the AGLFN? In this case a special naming convention using the Unicode Scalar Value [USV] of the character(s) should be used. 64 | 65 | Characters in Unicode's Basic Multilingual Plane (BMP) may be represented by either of the formats `u` or `uni`. Characters in Unicode's supplemental planes may be represented only by the format `u`. <CODE> is the Unicode Scalar Value of the character, an uppercase hexadecimal number four to six digits long. There must be no leading zeros, unless the code value would have fewer than four hexadecimal digits, in which case it must be padded to four digits. Surrogate code values (U+D800 to U+DFFF, inclusive) and the two noncharacter code values (U+FFFE and U+FFFF) are prohibited. 66 | 67 | **Caution:** while both the `uni` and `u` notations are likely to be supported in all modern tools, there may be older applications that do not recognize the `u` names. For that reason, for BMP characters, we recommend using `uni` 68 | 69 | Ligature or other decomposition sequences that contain only BMP characters may be represented by either of the following formats: 70 | 71 | - Underscore-separated: In this format, the underscore (`_`) separates component names. Component names may be AGL, `u` or `uni` names. For example: `uni1234_uni5678`. 72 | - Code-concatenated: In this format, the glyph name is expressed as `uni` followed by two or more BMP <CODE>s, which indicate the code values of the components. <CODE> follows the same specification as for `uni` names. For example, `uni12345678` represents <U+1234, U+5678>. 73 | 74 | Ligature or other decomposition sequences that contain a supplemental character may be represented only by the underscore-separated format. For example: `u12345_u102345`, `a_u12345`. 75 | 76 | No two glyph names in a font should yield the same (non-variant) Unicode character on analysis. If they do (e.g. `u1234` and `uni1234`), the results are unspecified. 77 | 78 | Examples: 79 | 80 | |Glyph name|Unicode characters(s)| 81 | |----------|---------------------| 82 | |`uni1234`|U+1234| 83 | |`u1234`|U+1234| 84 | |`u12345`|U+12345| 85 | |`u102345`|U+102345| 86 | |`uni102345`|UNRECOGNIZED (`uni` not allowed for supp chars)| 87 | |`uni123`|UNRECOGNIZED (zero padding required for < 4 digits)| 88 | |`u012345`|UNRECOGNIZED (zero padding not allowed for 5 digits)| 89 | |`uniFFFE`|UNRECOGNIZED (U+FFFE not allowed)| 90 | |`uniFFFF`|UNRECOGNIZED (U+FFFF not allowed)| 91 | |`a_u102345`|U+0061, U+102345| 92 | |`uni102345106789`|U+1023, U+4510, U+6789| 93 | |`u102345_u106789`|U+102345, U+106789| 94 | |`u110000`|UNRECOGNIZED (<CODE> must be <= 0x10FFFF)| 95 | |`u102345106789`|UNRECOGNIZED (use `_` for supp char ligatures)| 96 | |`uniD800DC00`|UNRECOGNIZED ([surrogates] not allowed)| 97 | 98 | 99 | [adobe-type-tools]: https://github.com/adobe-type-tools 100 | [AGL]: https://github.com/adobe-type-tools/agl-specification 101 | [agl-aglfn]: https://github.com/adobe-type-tools/agl-aglfn 102 | [aglfn]: https://github.com/adobe-type-tools/agl-aglfn/blob/master/aglfn.txt 103 | [surrogates]: http://unicode.org/glossary/#surrogate_code_point 104 | -------------------------------------------------------------------------------- /en-US/Background_Knowledge.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 4 5 | outlevel: 1.3 6 | category: Introduction 7 | title: Background Knowledge 8 | --- 9 | 10 | The discussions in the following chapters assume a certain amount of background knowledge. 11 | Some of this depends on the specific subject. 12 | For example, a font designer who is drawing glyphs needs to know different things than a script engineer who is constructing OpenType tables. 13 | 14 | The most important background knowledge that all those involved in font development need to have is an understanding of the differences and interrelationships between characters, keystrokes, codepoints and glyphs. Chapter 2 of the online book [Implementing Writing Systems][IWSc2] is an excellent and thorough resource. 15 | 16 | It is also important to understand the basic contents and structure of an OpenType/TrueType font. [An Introduction to TrueType Fonts][TTIntro] provides a brief orientation for designers and engineers. 17 | 18 | We try to provide references to documents that will provide you with this background information. 19 | If you find that we've assumed some knowledge that made the discussion confusing, we invite you to let us know and we'll try to provide more information. 20 | 21 | [IWSc2]: http://scripts.sil.org/IWS-Chapter02 22 | [TTIntro]: http://scripts.sil.org/IWS-Chapter08 23 | -------------------------------------------------------------------------------- /en-US/Browsers as a font test platform.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 692 5 | outlevel: 8.8.2 6 | category: Testing 7 | title: Using Browsers for no-install font testing 8 | shorttitle: Browsers as a test platform 9 | --- 10 | 11 | Because modern browsers support `@font-face`, you can test a font without actually installing it in your system. This is handy especially for comparing different versions of the same font and for systems, like Windows, where font install isn’t quite as reliable as one might like. 12 | 13 | With all source documents, stylesheets, and fonts to be tested on your local computer rather than a web server, this no-install testing can provide for rapid build and test cycles. 14 | 15 | Recent versions of Firefox, Chrome, and Edge all support this technique. 16 | 17 | ## Mozilla Firefox 18 | 19 | ### Useful configuration options 20 | 21 | Depending on your testing needs, there are a few Firefox preferences that you may want to adjust. To make these adjustments, enter `about:config` in the address bar. 22 | 23 | #### `gfx.font_rendering.graphite.enabled` 24 | 25 | This setting determines whether Graphite rendering is enabled. Changing this instantly refreshes other tabs and windows. 26 | - Data type: Boolean 27 | - Default value: Prior to FF22: `False`; FF22 and beyond: `True` 28 | 29 | #### [`security.fileuri.strict_origin_policy`](http://kb.mozillazine.org/Security.fileuri.strict_origin_policy) 30 | 31 | This setting determines whether local urls are restricted to current folder and below. When local documents (e.g., those located on your hard drive) are loaded into the browser, the scripts and links within have restrictions on what they can see and do. By default local documents have access to other local documents in the same directory and in subdirectories, but not directory listings. This means that CSS text such as: 32 | 33 |       `@font-face { font-family: Test; src: url(../myfont.ttf); }` 34 | 35 | will not be able to load myfont.ttf. To get around this you need to set this configuration setting to `False` so that the local documents are allowed to access any file on your harddrive. 36 | 37 | - Data type: Boolean 38 | - Default value: `True` (all urls restricted to current folder and below). 39 | 40 | #### `devtools.fontinspector.enabled` 41 | 42 | This setting determines whether the Developer tool called the Inspector will tell you exactly what font is being used for a selected text element. 43 | 44 | - Data type: Boolean 45 | - Default value: currently `True` 46 | 47 | ### OT Sanitizer testing 48 | 49 | Because Firefox does integrity checks on any `@font-face` fonts, you can get the benefit of checking your fonts with OT Sanitizer without having to build and install the utility. If your OpenType logic isn’t working, or maybe it isn't even your font at all, you might check the Firefox Browser Console for messages similar to this one: 50 | 51 | ![OT-Sanitizer-error](images/Firefox-OTSanitizer-error.png "OT Sanitizer error") 52 | 53 | which shows that OT Sanitizer didn’t like the `GPOS` table. 54 | 55 | To view the Browser Console, press Ctl-Shift-J or click the hamburger icon then `Developer` -> `Browser Console`. 56 | 57 | ### What font is being used? 58 | If you are not sure what font is actually being used for some text element in your document, you can find out with the Element Inspector. Ctl-Shift-C or press the hamburger icon then `Developer` -> `Inspector`. Finally, click on some text and look in the lower right corner of the Inspector for the Fonts panel: 59 | 60 | ![Firefox-Font-Inspector](images/FireFox-font-inspector.jpg "Firefox Element Inspector Fonts panel") 61 | 62 | If the font panel is not visible, see Useful Configuration Options, above. 63 | 64 | ### Oops — Font Caching! 65 | 66 | I had a problem with a "downloaded" (@font-face) font not behaving properly in Firefox even after making sure the css identified the corrected version of the font. 67 | As discussed in [Bug 816483](https://bugzilla.mozilla.org/show_bug.cgi?id=816483), Firefox v20.0 and later cache downloaded fonts (for a while) to speed up display of websites (e.g., newspapers) that use the same webfonts on lots of pages. Unfortunately, when this font caching was first introduced, there was no way to force Firefox to reload the font in case, for example, you had just built a new version. Starting with Firefox v24.0, cached webfonts are reloaded when the user performs a "shift" reload (hold shift key and press Reload, or for Windows users, ctl-F5). 68 | 69 | ### Graphite and OT feature testing 70 | 71 | With appropriate CSS, OpenType Stylistic Sets and Character Variants and Graphite features can all be tested with Firefox. 72 | 73 | ## Google Chrome 74 | 75 | ### Permitting local stylesheet 76 | 77 | By default Chrome does not allow access to certain types of *local* files -- even if the page you are displaying is a local file and the referenced file is in the same folder. Thus, when rendering a local document that references a local XSL stylesheet, Chrome will not load the stylesheet and thus your document will appear as a blank page. 78 | 79 | To override this behaviour you have to start Chrome with a particular command line option. To do this: 80 | 81 | * You must first stop *all* Chrome processes. This includes: 82 | * Close all Chrome windows 83 | * Close any site-specific Chrome browser (a.k.a. Chrome shortcut) windows 84 | * Stop any Chrome background tasks. NB: newer versions of Chrome default to keeping a background task running even after you have closed all Chrome windows. To change this, go to Chrome Settings then, in the System section, disable "Continue running background apps when Google Chrome is closed." 85 | * Launch Chrome with the `--allow-file-access-from-files` option. For Windows you can set up a Windows shortcut to Chrome using: 86 | * Target: `"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files` 87 | * Start in: `"C:\Program Files (x86)\Google\Chrome\Application"` 88 | 89 | ### Graphite and OT feature testing 90 | 91 | Stylistic sets, Character Variants, and other OpenType features can all be tested with appropriate CSS. 92 | 93 | As of Version 57.0.2987.110, Chrome does not support Graphite rendering 94 | 95 | ## Microsoft Edge 96 | 97 | We've recently become aware that Microsoft Edge can also be used for font testing as it now supports OpenType Stylistic Sets and Character Variant features. It does not support Graphite rendering. 98 | -------------------------------------------------------------------------------- /en-US/Characters_and_Glyphs.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 210 5 | outlevel: 4.1 6 | category: Glyph Metadata 7 | title: Characters and Glyphs 8 | --- 9 | 10 | It may seem obvious that a font must contain symbols for each _letter_ or _character_ of the writing system in focus. However, each of those _characters_ may be visually represented by one or more _glyphs_ - the individual graphic shapes defined in the font. At this point it's really important to have a clear understanding of the differences and interrelationships between characters, keystrokes, codepoints and glyphs. Chapter 2 of the online book [Implementing Writing Systems][IWSc2] is an excellent and thorough way to deepen that understanding. 11 | 12 | **When choosing which characters to support we recommend that you consider the full range of uses for the font, both linguistic and typographic.** In addition to the basic letters, numerals, and punctuation, you may need to consider: 13 | 14 | - letters and diacritics used for loan words, foreign terms, or names 15 | - punctuation used in publishing applications, such as formal quote marks, text markers, footnote symbols, and special-width spaces 16 | 17 | You may also need to consider alternate glyphs for special purposes, and create smart font rules for them: 18 | 19 | - different numeral forms (old-style and tabular in Latin, for example) 20 | - contextual alternates and ligatures 21 | 22 | **Non-Latin fonts should also contain a basic set of Latin glyphs.** For technical reasons, the font is less likely to cause problems in certain OSes and environments if a basic Latin set is present. Our recommendation is that you support the following list: [Basic Set of characters needed in a Non-Roman font][basicLatin]. 23 | 24 | If you don't want to draw all of these Latin glyphs yourself, and are making a font that will be released freely under the [SIL Open Font License](Copyright_and_Licensing.html), you can get the glyphs from some other OFL font as long as you acknowledge the source and follow the conditions of the OFL. 25 | 26 | [IWSc2]: https://scripts.sil.org/IWS-Chapter02 27 | [basicLatin]: https://github.com/silnrsi/pysilfont/blob/master/src/silfont/data/required_chars.csv 28 | -------------------------------------------------------------------------------- /en-US/Composite_Glyphs.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 340 5 | outlevel: 5.4 6 | category: Composite Glyphs 7 | title: Composite Glyphs 8 | --- 9 | 10 | Composite glyphs are made by referencing one or more other glyphs in the font. For example, the glyph for "é" can be composed of the glyph for the letter "e" (as the base) and the glyph for the acute accent (as the diacritic, or mark). 11 | 12 | Using composite glyphs saves design time by not requiring that each base and diacritic combination be drawn separately. 13 | 14 | It can also improve consistency since, for example, there is only one copy of the acute accent which is referenced by every glyph that needs it. 15 | 16 | One format for describing composites uses a single line in a text file to define the resulting glyph as a combination of other glyphs. The tool described in [Composite Tools](Composite_Tools.html) uses this format. 17 | -------------------------------------------------------------------------------- /en-US/Composite_Tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 348 5 | outlevel: 5.4.8 6 | category: Composite Glyphs 7 | title: Composite Tools 8 | --- 9 | 10 | This subsection describes one tool for creating composite glyphs. 11 | 12 | ## Composite building tool 13 | 14 | There is a python script named ```psfbuildcomp``` found in the [Pysilfont][pysilfont] collection. It accepts a list of composite definitions and constructs a composite glyph for each definition line. For example, 15 | 16 | ```psfbuildcomp -i composites.txt -r V CharisSIL-Regular.ufo ``` 17 | 18 | * reads composite definitions from the input (```-i```) file named ```composites.txt``` 19 | * uses "verbose" (```-r V```) option for recording progress in the log file 20 | * adds composite glyphs to the CharisSIL-Regular font 21 | * writes results to a log file CharisSIL-Regular.log (default name based on font name) 22 | 23 | ## Basic syntax of input file 24 | 25 | The format used for composite definitions is a subset of that used by RoboFont. It allows: 26 | 27 | ``` 28 | # everything after # is a comment 29 | result = base1 & base2 # two bases 30 | result = base + diacritic@AP # base plus diacritic (at attachment point) 31 | result = base + diac1@AP + diac2@AP # diac2 attaches to diac1 32 | result = base + diac1@AP +diac2@base:AP # diac2 attaches to base 33 | result = base + diac@AP | USV # USV is 4 to 6 hex digits 34 | result = base + diac@AP ^50,100 # add 50 to left and 100 to right sidebearings 35 | ``` 36 | 37 | Example (1): 38 | 39 | ```LtnCapDSmZCaron = LtnCapD & LtnSmZ + CombCaron@U |01C5``` 40 | 41 | defines the glyph ```LtnCapDSmZCaron``` (Latin capital letter D with small letter z with caron) as being composed of the glyph ```LtnCapD``` (Latin capital letter D) followed by the glyph ```LtnSmZ``` (Latin small letter z) with the glyph ```CombCaron``` (Combining caron) placed over the ```LtnSmZ``` glyph at the attachment point (or anchor) labeled ```U``` (which, by default, is matched to the attachment point ```_U``` on the attaching glyph). The resulting glyph is assigned the Unicode value U+01C5. 42 | 43 | Example (2): 44 | 45 | ```LtnSmECircumDotBlw = LtnSmE + CombDotBlw@L + CombCircum@LtnSmE:U |1EC7``` 46 | 47 | defines the glyph ```LtnSmECircumDotBlw``` (Latin small letter e with circumflex and dot below) as being composed of the glyph ```LtnSmE``` (Latin small letter e) with the glyph ```CombDotBlw``` (Combining dot below) placed below the ```LtnSmE``` glyph at attachment point ```L``` (matched to attachment point ```_L``` on the attaching glyph) as well as the glyph ```CombCircum``` (Combining circumflex) placed above the ```LtnSmE``` glyph at attachment point ```U```. The ```LtnSmE:``` after the ```@``` is needed to override the default of attaching a diacritic to the immediately preceding glyph. The resulting glyph is assigned the Unicode value U+1EC7. 48 | 49 | Example (3): 50 | 51 | ```LtnCapACircumGrave = LtnCapA + CombCircum@U + CombGrave@U |1EA6``` 52 | 53 | ```LtnCapACircumGrave.VN = LtnCapA + CombCircumGrave.VN@U``` 54 | 55 | The first line defines the glyph ```LtnCapACircumGrave``` (Latin capital letter A with circumflex and grave) as being composed of the glyph ```LtnCapA``` (Latin capital letter A) with the glyph ```CombCircum``` (Combining circumflex) placed over the ```LtnCapA``` glyph at attachment point ```U``` and with the glyph ```CombGrave``` (Combining grave) placed over the preceding glyph ```CombCircum``` (since the default action is to attach to the immediately preceding glyph) and using the attachment point of that glyph. So, in addition to having an attachment point ```_U``` which is used to attach to the base glyph, the Combining circumflex also has a ```U``` attachment point to which the Combining grave glyph attaches. The resulting glyph is assigned the Unicode value U+1EA6. 56 | 57 | The second line in the above example defines another composite glyph for this same Unicode character to be used when the Vietnamese writing system is active, since in Vietnamese these diacritics appear next to each other rather than one atop the other. 58 | 59 | ## Extension to basic syntax 60 | 61 | SIL added an extension to the RoboFont syntax in order to allow additional properties to be added with minimal conflict with the original syntax. The list of properties is enclosed in square brackets, entries are separated by semicolons and each entry consists of a property name, an equals sign and a value. 62 | 63 | ```[prop1=value1;prop2=value2] ``` 64 | 65 | If applied to a glyph that is being used to build the composite glyph, then the property list appears after the glyph to which it applies. 66 | If applied to the resulting composite glyph, the property list must follow a vertical bar and the USV (if it is present). 67 | 68 | Example (4): 69 | 70 | ```InvisibleTimes.ShowInv = BoxDotted + LtnCapX.Sophia@C11 [with=_C]``` 71 | 72 | defines a glyph composed of the ```BoxDotted``` glyph (a box made with a dotted line) with a glyph containing a sans-serif "X". The attachment point on the dotted box is ```C11```, so by default the corresponding attachment point on the ```LtnCapX.Sophia``` glyph would be ```_C11```. Using ```[with=_C]``` overrides that with the ```_C``` attachment point. 73 | 74 | [pysilfont]: https://github.com/silnrsi/pysilfont 75 | -------------------------------------------------------------------------------- /en-US/Copyright_and_Licensing.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 790 5 | outlevel: 9.9 6 | category: Production and Distribution 7 | title: Copyright and Licensing 8 | --- 9 | 10 | **All fonts should contain clear information on copyright and licensing.** 11 | 12 | ## Copyright 13 | 14 | **All fonts should contain a copyright statement that accurately reflects the legal copyright holder of the font software.** It is important that the copyright holder be a legal entity - an individual, organization, company. In the case of joint copyright this may be multiple legal parties. The copyright holder is the only legal entity that can choose the license under which a font is distributed. Without a copyright statement, or a copyright statement that does not state a real legal entity, the font is in legal limbo and will be strongly avoided. 15 | 16 | The basic copyright statement takes the form: 17 | 18 | > Copyright (c) 2016 Sarah Singh 19 | 20 | The use of `(c)` is preferred over the typographic copyright symbol due to potential cross-platform encoding issues. The statement may span multiple years, with optional comma, and even include multiple joint copyright holders, as in: 21 | 22 | > Copyright (c) 2009-2016, Sarah Singh and Fred Johnson 23 | 24 | If different portions of the software have different copyright holders, two copyright statements would be used, each indicating the part of the software that it applies to: 25 | 26 | > Glyph outlines copyright (c) 2004-2016, Sarah Singh. OpenType routines copyright (c) 2016 Fred Johnson. 27 | 28 | It can be very helpful to add a URL or domain to the copyright holder, as in: 29 | 30 | > Copyright (c) 2016 SIL International (www.sil.org) 31 | 32 | **The copyright statement(s) should be in at least two places in the font package, the font internal copyright field and the separate user documentation.** 33 | 34 | The internal copyright field is stored inside the font file, and font design packages provide an interface for entering it, usually in Font Info. Technically, this information is stored in the font's `name` table, in the entry with ID = 0. 35 | 36 | The same copyright statement(s) should also be in the font package documentation, typically in a LICENSE or ReadMe file. **For OFL-licensed fonts this should be at the very top of the OFL.txt file.** 37 | 38 | ## License 39 | 40 | **All fonts should contain a license statement that governs use and distribution of the font. We strongly recommend use of well-established licenses, whether free and open or restrictive.** We strongly recommend against using "Public Domain" or "This font may be freely used and distributed", as they have widely varying legal interpretations. 41 | 42 | **Fonts that are intended to be distributed and modified freely should use the [SIL Open Font License (OFL) version 1.1][OFL].** This is the standard license in the font industry for such font projects. Please consult the [OFL site][OFL] for detailed information and FAQs. 43 | 44 | ### Using the OFL 45 | 46 | In general, the process of licensing a font under the OFL has five steps: 47 | 48 | (1) _Put your copyright and the OFL text with any chosen Reserved Font Name(s) into your internal font copyright and license fields._ Here is a minimal example: 49 | 50 | > Copyright (c) 2016 Adina Masaro. 51 | 52 | > This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL... 53 | 54 | It is also allowed by the OFL, but not recommended, to replace the full OFL text with a reference to the OFL online, as in: 55 | 56 | > Copyright (c) 2016 Adina Masaro. 57 | 58 | > This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFL 59 | 60 | (2) _Add the same statement to any additional files that are in the project, such as build scripts, control files, smart font code, etc._ 61 | 62 | (3) _Put the same statement at the top of the standard OFL.txt file and include it in your release package._ 63 | 64 | (4) _Write an initial FONTLOG.txt for your font and include it in the release package._ 65 | 66 | (5) _Include the current OFL-FAQ.txt file in the release package._ 67 | 68 | ### Using OFL Reserved Font Names 69 | 70 | Reserved Font Names (RFNs) are a useful way to establish unique names by which only unmodified versions of your fonts are known. Some web fonts services (Google in particular) do not recommend using them because it makes more work for them, but don't be scared away from using them. For more detail see the [OFL-FAQ]. 71 | 72 | If you do choose to declare any RFNs, use this format for the License field: 73 | 74 | > Copyright (c) 2016 Adina Masaro with Reserved Font Name "Anaconda". 75 | 76 | > This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL... 77 | 78 | ## Internal Copyright and License locations 79 | 80 | Internal license information is stored in a font's `name` table alongside the copyright statement(s). There are two separate entries for `License` (also called License Description; ID 13) and `License URL` (ID 14). It can be difficult to find where to set these in a font, so here are some specific instructions: 81 | 82 | | FontForge | _Element > Font Info > TTF Names > New._ Choose the Language (typically 'English (US)'). Click on 'Styles (SubFamily)' to find the license fields. There is also a helpful OFL button that will add these automatically, then you can edit them. | 83 | | FontLab | _Font Info > Names and Copyright > License information._ | 84 | | Glyphs | _Font Info > Custom Parameter._ Click + then find the license fields under New Value | 85 | | in a UFO | Add _openTypeNameLicense_ and _openTypeNameLicenseURL_ keys to the `dict` | 86 | 87 | 88 | **For OFL projects `License URL` should be http://scripts.sil.org/OFL** 89 | 90 | Technically, the Copyright field was intended to be used only for the copyright string and the License only for the license. However the OFL model includes the copyright with the license text. **We recommend that the internal License field should include both, as in (1) above.** 91 | 92 | **If you are creating WOFF versions of fonts, be sure that the copyright and license metadata in the WOFF 'wrapper' matches what is in the font.** 93 | 94 | [OFL]: http://scripts.sil.org/OFL 95 | [OFL-FAQ]: http://scripts.sil.org/OFL-FAQ_web 96 | -------------------------------------------------------------------------------- /en-US/Design_Metrics.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 130 5 | outlevel: 3.3 6 | category: Font Metadata 7 | title: Design Metrics 8 | --- 9 | 10 | The curve shapes, letter widths, diacritic positions, and contextual adjustments in a font are defined in relation to a grid of either 1000 x 1000 units (Postscript and CFF-based OpenType fonts) or 2048 x 2048 units (TrueType and TrueType-based OpenType). **Other units-per-em (UPM) values are allowed, but such situations are rare and should be avoided unless there is a very specific reason to do so (see [Special UPM values](#special-upm-values))**. Although CFF-based fonts are supported by most systems, TrueType-based fonts have much better support, especially on older systems. **We recommend that you develop TrueType-based OpenType fonts, and set your UPM value to 2048.** The rest of this discussion on metrics assumes a 2048 UPM grid. 11 | 12 | The 'em' is a unit that has roots in traditional type founding, but is now well removed from that heritage. The idea was that the letters of a font would normally be sized so that every letter of the design could fit within that 'em-square'. That is no longer the case, and the em/UPM is now used to mathematically determine the physical size of a letter when rendered at a particular point size. Adam Twardoch wrote (in a [recovered Typophile post][Twardoch]): 13 | 14 | > The primary meaning of the UPM size is that it determines the size of glyphs at a given point size. When a font has 1000 UPM, and the capital H is 700 units tall, then when set at 10 pt, the capital H will be exactly 7 pt tall. When the font has 500 UPM and the capital H is 700 units tall, then when set at 10 pt, the capital H will be exactly 14 pt tall. 15 | 16 | This may make you think that you can resize a font simply by changing a font's UPM value - _but don't do it!_ It's technically true but can lead to other problems. There are better ways to size your font. 17 | 18 | ## Setting a font's perceived size 19 | 20 | Font sizing is relative. Because designers have full freedom to make letters 300 or 1400 or 2600 units high, there is no objective standard for how tall any particular letter should be at "12pt". 21 | 22 | For Latin-script fonts, the perceived size is determined primarily by the x-height, for example how tall your 12pt lowercase "x" is in relation to the 12pt lowercase "x" of Times or Georgia. For other scripts it is often determined by the height of the most common shapes, and how large those letters are in your font compared to the most commonly used fonts. **It makes the most sense to make your letters a similar size to other fonts in the same style or script or genre.** 23 | 24 | To do this, first be sure you've set the UPM size correctly (2048). Most design programs will give you a choice of whether to also scale your glyphs when you change the UPM value - let it do that. Then check to see if the general size of your letters is reasonable. For Latin fonts the x-height will normally be somewhere between 800 and 1100 units. For other scripts, open up a commonly used font in your font design program, check to see that the UPM size is 2048 in that font, then see how tall the letters are in units. If you need to resize your letters, select them all and use the Transform/Scale tool or menu option to change all your letters at once. 25 | 26 | To refine this size, create a document that compares text in your font to text in other fonts that you would consider to be in the same market or sphere as yours. For example, if you are creating a sans-serif newspaper face, compare it to other sans-serif faces used for newspapers (your competition). Then scale your whole design up or down to suit using the Transform tools. Making your font significantly larger or smaller than other fonts in your market could affect its success or acceptance. 27 | 28 | As you do this sizing, pay no attention to line metrics - the amount of space between lines of text. **Line spacing is not automatically determined by how many units tall your letters are, or the height of your ascenders or the depth of your descenders.** Technical issues around line spacing and ascender/descender values are complex, and are addressed in the [next major chapter](Line_Metrics.html). 29 | 30 | ## Drawing outside the box 31 | 32 | You may have heard that you need to keep your glyph designs ‘inside the UPM box’. In other words, if you’ve set the Font Info numeric values of ascender to 1500 and descender to -548, you cannot allow your curves to extend outside that 2048-unit ‘box’. **This is simply untrue and very misleading and can push you to make very bad decisions.** In the case of non-Latin fonts in particular, this would force you to unnecessarily shrink your glyphs to a fraction of the size they should be. 33 | 34 | If your glyphs extend higher or lower than these ascender or descender values, then on most screens and in print you will have no trouble, though your lines may be too close together unless you make other changes (see next chapter). Only in very rare situations, such as on older Windows apps or when highlighting text, will the parts ‘outside the box’ get cut off. **In the case of some Latin diacritics and some non-Latin letters and marks you have no choice but to let the letters extended higher or lower than those arbitrary values.** 35 | 36 | If you have set your x-height high and also have long ascenders, then your normal ascenders might end up ‘outside the box’. While not a technical problem, it may mean that your font size really is too large. You may want to reconsider the sizing - but there is no technical reason that requires you to shrink it. 37 | 38 | For example, say you decide that you want your font to appear as large as Georgia (about 960 units in a 2048 UPM font), and you set the height of the ‘x’ to 960. But then you also decide to give it long ascenders, much longer than Georgia’s, between 1600-1800, and deep descenders as well. Then it shouldn’t be a surprise that you get lines colliding. You can fix this technically. However, it may be that you’ve simply chosen an oversized x-height for a font that also has long ascenders. You may not be able to have both the perceived size of Georgia and tall, elegant ascenders. **This is a design issue, not a technical one.** 39 | 40 | ## Special UPM values 41 | 42 | It can be useful in certain cases to set the UPM value for a TrueType font to something other than 2048 - specifically 1000. Some of the technical reasons to avoid this are less relevant than in the past, and it's very likely that a TrueType font with a UPM of 1000 will work without problems. **It's still a good idea to use 2048 by default, however, a UPM of 1000 may be appropriate in certain situations:** 43 | 44 | - The font is based on some other source font with a UPM size of 1000, and you want to avoid rounding errors in scaling to 2048. 45 | - You want to import data or metrics from a font with 1000 UPM, such as kerning or hinting. 46 | - You are working with a team of designers that are all used to working in 1000 UPM and you want to make it easier for everyone to use consistent measurements. 47 | - When the fonts need to be delivered in multiple technology formats, such as both TrueType and OpenType/CFF. 48 | 49 | Some designers have chosen a UPM greater than 2048 (such as 4096) to gain greater design precision, but that is quite rare. 50 | 51 | 52 | 53 | 54 | [Twardoch]: http://typophile.com/node/77906 55 | -------------------------------------------------------------------------------- /en-US/Encoding.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 250 5 | outlevel: 4.6 6 | category: Glyph Metadata 7 | title: Encoding 8 | --- 9 | 10 | (This section will eventually have more information) 11 | 12 | ## Unicode 13 | 14 | (This section will eventually have more information) 15 | 16 | ## PUA 17 | 18 | (This section will eventually have more information) 19 | 20 | ## Double-encoding 21 | 22 | Double-encoding (needs definition). 23 | Adobe dogmatically discourages double-encoding. 24 | 25 | ## Codepages 26 | 27 | (This section will eventually have more information) 28 | -------------------------------------------------------------------------------- /en-US/Environments.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 800 5 | outlevel: 10 6 | category: Environments 7 | title: Environments 8 | --- 9 | 10 | This chapter will contain guidance on issues relevant to specific operating systems and environments: Windows, Linux, Mac OS X, iOS, Android, web and others. 11 | -------------------------------------------------------------------------------- /en-US/Font_Metadata.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 100 5 | outlevel: 3 6 | category: Font Metadata 7 | title: Font Metadata 8 | --- 9 | 10 | The following sections contain guidance on font naming, versioning, design metrics and line metrics. 11 | -------------------------------------------------------------------------------- /en-US/Font_Naming.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 110 5 | outlevel: 3.1 6 | category: Font Metadata 7 | title: Font Naming 8 | --- 9 | 10 | Fonts typically have two names by which they're identified: the internal font name that appears in application menus and the font filename. **These two names should be synchronized in a particular way.** 11 | 12 | ## Internal font names 13 | 14 | The most effective font names (those seen in application menus, etc.) have a few characteristics: 15 | 16 | - They are unique to the particular font family. 17 | - They do not include "Unicode", as most fonts are Unicode-encoded. If the font is _not_ Unicode-encoded, then an indication of that may be added to the name, as in "Anaconda L" (for legacy). 18 | - They do not include specific script or language names. If a font family has multiple language-specific versions, then some indication of the language (such as an [Ethnologue] code), may be added, as in "Anaconda GDX". 19 | - They are not strongly geographic, such as the name of a province or city. In some situations a font named after a particular place can cause people in other areas to not use it. 20 | - They are not references to particular people, such as political leaders or recent cultural heroes. Legendary or historic names are much better, as long as they are not strongly exclusive to a certain subculture. 21 | - They may include spaces, but not numerals or any punctuation. There are some rare situations in which numbers can cause technical problems. 22 | 23 | New fontnames should be checked for conflicts with existing fonts. The easiest way to do that is to search on [namecheck.fontdata.com]. 24 | 25 | ## Font filenames 26 | 27 | An individual font file name is typically no different from that of other files in an operating system, and is (for the most part) only bound by the limitations on legal names in that operating system. **However there is a pattern of font file naming that has become reasonably common, and that we recommend:** 28 | 29 | > FontFamilyName-StyleName.otf 30 | 31 | Here the spaces are removed in the family name and between any weight or style names, then a single hyphen is placed between the two. For example, the Bold Italic weight of "Source Sans Pro" would be named: 32 | 33 | > SourceSansPro-BoldItalic.otf 34 | 35 | Note that even if there is only one style in the family, that style should be included in the font filename, for example: 36 | 37 | > Lateef-Regular.ttf 38 | 39 | ## Font families 40 | 41 | Some applications and operating systems can handle complex font families with many weights, however many still do not, and trying to coordinate a well-functioning family across multiple platforms is a technical nightmare. **Best practice is that font families should normally be grouped in sets of four that correspond to Regular, Italic, Bold, and Bold Italic weights. If a design has more than four weights/styles, it is best to split them into separate groups of two or four and change the main font name for each group.** 42 | 43 | For example, say the "Anaconda Pro" font family has four upright weights (Light, Regular, Semibold, Bold) and four corresponding italic faces. The most trouble-free way to deliver these would be as two separate font families, Anaconda Pro Light: 44 | 45 | - Anaconda Pro Light - Regular _(designed as Anaconda Pro - Light)_ 46 | - Anaconda Pro Light - Italic _(designed as Anaconda Pro - Light Italic)_ 47 | - Anaconda Pro Light - Bold _(designed as Anaconda Pro - Semibold)_ 48 | - Anaconda Pro Light - Bold Italic _(designed as Anaconda Pro - Semibold Italic)_ 49 | 50 | and Anaconda Pro: 51 | 52 | - Anaconda Pro - Regular _(designed as Anaconda Pro - Regular)_ 53 | - Anaconda Pro - Italic _(designed as Anaconda Pro - Italic)_ 54 | - Anaconda Pro - Bold _(designed as Anaconda Pro - Bold)_ 55 | - Anaconda Pro - Bold Italic _(designed as Anaconda Pro - Bold Italic)_ 56 | 57 | ## About name strings stored in OpenType fonts 58 | Within the OpenType font file, the naming table (tag `name`) allows multilingual strings to be associated with the ‎font. These strings can represent copyright notices, font names, ‎family names, style names, feature names and values, etc.. Within the naming table, such strings are organized by Platform, Encoding, Language, and NameID. ‎ 59 | 60 | ### About platform-specific names 61 | In the early days of TrueType and OpenType, different operating systems needed different encodings for these strings. Apple operating systems needed names stored using "script manager" encodings, while Microsoft operating systems used UCS-2. In those days for a font to work on multiple platforms, each name (e.g., the _family name_ or _style name_) had to be included in the name table multiple times (once for each platform). 62 | 63 | While today's OpenType specification still permits inclusion of multiple platform-specific versions of each name, it is no longer necessary to do so, and they only serve to increase the size of the font file with no benefit. 64 | 65 | Based on [this GitHub issue comment], for fonts that have a usable set of PlatformID 3 (Windows) names, **if _any_ PlatformID 1 (macOS) strings are provided then at least four such -- those with NameIDs 1, 2, 3 and 6 -- must be provided for the font to work on some versions of macOS** (though this doesn't appear to be the case as of macOS 10.13.6). 66 | 67 | **We recommend that OpenType fonts do not include in the naming (`name`) table, any strings with PlatformID values other than 3 (Windows)**, as all modern operating systems will use naming tables constructed in this way. 68 | 69 | ### About language-specific names 70 | 71 | The naming table allows for any given name (e.g., _family name_) to be provided in more than one language. However, **every naming (`name`) table entry must be provided in at least the English language.** 72 | 73 | ## References 74 | 75 | [ScriptSource blog post regarding font naming recommendations] 76 | 77 | [Ethnologue]: http://www.ethnologue.com/ 78 | [namecheck.fontdata.com]: http://namecheck.fontdata.com 79 | [ScriptSource blog post regarding font naming recommendations]: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=k7dwx5fhnz 80 | [this GitHub issue comment]: https://github.com/fonttools/fonttools/issues/1170#issuecomment-368492829 81 | -------------------------------------------------------------------------------- /en-US/Glyph_Construction.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 300 5 | outlevel: 5 6 | category: Glyph Construction 7 | title: Glyph Construction 8 | --- 9 | 10 | The following section contains guidance on creating composite glyphs. Future content will include information on drawing good outlines, interpolating glyphs, and managing anchors. 11 | -------------------------------------------------------------------------------- /en-US/Glyph_Encoding_below_0020.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 210.6 5 | outlevel: 4.2 6 | category: Glyph Metadata 7 | title: Encoding glyphs below U+0020 SPACE 8 | shorttitle: Characters below U+0020 9 | --- 10 | ## Summary of Recommendations 11 | 12 | **We recommend that fonts not encode in the cmap characters below U+0020 SPACE.** 13 | 14 | ## Background 15 | 16 | The OS/2 table contains a field known as `usFirstCharIndex` which, according to the [OpenType specification][OTSpec], is: 17 | 18 | >The minimum Unicode index (character code) in this font, according to the cmap subtable for platform ID 3 and platform- specific encoding ID 0 or 1. For most fonts supporting Win-ANSI or other character sets, this value would be 0x0020. This field cannot represent supplementary character values (codepoints greater than 0xFFFF). Fonts that support supplementary characters should set the value in this field to 0xFFFF if the minimum index value is a supplementary character. 19 | 20 | which suggests that the norm is for Unicode cmaps to start encoding at U+0020. 21 | 22 | Historically, however, a number of vendors (most commonly Adobe and SIL) have released fonts with characters below U+0020 (space) encoded in the cmap, resulting in the `usFirstCharIndex` value being less than 0x0020. 23 | 24 | ## Why is this a problem? 25 | 26 | `usFirstCharIndex` values lower than 0x0020 can confuse software and cause unexpected results. 27 | 28 | One example is Scribus which, as of the May 2014, actually draws the glyph for CR (and possibly LF) if they are encoded. If the CR/LF glyphs have width (as CR does in many fonts), they will impact right-aligned text, as in this example: 29 | ![Right-aligned-Scribus](images/EncodedCRinScribus.png "Encoded CR and LF cause right-alignment issues") 30 | 31 | 32 | ## Solutions 33 | 34 | The exact procedures needed to make sure your font does not encode characters below U+0020 will depend on the toolchain you use. 35 | 36 | ### FontLab 37 | 38 | For FontLab Studio, follow these steps: 39 | 40 | 1. Make sure none of `.null` (sometimes called `NULL`), `CR` (may be called `nonmarkingreturn`), `tab`, or anything else before the `space` glyph have USVs in their glyph properties. 41 | 42 | 1. Set FontInfo to not add .null, CR and space (in other words, leave box unchecked): 43 | ![FLFontInfo](images/EncodingBelow0020_FLFontInfo.png "Fontlab FontInfo dialog") 44 | 45 | 1. Finally make sure in the TrueType generation options that the first 256 chars are not being re-encoded: 46 | ![FLTTGen](images/EncodingBelow0020_FLTTGen.png "Fontlab TT Generation") 47 | 48 | 49 | ### VOLT 50 | 51 | If the project uses Microsoft VOLT then the VOLT project (`.vtp` file) may be overriding the encoding of these first few glyphs, e.g.,: 52 | 53 | ``` 54 | DEF_GLYPH ".notdef" ID 0 TYPE BASE END_GLYPH 55 | DEF_GLYPH ".null" ID 1 UNICODE 0 TYPE BASE END_GLYPH 56 | DEF_GLYPH "nonmarkingreturn" ID 2 UNICODE 13 TYPE BASE END_GLYPH 57 | DEF_GLYPH "space" ID 3 UNICODE 32 TYPE BASE END_GLYPH 58 | DEF_GLYPH "tab" ID 4 UNICODE 9 END_GLYPH 59 | ``` 60 | 61 | These can be cleaned up within VOLT by using the Glyph Editor or by exporting the project to a text file, editing to remove the `UNICODE nn` reference, and re-importing the project. 62 | 63 | [OTSpec]: https://www.microsoft.com/typography/otspec/os2.htm#fci 64 | -------------------------------------------------------------------------------- /en-US/Glyph_Metadata.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 200 5 | outlevel: 4 6 | category: Glyph Metadata 7 | title: Glyph Metadata 8 | --- 9 | 10 | The following sections contain guidance on glyph naming, encoding and ordering. They also recommend a minimum set of glyphs that should be present in all fonts, Latin or non-Latin. 11 | -------------------------------------------------------------------------------- /en-US/Glyph_Naming.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 230 5 | outlevel: 4.3 6 | category: Glyph Metadata 7 | title: Glyph Naming 8 | --- 9 | ## Summary of Recommendations 10 | **We recommend that glyph names (also called psnames or PostScript® names) be included in released (that is, shipping) fonts.** 11 | 12 | **Developers may choose to manage two sets of glyph names: *working* glyph names ("friendly" names used during development) and *production* glyph names (used in the shipping font).** 13 | 14 | **Per the [Adobe Glyph List Specification \[AGL\]][AGL] specification, glyph names, whether working names or production names, should be no longer than 31 characters, must be entirely composed of characters from the following set: A–Z, a–z, 0–9, . (period, U+002E FULL STOP) and _ (underscore, U+005F LOW LINE), and must not start with a digit.** Note however that 15 | - Adobe Font Development Kit \[AFDKO\] [Feature File Specification][FEA] allows name length up to 63 but requires that names, with the exception of `.notdef`, must not start with a digit or a period. 16 | - [ISO/IEC 14496-22 "Open Font Format"][OFF] recommends that names, with the exception of `.notdef` and `.null`, must start with a letter. This is not a strict requirement. For example, it is common for glyphs that are only used as components of composite glyphs to have names that start with an underscore, as in `_dot`. 17 | - Various font tools may have other restrictions but such are not derived from any official font specifications. 18 | 19 | **For glyphs that can end up in the final output of rendered text, the production glyph names should be selected from the [Adobe Glyph List for New Fonts \[AGLFN\]][AGLFN].** 20 | 21 | ## Introduction 22 | For various reasons (historical, technical, convenience) most font development tools and formats provide mechanisms to name glyphs with human-readable strings (as opposed to just index numbers, for example). This section documents conventions, restrictions, and best practices for glyph naming. 23 | 24 | ## Why even have glyph names? 25 | Given the ubiquitous support for TrueType/OpenType fonts, one might ask why do we even have glyph names? Nothing _inside_ an OpenType font requires glyphs to have names — complex layout tables `GSUB` and `GPOS`, for example, do all their work in terms of glyph indexes. Even for the `post` table itself (where glyph names are stored), one of the allowed forms, called Version 3, is one that has no names. So one might reasonably ask: if functional fonts can be produced without glyph names, why have them at all? 26 | 27 | The answer starts in the era before TrueType came along, in which Adobe's sophisticated page layout engine accessed glyphs by their names — glyphs had no other way to be located other than by their name. In fact, glyph names were simply another identifier in the PostScript programming language — and that is why even today glyph names have a very strict allowed form. 28 | 29 | Going even further, some software packages are able to infer certain properties of a glyph from just its name. The most commonly cited case of this is that some PDF files do not include any representation of the _character_ stream that the document represents, but yet you can still copy _characters_ from the document to the clipboard. The reason this works at all — and it doesn't always work perfectly — is that Acrobat is able to deduce the character stream (or something close to it) by looking only at the names of the glyphs in the file. 30 | 31 | All of this can work, however, only if the glyphs have been correctly named — meaning named according to Adobe standards. It is for exactly these reasons that we give the recommendations at the top of this article. 32 | 33 | ## Working names vs production names 34 | The first thing to recognize is that, as we'll see in a minute, the glyph names that should be in a font when it is shipped (i.e. released) are not necessarily the most friendly and memorable names. Therefore many developers use a different set of glyph names for development purposes and, as a last step of production, change the glyph names to the "official" names. We will call these two sets of glyph names the **working names** and the **production names**, respectively. 35 | 36 | As an example, the acceptable *production name* for a glyph representing U+0628 ARABIC LETTER BEH would be one of: 37 | 38 | - `uni0628` 39 | - `u0628` 40 | - `afii57416` 41 | 42 | However, as none of these is particularly memorable, designers might, for example, choose a *working name* of `beh`. 43 | 44 | The use of working and production glyph names is common enough that at least one modern font format (the UFO format) provides a mechanism to manage both glyph names, and some font editing applications (GlyphsApp) automatically convert names from working to production during export. 45 | 46 | ### Not all glyphs need production names 47 | Note that even in a shipping font, there may be glyphs that do not need production names. Any glyphs used _only_ as components of some other [composite] glyph need not have production names because the component glyphs can never end up in the output glyph stream of rendered text. 48 | 49 | For example, many letters in the Arabic script are distinguished from each other only by the pattern of dots drawn above or below the main shape. A font might use component glyphs for each pattern of dots (one dot below, one dot above, two dots below, etc.) and also for each main shape, and then construct the desired glyph repertoire using composites that reference the appropriate base and dot glyphs. The glyphs for various patterns of dots can never appear in the output stream, so they do not need production names. 50 | 51 | ## Glyph names are also known as PostScript names 52 | 53 | As an early industry leader with its PostScript technologies, Adobe has set — and now maintains — the standard for how glyphs are named, both in terms of what constitutes a valid name and, within that framework, what specific names are recommended. Within an OpenType font, glyph names are stored in the [`post`] table. 54 | 55 | Because of this, glyph names are often referred to as *PostScript names* or sometimes, more simply, *psnames*. 56 | 57 | Note that it doesn't matter whether one is talking about working names or production names, they are still considered *PostScript names* and their construction should abide by the relevant Adobe standard. 58 | 59 | **Next:** the [Adobe Glyph List](Adobe_Glyph_List.html) standard 60 | 61 | [`post`]: https://www.microsoft.com/typography/otspec/post.htm 62 | [AGL]: https://github.com/adobe-type-tools/agl-specification 63 | [AGLFN]: https://github.com/adobe-type-tools/agl-aglfn 64 | [OFF]: http://standards.iso.org/ittf/PubliclyAvailableStandards/c066391_ISO_IEC_14496-22_2015.zip 65 | [FEA]: https://cdn.rawgit.com/adobe-type-tools/afdko/master/FDK/Technical%20Documentation/OpenTypeFeatureFileSpecification.html#2.f.i 66 | -------------------------------------------------------------------------------- /en-US/Introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 1 5 | outlevel: 1 6 | category: Introduction 7 | title: Introduction 8 | --- 9 | 10 | 11 | This book has been produced to document what we think are the best practices to use in font development. They are generally the practices we use - or intend on using as soon as practically possible. 12 | 13 | This is not intended to be a comprehensive encyclopedia of information, nor to cover the full range of techniques and options. It will generally offer a single recommended procedure, setting, or tool. However we encourage adding links to alternatives when appropriate. 14 | 15 | It is very much a work in progress. If you wish to help us, you can contribute to this documentation [on GitHub]. 16 | See README.md for contribution instructions. 17 | 18 | *— The Font Development Best Practices [Contributors]* 19 | 20 | [on GitHub]: {{site.repourl}} 21 | [Contributors]: https://github.com/silnrsi/FDBP/blob/gh-pages/AUTHORS.txt 22 | -------------------------------------------------------------------------------- /en-US/Line_Metrics.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 140 5 | outlevel: 3.4 6 | category: Font Metadata 7 | title: Line Metrics 8 | --- 9 | 10 | Most word processors and page layout programs have two ways of setting line spacing (how far apart vertically two lines of text will be)—automatic and manual (“exactly”). Each program has a built-in way of automatically guessing at a good default line spacing, but those techniques differ. Some programs look inside the font for information. Others, such as InDesign, simply set it at a percentage of the point size, usually 120%. Many also have a way to explicitly (manually) set the line spacing to a certain amount. **Whenever possible, line spacing should be set explicitly by the user rather than relying on an application’s defaults. There is no technical means of specifying a consistent default line spacing across all environments from within the font. However it is important to try and make it as consistent as is reasonable, and to provide good default spacing.** 11 | 12 | ## Internal font line spacing settings 13 | 14 | OpenType has a variety of internal metrics, stored in the `hhea` and `OS/2` tables, that are used by many operating systems and applications to determine default line spacing: 15 | 16 | - in `hhea` table 17 | - Ascender 18 | - Descender 19 | - LineGap 20 | - in `OS/2` table 21 | - sTypoAscender 22 | - sTypoDescender 23 | - sTypoLineGap 24 | - usWinAscent 25 | - usWinDescent 26 | 27 | The `hhea` values are the historically oldest, originally established by Apple. The `OS/2` sTypo* values were added later by Microsoft and are the ones most apps should be using today. The `OS/2` usWin* values were initially intended to determine clipping—meaning that any part of the glyph that extends above _usWinAscent_, or below _usWinDescent_, could get chopped off. Unfortunately some apps misused usWin* to also set line spacing. 28 | 29 | **It is important to set all eight of these values sensibly in order to minimize inconsistencies and problems in line spacing and clipping across a variety of environments.** 30 | 31 | Glyphs tries to make line spacing easy to set and simplifies this to two settings in the _Font Info/Masters_ panel: _Ascender_ and _Descender_, which it uses to set all the others. However, setting optimum line spacing metrics requires manually overriding these settings through _Custom Parameters_ (see [Glyphs vertical metrics tutorial](https://glyphsapp.com/learn/vertical-metrics)). FontLab also provides access to individual vertical metrics. FontForge is particularly misleading: _Element > Font Info > General_ has _Ascent_ and _Descent_ fields, but those are best ignored. There is a restriction in FontForge that enforces that _Ascent + Descent = Em Size_, which is unnecessary. All the eight values above are instead set in _Element > Font Info > OS/2_, including the `hhea` values. 32 | 33 | There is an additional parameter in the `OS/2` table—bit 7 of _fsSelection_—that affects line spacing. Setting this bit tells applications to use the sTypo* values for line spacing. In Glyphs you set this by adding a `Use Typo Metrics` custom parameter. In FontLab check _Prefer typo metrics_ in _File > Font Info > Other Values > Family dimensions_. In FontForge set the _Really use Typo metrics_ box. **This bit should be set for all fonts, even though some old software (e.g. Word 2003) may misinterpret it.** 34 | 35 | The _Cap height_ and _x-height_ values in some font design programs are not used directly by apps, but setting them correctly might be helpful, as they may be used as guidelines. Recent CSS proposals also hint that setting these correctly in the font will enable improved layout alignment for things like drop caps. 36 | 37 | **Keep the ascender and descender values the same across a font family (R, B, I, BI).** Some font testing tools report a mismatch between family members as a technical error. If they are not the same, then selecting a word in a paragraph and making it bold or italic may change the line spacing for just that one line—a frustrating and ugly problem. You may, however, set the numbers differently if you have separate font families. 38 | 39 | ## Three main strategies 40 | 41 | Since you don’t have direct control over default line spacing everywhere, your primary goal is to avoid situations where some unkind OS or app does something really bad, such as cutting off the tops or bottoms of your letters. Your secondary goal is to give the font reasonable default line spacing. The following three strategies can be used to address both goals. 42 | 43 | These strategies almost exactly match what Google recommends in their [vertical metrics specification](https://googlefonts.github.io/gf-guide/metrics.html). There are minor differences. One area of strong agreement is that _LineGap/sTypoLineGap_ be set to zero. There are legitimate reasons you might consider setting these to some other value, but we don’t recommend it unless you have a specific purpose. For those alternate strategies see the [Glyphs vertical metrics tutorial](https://glyphsapp.com/learn/vertical-metrics) and [John Hudson’s technique](https://typedrawers.com/discussion/4554/on-vertical-metrics-in-the-context-of-a-biscript-tamil-and-latin-font). 44 | 45 | ### Minimal—eliminate clipping 46 | 47 | _Use this strategy if you want to do the minimum amount of work, keep things simple, and eliminate clipping. However, it may result in line spacing that is wider than desired._ 48 | 49 | **Find the highest point in the tallest glyph in your font and set all the ascender-related values to at least that height (_yMax_), then set all the descender-related values to the lowest point in the deepest glyph or lower (_yMin_).** If your capital ‘É’ extends to 2400 height, set your ascender values to at least 2400. Then if you have a deep swash on the ‘g’ that goes down to -900, set the descender to -900. Yes, 2400 + 900 = 3300 — much larger than the font UPM (2048 in this case)! There is a script for Glyphs (see [tutorial](https://glyphsapp.com/learn/vertical-metrics)) that will do this analysis for you. 50 | 51 | Apps and OSes that look at these values, particularly those that might do some clipping, will then set the line spacing so that lines never collide. This is the safest, easiest, and most broad solution. _Note that the usWinDescent value is specified in FontForge (only) as a positive number, while the other Descender values are negative._ 52 | 53 | For example, in UFO3 format font sources (fontinfo.plist) this would mean: 54 | 55 | ``` 56 | openTypeHheaAscender = openTypeOS2TypoAscender = openTypeOS2WinAscent = ascender` 57 | openTypeHheaDescender = openTypeOS2TypoDescender = descender 58 | openTypeOS2WinDescent = -descender 59 | openTypeHheaLineGap = openTypeOS2TypoLineGap = 0 60 | ``` 61 | 62 | **When using this strategy you should also take into account the effects of any diacritic positioning done via [Graphite](http://graphite.sil.org/) or [OpenType](http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=kr5s6gwpdy).** For example, your analysis may determine that the tallest glyph in the font has a height of 2100. However, you also have OpenType code that positions a diacritic above that letter, even though there is no composite glyph for that combination in the font. When positioned by OpenType, the diacritic is raised so that the top reaches 2600 units. In this case the _ascender_ value should be set to at least 2600. This may be particularly important for non-Latin fonts with floating elements that are attached to ascenders/descenders. 63 | 64 | The one main disadvantage of this strategy is that it may cause line spacing to be wider than would be ideal for normal usage. If you have even one rare glyph or combination that is extremely high or low the line spacing will be maximized for that glyph. Users may complain that the lines are too far apart. 65 | 66 | The next strategy allows greater control over default line spacing without additional risk of clipping. 67 | 68 | ### Recommended—ideal line spacing for new fonts 69 | 70 | _Use this strategy if you are creating a new font and want to fine-tune line spacing without additional risk of clipping. This may not be appropriate for fonts that have already been released._ 71 | 72 | **Begin by setting the _usWinAscent_ and _usWinDescent_ values based on the _yMax_ and _yMin_ values as in the _Minimal_ strategy.** This will eliminate most clipping. 73 | 74 | **Set preliminary line spacing by looking at the most commonly-used glyphs and combinations in the font.** Take the high and low points of those glyphs and round the height up and depth down slightly to set the _sTypoAscender_ and _sTypoDescender_. Set the `hhea` _Ascender_ and _Descender_ to the same values and _LineGap/sTypoLineGap_ to zero. 75 | 76 | **Test the line spacing in an application that uses the default spacing defined in the font**, such as TextEdit (macOS) or Microsoft Word (Windows). Be sure to use the current version of the app, not old versions. Do not use InDesign (see below). If the line spacing seems too large, reduce the values proportionally. If the spacing is too tight, add more proportionally. 77 | 78 | The goal with this is to determine a line spacing that will likely please most users, even though it may be too close for some rare combinations. For example, in a Latin-script font the ascender values will need to be at least the height of Á but maybe not the rarer Ǻ (A with ring and acute above). For fonts that support multiple scripts (such as Devanagari and Latin) give more importance to the primary script (which may not be the Latin). 79 | When you’ve settled on pleasant line spacing settings, then review the usWin* values. If they are smaller than the sTypo* ones, increase them to match. In most cases the usWin* values will be greater—leave them that way. 80 | 81 | ### Legacy—for existing fonts 82 | 83 | _Use this strategy for updating the line spacing metrics in an existing, published font family._ 84 | 85 | Changing any line spacing metrics in an existing font is risky. It can cause existing documents to “break” if a new version is installed. If the application has set the document line spacing based on the default spacing in the font, a change can affect page breaks, document length, and other important aspects (e.g. spacing of headers, captions, etc.). **If you decide to change the line metrics of an existing font, then be as kind to your users as is possible.** 86 | 87 | **If your users don’t like the current line spacing treat it as a new font and use the _Recommended_ strategy above.** However you should be very careful to help users understand that it may change all their documents! If your users like the current line spacing, continue with the next steps. 88 | 89 | **Determine the _yMax/yMin_ of the font as in the _Minimum_ strategy and compare that to the existing usWin* metrics.** If the usWin* metrics are less than _yMax/yMin_ then the glyphs may be clipped in some environments and should be changed to at least _yMax/yMin_. There are few applications that this will affect badly, and they are not often used for typographic layout (e.g. Windows Notepad). 90 | 91 | **Change other metrics only if they are inconsistent or produce bad line spacing.** If the other line metrics are consistent with one another (_sTypoAscender=Ascender_, _sTypoDescender=Descender_, _sTypoLineGap=LineGap_), and users like the current line spacing, then set the _fsSelection_ bit 7 (_Use Typo Metrics_) and leave everything alone! 92 | 93 | If these values are inconsistent then you may need to decide which applications/environments are more important to keep unchanged. In most cases, keeping the sTypo* metrics unchanged, and setting _fsSelection_ bit 7, will have the least impact on users. Change _Ascender_, _Descender_, and _LineGap_ to match. If iOS and macOS apps (not including InDesign) are most important, then in some cases it may be better to change the sTypo* metrics. 94 | 95 | **Communicate your changes to users.** Any change in line spacing should be considered a “breaking” change and should only be made in major font version updates (e.g. 3.000 to 4.000). You may even consider changing the font family name to enable users to have both old and new installed at the same time (e.g. Scheherazade to Scheherazade New). 96 | 97 | ## Testing and design considerations 98 | 99 | **Good line spacing is determined by typographic culture rather than mathematical measurements.** Typographic history and tradition shapes what a particular culture considers acceptable or ideal line spacing for their script. In some scripts the expected line spacing may be much wider than is technically necessary. Even within a single script the expectations may very for different styles and purposes. For example, in the Latin script a traditional _Garamond_ design designed for fine books may be expected to have more generous default line spacing than a simple sans serif design for UI purposes. 100 | 101 | **Make decisions based on the primary script.** For fonts that support multiple scripts there may be no line spacing that is ideal for all the supported scripts. In those situations you need to decide which script is most important for line spacing purposes—usually (but not always) the script for which the font will be used the most. Fonts that are designed to be part of a set of related fonts (like Noto) may need to set line spacing metrics to be more consistent with other members of the superfamily. Unfortunately there is no way to define multiple sets of metrics in a font on a per-script basis, although John Hudson has made valiant efforts to get the industry to embrace that possibility. 102 | 103 | **Test using real-life documents.** Good line spacing is affected by context, and column width in particular. Thin columns, such as those in many newspapers, can be tightly spaced since the eye has no difficulty in finding where the next line begins. Wide columns, however, need more interlinear space since the eye needs to travel further to the beginning of the next line and needs greater distinction between lines. Testing with real documents and likely typographic contexts, especially when the application depends on default spacing, is more likely to produce useful results. 104 | 105 | **Do not test line spacing with InDesign or any other applications that calculate line spacing as a percentage of the point size.** No matter what you set in the font, InDesign will still calculate the default line spacing using the 120% of point-size method. This means that you need to test your font outside of InDesign and especially in apps that allow no control over line spacing. Do not allow the default line spacing in InDesign, LibreOffice, or any other application to push you into making the font less useful in other environments. 106 | 107 | ## References 108 | 109 | The following sources provide background material on line spacing technical issues. Some of them suggest alternate methods of setting line metrics. Depending on your particular use these methods may be useful. However, the _Recommended_ strategy above remains the most reliable and consistent method of setting consistent line metrics across a broad range of operating system and application versions. 110 | 111 | - [Google Vertical Metrics Specification](https://googlefonts.github.io/gf-guide/metrics.html). A clear specification, especially for web fonts, that agrees almost completely with our recommendations. 112 | - [Glyphs vertical metrics tutorial](https://glyphsapp.com/learn/vertical-metrics). An excellent summary of different techniques, focused on a “webfont” strategy that works well for web fonts but is slightly different from ours. 113 | - [John Hudson’s Typedrawers post on line metrics](https://typedrawers.com/discussion/4554/on-vertical-metrics-in-the-context-of-a-biscript-tamil-and-latin-font). A solid alternate technique with similar results to the _Recommended_ technique above. 114 | - [Karsten Lücke’s PDF on font metrics](http://www.kltf.de/downloads/FontMetrics-kltf.pdf) 115 | Contains valuable and interesting historical detail. 116 | -------------------------------------------------------------------------------- /en-US/OpenType.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 430 5 | outlevel: 6.3 6 | category: OpenType 7 | title: OpenType 8 | --- 9 | Links to the OpenType specification, as well as other font specifications, can be found on [ScriptSource][OTinfo on SS]. 10 | 11 | ## Lookup Orders 12 | 13 | The OpenType specification suggests that software should: 14 | > assemble all lookups from the set of chosen features, and apply the lookups in the order given in the LookupList table. 15 | 16 | However in actual implementations this isn't how it is usually done. Instead, features are divided into sets, and the sets are processed in a specific order. Within a set, all the lookups associated with the included features are executed (in lookup order) before moving on to the next set of features. 17 | 18 | It is important, therefore, that font developers know how features are divided into sets, and the order in which these sets are executed. To complicate matters, this is: 19 | - not always consistent among shaping engines 20 | - script-specific, and 21 | - not well documented. 22 | 23 | The most useful information is gleaned by reading the Harfbuzz code[^1] since (a) the code is opensource and thus accessible, and (b) Harfbuzz tries to be compatible with Microsoft's Uniscribe. 24 | 25 | The following tables attempt to document what the Harfbuzz code indicates for GSUB execution. Each row represents a set of features, each feature identified by its 4-character tag. All the lookups in the list of features in a row a processed together in lookup order. 26 | 27 | ||Default shaper| 28 | |---|---| 29 | |GSUB|rvrn| 30 | ||ltra ltrm frac numr dnom rand ccmp locl rlig calt clig liga rclt _userfeatures_| 31 | |GPOS|mark mkmk curs kern _userfeatures_| 32 | 33 | ||USE shaper| 34 | |---|---| 35 | |GSUB|rvrn| 36 | |syllable analysis|ltra ltrm rtla rtlm frac numr dnom rand trak HARF 37 | ||locl ccmp nukt akhn| 38 | ||rphf| 39 | ||pref| 40 | ||rkrf abvr blwf half pstf vatu cjct| 41 | |insert dotted circles, reorder|isol init med fina | 42 | ||abvs blws haln pres psts BUZZ ccmp locl rlig calt clig liga rclt vert _userfeatures_| 43 | |GPOS|dist abvm blwm mark mkmk curs kern _userfeatures_| 44 | 45 | ||Arabic shaper (including Arabic, Mongolian, N'Ko, Syriac, and several other connected or cursive scripts.) 46 | |---|---| 47 | |GSUB|rvrn| 48 | ||rtla rtlm frac numr dnom rand| 49 | ||stch| 50 | ||ccmp locl| 51 | ||isol| 52 | ||fina| 53 | ||fin2 (Syriac only)| 54 | ||fin3 (Syriac only)| 55 | ||medi| 56 | ||med2 (Syriac only)| 57 | ||init| 58 | ||rlig| 59 | ||rclt calt| 60 | ||mset clig liga _userfeatures_| 61 | |GPOS|mark mkmk curs kern| 62 | 63 | ||Indic|Khmer| 64 | |---|---|---| 65 | |GSUB|rvrn|rvrn| 66 | ||ltra ltrm frac numr dnom rand|ltra ltrm frac numr dnom rand| 67 | ||ccmp locl|ccmp locl| 68 | ||nukt|| 69 | ||akhn|| 70 | ||rphf|| 71 | ||rkrf|| 72 | ||pref|pref blwf abvf| 73 | ||blwf|| 74 | ||abvf|| 75 | ||half|| 76 | ||pstf|| 77 | ||vatu|| 78 | ||cjct|| 79 | |||cfar| 80 | ||init pres abvs blws psts haln rlig calt clig rclt|pres abvs blws psts rlig calt clig rclt _userfeatures_| 81 | ||_userfeatures_|| 82 | |GPOS|curs kern dist abvm blwm|curs dist abvm blwm| 83 | 84 | where _userfeatures_ includes everything else that the user (or CSS) might have requested, such as dlig, ssxx, cvxx, smcp, onum, etc. 85 | 86 | ## Language Tags 87 | 88 | (This section has not yet been written.) 89 | 90 | ## Feature Tags 91 | 92 | The OpenType specification provides for Layout Feature tables, each of which is identified by a 4-character tag. 93 | 94 | (This rest of this section has not yet been written.) 95 | 96 | ## Stylistic Sets and Character Variants 97 | 98 | Tags for Layout Feature tables which are in the range "ss01" to "ss20" are registered as Stylistic Set 1 through 20. Tags in the range "cv01" to "cv99" are registered as Character Variant 1 through 99. 99 | 100 | When should one use [Stylistic Sets] and when should one use [Character Variants]? 101 | 102 | According to the OpenType spec, Character Variants (cvxx tags) should be preferred when only one character or very closely related characters are affected. Examples include: 103 | 104 | - matching lower and upper case characters 105 | - a lower case character and its small capital form 106 | - all characters that use a particular diacritic, where the diacritic has two forms 107 | 108 | Stylistic Sets (ssxx tags) are preferred when systematically related changes affect more distinct characters. Examples include: 109 | 110 | - 'barred b', 'barred d', and 'barred g' characters with different placements for the bar 111 | - 'a' and 'g' characters with literacy forms 112 | 113 | Having said that, there are some technical and practical distinctions that may require violating these guidelines: 114 | 115 | - The cvxx tags can utilize GSUB “alternate” (type 3) lookups, thus allowing a feature to have more than on/off values. 116 | - There are only 20 registered ssxx features, but 99 cvxx features. 117 | - Some apps (MS Word for example) assume that users would need to turn on only one ssxx feature at a time. 118 | - Not as many apps support cvxx (yet). 119 | 120 | ### GSUB only 121 | 122 | Note that only substitution type lookups are allowed in Stylistic Set and Character Variant features and the features must be in the GSUB table. There may be cases where variant positioning behavior is needed, such as a feature that controls whether a particular diacritic is drawn touching its base or separated from it. While it may seem reasonable to use positioning type lookups and place the features in the GPOS table, it is unlikely that rendering engines will actually process such features. 123 | 124 | ## Mark classes and filter sets 125 | 126 | (This section has not yet been written.) 127 | 128 | ---- 129 | [^1]: The Harfbuzz source is maintained [on Github](https://github.com/harfbuzz/harfbuzz/tree/master/src), and the pertinent information gleaned from the `collect_features` methods of the various shaper modules (`hb-ot-shape.cc`, `hb-ot-shape-complex-arabic.cc`, `hb-ot-shape-complex-arabic.cc`, etc.) 130 | 131 | [OTinfo on SS]: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=kr5s6gwpdy 132 | 133 | [Stylistic Sets]: http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx 134 | 135 | [Character Variants]: http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 136 | -------------------------------------------------------------------------------- /en-US/Optimization.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 500 5 | outlevel: 7 6 | category: Optimization 7 | title: Optimization 8 | --- 9 | 10 | This chapter will contain guidance on font optimization, such as hinting, compression, subsetting, and tuning (with TypeTuner). 11 | -------------------------------------------------------------------------------- /en-US/Production_and_Distribution.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 700 5 | outlevel: 9 6 | category: Production and Distribution 7 | title: Production and Distribution 8 | --- 9 | 10 | This chapter will contain guidance on source code management, release package structures, copyright, licensing, and building and packaging tools. 11 | -------------------------------------------------------------------------------- /en-US/Python-based_tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 950 5 | outlevel: 11.5 6 | category: Tools 7 | title: Python-based Tools 8 | --- 9 | 10 | In addition to the various font editors already listed, it is often useful to use scripts to modify fonts, either changing source files (eg UFO) or the actual fonts (eg .ttf). 11 | 12 | This could apply during the design process (for example, automatically creating composite glyphs) or during the build process (for example, automatically updating glyph names from design names to production names). 13 | 14 | Python has become the de facto standard for such scripting, and there are several python-based collections of fonts tools available. These include both pre-written scripts to perform specific tasks as well as python libraries which can be used when writing new scripts or when modifying existing scripts to meet specific needs. 15 | 16 | Those available include: 17 | 18 | [Fonttools](https://github.com/behdad/fonttools) - a library for manipulating fonts, written in Python. See the section below for more information. 19 | 20 | [Pysilfont](https://github.com/silnrsi/pysilfont) - a growing collection of tools for font development and building. See the section below for more information. 21 | 22 | [Fontforge](https://fontforge.github.io/en-US) - as well as being a font editor, FontForge comes with a python object library that can work with FontForge’s own format (.sfd), as well as with UFOs and ttf files. 23 | 24 | All of the above are open-source projects. 25 | 26 | Many font editors also support python scripting within their GUI. 27 | 28 | ## Fonttools 29 | 30 | Fonttools - a library for manipulating fonts, written in Python. The project includes the TTX tool, which can convert TrueType and OpenType fonts to and from an XML text format (also called TTX). It supports TrueType, OpenType, AFM and, to an extent, Type 1 and some Mac-specific formats. 31 | 32 | (More details to be added) 33 | 34 | ## Pysilfont 35 | 36 | This a growing collection of tools, initially written by members of SIL International’s Writing Systems Technology team (formerly the Non-Roman Script Initiative), with a broader set of contributors welcome. 37 | Included are a UFO object library, support for testing fonts and scripts for specific tasks. 38 | These tools are designed with a UFO-based workflow in mind, though many would also be useful in other workflows. 39 | 40 | Most scripts are written to use a standard framework (which is included in the libraries). This framework provides for help text, parameter handling, file opening and error reporting, thereby simplifying script writing and giving users a standard interface. 41 | 42 | ### UFO support in Pysilfont 43 | With some limitations, all UFO scripts in Pysilfont should work with UFO2 or UFO3 source files - and can convert from one format to the other. 44 | 45 | In addition all scripts will output in a normalized form, designed to work with source control systems. Most aspects of the normalization can be set by parameters, so projects are not forced to use Pysilfont’s default normalization. 46 | 47 | The simplest script is UFOconvert, which will convert between UFO 2 and UFO3 (if -v is used to specify the alternative version) or otherwise simply normalize the UFO by ‘converting’ to the existing version. Note that this same functionality is in most other scripts, so UFOconvert is normally only needed after fonts have been processed by external font tools. 48 | 49 | The following are known limitations that are due to be addressed in the future: 50 | 51 | * UFO 3 specific folders (data and images) are not copied 52 | * Converting from UFO 3 to UFO 2 only handles data that has a place in UFO 2, but does include converting UFO 3 anchors to the standard way of handling them in UFO 2 53 | 54 | There is further [documentation in GitHub](https://github.com/silnrsi/pysilfont/blob/master/docs/docs.md). 55 | -------------------------------------------------------------------------------- /en-US/Referencing_Guidelines.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 2 5 | outlevel: 1.1 6 | category: Introduction 7 | title: Referencing Guidelines 8 | --- 9 | 10 | Whenever reasonable and appropriate, this book should reference sources, and fully respect the copyright and licensing that applies to content, and the moral rights of the author. 11 | 12 | When the source is a web page, and no information is reproduced verbatim, a link to the web page is usually sufficient. The preferred style for linking is to insert links using reference names within the text, then complete references at the bottom of the page, as in: 13 | 14 | ~~~ 15 | According to the [OpenType Specification][OTSpec]... 16 | 17 | [OTSpec]: https://www.microsoft.com/typography/otspec/ 18 | ~~~ 19 | 20 | The second [] is optional, and the text itself can serve as the reference tag, as in: 21 | 22 | ~~~ 23 | According to the [OpenType] Specification... 24 | 25 | [OpenType]: https://www.microsoft.com/typography/otspec/ 26 | ~~~ 27 | 28 | A link to another page in this book looks like this (note the .html extension): 29 | 30 | ~~~ 31 | Read more about [OpenType](OpenType.html) 32 | ~~~ 33 | 34 | If the information is a direct quote, or the source is not a web page, then a formal reference is needed. The formal referencing style is a footnote-based system. If a reference is needed, insert a footnote reference `[^1]` into the text, then add the reference details at the bottom of the page, as in `[^1]: This is the reference.` The full reference should be formatted according to the [MHRA Style Guide][MHRA]. 35 | 36 | [MHRA]: http://www.mhra.org.uk/Publications/Books/StyleGuide/quickstyleguide.html 37 | -------------------------------------------------------------------------------- /en-US/Script_Specific.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 1000 5 | outlevel: 12 6 | category: Script-Specific 7 | title: Script Specific 8 | --- 9 | 10 | This chapter will contain guidance on developing fonts for specific scripts and writing systems. 11 | -------------------------------------------------------------------------------- /en-US/Shaping_and_Rendering.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 400 5 | outlevel: 6 6 | category: Shaping and Rendering 7 | title: Shaping and Rendering 8 | --- 9 | 10 | This chapter will contain guidance on OpenType, Graphite and related shaping engines. 11 | -------------------------------------------------------------------------------- /en-US/Source_Formats.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 10 5 | outlevel: 2 6 | category: Source Formats 7 | title: Source Formats 8 | --- 9 | 10 | Installable, end-user fonts come in a variety of formats: OpenType (containing either Postscript/CFF or TrueType glyph data), TrueType, PS Type 1, SVG, WOFF, and others. The current standard for most uses is [OpenType]. 11 | 12 | Although many font tools can use these end-user formats as source for derivative fonts, it is more common to store master font data in formats specifically designed for that purpose. These are usually associated with a particular application, such as FontLab (.vfb), FontForge (.sfd), and Glyphs (.glyphs). They contain data such as guidelines and multiple layers that may be useful in the design process but are not present in the end-user font. The formats vary in their levels of openness and documentation. 13 | 14 | **We recommend that new font projects avoid these proprietary formats and instead adopt an open, platform-neutral standard: [UFO (Unified Font Objects)][UFO].** UFO is a public, human-readable, text-based source format for storing font source data. It's now being used by many foundries, including Adobe, as their primary source format. [Read more about using UFO](UFO.html). 15 | 16 | This book will also cover relevant issues for other source formats. 17 | 18 | [OpenType]: https://en.wikipedia.org/wiki/OpenType 19 | [UFO]: http://unifiedfontobject.org/ 20 | -------------------------------------------------------------------------------- /en-US/Style_Guidelines.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 3 5 | outlevel: 1.2 6 | category: Introduction 7 | title: Style Guidelines 8 | --- 9 | 10 | The purpose of this book is to give helpful guidance to those who want to create fonts that work well in the intended environments. The recommendations may seem at times dogmatic, but that's the nature of a book of recommendations based on well-informed opinion. 11 | 12 | With each recommendation we've tried to provide some indication of whether it's subjective opinion or objective fact. Recommendations are generally in **bold**, and they fall into four loose types: 13 | 14 | - **"Developers may choose to"** - there is no single good option, and developers should consider various alternatives. 15 | - **"We recommend that"** - there seems to be one option that is best for most developers, that we ourselves have chosen and that we suggest that others follow. 16 | - **"Ascender and descender values should"** - there is clearly a best option and to do otherwise would be asking for problems. 17 | - **"Production glyph names must"** - if you don't do this then your font is unlikely to work properly. 18 | 19 | The style of writing is intended to be friendly but not too informal, from experienced font developers (the "We") to fellow developers and industry colleagues. The goal is to be helpful! 20 | -------------------------------------------------------------------------------- /en-US/Testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 600 5 | outlevel: 8 6 | category: Testing 7 | title: Testing 8 | --- 9 | 10 | This chapter will contain guidance on techniques and tools to test font inventory, design, metrics, rendering, and integrity. 11 | -------------------------------------------------------------------------------- /en-US/Tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 900 5 | outlevel: 11 6 | category: Tools 7 | title: Tools 8 | --- 9 | 10 | This chapter will contain guidance specific to certain design and production tools: FontLab, Glyphs, FontForge, AFDKO, Font Tools, pysilfont and others. 11 | -------------------------------------------------------------------------------- /en-US/UFO.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 30 5 | outlevel: 2.2 6 | category: Source Formats 7 | title: UFO 8 | --- 9 | 10 | UFO (Unified Font Object) is our recommended format for new font projects, and can offer advantages for existing projects. The [UFO specification] calls it a "cross-platform, cross-application, human readable, future proof format for storing font data". It is a text-based format that draws on XML and plist structures. A UFO is a folder with a .ufo extension that contains files for font-wide metadata and a 'glyphs' folder that contains each glyph as a separate .glif file. 11 | 12 | ## UFO versions, or 'flavors' 13 | 14 | UFO is actually not one single standard. There are multiple versions, or 'flavors' of UFO: 15 | 16 | - *UFO 1* - The original from 2004. Rarely used now. 17 | - *UFO 2* - The most common version (since 2009), with the broadest application support. Only slightly different from UFO 1. Still lacks some basic features, such as explicit glyph anchor elements. 18 | - *UFO 3* - A much-improved and expanded spec from 2012. 19 | 20 | **We currently recommend the UFO3 format.** 21 | 22 | There are various discussions going on concerning future UFO versions beyond 3, by both the original UFO authors and others, but there is no clear successor at this point. 23 | 24 | ## Application support 25 | 26 | Every major font design program supports UFO, but to varying degrees. 27 | 28 | - [Robofont] provides the most seamless and native support (requires Mac OS X 10.9 or later, though older versions are available for OS X 10.6 or later; commercial). 29 | - [Glyphs] can use UFO as a native format (requires Mac OS X 10.9 or later; commercial). 30 | - [FontForge] can import and export UFOs, including the UFO3 format (available for Windows, Mac, Linux; free). 31 | 32 | **We have used each of the above successfully in UFO development, and can recommend their use. The key to successful use is to store UFOs in a normalized format then re-normalize them after editing them.** 33 | 34 | Other possibilities include: 35 | 36 | - [Trufont] uses UFO3 as a native format. It doesn't have as many features as a commercial product (available for Windows, Mac, Linux; free). 37 | - [Fontlab 7][Fontlab] opens UFOs directly (available for Windows, Mac; commercial). 38 | 39 | In addition to these visual design programs there are other applications and utilities that support UFO: 40 | 41 | - [The Adobe Font Development Kit for OpenType][AFDKO] 42 | - [Smith] 43 | - [Tools from TypeSupply][TypeSupply] 44 | - [pysilfont] 45 | 46 | ## UFO Normalization 47 | 48 | A weakness of the UFO format is that there is no normalized form. The ordering and normal default settings for various elements can differ between applications. The unfortunate result is that opening a UFO with an app, changing one point coordinate, then saving, can result in hundreds of changes, even to files seemingly unrelated to the single coordinate change. This makes source code version control very difficult. 49 | 50 | The solution is to define a *normalized* form and always *normalize* the UFO prior to committing any changes to a source code repository (such as one on Github). This will ensure that the master version is always in normalized form, and any changes can be easily compared. 51 | 52 | The [pysilfont] project provides UFO normalization through the `psfnormalize` command. After installing [pysilfont], the workflow then becomes: 53 | 54 | - Check out (or clone) project from source code repository 55 | - Open UFO in editing application 56 | - Save changes 57 | - Run psfnormalize on the UFO with the command `psfnormalize filename.ufo` 58 | - Review changes via your version control client 59 | - Commit your changes 60 | 61 | The normalization scheme imposed by psfnormalize has been reviewed by many people and although it is not a standard, it is reasonably well accepted by those who care about UFO normalization. **We recommend that any UFO-based font projects stored in version control repositories always store the UFO in normalized form as set by psfnormalize.** 62 | 63 | ## Example projects 64 | 65 | Adobe has a number of public projects that are based on UFO. [Source Sans Pro] is a good example. 66 | 67 | SIL also has two example projects that we've used in testing UFO workflows: [Nokyung] and [Andika Mtihani]. 68 | 69 | ## Why use UFO? 70 | 71 | Our main motivation is that it is a well-supported, open, application-neutral format. We do not want to require that someone use a particular commercial program on a particular platform in order to access and use our font source. It also allows us to use common industry tools, and frees us from being locked into any one tool. It is handled well by version control systems, and has strong long-term readability. 72 | 73 | 74 | [UFO specification]: http://unifiedfontobject.org/ 75 | [pysilfont]: https://github.com/silnrsi/pysilfont 76 | [Robofont]: http://robofont.com/ 77 | [Glyphs]: https://glyphsapp.com/ 78 | [Trufont]: https://github.com/trufont/trufont 79 | [FontForge]: https://fontforge.github.io 80 | [FontLab]: https://www.fontlab.com/font-editor/fontlab/ 81 | [vfb2ufo]: http://blog.fontlab.com/font-utility/vfb2ufo/ 82 | [Source Sans Pro]: https://github.com/adobe-fonts/source-sans-pro 83 | [Nokyung]: https://github.com/silnrsi/font-nokyung 84 | [Andika Mtihani]: https://github.com/silnrsi/font-andika-mtihani 85 | [AFDKO]: https://github.com/adobe-type-tools/afdko 86 | [TypeSupply]: https://github.com/typesupply 87 | [Smith]: https://github.com/silnrsi/smith 88 | -------------------------------------------------------------------------------- /en-US/Unicode_Ranges.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 190 5 | outlevel: 3.6 6 | category: Font Metadata 7 | title: Unicode Ranges 8 | --- 9 | 10 | There are two means within an OpenType font to indicate which scripts and Unicode ranges a font supports: the OpenType _ulUnicodeRange_ bits in the 'OS/2' table and the newer 'meta' table. 11 | 12 | ## ulUnicodeRange 13 | 14 | The [OpenType OS/2 table specification][UnicodeRanges] lists the ranges defined by _ulUnicodeRange_ and which bits must be set to indicate support for that range. Most font editors provide a user interface that lists the ranges and allows you turn ranges on and off, so hacking bit fields is rarely necessary. 15 | 16 | According to [Peter Constable's presentation at TYPO Labs 2018][PCTYPOLabs18] the _ulUnicodeRange_ field is rarely used anymore by OSes to determine font script coverage. One major reason is that the field has run out of space, and no new ranges can be added. However there are older systems that still look at this info, so **the _ulUnicodeRange_ bits should be set if the font is intended to support any of the ranges defined in the [spec][UnicodeRanges]**. 17 | 18 | One special case: **If the font includes any supplemental plane characters, then the _Non-Plane 0_ bit (57) should be set. This is true whether or not the character is in a range that has a _ulUnicodeRange_ bit defined**. So in the case of Phoenician, which is in a supplemental plane (10900-1091F) and has a defined bit (58), both that bit and the _Non-Plane 0_ bit (57) should be set. 19 | 20 | 21 | ## 'meta' table 22 | 23 | Because of the above-mentioned limitations of the existing _ulUnicodeRange_ field, the [meta table][MetaTable] was added to the OpenType specification (starting with version 1.8 in 2016). **OpenType fonts should include the 'meta' table describing the languages and scripts for which the font was designed as well as the languages and scripts that the font is capable of supporting.** 24 | 25 | 26 | [UnicodeRanges]: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur 27 | [MetaTable]: https://docs.microsoft.com/en-us/typography/opentype/spec/meta 28 | [PCTYPOLabs18]: https://www.youtube.com/watch?v=eVWWAvhzrq8 29 | [Miao]: https://www.unicode.org/charts/PDF/U16F00.pdf 30 | -------------------------------------------------------------------------------- /en-US/User_Interface_Strings.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 490 5 | outlevel: 6.5 6 | category: Shaping and Rendering 7 | title: User Interface (UI) Strings 8 | --- 9 | 10 | ## Summary of Recommendations 11 | **We recommend that fonts include UI strings for the names of all `ssxx` and `cvxx` OpenType features. For `cvxx` features, fonts should also include UI strings for the non-default feature values.** 12 | 13 | **For fonts that include both Graphite and OpenType logic, we recommend that both technologies use the same UI strings for corresponding features and values (except that OpenType character variant must not include UI strings for the default value).** 14 | 15 | ## Update history 16 | 2021-05-06 Per OpenType specification, character variant features should not include a `ParamUILabelNameID` for the default (0 or off) value. 17 | 18 | ## What are UI strings? 19 | 20 | Generically speaking, font features can be considered in two broad categories: 21 | * features required by a specific script, such as Arabic initial, medial, and final forms. 22 | * optional behavior that the user can enable or disable, such as small caps or lining numerals. 23 | 24 | The second category (optional behavior) further subdivides into: 25 | * features whose behavior is defined by standards such as the OpenType specification, for example the *Discretionary Ligatures* (`dlig`) and *Petite Capitals From Capitals* (`c2pc`) features. 26 | * features whose behavior is defined entirely by the logic within the font. For Graphite this would be all features; for OpenType this includes only the *Stylistic Set* (`ssxx`) and *Character Variant* (`cvxx`) features. 27 | 28 | For an application to provide a user interface for these optional behaviors, it needs human-readable (and preferably localizable) text giving the name of each feature and, where feasible, the names of the various values that feature can take on. We call this human-readable text data _User Interface Strings_, or **UI strings** for short. 29 | 30 | For behaviors defined by a standard such as OpenType, suitable text for UI strings can easily obtained from the standard itself. 31 | 32 | But what to do for that last category — features whose behavior is defined entirely by logic within the font? The answer is that the _font itself must provide the text_. Font vendors should, therefore, ensure that their fonts contain all needed UI strings. 33 | 34 | ### Coordinating OpenType and Graphite 35 | 36 | For fonts that contain both Graphite and OpenType logic, it is usually the case that many of the features have the same purpose and result in both technologies. For such features it is best practice if the human readable strings are the same for corresponding Graphite and OpenType features. So for example, don’t call the feature *Literacy Alternates* in Graphite and *Literacy feature* in OpenType. 37 | 38 | Not only does using the same UI strings make sense from the point of view of the user experience, it can also make the font smaller since, with some toolchains, one copy of each UI string can be shared by both Graphite and OpenType. 39 | 40 | ## Graphite 41 | Adding UI strings for Graphite fonts is easy since the Graphite Description Language (GDL) used to create Graphite fonts includes the UI strings within the Feature Table, for example: 42 | ``` 43 | eng { 44 | id = "Engs"; 45 | name.1033 = string("Uppercase Eng alternates"); 46 | default = descender; 47 | settings { 48 | descender { 49 | value = 0; 50 | name.1033 = string("Large eng with descender"); 51 | } 52 | base { 53 | value = 1; 54 | name.1033 = string("Large eng on baseline"); 55 | } 56 | short { 57 | value = 3; 58 | name.1033 = string("Large eng with short stem"); 59 | } 60 | capital { 61 | value = 2; 62 | name.1033 = string("Capital N with tail"); 63 | } 64 | } 65 | } 66 | ``` 67 | 68 | Notice that there is a name for the feature itself, and then a name for each of the possible values for that feature, including the default value. 69 | 70 | Graphite UI strings can be localized by including translations for desired languages. 71 | 72 | For further information see the description of the _Feature Table_ in the [GDL manual][GDL]. 73 | 74 | ## OpenType 75 | 76 | For OpenType, the two features that need UI strings are the [Stylistic Sets][SSXX] (`ss01`, `sso2`, ... `ss20`) and [Character Variants][CVXX] (`cv01`, `cv02`, ... `cv99`). 77 | 78 | ### Differences between `ssnn` and `cvnn` features 79 | 80 | It is important to keep in mind fundamental differences between Stylist Sets and Character Variants: 81 | 82 | * Stylistic Sets are, by definition, binary features — a given Stylistic Set is either on or off. 83 | * Character Variants can be binary, but they can also be defined with more than two possible values. 84 | 85 | Similarly, the UI strings that can be provided for Stylist Sets are different than that for Character Variants: 86 | 87 | * Stylist Sets: the only UI string that can be provided for ssxx features is: 88 | * The name of the feature; there is no way to provide names for the values. 89 | * Character Variants: The UI strings that can be provided for cvnn features include: 90 | * The name of the feature itself, e.g., *Rams horn alternates* 91 | * The names of the non-default values, e.g. *Large bowl* and *Small gamma*. 92 | 93 | One implication of the above is that the UI string for a Stylistic Set should have an obvious yes/no meaning. For example, *Barred bowl forms* and *Vietnamese-style diacritics* are good names — the user can predict what turning on this feature is going to do — whereas *Alternate noon* might not be such a good name. 94 | 95 | While feature name and value name strings are the minimum we should be providing, Character Variant features can provide additional data that may be useful within a UI: 96 | 97 | * *Tool tip*: a string that an application can use as a tool tip in the UI 98 | * *Sample Text*: a string that illustrates the effect of the feature 99 | * *USV list*: not a string, but rather a list of Unicode Scalar Value of the characters for which this feature provides glyph variants. (NB: This is not an array of strings, therefore features which affect character sequences cannot be represented by this entry). 100 | 101 | ## How to add UI Strings to OpenType 102 | 103 | For OpenType, we can define the UI strings in two ways: 104 | 1. via the FEA source files 105 | 2. using a separate utility program from FontUtils 106 | 107 | Method 1, defining them directly in FEA, is the most convenient. However, for fonts containing both Graphite and OpenType, neither the Graphite compiler nor existing FEA compilers are clever enough to re-use UI strings added to the font by the other, which means that such fonts will have two sets of UI Strings, slightly bloating the font size. Using Method 2 avoids this. 108 | 109 | ### Method 1: Defining OpenType UI Strings in FEA 110 | 111 | The Adobe FDK documentation defines the syntax and provides examples for both [Descriptive names for Stylistic Set ('ss01 - ss20') features][FDKSSXX] and [UI Label names for Character Variant 'cv01 - cv99') features][FDKCVXX]. 112 | 113 | Simply add the desired parameter blocks (`featureNames` for stylistic sets; `cvParameters` for character variants) to your feature code and compile the FEA into the font, for example: 114 | 115 | ``` 116 | feature ss02 { 117 | featureNames { name 3 1 0x409 "UI String for SS02" ; }; 118 | # --- rules for ss02 feature: 119 | # ... 120 | } ss02 ; 121 | 122 | feature cv01 { 123 | cvParameters { 124 | FeatUILabelNameID { name 3 1 0x0409 "Name of the cv01 feature" ; }; 125 | ParamUILabelNameID { name 3 1 0x0409 "First named param for cv01" ; }; 126 | ParamUILabelNameID { name 3 1 0x0409 "Second named param for cv01" ; }; 127 | } ; 128 | # --- rules for cv01 feature: 129 | # ... 130 | } cv01 ; 131 | ``` 132 | Here is the same example with French localization added: 133 | ``` 134 | feature ss02 { 135 | featureNames { 136 | name 3 1 0x0409 "UI String for SS02" ; 137 | name 3 1 0x040C "nom de ss02" ; 138 | }; 139 | # --- rules for ss02 feature: 140 | # ... 141 | } ss02 ; 142 | 143 | feature cv01 { 144 | cvParameters { 145 | FeatUILabelNameID { 146 | name 3 1 0x0409 "Name of the cv01 feature" ; 147 | name 3 1 0x040C "Nom de la fonction cv01" ; 148 | }; 149 | ParamUILabelNameID { 150 | name 3 1 0x0409 "First named param for cv01" ; 151 | name 3 1 0x040C "Premier paramètre nommé pour cv01" ; 152 | }; 153 | ParamUILabelNameID { 154 | name 3 1 0x0409 "Second named param for cv01" ; 155 | name 3 1 0x040C "Deuxième paramètre nommé pour cv01" ; 156 | }; 157 | } ; 158 | # --- rules for cv01 feature: 159 | # ... 160 | } cv01 ; 161 | ``` 162 | 163 | 164 | ### Method 2: Defining OpenType UI Strings using `ttffeatparms` 165 | For fonts containing both OpenType and Graphite logic, you may want to use the `ttffeatparms` utility to add the OpenType UI strings in order to reduce the font size. This utility is part of SIL's [FontUtils][FONTUTILS] library. 166 | 167 | To get help with this utility, at the command line type: 168 | 169 | ``` 170 | ttffeatparms -h 171 | ``` 172 | OpenType UI strings are coded in an xml control file. Here are the same examples as above: 173 | ``` 174 | 175 | 176 | 177 | UI string for SS02 178 | 179 | 180 | Jha alternates 181 | First named param for cv01 182 | Second named param for cv01 183 | 184 | 185 | ``` 186 | and with French localization added: 187 | ``` 188 | 189 | 190 | 191 | 192 | UI string for SS02 193 | nom de ss02 194 | 195 | 196 | 197 | Jha alternates 198 | First named param for cv01 199 | Second named param for cv01 200 | Premier paramètre nommé pour cv01 201 | Deuxième paramètre nommé pour cv01 202 | 203 | 204 | ``` 205 | 206 | The required build steps are as follows: 207 | 208 | * Compile OpenType and Graphite features into the font before adding OpenType UI strings 209 | * Add OpenType UI strings into the font. The basic command to do this looks as follows: 210 | 211 | ``` 212 | tffeatparms -c control.xml input.ttf output.ttf 213 | ``` 214 | 215 | ## Application support 216 | 217 | Support for UI strings is a chicken-or-egg problem: not many commercial fonts have the UI strings, so not many application vendors are motivated to add support, and since not many applications have support, few font vendors are motivated to add the strings. In spite of this, most of the recent SIL fonts include UI strings. 218 | 219 | Because UI strings have always been part of Graphite, some Graphite-enabled apps populate their UI with Graphite features. Here is an example screenshot from SIL FieldWorks suite showing that UI: 220 | 221 | ![Fieldworks font feature UI](images/UI-strings-in-use.png) 222 | 223 | LibreOffice now uses UI strings for Graphite-enabled fonts, but not for OpenType. 224 | 225 | Some of Adobe's Creative Cloud suite (such as InDesign) support UI strings for Stylistic Sets but not Character Variants. 226 | 227 | SIL's ptxprint supports both Graphite and OpenType UI strings. 228 | 229 | Please let us know if you become aware of other applications that support UI strings so we can include them here. 230 | 231 | [GDL]:https://github.com/silnrsi/grcompiler/blob/master/doc/GDL.pdf 232 | [CVXX]:https://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 233 | [SSXX]:https://www.microsoft.com/typography/otspec/features_pt.htm#ssxx 234 | [FDKSSXX]:https://github.com/adobe-type-tools/afdko/blob/develop/docs/OpenTypeFeatureFileSpecification.md#8c-descriptive-names-for-stylistic-set-features-ss01---ss20 235 | [FDKCVXX]:https://github.com/adobe-type-tools/afdko/blob/develop/docs/OpenTypeFeatureFileSpecification.md#8d-ui-label-names-for-character-variant-features-cv01---cv99 236 | [FTCVXXBUG]:https://github.com/fonttools/fonttools/issues/860 237 | [FONTUTILS]:http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=fontutils 238 | -------------------------------------------------------------------------------- /en-US/Versioning.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: bookpage 4 | weight: 120 5 | outlevel: 3.2 6 | category: Font Metadata 7 | title: Versioning 8 | --- 9 | 10 | A version number in a font is useful in (at least) two situations: 11 | 12 | - Operating systems can know, based on the version number, when to update a package containing a font. 13 | - If users are having difficulty with a font you have created, they can let you know what version of the font they have, and then you can figure out if the installed version of the font is outdated, or has known problems. 14 | 15 | **We recommend using a version number in the form of x.yyy (that is, three places past the decimal point).** For example, use a version number such as `1.500`, not `1.5`. This will help the version number to be correctly understood in a variety of environments. 16 | 17 | ## What to use for a version number 18 | 19 | You _could_ use a version number based on [semantic versioning][Semver] which has a form of `MAJOR.MINOR.PATCH`. However, it is not straightforward how the three parts of semantic versioning map to the two parts of a font version. In this [discussion][Twardoch] Adam Twardoch states he personally uses a font version in the form of _M.mpp_ where 20 | 21 | - _M_ is the major version 22 | - _m_ is the minor version 23 | - _pp_ is the patch version 24 | 25 | to connect these two concepts. He does not, however, specify what these values might represent in a project. We've chosen to use a change in _M_ (major) and _m_ (minor) to reflect significant changes in the functionality of the font and use _pp_ (patch) to indicate both small maintenance fixes (as in 6.301) and work leading up to a major/minor release (such as 6.381, leading up towards 6.400) 26 | 27 | Google recommends that the major version value be greater than zero for any fonts that are widely distributed. 28 | 29 | ## Location of the version number and version string 30 | 31 | Version information in stored in [two locations within a font][OTSpec]: 32 | 33 | - `head` table - a 16.16 decimal number encoded in the `fontRevision` field. 34 | - `name` table - a longer string that can also contain additional information 35 | 36 | **We recommend that the `head` and `name` tables be consistent in the version information represented therein.** 37 | 38 | The `head.fontRevision` number may be the only data that operating systems and installation routines use to compare multiple font versions and choose the most recent, so **it is important that if two fonts have differences they should have different `head.fontRevision` values**. 39 | 40 | The `name` table version string is text that can contain numbers, letters, and punctuation. **We recommend that this string have three parts, separated by spaces, in the form** `Version M.mpp extrainfo` where 41 | 42 | - `Version` is just the word "Version" 43 | - `M.mpp` is the major.minorpatch version number 44 | - `extrainfo` is any additional text that may be useful to the user 45 | 46 | This `extrainfo` may be a build number, a test version indicator such as 'beta3', a date or time stamp, or any other brief bit of information that can help the user know further information about this particular version. **We recommend that developers do not use this additional info as the only indicator that two fonts are different. Only the _M.mpp_ version number should be used to differentiate between versions.** Some operating systems show the `name` table version to users, but may not look at it when comparing font version numbers. 47 | 48 | ## Calculating `head.fontRevision` 49 | 50 | OpenType does not specify the content of the `head.fontRevision` field, but only that it is a fixed-point number stored with 16 bits before the decimal and 16 bits after. 51 | Font vendors have been inconsistent in how they encode a font version in such a numeric field. For example is version 1.1 stored as 0x00010001 or 0x00011999 or even 0x00011000 ? 52 | 53 | **We recommend the following calculation: Treating the 32 bit `fontRevision` as two 16 bit integers, calculate them as follows:** 54 | - first 16 bits = _M_ 55 | - second 16 bits = _int( .mpp * 65536 )_ 56 | 57 | 58 | ## Examples of version information: 59 | 60 | | M | mpp | `head.fontRevision` | `name` version string | 61 | | --- | --- | --- | 62 | | 1 | 290 | 0x00014A3d | Version 1.290 alpha1 | 63 | | 1 | 295 | 0x00014B85 | Version 1.295 beta1 | 64 | | 1 | 296 | 0x00014BC6 | Version 1.296 beta2 | 65 | | 1 | 300 | 0x00014CCC | Version 1.300 | 66 | | 2 | 101 | 0x000219DB | Version 2.101 build 693 | 67 | | 3 | 560 | 0x00038F5C | Version 2.560 20170329-1 | 68 | | 6 | 101 | 0x000619DB | Version 6.101 FW bundle | 69 | 70 | ## Development versions 71 | 72 | **We recommend that development versions and releases should not share the same version numbers**. No two fonts should have the same version number but two different version strings. For example, there should not be two fonts that have version strings `Version 1.234` and `Version 1.234 beta`. 73 | 74 | Development versions may have indicators such as _alpha_ or _beta_ in the version string, but that should not be used as the only indicator that two fonts are different. For example, `Version 5.678 beta3` means "This font is version 5.678, and by the way, we're using this version as a third beta test.". It does not mean "We're intending to someday release version 5.678, and this is the third beta leading up to that release." 75 | 76 | ## How to set the version number and version string 77 | 78 | In UFO sources the information is held in three keys in `fontinfo.plist`. FontLab (in the _Font Info_ dialog) and FontForge (go to _Element > Font Info > PS Names_) have fields for both tables. 79 | 80 | By default, Glyphs only provides a way to set the Version major and minor numbers (in the _Font Info > Font_ panel). However there is a way to set the version string in that panel: 81 | 82 | - Click on the + sign next to _Custom Parameter_ 83 | - Under _Property_ choose _versionString_ 84 | - Type the version string into the _Value_ field 85 | 86 | Here is a summary of where to set version numbers and version strings: 87 | 88 | | | FontLab | Glyphs | FontForge | UFOv2 | 89 | | --- | --- | --- | --- | --- | 90 | | `head` table | Complete Version record | Version | sfnt Version | versionMajor, versionMinor | 91 | | `name` table | TrueType Version record | versionString | Version | openTypeNameVersion | 92 | 93 | 94 | [Semver]: http://semver.org/ 95 | 96 | [Twardoch]: https://groups.google.com/d/msg/googlefonts-discuss/w6-i0Opikbc/nlFPEibsCQ8J 97 | 98 | [OTSpec]: https://www.microsoft.com/en-us/Typography/OpenTypeSpecification.aspx 99 | -------------------------------------------------------------------------------- /en-US/images/EncodedCRinScribus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/EncodedCRinScribus.png -------------------------------------------------------------------------------- /en-US/images/EncodingBelow0020_FLFontInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/EncodingBelow0020_FLFontInfo.png -------------------------------------------------------------------------------- /en-US/images/EncodingBelow0020_FLTTGen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/EncodingBelow0020_FLTTGen.png -------------------------------------------------------------------------------- /en-US/images/FireFox-font-inspector.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/FireFox-font-inspector.jpg -------------------------------------------------------------------------------- /en-US/images/Firefox-OTSanitizer-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/Firefox-OTSanitizer-error.png -------------------------------------------------------------------------------- /en-US/images/UI-strings-in-use.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silnrsi/FDBP/352cd7c7bdac490164cd818ae5dda50005a5b5c1/en-US/images/UI-strings-in-use.png -------------------------------------------------------------------------------- /en-US/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | published: true 3 | layout: homepage 4 | weight: 0 5 | title: Font Development Best Practices 6 | --- 7 | 8 |
    9 | {% assign pageList = site.pages | sort: 'weight' %} 10 | {% for p in pageList %} 11 | {% if p.path contains 'en-US' and p.title != page.title %} 12 |
  1. 13 | 14 | {{ p.outlevel }} 15 | 16 | 17 | {{ p.title }} 18 | 19 |
  2. 20 | {% endif %} 21 | {% endfor %} 22 |
23 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | {{site.title}} 13 | 14 | 15 | 16 |

{{site.subtitle}}

17 | 18 | --------------------------------------------------------------------------------