profile
viewpoint

harfbuzz/harfbuzz 1681

HarfBuzz text shaping engine

googlefonts/Inconsolata 450

Development repo of Inconsolata Fonts by Raph Levien

linebender/runebender 390

A font editor written in Rust.

raphlinus/crochet 267

Explorations in reactive UI patterns

Connicpu/direct2d-rs 26

`direct2d` is trying to be a safe, thin abstraction for Direct2D to let you easily write 2D drawing on Windows

linebender/rbf-interp 10

An implementation of Radial Basis Function multidimensional interpolation

raphlinus/aturon.github.io 1

turon's web site

raphlinus/coremidi 1

CoreMIDI library for Rust

pull request commentlinebender/runebender

Add basic sidebearing editing

So far just playing with it, not looking at the code. It's not behaving quite as I expected, as applying a delta to both LSB and RSB should have that delta applied to the advance width of the glyph as well. Other than that it seems like a nice feature.

cmyr

comment created time in 6 hours

PullRequestReviewEvent

pull request commentlinebender/runebender

Selection transform

Taking a pass through the code, it seems pretty reasonable, but when I try it, there's no transforming. It seems to just lose selection of the bbox handle when dragging. Am I missing something?

cmyr

comment created time in 6 hours

issue commentraphlinus/pulldown-cmark

question: Are `Start` and `End` tags guarunteed to be ordered correctly?

Yes, it is a tree. It's remotely possible there is a bug because this is only enforced by convention, but internally the parse state is represented with stacks so each push should have a corresponding pop.

Thanks for the kind words, hope this helps.

kneasle

comment created time in 9 hours

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentlinebender/runebender

Add Selection struct and selection.rs

Oops, sorry I didn't review. Email notifications are porous, feel free to ping me on Zulip when there's something waiting for review.

cmyr

comment created time in a day

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentlinebender/druid

Reduce flashing on window creation

Any reason not to merge this now? There are no conflicts, and I've verified again that it works on my machine.

rhzk

comment created time in a day

PullRequestReviewEvent

push eventraphlinus/raphlinus.github.io

Raph Levien

commit sha 93abaa822d3c0dfb57a13c492a836b302761e456

Add draft of text layout post

view details

Raph Levien

commit sha 08ad5746b3e45f7b25d83cf5fec1db1895484100

Edits and images

view details

Raph Levien

commit sha 7489fb2aa8889ff1bfb2abef0ec53aba0e5aeacf

Fix link

view details

Raph Levien

commit sha a01444469b353e3728bea9c1d98cb5de6e575991

Add para on writing modes

view details

Raph Levien

commit sha 7588e62876a668180f1b0a492f1faa623b18eb7d

Merge pull request #36 from raphlinus/text_layout Add draft of text layout post

view details

push time in 2 days

push eventraphlinus/raphlinus.github.io

Raph Levien

commit sha a01444469b353e3728bea9c1d98cb5de6e575991

Add para on writing modes

view details

push time in 2 days

push eventraphlinus/raphlinus.github.io

Raph Levien

commit sha 7489fb2aa8889ff1bfb2abef0ec53aba0e5aeacf

Fix link

view details

push time in 2 days

Pull request review commentraphlinus/raphlinus.github.io

Add draft of text layout post

+---+layout: post+title:  "Text layout is a loose hierarchy of segmentation"+date:   2020-10-25 15:00:42 -0700+categories: [text]+---+I love text layout, and have been working with it in one form or other for over 35 years. Yet, knowledge about it is quite arcane. I don't believe there is a single place where it's all properly written down. I have some explanation for that: while basic text layout is very important for UI, games, and other contexts, a lot of the "professional" needs around text layout are embedded in *much* more complicated systems such as Microsoft Word or a modern Web browser.++A complete account of text layout would be at least a small book. Since there's no way I can write that now, this blog post is a small step towards that - in particular, an attempt to describe the "big picture," using the conceptual framework of a "loose hierarchy." Essentially, a text layout engine breaks the input into finer and finer grains, then reassembles the results into a text layout object suitable for drawing, measurement, and hit testing.++The main hierarchy is concerned with laying out a single strip of text. Line breaking is also important, but has a separate, parallel hierarchy.++## The main text layout hierarchy++The hierarchy is:+- (a) paragraph segmentation+- (b) rich text style+- (c) BiDi+- (d) itemization (coverage by font)+- (e) script+- (f) shaping (cluster)

I got rid of the list, it was only a stand-in for the diagram.

raphlinus

comment created time in 2 days

PullRequestReviewEvent

Pull request review commentraphlinus/raphlinus.github.io

Add draft of text layout post

