{"action":"created","issue":{"url":"https://api.github.com/repos/jwilm/alacritty/issues/957","repository_url":"https://api.github.com/repos/jwilm/alacritty","labels_url":"https://api.github.com/repos/jwilm/alacritty/issues/957/labels{/name}","comments_url":"https://api.github.com/repos/jwilm/alacritty/issues/957/comments","events_url":"https://api.github.com/repos/jwilm/alacritty/issues/957/events","html_url":"https://github.com/jwilm/alacritty/issues/957","id":284277809,"number":957,"title":"RFC: Font Configuration","user":{"login":"jwilm","id":4285147,"avatar_url":"https://avatars2.githubusercontent.com/u/4285147?v=4","gravatar_id":"","url":"https://api.github.com/users/jwilm","html_url":"https://github.com/jwilm","followers_url":"https://api.github.com/users/jwilm/followers","following_url":"https://api.github.com/users/jwilm/following{/other_user}","gists_url":"https://api.github.com/users/jwilm/gists{/gist_id}","starred_url":"https://api.github.com/users/jwilm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwilm/subscriptions","organizations_url":"https://api.github.com/users/jwilm/orgs","repos_url":"https://api.github.com/users/jwilm/repos","events_url":"https://api.github.com/users/jwilm/events{/privacy}","received_events_url":"https://api.github.com/users/jwilm/received_events","type":"User","site_admin":false},"labels":[{"id":786086088,"url":"https://api.github.com/repos/jwilm/alacritty/labels/rfc","name":"rfc","color":"b8f754","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"2017-12-23T01:31:00Z","updated_at":"2018-02-10T01:10:58Z","closed_at":null,"author_association":"OWNER","body":"I've been thinking about many of the current limitations of how Alacritty's font configuration and possible solutions. This is an RFC for a fully capable font configuration section.\r\n\r\nFeedback is very much invited! I may have missed out on some important requirement, and I may have missed out on an obviously better solution. Please feel welcome to comment and suggest improvements or add to the list of use cases this should handle.\r\n\r\n## Font Configuration, today\r\n\r\nCurrent font configuration is achieved through the following block of YAML. Most of the comments are preserved for clarity.\r\n\r\n```yaml\r\nfont:\r\n  # The normal (roman) font face to use.\r\n  normal:\r\n    family: monospace\r\n    style: Regular\r\n\r\n  # The bold font face\r\n  bold:\r\n    family: monospace\r\n    style: Bold\r\n\r\n  # The italic font face\r\n  italic:\r\n    family: monospace\r\n    style: Italic\r\n\r\n  # Point size of the font\r\n  size: 11.0\r\n\r\n  # Offset is the extra space around each character. offset.y can be thought of\r\n  # as modifying the linespacing, and offset.x as modifying the letter spacing.\r\n  offset:\r\n    x: 0.0\r\n    y: 0.0\r\n\r\n  # Glyph offset determines the locations of the glyphs within their cells with\r\n  # the default being at the bottom. Increase the x offset to move the glyph to\r\n  # the right, increase the y offset to move the glyph upward.\r\n  glyph_offset:\r\n    x: 0.0\r\n    y: 0.0\r\n\r\n  # OS X only: use thin stroke font rendering. Thin strokes are suitable\r\n  # for retina displays, but for non-retina you probably want this set to\r\n  # false.\r\n  use_thin_strokes: true\r\n```\r\n\r\n### Limitations in the current system\r\n\r\n- Size is set globally. This is a problem because it may be desirable to have different sizes for latin text vs CJK or others.\r\n- Glyph offsets are set globally. Setting this per face would be beneficial for things like powerline which often has alignment problems.\r\n- There's no way to specify fallbacks. It may be desirable for users to provide their own fallback list.\r\n- Several properties are not configurable because we don't yet offer them. These are things like subpixel AA, lcd filter, and antialiasing. In theory, these can all be configured per-font, so it might make sense to include them when thinking about a solution for size.\r\n\r\n### Other issues\r\n\r\nThe `font.offset` block is confusingly named. Its name sounds like it's doing what the `glyph_offset` config does, but in reality it is changing cell dimensions.\r\n\r\nA better naming system for `font.offset` might be `font.spacing` and give it properties of `line` and `letter` to match convention.\r\n\r\n### Considerations for next system\r\n\r\nIn addition to solving the limitations outlined above, the next system should interact well with system level font settings such as `fontconfig` on Linux platforms.\r\n\r\n## Proposal\r\n\r\n### Common Font Options\r\n\r\nThree out of the four issues are about providing settings per face. To keep things simple, this suggests there should be a common structure for setting size, glyph offsets, antialiasing, and etc. per font. Such a blob might look like this:\r\n\r\n```yaml\r\noptions:\r\n  size: 12\r\n  thin_strokes: true\r\n  antialias: lcd # Can have values like lcd, lcdv, gray, and none\r\n  hinting: true\r\n  style: Regular\r\n  offset:\r\n    x: 0\r\n    y: 0\r\n```\r\n\r\nThis blob (henceforth referred to as _font options_) can exist in multiple places, such as on `normal`, `italic`, `bold`, and globally under `font`.\r\n\r\nTo keep subsequent examples succint, this shorthand will be used for _font options_:\r\n\r\n```yaml\r\noptions: { size: 12 }\r\n```\r\n\r\nKnow that whenever this line is specified it is simply a shorthand, and all of the other properties are valid in the context despite not being present in the shorthand.\r\n\r\nNo properties of _font options_ are required.\r\n\r\n#### Cascading and priority\r\n\r\n\r\nGlobal _font options_ will be the default for each of `normal`, `italic`, and `bold`; they will also be used for non-configured fallback fonts.\r\n\r\nBeyond the global cascade, this proposal specifies a priority order for applying settings. In the following list, items at the top are prioritized above items at the bottom.\r\n\r\n1. _font options_ attached to an individual font\r\n2. Gloabl _font options_\r\n3. System font configuration such as that from the _fontconfig_ library\r\n4. Alacritty provided defaults\r\n\r\nCascading will work at the property level. That is, a global _font options_ of `options: { size: 12 }` will become the default size for subsequent priority levels, but it won't provide any other defaults since they were not specified.\r\n\r\n### Specifying fallbacks\r\n\r\nTo support specifying fallbacks, each of `normal`, `italic`, and `bold` will now accept a list of _font specifications_. Currently, that looks like:\r\n\r\n```yaml\r\nnormal:\r\n  family: monospace\r\n  style: Italic\r\n```\r\n\r\nwhere the properties `family` and `style` are part of the specification. Note that, under the current propsal, `style` is actually moved into _font options_.\r\n\r\nWith the addition of _font options_, a specification looks like\r\n\r\n```yaml\r\nnormal:\r\n  family: monospace\r\n  options: { size: 12 }\r\n```\r\n\r\nAnd with the addition of fallback specifications, each section of font configuration will now look like\r\n\r\n```yaml\r\nnormal:\r\n  - family: Source Code Pro\r\n  - family: Powerline\r\n    options: { size: 12 }\r\n```\r\n\r\n### Complete Example\r\n\r\nTaking all of this into account, the new config format will be\r\n\r\n```yaml\r\nfont:\r\n  # These options tweak how each font is rasterized. Each section\r\n  # Under font that accepts an `options` parameter can specify\r\n  # any of the configuration listed here.\r\n  #\r\n  # Available options:\r\n  # `size` - The font size in points\r\n  # `thin_stokes` - macOS setting controlling stem thickness\r\n  # `antialias` - antialiasing strategy, can be `lcd`, `gray`, or `mono`.\r\n  # `hinting` - how glyphs are aligned to the pixel grid; can be\r\n  #          `lcd`, `light`, or `none`.\r\n  # `style` - style to use for a font - `Regular`, `Italic`, or `Bold`\r\n  # `offset.x` - horizontal offset of glyphs within the cell\r\n  # `offset.y` - vertical offset of glyphs within the cell\r\n  options:\r\n    size: 11\r\n\r\n  # The normal (roman) font face to use.\r\n  normal:\r\n    - family: monospace\r\n      # style: Regular will be the default in this section\r\n      options: { style: Regular }\r\n    - family: Powerline Symbols\r\n      options: { offset: { x: 0, y: -1.0 } }\r\n\r\n  # The bold font face\r\n  bold:\r\n    - family: monospace\r\n      # style: Bold will be the default in this section\r\n      options: { style: Bold }\r\n\r\n  # The italic font face\r\n  italic:\r\n    family: monospace\r\n    - family: monospace\r\n      # style: Bold will be the default in this section\r\n      options: { style: Italic }\r\n\r\n  # Spacing is the extra space around each character.\r\n  #\r\n  # `spacing.line` is a delta to the height of cells\r\n  # `spacing.letter` is a delta to the width of cells\r\n  spacing:\r\n    line: 0.0\r\n    letter: 0.0\r\n```\r\n\r\n## Alternatives\r\n\r\nThis config strategy is quite verbose, but it does allow full customization of font settings. Another much more succint version of this might be stealing `fontconfig`'s pattern format; for example:\r\n\r\n```\r\nxft:DejaVu Sans Mono:size=10,xft:PowerlineSymbols:pixelsize=12,\r\n```\r\n\r\nThis has the format of `<family>[:<property>=<value>]*`. Although this would keep the config file much more succint, the contents are quite terse.\r\n\r\n## Outstanding Questions\r\n\r\nHow do we communicate this in the (future) documentation or in config file comments, presently? The proposed format here is significantly more complex than the previous format."},"comment":{"url":"https://api.github.com/repos/jwilm/alacritty/issues/comments/364612607","html_url":"https://github.com/jwilm/alacritty/issues/957#issuecomment-364612607","issue_url":"https://api.github.com/repos/jwilm/alacritty/issues/957","id":364612607,"user":{"login":"chrisduerr","id":8886672,"avatar_url":"https://avatars3.githubusercontent.com/u/8886672?v=4","gravatar_id":"","url":"https://api.github.com/users/chrisduerr","html_url":"https://github.com/chrisduerr","followers_url":"https://api.github.com/users/chrisduerr/followers","following_url":"https://api.github.com/users/chrisduerr/following{/other_user}","gists_url":"https://api.github.com/users/chrisduerr/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisduerr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisduerr/subscriptions","organizations_url":"https://api.github.com/users/chrisduerr/orgs","repos_url":"https://api.github.com/users/chrisduerr/repos","events_url":"https://api.github.com/users/chrisduerr/events{/privacy}","received_events_url":"https://api.github.com/users/chrisduerr/received_events","type":"User","site_admin":false},"created_at":"2018-02-10T01:10:58Z","updated_at":"2018-02-10T01:10:58Z","author_association":"COLLABORATOR","body":"While playing around with this I've run into another problem.\r\n\r\nAssuming the character which is looked up is not present in any of the fonts, the character still has to be rendered. Usually you'd go about this by selecting the character from the primary font, which will then display the \"missing glyph\" glyph.\r\n\r\nIf we use a configuration without ranges, it would be fair to assume the first font is always the primary font, however with a range the first font might override the actual primary font for a few glyphs.\r\n\r\nNow we could just use the missing glyph glyph from `Menlo`/`monospace`, however that would probably lead to odd results.\r\n\r\nAnother alternative is to store the first glyph lookup, so we would walk the fonts once and remember the first font where the range contains the glyph. Then when we're through all fonts and the glyph has not been found, we'd fall back to the one we memorized. This is probably the best strategy, however it might lead to different \"missing glyph\" symbols which could look odd.\r\n\r\nAlternatively we could ask the user to specify which font will be the primary font. This would be a flag just for falling back to a specific font once no glyph has been found.\r\n\r\nThen we could also just always use the first/last font. This will always be consisnent, however the chance to get it wrong is pretty high when ranges are used."}}
{"actor":{"display_login":"chrisduerr"}}