├── README.md ├── SUMMARY.md ├── color-spaces.md ├── drawing-coordinate-system.md ├── gamma.md ├── immediate-mode.md ├── mouse-wheel.md └── useful-links.md /README.md: -------------------------------------------------------------------------------- 1 | # Linebender graphics wiki 2 | 3 | 4 | 5 | {% hint style="info" %} 6 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 7 | {% endhint %} 8 | 9 | 10 | > [!IMPORTANT] 11 | > This wiki has been archived. Its content is maintained for posterity. 12 | > 13 | > The [Linebender wiki](https://linebender.org/wiki/) at has the updated content. 14 | > 15 | > To contribute to that wiki, open a PR on [its repository](https://github.com/linebender/linebender.github.io). 16 | 17 | Right now this is just an experiment to see if gitbook wiki structure will work well for 2D graphics related knowledge. The Linebender project has a lot of graphics-related subprojects, encompassing curves, text layout, and and experimental GPU-based renderer. 18 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [Linebender graphics wiki](README.md) 4 | * [Gamma](gamma.md) 5 | * [Color spaces](color-spaces.md) 6 | * [Drawing coordinate system](drawing-coordinate-system.md) 7 | * [Immediate mode](immediate-mode.md) 8 | * [Mouse wheel](mouse-wheel.md) 9 | * [Useful links](useful-links.md) 10 | -------------------------------------------------------------------------------- /color-spaces.md: -------------------------------------------------------------------------------- 1 | # Color spaces 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | Many vector shapes in the druid/piet world are drawn with a solid color, and others are drawn with gradients which are defined in terms of colors. This raises the question: what’s the best way to specify colors? 8 | 9 | The simplest approach is to use RGB colors. These are well understood, and even standardized in the form of the [sRGB] colorspace. However, it’s not ideal from a color communication perspective, because it’s hard to intuitively understand the relationship between the color and the numeric or hex code. For example, it’s extremely non-obvious when two colors have the same hue. When designing colorways for user interfaces, it’s often desirable to have highlight and accent colors drawn from the same hue, for example. 10 | 11 | Another limitation of sRGB is that it covers a fairly limited gamut, and high-gamut (and HDR) displays are entering the mainstream. Fully supporting these HDR colors is beyond the scope of piet now, but we’d like a convention for representing color that will grow to support HDR in the future. 12 | 13 | Thus, we’ve recently (in the form of [piet#70]) added a way to specify color using Hue, Luminance, and Chroma. It is based on the colorimetrically sound CIE L*a*b* standard (as opposed to RGB-derived color spaces such as HSV), but these quantities are intuitively clear, and it makes it especially easy to define a family of colors with the same hue. This color space is the same as used by freiefarbe.de. 14 | 15 | Following freiefarbe.de, we chose the L*a*b*-based approach because of its simplicity and widespread existing adoption. Newer color spaces such as Jzazbz, IPT, and CAM16 (see references below) promise more perceptually accurate, particularly in hue constancy (where L*a*b* has errors particularly in the blue region). But they are also more complex and there is no consensus on which is best. 16 | 17 | ## Resources 18 | 19 | * [IPT color space](https://www.researchgate.net/publication/221677980_Development_and_Testing_of_a_Color_Space_IPT_with_Improved_Hue_Uniformity) 20 | 21 | * [Jzazbz color space](https://www.researchgate.net/publication/325490579_15-3_New_ICtCp_and_Jzazbz_Color_Spaces_to_Analyze_the_Color_Viewing-Angle_Dependence_of_HDR_and_WCG_Displays) 22 | 23 | * [CIECAM02 and CAM 16](https://arxiv.org/pdf/1802.06067.pdf) 24 | 25 | * [freiefarbe.de](https://www.freiefarbe.de/en/) 26 | 27 | ### HDR 28 | 29 | * Krita talk on implementing HDR: [slides](https://github.com/libregraphicsmeeting/slides-2019/blob/master/slides/2019-06-01-1000-hdr-support-in-krita.pdf), [video](https://www.youtube.com/watch?v=5MrocfwJd4k) 30 | 31 | * [scRGB](https://en.wikipedia.org/wiki/ScRGB) 32 | 33 | * [Rec.2020](https://en.wikipedia.org/wiki/Rec._2020) 34 | 35 | {% hint style="info" %} 36 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 37 | {% endhint %} 38 | 39 | [piet#70]: https://github.com/linebender/piet/pull/70 40 | [sRGB]: https://en.wikipedia.org/wiki/SRGB 41 | 42 | -------------------------------------------------------------------------------- /drawing-coordinate-system.md: -------------------------------------------------------------------------------- 1 | # Drawing: coordinate system 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | ## Device independence 8 | 9 | Distinguishing between logical user space coordinates and physical device space coordinates 10 | 11 | Precedence: 12 | * [Core Graphics](https://developer.apple.com/documentation/coregraphics/cgcontext/1455677-userspacetodevicespacetransform) 13 | * [Direct2D](https://docs.microsoft.com/en-us/windows/desktop/Direct2D/direct2d-portal) 14 | * [Java2D](https://docs.oracle.com/javase/tutorial/2d/overview/coordinate.html) 15 | * [Qt](https://doc.qt.io/qt-5/paintsystem-devices.html) 16 | 17 | 18 | ## Y-coordinates: up or down? 19 | 20 | Affects the meaning of angles, winding and rectangle parameters (top/bottom). 21 | 22 | Precedence: 23 | * _Y-coordinates down_: 24 | * [Direct2D](https://docs.microsoft.com/en-us/windows/desktop/Direct2D/direct2d-portal), but can be [transformed](https://docs.microsoft.com/en-us/windows/desktop/Direct2D/id2d1rendertarget-settransform) 25 | * [Java 2D](https://docs.oracle.com/javase/tutorial/2d/overview/coordinate.html), but can be transformed 26 | * [Qt](https://doc.qt.io/qt-5/coordsys.html), but can be [transformed](https://doc.qt.io/qt-5/qpainter.html#setWorldTransform) 27 | * _Y-coordinates up_: 28 | * [Core Graphics](https://developer.apple.com/documentation/coregraphics), but can be [transformed](https://developer.apple.com/documentation/appkit/nsview/1483532-isflipped) 29 | 30 | ### Discussion 31 | 32 | * Pro _Y-coordinates down_: 33 | * used widely. [Early APIs](https://en.wikipedia.org/wiki/QuickDraw) used it probably due to the use of [CRTs](https://en.wikipedia.org/wiki/Cathode-ray_tube). 34 | * Pro _Y-coordinates up_: 35 | * matches convention in mathematics 36 | 37 | ### Status 38 | 39 | [open](https://github.com/linebender/kurbo/issues/4): use _Y-coordinates down_? 40 | 41 | {% hint style="info" %} 42 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 43 | {% endhint %} 44 | -------------------------------------------------------------------------------- /gamma.md: -------------------------------------------------------------------------------- 1 | # Gamma 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | One of the trickiest aspects to get right in 2D graphics is gamma. A good starting point on the topic is John Novak’s blog, [What Every Coder Should Know About Gamma](https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/). 8 | 9 | Most of what this page says is right, but I bristle a little at the characterization of blending in linear sRGB space as “correct.” Very simply, in many cases it just looks worse. We see that clearly in the examples in the [Massively-Parallel Vector Graphics](http://w3.impa.br/~diego/projects/GanEtAl14/) project; the text in the renders with correct gamma looks weak and spindly, while the versions that blend text in a perceptual sRGB space look much better. 10 | 11 | I don’t think this question has a mathematically correct answer, it’s fundamentally a question of aesthetics. At the heart is the most visualy appealing rendering of thin strokes \(especially dark strokes on a light background\). There’s substantial evidence that some form of stroke darkening improves the overall perception. Apple has applied fairly heavy stem darkening in their LCD rendering for some time \(see this [freetype page](https://www.freetype.org/freetype2/docs/text-rendering-general.html) on the subject for more background\). Obviously it’s critical for text reproduction, but also important for fine stroked lines in vector content. 12 | 13 | Should this be considered an authoring question \(the designer should specify font and stroke weights that look best with correct rendering\), or an rendering question \(it is up to the renderer to produce the best appearance for the content\)? This is not a question of correctness, but depends on the source of the content. When rendering existing documents, it’s not useful to say, “it should have been created with heavier fonts.” 14 | 15 | An interesting parallel is the ink spread in many printing processes, especially letterpress. It’s well known that many digital fonts were created from the metal masters and look too thin, the appearance on a screen very anemic compared with the satisfyingly thick printed representation. 16 | 17 | Two other related factors are the scale of the rendering and the resolution of the target screen. Strokes less than one pixel in width look pretty bad no matter what gamma and rendering technique is used; at higher resolution and as the zoom scales up, it looks much nicer, even if lower contrast than it might otherwise be. 18 | 19 | In any case, rendering with gamma different than the author’s experience can yield worse results, simply by not respecting the author’s intent, no matter which is “correct.” 20 | 21 | As a final critique of Novak’s essay, I found some of the gradient examples unconvincing. It makes sense that they _should_ traverse a perceptual space, rather than one linear in physical light intensity. And I think a strong case can be made that a white-to-black gradient computed in linear intensity is too light, with way too much contrast on the dark side. Here I think it’s important to provide a good set of gradient design tools to the artist, with a choice of colorspace optimized to provide visually satisfying results, and then render that accurately, rather than dictating that gradients computed in a linear space are inherently more “correct.” 22 | 23 | That said, especially at 4k, the appearance of vector content antialiased and blended in a linear space is _vastly_ superior, with almost all of the “ropiness”ß gone. Image resampling is similarly much smoother. I agree with Novak that linear blending should be at the basis of rendering, but disagree rather strongly with the assertion that “This is pretty much all there is to gamma encoding and decoding.” Without some attention paid to the fate of very thin strokes, users will be less pleased with correct rendering. 24 | 25 | {% hint style="info" %} 26 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 27 | {% endhint %} 28 | -------------------------------------------------------------------------------- /immediate-mode.md: -------------------------------------------------------------------------------- 1 | # immediate mode vs retained mode 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | There was a [discussion] on the Zulip on immediate mode vs retained mode. 8 | 9 | {% hint style="info" %} 10 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 11 | {% endhint %} 12 | 13 | [discussion]: https://xi.zulipchat.com/#narrow/stream/147932-chatter/topic/HN.20discusses.20imgui 14 | -------------------------------------------------------------------------------- /mouse-wheel.md: -------------------------------------------------------------------------------- 1 | # Mouse wheel notes 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | What does scrolling actually mean? It depends on the platform and on the mouse. 8 | 9 | See [druid#68](https://github.com/xi-editor/druid/pull/68) for the code that implements this. There are some additional links and comments in the review. 10 | 11 | ## Web 12 | [W3C's WheelEvent](https://w3c.github.io/uievents/#event-type-wheel) specifies it as the “expected amount the page will scroll” 13 | 14 | On my Windows machine, “away from user” is a negative number. At lines = 3 (in preferences), one bump of the physical mouse wheel is 200. Rightward motion on the trackpad is a positive number. 15 | 16 | On my Mac, when “Scroll direction: Natural” is checked, “away from user” is a positive number, and rightward motion on the trackpad is a negative number. Both flip when it is unchecked. The magnitude is dependent on the rate of scrolling (i.e. this is adaptively scaled). 17 | 18 | See significant discussion in [Chromium issue 227454](https://bugs.chromium.org/p/chromium/issues/detail?id=227454), including having got the polarity wrong. 19 | 20 | ## Windows 21 | [The doc for WM_MOUSEWHEEL message](https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel) specifies that rolling away from the user is a positive number. Rightward motion on the trackpad is a positive number. 22 | 23 | One bump of the external scroll wheel is 120, consistent with documentation. 24 | 25 | The sensitivity setting should be read from `SystemParametersInfo`. 26 | 27 | ## macOS 28 | [The doc for NSEvent scrollingDeltaY](https://developer.apple.com/documentation/appkit/nsevent/1535387-scrollingdeltay) is not helpful. 29 | 30 | The value of `scrollingDeltaX` and `scrollingDeltaY` is the negative of the web value. Note also, `hasPreciseScrollingDeltas` is true for trackpad and false for external mice. 31 | 32 | The value of `scrollingDeltaX` and `scrollingDeltaY` inverts when the “Scroll direction: Natural” setting is toggled, i.e .the setting is applied before the event is given to the app. 33 | 34 | ## External mouse wheel vs trackpad 35 | 36 | An external mouse wheel delta is traditionally multiplied by 32, while a touchpad delta is not. Here's the [corresponding Makepad version](https://github.com/makepad/makepad/blob/07f1e72ba19f327d56c6bdfe4211358b2aaee006/render/src/cx_cocoa.rs#L333). Also note that [Winit keeps the distinction](https://github.com/rust-windowing/winit/blob/34db2d7d4c1deebbb706194113853591e7c6b60c/src/event.rs#L360) (using LineDelta for an ext mouse wheel, PixelDelta for the trackpad). 37 | 38 | {% hint style="info" %} 39 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 40 | {% endhint %} 41 | -------------------------------------------------------------------------------- /useful-links.md: -------------------------------------------------------------------------------- 1 | # Useful Links 2 | 3 | {% hint style="info" %} 4 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 5 | {% endhint %} 6 | 7 | There are no well-condensed sources of 2D graphics knowledge. Rather, it is dispersed over a wide number of blogs, pages, articles, and brains. This page attempts to collate _links_ to some of this information. 8 | 9 | ### History 10 | 11 | * A brief history of 2D graphics is presented in this [introduction for a course](https://hal.inria.fr/hal-01815193/document) on digital typography. 12 | * [Font rendering is getting interesting](https://aras-p.info/blog/2017/02/15/Font-Rendering-is-Getting-Interesting/) 13 | * [Why are 2D vector graphics so much harder than 3D?](https://blog.mecheye.net/2019/05/why-is-2d-graphics-is-harder-than-3d-graphics/) 14 | 15 | ### Blogs 16 | 17 | * [Mozilla gfx team ](https://mozillagfx.wordpress.com)\(WebRender, design of 2D graphics APIs for the browser\) 18 | * [nical's blog](https://nical.github.io/index.html) \(Lyon, WebRender, general 2D graphics API design considerations\) 19 | * [kvark's blog](http://kvark.github.io/) \(WebRender, gfx-rs\) 20 | * [pcwalton's blog](https://pcwalton.github.io/) \(Pathfinder 3\) 21 | * [raphlinus' blog](https://raphlinus.github.io/) \(piet, 2D graphics API considerations, fonts, text rendering, splines, general 2D graphics API design considerations\) 22 | * [behdad's page](http://behdad.org/) \(harfbuzz, fonts, text rendering\) 23 | 24 | ### 2D Graphics API design 25 | 26 | * [raphlinus: "A crate I want: 2d graphics"](https://raphlinus.github.io/rust/graphics/2018/10/11/2d-graphics.html) 27 | * [nical: Following up on the 2d graphics in Rust discussion](https://nical.github.io/posts/rust-2d-graphics-01.html) 28 | 29 | #### Rust 2D or 3D libs (that aren't `kurbo`) 30 | 31 | * [`euclid`](https://lib.rs/crates/euclid) and [`lyon_geom`](https://lib.rs/crates/lyon_geom) 32 | * [`arcs` by Michael-F-Bryan](https://github.com/Michael-F-Bryan/arcs) 33 | 34 | ### 2D antialiasing and font rasterization 35 | 36 | #### Trapezoidal pixel coverage algorithm 37 | 38 | * [How the stb\_truetype Anti-Aliased Software Rasterizer v2 Works](https://nothings.org/gamedev/rasterize/) 39 | * [raphlinus: Inside the fastest fontest renderer in the world](https://medium.com/@raphlinus/inside-the-fastest-font-renderer-in-the-world-75ae5270c445) 40 | * \(Skia/Spinel team members\) [Path rendering by counting pixel coverage](https://www.tdcommons.org/cgi/viewcontent.cgi?article=1580&context=dpubs_series) 41 | 42 | #### Other 43 | 44 | * [Texts Rasterization Exposures: An attempt to improve text rasterization algorithms using only publicly available information](https://web.archive.org/web/20180921225907/http://antigrain.com/research/font_rasterization/index.html#FONT_RASTERIZATION) 45 | * [The Raster Tragedy at Low-Resolution Revisited: Opportunities and Challenges beyond “Delta-Hinting”](http://rastertragedy.com/) \("RL: ...a justification for why Microsoft made exactly the choices they did 10+ years ago..."\) 46 | 47 | ### Gamma Correction 48 | 49 | * [What every coder should know about gamma](https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/) 50 | * [Wikipedia](https://en.wikipedia.org/wiki/Gamma_correction) 51 | 52 | ### Papers on approaches to efficient rendering of 2D graphics 53 | 54 | * [\(2014\) \(Ganacim, Lima, de Figueiredo, Nehab\) Massively-Parallel Vector Graphics](http://w3.impa.br/~diego/projects/GanEtAl14/) 55 | * [\(2017\) \(Lengyel\) GPU-Centered Font Rendering Directly from Glyph Outlines](http://jcgt.org/published/0006/02/02/) \(Slug Font Rendering Library\) 56 | * [\(2016\) \(Li, Hou, Zhou\) Efficient GPU Path Rendering Using Scanline Rasterization](http://kunzhou.net/zjugaps/pathrendering/) 57 | 58 | ### Other links on approaches to efficient rendering of 2D graphics 59 | 60 | * [Blend 2D - Innovations](https://blend2d.com/doc/innovations.html) \([HN discussion](https://news.ycombinator.com/item?id=19580647)\) 61 | * [thetamath.com - Easy Scalable Text Rendering on the GPU](https://medium.com/@evanwallace/easy-scalable-text-rendering-on-the-gpu-c3f4d782c5ac) 62 | * [nical's Google doc on Pathfinder 3](https://docs.google.com/document/d/146WIsAu7aYC_uvinpCURLS1K8TTSVREAorBi0GCIAMw/edit) 63 | 64 | ### Mathematics 65 | 66 | * [Inclusion of a Point in a Polygon](http://geomalgorithms.com/a03-_inclusion.html) \(winding number\) 67 | * [2D graphics rendering course](http://w3.impa.br/~diego/teaching/2021.0/index.html) 68 | 69 | ### Repositories of interest 70 | 71 | * [makepad](https://github.com/makepad/makepad) \(immediate mode 2D graphics\) 72 | * [spinel](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/src/graphics/lib/compute) \(hyper-optimized, Vulkan 1.1 2D graphics\) 73 | * [nanovg](https://github.com/memononen/nanovg) 74 | * [piet-metal](https://github.com/linebender/piet-metal) \(experimental compute approach to 2D graphics\) 75 | * [pathfinder](https://github.com/pcwalton/pathfinder/) \(pcwalton's Pathfinder 3\) 76 | * [webrender](https://github.com/servo/webrender) \(Mozilla gfx team's WebRender\) 77 | * [glyphy](https://github.com/behdad/glyphy) \(behdad's signed distance field approach to font rendering\) 78 | * [msdfgen](https://github.com/Chlumsky/msdfgen) \(multi-channel signed distance field generator\) 79 | 80 | ### xi-org Zulip discussions of interest 81 | 82 | * [makepad](https://xi.zulipchat.com/#narrow/stream/147926-druid/topic/makepad) 83 | * [Conflation artifacts](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/Conflation.20artifacts) 84 | * [Thoughts on piet-metal](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/Thoughts.20on.20piet-metal) 85 | * [gpu stream](https://xi.zulipchat.com/#narrow/stream/197075-gpu) 86 | 87 | {% hint style="info" %} 88 | This wiki is now **archived**. You should instead visit the [Linebender wiki](https://linebender.org/wiki/) at 89 | {% endhint %} 90 | --------------------------------------------------------------------------------