+---+layout: post+title:  "Text layout is a loose hierarchy of segmentation"+date:   2020-10-25 15:00:42 -0700+categories: [text]+---+I love text layout, and have been working with it in one form or other for over 35 years. Yet, knowledge about it is quite arcane. I don't believe there is a single place where it's all properly written down. I have some explanation for that: while basic text layout is very important for UI, games, and other contexts, a lot of the "professional" needs around text layout are embedded in *much* more complicated systems such as Microsoft Word or a modern Web browser.++A complete account of text layout would be at least a small book. Since there's no way I can write that now, this blog post is a small step towards that - in particular, an attempt to describe the "big picture," using the conceptual framework of a "loose hierarchy." Essentially, a text layout engine breaks the input into finer and finer grains, then reassembles the results into a text layout object suitable for drawing, measurement, and hit testing.++The main hierarchy is concerned with laying out a single strip of text. Line breaking is also important, but has a separate, parallel hierarchy.++## The main text layout hierarchy++The hierarchy is:+- (a) paragraph segmentation+- (b) rich text style+- (c) BiDi+- (d) itemization (coverage by font)+- (e) script+- (f) shaping (cluster)++TODO: diagram++### Paragraph segmentation++The coarsest, and also simplest, segmentation task is paragraph segmentation. Most of the time, paragraphs are simply separated by newline (U+000A) characters, though Unicode in its infinite wisdom specifies a number of code point sequences that function as paragraph separators in plain text:++* U+000A LINE FEED+* U+000B VERTICAL TAB+* U+000C FORM FEED+* U+000D CARRIAGE RETURN+* U+000D U+000A (CR + LF)+* U+0085 NEXT LINE+* U+2008 LINE SEPARATOR+* U+2009 PARAGRAPH SEPARATOR++In rich text, paragraphs are usually indicated through markup rather than special characters, for example `<p>` or `<div>` in HTML. But in this post, as in most text layout APIs, we'll treat rich text as plain text + attribute spans.++### Rich text style++A paragraph of rich text may contain *spans* that can affect formatting. In particular, choice of font, font weight, italic or no, and a number of other attributes can affect text layout. Thus, each paragraph is typically broken into a some number of *style runs,* so that within a run the style is consistent.++Note that some style changes don't *necessarily* affect text layout. A classic example is color. Firefox, rather famously, does *not* define segmentation boundaries here for color changes. If a color boundary cuts a ligature, it uses fancy graphics techiques to render parts of the ligature in different color. But this is a subtle refinement and I think not required for basic text rendering. For more details, see [Text Rendering Hates You].++### Bidirectional analysis++Completely separate from the style spans, a paragraph may in general contain both left-to-right and right-to-left text. The need for bidirectional (BiDi) text is certainly one of the things that makes text layout more complicated.++Fortunately, this part of the stack is defined by a standard (UAX #9), and there are a number of good implementations. The interested reader is referred to [Unicode Bidirectional Algorithm basics]. The key takeaway here is that BiDi analysis is done on the plain text of the entire paragraph, and the result is a sequence of *level runs,* where the level of each run defines whether it is LTR or RTL.++The level runs and the style runs are then merged, so that in subsequent stages each run is of a consistent style and directionality. As such, for the purpose of defining the hierarchy, the result of BiDi analysis could alternatively be considered an implicit or derived rich text span.++### Itemization (font coverage)++Itemization is the trickiest and least well specified part of the hierarchy. There is no standard for it, and no common implementation. Rather, each text layout engine deals with it in its own special way.++Essentially, the result of itemization is to choose a single concrete font for a run, from a *font collection.* Generally a font collection consists of a main font (selected by font name from system fonts, or loaded as a custom asset), backed by a *fallback stack,* which are usually system fonts, but thanks to [Noto] it is possible to bundle a fallback font stack with an application, if you don't mind spending a few hundred megabytes for the assets.++Why is it so tricky? A few reasons, which I'll touch on.++First, it's not so easy to determine whether a font can render a particular string of text. One reason is [Unicode normalization]. For example, the string "é" can be encoded as U+00E9 (in NFC encoding) or as U+0065 U+0301 (in NFD encoding). Due to the principle of [Unicode equivalence], these should be rendered identically, but a font may have coverage for only one or the other in its [Character to Glyph Index Mapping] (cmap) table. The shaping engine has all the Unicode logic to handle these cases.++Of course, realistic fonts with Latin coverage will have both of these particular sequences covered in the cmap table, but edge cases certainly do happen, both in extended Latin ranges, and other scripts such as Hangul, which has complex normalization rules (thanks in part to a Korean standard for normalization which is somewhat at odds with Unicode). It's worth noting that [DirectWrite gets Hangul normalization quite wrong].++I believe a similar situation exists with the Arabic presentation forms; see [Developing Arabic fonts] for more detail on that.++Because of these tricky normalization and presentation issues, the most robust way to determine whether a font can render a string is to try it. This is how LibreOffice has worked for a while, and in 2015 [Chromium followed](https://lists.freedesktop.org/archives/harfbuzz/2015-October/005168.html). See also [Eliminating Simple Text](https://www.chromium.org/teams/layout-team/eliminating-simple-text) for more background on the Chromium text layout changes.++*Another* whole class of complexity is emoji. A lot of emoji can be rendered with either [text or emoji presentation], and there are no hard and fast rules to pick one or the other. Generally the text presentation is in a symbol font, and the emoji presentation is in a separate color font. A particularly tough example is the smiling emoji, which began its encoding life as 0x01 in [Code page 437], the standard 8-bit character encoding of the original IBM PC, and is now U+263A in Unicode. However, the suggested default presentation is text, which won't do in a world which expects color. Apple on iOS unilaterally chose an emoji presentation, so many text stacks follow Apple's lead. (Incidentally, the most robust way to encode such emoji is to append a [variation selector] to pin down the presentation).++Another source of complexity when trying to write a cross-platform text layout engine is querying the system fonts. See [Font fallback deep dive] for more information about that.++I should note one thing, which might help people doing archaeology of legacy text stacks: it used to be pretty common for text layout to resolve "compatibility" forms such as NFKC and NFKD, and this can lead to various problems. But today it is more common to solve that particular problem by providing a font stack with *massive* Unicode coverage, including all the code points in the relevant compatibility ranges.++### Script++The *shaping* of text, or the transformation of a sequence of code points into a sequence of positioned glyphs, depends on the script. Some scripts, such as Arabic and Devanagari, have extremely elaborate shaping rules, while others, such as Chinese, are a fairly straightforward mapping from code point into glyph. Latin is somewhere in the middle, starting with a straightforward mapping, but ligatures and kerning are also required for high quality text layout.++Determining script runs is reasonably straightforward - many characters have a Unicode script property which uniquely identifies which script they belong to. However, some characters, such as space, are "common," so the assigned script just continues the previous run.++A simple example is "hello мир". This string is broken into two script runs: "hello " is Latn, and "мир" is Cyrl.++### Shaping (cluster)++At this point, we have a run of constant style, font, direction, and script. It is ready for *shaping.* Shaping is a complicated process that converts a string (sequence of Unicode code points) into positioned glyphs. For the purpose of this blog post, we can generally treat it as a black box. Fortunately, a very high quality open source implementation exists, in the form of HarfBuzz.++We're not *quite* done with segmentation, though, as shaping assigns substrings in the input to [clusters] of glyphs. The correspondence depends a lot on the font. In Latin, the string "fi" is often shaped to a single glyph ( a ligature). For complex scripts such as Devanagari, a cluster is most often a syllable in the source text, and complex reordering can happen within the cluster.++Clusters are important for *hit testing,* or determining the correspondence between a physical cursor position in the text layout and the offset within the text. Generally, they can be ignored if the text will only be rendered, not edited (or selected).++Note that these shaping clusters are distinct from grapheme clusters. The "fi" example has two grapheme clusters but a single shaping cluster, so a grapheme cluster boundary can cut a shaping cluster. Since it's possible to move the cursor between the "f" and "i", one tricky problem is to determine the cursor location in that case. Fonts *do* have a [caret table], but implementation is spotty. A more robust solution is to portion the width of the cluster equally to each grapheme cluster within the cluster. See also [Let’s Stop Ascribing Meaning to Code Points] for a detailed dive into grapheme clusters.++## Line breaking++While short strings can be considered a single strip, longer strings require breaking into lines. Doing this properly is quite a tricky problem. In this post, we treat it as a separate (small) hierarchy, parallel to the main text layout hierarchy above.++The problem can be factored into identifying line break *candidates*, then choosing a subset of those candidates as line breaks that satisfy the layout constraints. The main constraint is that lines should fit within the specified maximum width. It's common to use a greedy algorithm, but high end typography tends to use an algorithm that minimizes a raggedness score for the paragraph. Knuth and Plass have a famous paper, [Breaking Paragraphs into Lines], that describes the algorithm used in TeX in detail. But we'll focus on the problems of determining candidates and measuring the widths, as these are tricky enough.++In theory, the Unicode Line Breaking Algorithm ([UAX #14]) identifies positions in a string that are candidate line breaks. In practice, there are some additional subtleties. For one, some languages (Thai is the most common) don't use spaces to divide words, so need some kind of natural language processing (based on a dictionary) to identify word boundaries. For two, automatic [hyphenation] is often desirable, as it fills lines more efficiently and makes the right edge less ragged. Liang's algorithm is most common for automatically inferring "soft hyphens," and there are many good implementations of it.++Android's line breaking implementation (in the [Minikin] library) applies an additional refinement: since email addresses and URLs are common in strings displayed on mobile devices, and since the UAX #14 rules give poor choices for those, it has an additional parser to detect those cases and apply different rules.++Finally, if words are very long or the maximum width is very narrow, it's possible for a word to exceed that width. In some cases, the line can be "overfull," but it's more common to break the word at the last grapheme cluster boundary that still fits inside the line. In Android, these are known as "desperate breaks."++So, to recap, after the paragraph segmentation (also known as "hard breaks"), there is a loose hierarchy of 3 line break candidates: word breaks as determined by UAX #14 (with possible "tailoring"), soft hyphens, and finally grapheme cluster boundaries. The first is preferred, but the other two may be used in order to satisfy the layout constraints.++This leaves another problem, which is suprisingly tricky to get fully right: how to measure the width of a line between two candidate breaks, in order to validate that it fits within the maximum width (or, in the more general case, to help compute a global raggedness score). For Latin text in a normal font, this seems almost ridiculously easy: just measure the width of each word, and add them up. But in the general case, things are nowhere nearly so simple.++First, while in Latin, most line break candidates are at space characters, in the fully general case they can cut anywhere in the text layout hierarchy, even in the middle of a cluster. An additional complication is that hyphenation can add a hyphen character.++Even without hyphenation, because [shaping is Turing Complete], the width of a line (a substring between two line break candidates) can be any function. Of course, such extreme cases are rare; it's most common for the widths to be exactly equal to the sum of the widths of the words, and even in the other cases this tends to be a good approximation.++So getting this exactly right in the general case is conceptually not difficult, but is horribly inefficient: for each candidate for the end of the line, perform text layout (mostly shaping) on the substring from the beginning of the line (possibly inserting a hyphen), and measure the width of that layout.++Very few text layout engines even try to handle this general case, using various heuristics and approximations which work well most of the time, but break down when presented with a font with shaping rules that change widths aggressively. DirectWrite does, however, using very clever techniques that took several years of iteration. The full story is in [harfbuzz/harfbuzz#1463 (comment)]. Further analysis, towards a goal of getting this implemented in an open source text layout engine, is in [yeslogic/allsorts#29]. If and when either HarfBuzz or Allsorts implements the lower-level logic, I'll probably want to write another blog post explaining in more detail how a higher level text layout engine can take advantage of it.++## Implementations to study++While I still feel a need for a solid, high-level, cross-platform text layout engine, there are good implementations to study. In open source, on of my favorites (though I am biased), is the Android text stack, based on [Minikin] for its lower levels. It is fairly capable and efficient, and also makes a concerted effort to get "all of Unicode" right, including emoji. It is also reasonably simple and the code is accessible.++While not open source, [DirectWrite] is also well worth study, as it is without question one of the most capable engines, supporting Word and the previous iteration of Edge before it was abandonded in favor of Chromium. Note that there is a [proposal][DWriteCore proposal] for a cross-platform implementation and also potentially to take it open-source. If that were to happen, it would be something of a game changer.++### Android++Paragraph and style segmentation (with BiDi) is done at higher levels, in [Layout.java] and [StaticLayout.java]. At that point, runs are handed to [Minikin] for lower-level processing. Most of the rest of the hierarchy is in Layout.cpp, and ultimately shaping is done by HarfBuzz.++Minikin also contains a sophisticated line breaking implementation, including Knuth-Plass style optimized breaking.++Android deals with shaping boundaries by using heuristics to further segment the text to implied word boundaries (which are also used as the grain for layout cache). If a font does shaping across these boundaries, the shaping context is simply lost. This is a reasonable compromise, especially in mobile, as results are always consistent, ie the width for measurement never mismatches the width for layout. And none of the fonts in the system stack have exotic behavior such as shaping across spaces.++Android does base its itemization on cmap coverage, and builds sophisticated bitmap structures for fast queries. As such, it can get normalization issues wrong, but overall this seems like a reasonable compromise. In particular, most of the time you'll run into normalization issues is with Latin and the combining diacritical marks, both of which are supplied by Roboto, which in turn has massive Unicode coverage (and thus less need to rely on normalization logic). But with custom fonts, handling may be less than ideal, resulting in more fallback to Roboto than might actually be needed.++Note that Minikin was also the starting point for [libTxt](https://github.com/flutter/flutter/issues/11092), the text layout library used in Flutter.++## DirectWrite++Some notes on things I've found while studying the API; these observations are quite a bit in the weeds, but might be useful to people wanting to deeply understand or engage the API.++Hit testing in DirectWrite is based on leading/trailing positions, while in Android it's based on primary and secondary. The latter is more useful for text edition, but leading/trailing is a more well-defined concept (for one, it doesn't rely on paragraph direction). For more information on this topic, see [linebender/piet#323](https://github.com/linebender/piet/issues/323). My take is that proper hit testing requires iterating through the text layout to access lower level structures.++While Core Text (see below) exposes a hierarchy of objects, DirectWrite uses the [TextLayout](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritetextlayout) as the primary interface, and exposes internal structure (even including lines) by iterating over a callback per run in the confusingly named [Draw](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritetextlayout-draw) method. The granularity of this callback is a [glyph run](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_glyph_run), which corresponds to "script" in the hierarchy above. Cluster information is provided in an associated [glyph run description](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_glyph_run_description) structure.++There are other ways to access lower level text layout capabilities, including +[TextAnalyzer](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritetextanalyzer), which computes BiDi and line break opportunities, script runs, and shaping. In fact, the various methods on that interface represents much of the internal structure of the text layout engine. Itemization, however, is done in the [FontFallback](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_2/nn-dwrite_2-idwritefontfallback) interface, which was added later.++### Core Text++Another high quality implementation is [Core Text]. I don't personally find it as well designed as DirectWrite, but it does get the job done. In general, though, Core Text is considered a lower level interface, and applications are recommended to use a higher level mechanism (Cocoa text on macOS, Text Kit on iOS).++When doing text layout on macOS, it's probably better to use the platform-provided itemization method (), rather than getting the font list and doing itemization in the client. See [linebender/skribo#14](https://github.com/linebender/skribo/issues/14) for more information on this tradeoff.++### Druid/Piet++At this point, the Druid GUI toolkit does not have its own native text layout engine, but rather *does* provide a [cross-platform API][Piet text layout API] which is delegated to platform text layout engines, DirectWrite and Core Text in particular.++The situation on Linux is currently unsatisfactory, as it's based on the Cairo toy text API. There is work ongoing to improve this, but no promises when.++While the Piet text API is currently fairly basic, I do think it's a good starting point for text layout, especially in the Rust community. While the complexity of Web text basically forces browsers to do all their text layout from scratch, for UI text there are serious advantages to using the platform.

