Code Monkey home page Code Monkey logo

Comments (7)

lexi-lambda avatar lexi-lambda commented on September 28, 2024 1

Hi, @soegaard—I just took a look at this. After some investigation, I suspect that pango_context_set_round_glyph_positions may be relevant. By default, Pango rounds all glyph positions to pixels, regardless of hinting settings, but that function can be used to disable that behavior.

Unfortunately, when I actually experimented with disabling rounding, I found that it didn’t seem to affect the rendering at all on my machine. While I’m not sure why that would be the case, after some further reading, I get the sense this may be because the version of Cairo I have on my machine (which is running Ubuntu 20.04) doesn’t support subpixel positioning (which is distinct from what’s normally called “subpixel rendering”!) for the necessary font backend. If you’re on macOS, you might want to give it a try yourself (and disable hinting) and see if that changes anything.

Having said all of this, I think you probably don’t want to be using draw-text if you’re animating text, anyway. Font rendering is really complicated, and there are so many different moving parts involved in a modern text rendering stack that it makes my head spin. Lots of those parts have to make tough choices about how to place glyphs in a readable fashion, and arranging for all those choices to be temporally consistent under transformation seems like probably a lost cause.

Instead, I think what you almost certainly want to do is convert the text to an outline first using the text-outline method of dc-path%, then fill the resulting path using the draw-path method of dc<%>. This will run through the whole text shaping and layout pipeline with the glyphs in a well-behaved configuration, namely placed in a straight line, then give you back a set of vector paths. Then, when you call draw-path, Cairo will render the path itself as an ordinary shape, skipping the OS- and backend-specific text rendering pathways altogether. Cairo certainly knows how to do antialiasing for arbitrary paths, so you’ll get a smooth animation.

There are two major downsides to rendering text this way:

  1. Since Cairo’s drawing the paths itself, all of the fancy logic in your operating system’s text layout and rendering stack will be skipped: you’ll get no font hinting or subpixel antialiasing/LCD smoothing, and any user-controlled, OS-wide font rendering options will be ignored.

    In your case, this is more of a feature than a bug, since you want to animate the paths yourself. But it does mean that you may need to take some extra care to avoid blurry edges resulting from misalignment—though, fortunately, dc<%>’s 'aligned drawing mode is probably sufficient to avoid that most of the time.

  2. Since you’ve converted the glyphs to a shape, their textual content is necessarily lost before they get to the backend. This means that if you’re using a pdf-dc%, for example, the rendered text won’t be selectable in a PDF viewer.

    This probably doesn’t matter to you, because if you’re rendering an animation, you aren’t going to be using the PDF backend, anyway. Moreover, I’m not sure racket/draw currently actually sets the relevant options to have the text stored in the PDF in the first place.

tl;dr: I’m not exactly sure what the problem is, but there are probably too many moving parts to make animated text look good in a backend-agnostic way without just drawing the glyphs yourself. Try that, instead.

from draw.

mflatt avatar mflatt commented on September 28, 2024

FWIW, I thought the answer to the dancing text was going to be creating a font with 'unaligned hinting, but that does not solve the problem.

from draw.

soegaard avatar soegaard commented on September 28, 2024

An obversation - made after I wrote the guess below:

The rotate? flag in do-text is set to (and draw-mode (not (zero? angle))).
But what if a rotation has been made with (send dc rotate angle) then the normal code path is taken.
Is that intended?

The loop in do-text draws in one of the paths each character individually.

https://github.com/racket/draw/blob/master/draw-lib/racket/draw/private/dc.rkt#L1709

My intution - but I am far from sure - is that the alignments of each individual character
gives a different result than using the line "top line" of the rectangular binding box
of the string.

Let's say we want to draw the text hello. The bounding box is a rectangle ABCD with the line AB
being at the top. Due to rotation the line AB might no be parallel to an axis.

If A is aligned to A1 and we set B1 to B+(A1-A), then the upper left corners of each
character ought to be on the line from A1 to B1. However if we align each individual
character, then I think there is a risk that two neighbour characters might move in
different directions relative to the line when aligned. At least when rotation is involved.

I haven't grooked the Pango part of the draw-text code, but this aligns each individual character:
https://github.com/racket/draw/blob/master/draw-lib/racket/draw/private/dc.rkt#L1709

from draw.

mflatt avatar mflatt commented on September 28, 2024

You can avoid the character-by-character loop by providing #t as the combine? argument to draw-text. But I think that doesn't solve the problem here.

Yes, as I remember/understand the code, the normal code path is meant to be taken when rotation is in the transformation.

from draw.

soegaard avatar soegaard commented on September 28, 2024

You are right, using #t as the combine? flag for draw-text didn't help.

from draw.

soegaard avatar soegaard commented on September 28, 2024

@lexi-lambda

You have looked at fonts and text rendering recently.

Have you spotted something that explains the behaviour in the video?

/Jens Axel

from draw.

soegaard avatar soegaard commented on September 28, 2024

Hi @lexi-lambda

Thanks for the very thorough answer.

I am currently using draw-text to implement text [1] in Sketching.
The text function optionally accepts a rectangle to draw the text within
and supports left, center and right alignment of the text.

Since it is part of Sketching, I don't know whether the text will be used
for animation or for static text.

I'll make an experiment with text-outline + draw-path instead of draw-text.
If the results look identically I'll just use the new method.

I was hoping there were some low-level Cairo routines I could have used.

[1]
https://github.com/soegaard/sketching/blob/3773cb790ac69201c967201a2fa1727d90a4ad62/sketching-lib/sketching/typography.rkt#L214

from draw.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.