I've expanded it, hopefully it's clear now.

raphlinus

comment created time in 2 days

PullRequestReviewEvent

push eventraphlinus/raphlinus.github.io

Raph Levien

commit sha 08ad5746b3e45f7b25d83cf5fec1db1895484100

Edits and images

view details

push time in 2 days

MemberEvent
PullRequestReviewEvent
PullRequestReviewEvent

issue commentlinebender/druid

Lifecycle issues on dynamic widget change

Thanks, this is a very useful analysis, and not what I was expecting. I haven't thought about it too deeply yet, but it seems like the right path forward might be to add a method to Druid to create an appropriate child context.

raphlinus

comment created time in 2 days

Pull request review commentraphlinus/raphlinus.github.io

Add draft of text layout post

+---+layout: post+title:  "Text layout is a loose hierarchy of segmentation"+date:   2020-10-25 15:00:42 -0700+categories: [text]+---+I love text layout, and have been working with it in one form or other for over 35 years. Yet, knowledge about it is quite arcane. I don't believe there is a single place where it's all properly written down. I have some explanation for that: while basic text layout is very important for UI, games, and other contexts, a lot of the "professional" needs around text layout are embedded in *much* more complicated systems such as Microsoft Word or a modern Web browser.++A complete account of text layout would be at least a small book. Since there's no way I can write that now, this blog post is a small step towards that - in particular, an attempt to describe the "big picture," using the conceptual framework of a "loose hierarchy." Essentially, a text layout engine breaks the input into finer and finer grains, then reassembles the results into a text layout object suitable for drawing, measurement, and hit testing.++The main hierarchy is concerned with laying out a single strip of text. Line breaking is also important, but has a separate, parallel hierarchy.++## The main text layout hierarchy++The hierarchy is:+- (a) paragraph segmentation+- (b) rich text style+- (c) BiDi+- (d) itemization (coverage by font)+- (e) script+- (f) shaping (cluster)++TODO: diagram++### Paragraph segmentation++The coarsest, and also simplest, segmentation task is paragraph segmentation. Most of the time, paragraphs are simply separated by newline (U+000A) characters, though Unicode in its infinite wisdom specifies a number of code point sequences that function as paragraph separators in plain text:++* U+000A LINE FEED+* U+000B VERTICAL TAB+* U+000C FORM FEED+* U+000D CARRIAGE RETURN+* U+000D U+000A (CR + LF)+* U+0085 NEXT LINE+* U+2008 LINE SEPARATOR+* U+2009 PARAGRAPH SEPARATOR++In rich text, paragraphs are usually indicated through markup rather than special characters, for example `<p>` or `<div>` in HTML. But in this post, as in most text layout APIs, we'll treat rich text as plain text + attribute spans.++### Rich text style++A paragraph of rich text may contain *spans* that can affect formatting. In particular, choice of font, font weight, italic or no, and a number of other attributes can affect text layout. Thus, each paragraph is typically broken into a some number of *style runs,* so that within a run the style is consistent.++Note that some style changes don't *necessarily* affect text layout. A classic example is color. Firefox, rather famously, does *not* define segmentation boundaries here for color changes. If a color boundary cuts a ligature, it uses fancy graphics techiques to render parts of the ligature in different color. But this is a subtle refinement and I think not required for basic text rendering. For more details, see [Text Rendering Hates You].++### Bidirectional analysis++Completely separate from the style spans, a paragraph may in general contain both left-to-right and right-to-left text. The need for bidirectional (BiDi) text is certainly one of the things that makes text layout more complicated.++Fortunately, this part of the stack is defined by a standard (UAX #9), and there are a number of good implementations. The interested reader is referred to [Unicode Bidirectional Algorithm basics]. The key takeaway here is that BiDi analysis is done on the plain text of the entire paragraph, and the result is a sequence of *level runs,* where the level of each run defines whether it is LTR or RTL.++The level runs and the style runs are then merged, so that in subsequent stages each run is of a consistent style and directionality. As such, for the purpose of defining the hierarchy, the result of BiDi analysis could alternatively be considered an implicit or derived rich text span.++### Itemization (font coverage)++Itemization is the trickiest and least well specified part of the hierarchy. There is no standard for it, and no common implementation. Rather, each text layout engine deals with it in its own special way.++Essentially, the result of itemization is to choose a single concrete font for a run, from a *font collection.* Generally a font collection consists of a main font (selected by font name from system fonts, or loaded as a custom asset), backed by a *fallback stack,* which are usually system fonts, but thanks to [Noto] it is possible to bundle a fallback font stack with an application, if you don't mind spending a few hundred megabytes for the assets.++Why is it so tricky? A few reasons, which I'll touch on.++First, it's not so easy to determine whether a font can render a particular string of text. One reason is [Unicode normalization]. For example, the string "é" can be encoded as U+00E9 (in NFC encoding) or as U+0065 U+0301 (in NFD encoding). Due to the principle of [Unicode equivalence], these should be rendered identically, but a font may have coverage for only one or the other in its [Character to Glyph Index Mapping] (cmap) table. The shaping engine has all the Unicode logic to handle these cases.++Of course, realistic fonts with Latin coverage will have both of these particular sequences covered in the cmap table, but edge cases certainly do happen, both in extended Latin ranges, and other scripts such as Hangul, which has complex normalization rules (thanks in part to a Korean standard for normalization which is somewhat at odds with Unicode). It's worth noting that [DirectWrite gets Hangul normalization quite wrong].++I believe a similar situation exists with the Arabic presentation forms; see [Developing Arabic fonts] for more detail on that.++Because of these tricky normalization and presentation issues, the most robust way to determine whether a font can render a string is to try it. This is how LibreOffice has worked for a while, and in 2015 [Chromium followed](https://lists.freedesktop.org/archives/harfbuzz/2015-October/005168.html). See also [Eliminating Simple Text](https://www.chromium.org/teams/layout-team/eliminating-simple-text) for more background on the Chromium text layout changes.++*Another* whole class of complexity is emoji. A lot of emoji can be rendered with either [text or emoji presentation], and there are no hard and fast rules to pick one or the other. Generally the text presentation is in a symbol font, and the emoji presentation is in a separate color font. A particularly tough example is the smiling emoji, which began its encoding life as 0x01 in [Code page 437], the standard 8-bit character encoding of the original IBM PC, and is now U+263A in Unicode. However, the suggested default presentation is text, which won't do in a world which expects color. Apple on iOS unilaterally chose an emoji presentation, so many text stacks follow Apple's lead. (Incidentally, the most robust way to encode such emoji is to append a [variation selector] to pin down the presentation).++Another source of complexity when trying to write a cross-platform text layout engine is querying the system fonts. See [Font fallback deep dive] for more information about that.++I should note one thing, which might help people doing archaeology of legacy text stacks: it used to be pretty common for text layout to resolve "compatibility" forms such as NFKC and NFKD, and this can lead to various problems. But today it is more common to solve that particular problem by providing a font stack with *massive* Unicode coverage, including all the code points in the relevant compatibility ranges.++### Script++The *shaping* of text, or the transformation of a sequence of code points into a sequence of positioned glyphs, depends on the script. Some scripts, such as Arabic and Devanagari, have extremely elaborate shaping rules, while others, such as Chinese, are a fairly straightforward mapping from code point into glyph. Latin is somewhere in the middle, starting with a straightforward mapping, but ligatures and kerning are also required for high quality text layout.++Determining script runs is reasonably straightforward - many characters have a Unicode script property which uniquely identifies which script they belong to. However, some characters, such as space, are "common," so the assigned script just continues the previous run.++A simple example is "hello мир". This string is broken into two script runs: "hello " is Latn, and "мир" is Cyrl.++### Shaping (cluster)++At this point, we have a run of constant style, font, direction, and script. It is ready for *shaping.* Shaping is a complicated process that converts a string (sequence of Unicode code points) into positioned glyphs. For the purpose of this blog post, we can generally treat it as a black box. Fortunately, a very high quality open source implementation exists, in the form of HarfBuzz.++We're not *quite* done with segmentation, though, as shaping assigns substrings in the input to [clusters] of glyphs. The correspondence depends a lot on the font. In Latin, the string "fi" is often shaped to a single glyph ( a ligature). For complex scripts such as Devanagari, a cluster is most often a syllable in the source text, and complex reordering can happen within the cluster.++Clusters are important for *hit testing,* or determining the correspondence between a physical cursor position in the text layout and the offset within the text. Generally, they can be ignored if the text will only be rendered, not edited (or selected).++Note that these shaping clusters are distinct from grapheme clusters. The "fi" example has two grapheme clusters but a single shaping cluster, so a grapheme cluster boundary can cut a shaping cluster. Since it's possible to move the cursor between the "f" and "i", one tricky problem is to determine the cursor location in that case. Fonts *do* have a [caret table], but implementation is spotty. A more robust solution is to portion the width of the cluster equally to each grapheme cluster within the cluster. See also [Let’s Stop Ascribing Meaning to Code Points] for a detailed dive into grapheme clusters.

Fantastic, I actually added a paragraph and the image from the big. The post is short on images illustrating the concepts, and I think I'll try to add some.

raphlinus

comment created time in 2 days

PullRequestReviewEvent

pull request commentxi-editor/xi-editor

[xi-unicode] Explicit breaks at end of text

Ok, 0.3.0 is published. Let me know if there are any issues.

raphlinus

comment created time in 3 days

create barnchraphlinus/raphlinus.github.io

branch : text_layout

created branch time in 3 days

pull request commentraphlinus/crochet

Avoid stale state with a timer event.

Ugly indeed but I'm happy to see the issue closed. I'd definitely want to come back to it with a more robust solution.

Finnerale

comment created time in 3 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3+//!    (white flag), U+200D (zwj), U+1F308 (rainbow)`) which produces a single rainbow flag glyph.+//!  - *script* - A set of graphemes that are used together to achieve written communcation.+//!  - *language* - A context for deriving meaning from a script. Collections of graphemes from a+//!    script will have different meanings in different languages, for example the word "pain"+//!    means different things in English and French ("bread" in french).+//!  - *locale* - Contextual information that defines how certain properties of the user interface+//!    should look. Examples are whether text should be rendered left-to-right, or right-to-left+//!    (as is the case in Hebrew, for example), and which varaint of Han characters to use.+//!    Non-text locale information includes date format and timezone.+//!  - *Han unification, CJK* - A number of Asian languages derive from ancient Chinese. The+//!    acronym CJK expands to Chinese, Japanese, Korean. Traditional Taiwanese also has this+//!    property, but since Taiwan has now adopted the Latin script it is less of an issue in+//!    practice. These languages use different glyphs for the same unicode grapheme (the graphemes+//!    can be thought of as representing ancient Han Chinese).+//!  - *RTL, LTR, BiDi* - Some scripts are read from the right to the left (RTL), the opposite of latin+//!    which is read left-to-right (LTR). If a span of text contains graphemes from both LTR and+//!    RTL languages, then multiple directions of text will be used, and this is known as+//!    bi-directional (BiDi) text. For example, if an english sentence contains a hebrew word, a+//!    reader would expect that the order of letters in that word to be flipped.+//!  - *cursive* - todo (text rendering hates you says the word cursive describes the situation+//!    where the position of a grapheme in a word affects which glyph is used).+//!  - *font shaping* - The act of selecting particular glyphs to represent graphemes based on

https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping is a good reference for either summarizing or pointing to or both.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing

I think this is a very useful guide, and very useful to have in the module-level docs. I can see expanding it in time. Below I have a bunch of comments, but we don't have to revise it completely, especially thanks to the disclaimer above.

I think generally it would be useful for most of these to have pointers to an authoritative source. Sometimes that will be a particular place in the Unicode spec (including the annexes). Other times, Wikipedia is reasonable.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as

known

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3+//!    (white flag), U+200D (zwj), U+1F308 (rainbow)`) which produces a single rainbow flag glyph.+//!  - *script* - A set of graphemes that are used together to achieve written communcation.+//!  - *language* - A context for deriving meaning from a script. Collections of graphemes from a+//!    script will have different meanings in different languages, for example the word "pain"+//!    means different things in English and French ("bread" in french).+//!  - *locale* - Contextual information that defines how certain properties of the user interface+//!    should look. Examples are whether text should be rendered left-to-right, or right-to-left+//!    (as is the case in Hebrew, for example), and which varaint of Han characters to use.+//!    Non-text locale information includes date format and timezone.+//!  - *Han unification, CJK* - A number of Asian languages derive from ancient Chinese. The+//!    acronym CJK expands to Chinese, Japanese, Korean. Traditional Taiwanese also has this+//!    property, but since Taiwan has now adopted the Latin script it is less of an issue in

I think you meant "Vietnamese" rather than "Taiwanese" here. Taiwan uses Traditional Chinese.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3+//!    (white flag), U+200D (zwj), U+1F308 (rainbow)`) which produces a single rainbow flag glyph.+//!  - *script* - A set of graphemes that are used together to achieve written communcation.+//!  - *language* - A context for deriving meaning from a script. Collections of graphemes from a+//!    script will have different meanings in different languages, for example the word "pain"+//!    means different things in English and French ("bread" in french).+//!  - *locale* - Contextual information that defines how certain properties of the user interface+//!    should look. Examples are whether text should be rendered left-to-right, or right-to-left+//!    (as is the case in Hebrew, for example), and which varaint of Han characters to use.+//!    Non-text locale information includes date format and timezone.+//!  - *Han unification, CJK* - A number of Asian languages derive from ancient Chinese. The+//!    acronym CJK expands to Chinese, Japanese, Korean. Traditional Taiwanese also has this+//!    property, but since Taiwan has now adopted the Latin script it is less of an issue in+//!    practice. These languages use different glyphs for the same unicode grapheme (the graphemes

I would say "code point" rather than "grapheme." The word "grapheme" is seldom used in computer text outside the pleonasm "grapheme cluster."

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3+//!    (white flag), U+200D (zwj), U+1F308 (rainbow)`) which produces a single rainbow flag glyph.+//!  - *script* - A set of graphemes that are used together to achieve written communcation.+//!  - *language* - A context for deriving meaning from a script. Collections of graphemes from a

You might want to introduce the term "writing system" here, which is similar to script but subtly different. See https://en.wikipedia.org/wiki/Script_(Unicode) and https://en.wikipedia.org/wiki/Writing_system

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3+//!    (white flag), U+200D (zwj), U+1F308 (rainbow)`) which produces a single rainbow flag glyph.+//!  - *script* - A set of graphemes that are used together to achieve written communcation.

I think it's slightly odd to define this in terms of graphemes. Also might want to reference UAX #24, which defines the Unicode script property for each codepoint: https://unicode.org/reports/tr24/

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification+//!    (see below). It's important to note that a grapheme cluster may be 1 or more unicode+//!    characters.  An example of a multi-character grapheme cluster is a rainbow flag (`U+1F3F3

I would say "code points" rather than characters.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".

"Bitmap" is not a format, but rather a family of formats (including PCF etc).

This could be stronger by saying that OpenType is now the consensus standard, though historically there were many other types.

It might be worth mentioning WOFF, but it's not really a font format in and of itself (despite the name), more of a compression container.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer

This is a whole rant. Here's how I would write it.

The word "character" is often used informally, but is ambiguous and has no clear formal meaning. In Rust, the char type actually represents a code point. In simple contexts (such as ASCII-only text), "character" can be considered identical, but in a general context it should generally be avoided if precise meaning is desired.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters

Oblique (slanting) is distinct from italic, which often has a more rounded form than the upright.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to+//!    mean *glyph* is *letter*, but "letter" can also mean grapheme (because in latin script all+//!    of the meanings are equivalent, they are often used interchangeably).+//!  - *font* - A set of glyphs that can be printed to paper or a screen. Sometimes the word+//!    font is used to mean typeface, and this can cause some confusion. In computing, a font can+//!    also refer to 1 or more font descriptions, which contain the information required to draw+//!    glyphs. These descriptions could be stored in a file on disk, or in memory, or somewhere+//!    else. Popular formats include "OpenType/TrueType", "Bitmap", "PostScript", "Web Open Font+//!    Format (WOFF)".+//!  - *typeface* - A collection of fonts that all share the same "look", but have different sizes,+//!    weights, and styles.+//!  - *size* An indication of the size of a font. A font's size is often given as the width of a+//!    latin `m` character. Sizes are often given in pixels on a computer, but screen pixels do not+//!    have a fixed physical width. To see this think about the fact that a 14" screen with the+//!    same number of pixels as a 21" screen will not have pixels of the same size.+//!  - *weight* The thickness of glyphs in the font. Thicker weighted fonts are known as *bold*+//!    whilst thinner weighted fonts are sometimes know as *light*. Weight can also be expressed as+//!    a number.+//!  - *style* - Variations of a specific typeface other than weight and size. Examples include+//!    slanting text (*italics*) or using small upper case letters instead of lower case letters+//!    (`small-caps` in CSS).+//!  - *character* - Characters or `char`s can mean many things, but outside and within computer+//!    typesetting. The wort character is often used as a lay term for grapheme, and one could+//!    argue that given their relative usage that this is character's canonical meaning. In the `c`+//!    programming language, a `char` is almost always just a name for a byte of data; this meaing+//!    comes from a time when computer software engineers only considered English, and so a byte+//!    was enough space to encode all possible glyphs.  Within rust, characters are specific+//!    unicode code points, which are combined into graphemes. They don't really have any semantic+//!    meaning on their own, although many characters consist of 1 grapheme, and so they are+//!    sometimes mistakenly thought of as equivalent.+//!  - *unicode* - When computers were first created in America, they all used the latin alphabet,+//!    which fits into a byte. The *ASCII* encoding was developed to store latin characters in a+//!    byte of data. As other countries began to use computers, they created their own encodings to+//!    include their non-latin letters (for example É in French). Asian languages had to widen the+//!    character to 2 or more bytes since there are more than 256 glyphs in these languages.+//!    Unicode was developed as a (successful as it turns out) attempt to unify all languages and+//!    scripts into a single encoding scheme. Unicode characters are 4 bytes wide, meaning that+//!    there is space for 4_294_967_296 different characters, which is expected to be enough. (It's+//!    not quite this many in practice - some bit patterns are reserved).+//!  - *utf-8* - Unicode was a very useful in making it easier to use the same software in+//!    different parts of the world, but if all your text is latin then it takes 4 bytes per+//!    character instead of 1 for ASCII. This would be quite wasteful, so the most popular way to+//!    store unicode strings (utf-8) uses a continuation-bit style scheme to compress unicode+//!    characters where possible. Another older scheme is utf-16, which works similarly, but uses 2+//!    bytes (16 bits) as its smallest size.+//!  - *grapheme, grapheme cluster* - Outside of computer typesetting, graphemes can have multiple+//!    meanings in linguistics (see wikipedia). Within computer typesetting (and unicode in+//!    particular), a grapheme cluster (called grapheme in the rest of these docs) can be thought+//!    of as the conceptual version of a glyph. One exception to this is Han unification

I wouldn't define it in terms of a glyph because it is not 1-1. For example, the "fi" ligature is one glyph but two grapheme clusters. Conversely, "न्दी" is one grapheme cluster but often represented by 3 glyphs.

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

 impl FontRef { }  impl FontFamily {+    /// Create an empty font family.     pub fn new() -> FontFamily {         FontFamily { fonts: Vec::new() }     } +    /// Adda a font to an existing family.

Add

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

+//! A library to help convert from a unicode string and attributes to a list of glyphs and+//! positions.+//!+//! Converting unicode strings to glyphs is a complex process, requiring knowledge of+//!  - which fonts to use (and choosing an appropriate font given a size, script, typeface, weight,+//!    etc.),+//!  - a description of how to render a font (e.g. a truetype font file)+//!  - the space available for drawing and what to do if it's not enough,+//!  - and information on the user's locale.+//!+//! # Font terms+//!+//! The terminology of printing can be confusing. Partly this is because printing has been so+//! important for so long, and so has historical baggage, but it is also because unifying the+//! written methods of many different cultures requires a complicated system with many parts.+//! Unfortunately, a consequence of this is that most of the terms used in typesetting have+//! different meanings to different people. The unicode standard is useful in that it precisely+//! defines the terms it uses, but these meanings aren't necessarily the same as those that are in+//! common usage.  Below are some important terms in font rendering and the meanings some ascribe+//! to them:+//!+//! This is a work in progress and will be wrong in places (for now).+//!+//!  - *typography* - The study of drawing text to paper, screen, or some other medium. Drawing+//!    text is also known as *typesetting*, or *rendering*.+//!  - *symbol* - An image drawn or printed on a canvas, sheet of paper, or screen. Physically the+//!    same as a picture.+//!  - *glyph* - A symbol from a collection of symbols with some semantic meaning. The collection+//!    could be a script (like latin - `ABCDE....abcde...`, or it could be from the set of+//!    mathemtatical symbols (`+-×÷`). In the case of languages, another word more commonly used to

mathematical

derekdreery

comment created time in 4 days

Pull request review commentlinebender/skribo

Add some docs, especially top-level.

 impl fmt::Debug for FontRef {     } } +/// An iterator over `(Range<usize>, &FontRef)` pairs. Use the given font for the given range. When

Probably best to reference the function that generates it, the type of the iterator is not that important (some APIs just write impl Iterator<Item = ...>).

Also, not 100% clear this should be public, I think pub(crate) might be better, but we can err on the side of exposing more for now.

derekdreery

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentxi-editor/xi-editor

[xi-unicode] Explicit breaks at end of text

I can push a release today. Any other concerns from anyone before I do?

raphlinus

comment created time in 4 days

delete branch linebender/runebender

delete branch : rev_contour

delete time in 5 days

push eventlinebender/runebender

Raph Levien

commit sha e4d2839f1d2b514cb762752e1d2ad965cc5b6241

Add "reverse contours" command Also changes key-binding for scroll wheel zoom.

view details

Raph Levien

commit sha 3a55f4598152ed1e5bc1659f5a01593bf4bdaa7e

Merge pull request #163 from linebender/rev_contour Add "reverse contours" command

view details

push time in 5 days

PR merged linebender/runebender

Add "reverse contours" command

Also changes key-binding for scroll wheel zoom.

+47 -9

1 comment

7 changed files

raphlinus

pr closed time in 5 days

Pull request review commentlinebender/runebender

Add "reverse contours" command

 impl EditSession {         }     } +    pub(crate) fn reverse_contours(&mut self) {+        let mut path_ixs = BTreeSet::new();+        for entity in &*self.selection {+            if let Some(path_ix) = self.paths.iter().position(|p| p == entity) {

It matches the Glyphs behavior, and seems reasonable to me.

raphlinus

comment created time in 5 days

PullRequestReviewEvent

PR opened linebender/runebender

Add "reverse contours" command

Also changes key-binding for scroll wheel zoom.

+47 -9

0 comment

7 changed files

pr created time in 5 days

create barnchlinebender/runebender

branch : rev_contour

created branch time in 5 days

Pull request review commentlinebender/runebender

Handle unexpected point orderings

 impl Path {      pub fn from_raw_parts(         id: usize,-        points: Vec<PathPoint>,+        mut points: Vec<PathPoint>,         trailing: Option<DPoint>,         closed: bool,     ) -> Self {         assert!(!points.is_empty(), "path may not be empty");         assert!(points.iter().all(|pt| pt.id.parent == id), "{:#?}", points);+        if !closed {+            assert!(points.first().unwrap().is_on_curve());

As a general thought, I think we should export validation errors through the UI rather than asserts. But that can be a matter for another PR.

cmyr

comment created time in 6 days

Pull request review commentlinebender/runebender

Handle unexpected point orderings

 use crate::data::{FontMetrics, Workspace}; use crate::design_space::ViewPort; use crate::edit_session::EditSession; use crate::guides::{Guide, GuideLine};-use crate::path::{EntityId, Path, PointType};-use druid::kurbo::{Affine, BezPath, Circle, CubicBez, Line, PathSeg, Point, Rect, Vec2};+use crate::path::{EntityId, Path, PathSeg, PointType};+use druid::kurbo::{+    Affine, BezPath, Circle, CubicBez, Line, PathSeg as KurboPathSeg, Point, Rect, Vec2,

Personally I prefer importing kurbo::self and then saying kurbo::PathSeg, but that's a matter of style, certainly won't block on this.

cmyr

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent

issue commentlinebender/runebender

Regression on Linux

I'll note, the frac check causes panics when loading Inconsolata, so there are two problems here :)

alerque

comment created time in 6 days

issue commentlinebender/runebender

Regression on Linux

FWIW, the ufo spec states "The actual list of points can be rotated arbitrarily", so we should probably deal with that on load. I think for our own internal data model, we can have the invariant that the "first" point (which is the last when the path is closed) is on-curve. (Note that if we ever deal with quadratics, outlines with no on-curve points are possible)

alerque

comment created time in 6 days

PullRequestReviewEvent

issue commentlinebender/piet

0.2.0-pre6 broke crochet

I don't think that will work. Currently, crochet needs to be pinned on an old version of druid because of https://github.com/linebender/druid/issues/1258. That in turn needs to pin piet 0.2.0-pre4 because of the various changes.

I think the short-term patch might be to commit Cargo.lock on crochet. The longer term solution is to fix the druid dynamic issues so we can move the pin forward on crochet.

Fi3

comment created time in 6 days

issue commentlinebender/runebender

Regression on Linux

This might be the check for coordinate frac == 0.0, which is too strict.

alerque

comment created time in 6 days

MemberEvent
PullRequestReviewEvent
PullRequestReviewEvent

push eventraphlinus/crochet

MTRNord

commit sha aaca78bab4c2b5178690231b7252201d1bac579e

fix(ListData): Allow Default for T types that don't implement Default ListData in the core is a Vec and Vec also allows implementing Default if it's Item do not implement Default. This change makes the same thing possible while the derive strictly requires T to implement Default.

view details

Raph Levien

commit sha f411946d6bf9ec6ccfb93a552b03890a026d4ec7

Merge pull request #11 from daydream-mx/MTRNord/better-ListData-Default-implementation fix(ListData): Allow Default for T types that don't implement Default

view details

push time in 7 days

PR merged raphlinus/crochet

fix(ListData): Allow Default for T types that don't implement Default

ListData in the core is a Vec and Vec also allows implementing Default if it's Item do not implement Default. This change makes the same thing possible while the derive strictly requires T to implement Default.

+6 -1

0 comment

1 changed file

MTRNord

pr closed time in 7 days

PullRequestReviewEvent

PR opened linebender/druid

Make platform-specific menus more portable

If an application were to misuse a platform-specific for the wrong platform, it would get unusable keybindings. With this patch, it might not be the most appropriate for the platform, but it would work.

The linked bug below suggests a more systematic approach, but this is a minimal patch to get things to a less broken state.

Part of work tracked in #1306.

+24 -24

0 comment

1 changed file

pr created time in 7 days

create barnchlinebender/druid

branch : menu_work4

created branch time in 7 days

push eventlinebender/druid

Raph Levien

commit sha d0d88653f27690b7ce6929048bb0c1faf48d4387

Display hotkeys for menu items in Windows This patch adds a string to describe hotkeys for menu items in the Windows back-end. Part of work tracked in #1306

view details

Raph Levien

commit sha 172ae3ccfce6fd37473f8549fa9f7ac8050a15e3

Merge branch 'master' into win_menu_hotkeys

view details

Raph Levien

commit sha 31d4bdf9c5c97250804157ddbe88d758055b057a

Merge pull request #1310 from linebender/win_menu_hotkeys Display hotkeys for menu items in Windows

view details

push time in 7 days

PR merged linebender/druid

Display hotkeys for menu items in Windows S-ready

This patch adds a string to describe hotkeys for menu items in the Windows back-end.

Part of work tracked in #1306

+50 -4

0 comment

3 changed files

raphlinus

pr closed time in 7 days

PullRequestReviewEvent

Pull request review commentlinebender/piet

Link README in Cargo.toml, add piet-common readme

 A companion for Bézier path representation and geometry is [kurbo].  ## Backends +*For cross-platform use, the [`piet-common`][] crate reexports the most

I don't think you need the following [], but maybe I'm missing something.

cmyr

comment created time in 7 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

pull request commentlinebender/piet

Bump version and update dependencies

I also have a not-great feeling about web text (#311), as this is a regression from the previous release. But I'm not sure that should block an 0.2, I think it can be fixed in a point release.

cmyr

comment created time in 8 days

Pull request review commentlinebender/piet

Bump version and update dependencies

 keywords = ["graphics", "2d"] categories = ["rendering::graphics-api"]  [dependencies]-piet = { version = "0.2.0-pre5", path = "../piet" }+piet = { version = "0.2.0-pre6", path = "../piet" }

Did you mean "=0.2.0-pre6" here? Same is true for piet dep in the other back-ends.

cmyr

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentlinebender/druid

Use '=' on pre-release dependencies

A warning, I'm pretty sure this won't work unless piet internally uses '=' dependencies. I think pre5 might be a lost cause, but we can make things more robust for pre6.

cmyr

comment created time in 8 days

Pull request review commentlinebender/kurbo

Impl Shape for QuadBez, CubicBez, & PathSeg

 impl QuadBez {     } } +/// An iterator for quadratic beziers.+pub struct QuadBezIter {+    quad: QuadBez,+    ix: usize,+}++impl Shape for QuadBez {+    type PathElementsIter = QuadBezIter;++    #[inline]+    fn path_elements(&self, _tolerance: f64) -> QuadBezIter {+        QuadBezIter { quad: *self, ix: 0 }+    }++    /// The area under the curve.+    ///+    /// We could just return 0, but this seems more useful.

I think I'd prefer 0, to be consistent with Line. The idea of these individual signed_area methods is that you can add them up for all the segments of a closed path.

I'm wondering now whether it might be better do implement it for all such segments, that way you get the "shoelace algorithm" for polygon area. In any case, I'd prefer that Line, QuadBez, and CubicBez are consistent. I'm fine with PathSeg having the same behavior as a single element BezPath though.

cmyr

comment created time in 8 days

Pull request review commentlinebender/kurbo

Impl Shape for QuadBez, CubicBez, & PathSeg

 impl<'a> Shape for &'a [PathEl] {     } } +/// An iterator for path segments.+pub struct PathSegIter {+    seg: PathSeg,+    ix: usize,+}++impl Shape for PathSeg {+    type PathElementsIter = PathSegIter;++    #[inline]+    fn path_elements(&self, _tolerance: f64) -> PathSegIter {+        PathSegIter { seg: *self, ix: 0 }+    }++    /// The area under the curve.+    ///+    /// We could just return 0, but this seems more useful.+    fn area(&self) -> f64 {+        self.signed_area()+    }++    #[inline]+    fn perimeter(&self, accuracy: f64) -> f64 {+        self.arclen(accuracy)+    }++    fn winding(&self, _pt: Point) -> i32 {+        0+    }++    #[inline]+    fn bounding_box(&self) -> Rect {+        ParamCurveExtrema::bounding_box(self)+    }++    fn as_line(&self) -> Option<Line> {+        if let PathSeg::Line(line) = self {+            Some(*line)+        } else {+            None+        }+    }+}++impl Iterator for PathSegIter {+    type Item = PathEl;++    fn next(&mut self) -> Option<PathEl> {+        self.ix += 1;+        match (self.ix, self.seg) {+            // yes I could do some fancy bindings thing here but... :shrug:+            (1, PathSeg::Line(line)) => Some(PathEl::MoveTo(line.p0)),+            (1, PathSeg::Quad(line)) => Some(PathEl::MoveTo(line.p0)),

Don't use "line". I think "seg" would be ok if we want consistency.

cmyr

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentlinebender/runebender

Update druid

 impl<T: Widget<EditorState>> ScrollZoom<T> {      fn handle_zoom_cmd(&mut self, cmd: &Command, view_size: Size, data: &mut EditorState) {         use crate::consts::cmd;+        const ZOOM_DELTA: Vec2 = Vec2::new(50.0, 0.0);

FWIW, I find this way too small. I don't fully understand the logic of wheel_zoom, but I note that Glyphs is approximately sqrt(2) each step (while adjusting to nice round numbers) and Chrome is approximately 2^(1/5). But refining the zoom logic (including a more useful center) should probably be separate than the Druid update.

cmyr

comment created time in 8 days

PullRequestReviewEvent

Pull request review commentlinebender/runebender

Add selection size adjustment to CoordPane

 impl std::default::Default for ViewPort {         }     } }++impl Default for DPoint {

You can just #[derive(Default)] here.

cmyr

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent
MemberEvent
MemberEvent
PullRequestReviewEvent
more