Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plan: text decoration blob support #1418

Closed
Gankra opened this issue Jun 22, 2017 · 3 comments
Closed

plan: text decoration blob support #1418

Gankra opened this issue Jun 22, 2017 · 3 comments

Comments

@Gankra
Copy link
Contributor

@Gankra Gankra commented Jun 22, 2017

So today if gecko has text decorations that webrender can't handle we give up completely and produce a blob image for the text. I'd like to improve this situation so that webrender handles the things it can natively, but invokes gecko via blob images for the parts that it can't.

At the high level I want webrender to receive something like:

text
  - glyphs
  - font/style details
  - shadows [(color, offset, blur, ...), ...]
  - underline (kindICanHandle | blob)
  - overline (kindICanHandle | blob)
  - line-through (kindICanHandle | blob)

And for its rendering strategy to be something like:

drawText:
  for shadow in shadows {
    drawTextWithEffect(shadow)
  }
  drawTextWithEffect(None)

drawTextWithEffect(effect):
  drawUnderline(effect)
  drawOverline(effect)
  drawText(effect)
  drawLineThrough(effect) 

Potentially the drawTextWithEffect can actually be cached like:

drawText:
  let text = drawTextToTemp() // like drawTextWithEffect(None), but to temporary surface
  for shadow in shadows {
    compositeAndApplyEffect(text, shadow)
  }
  compositeAndApplyEffect(text, None)

But I have no idea if that approach is actually practical.

Note: I am currently omitting text-emphasis marks and selection from this description. I think selection can be handled by the client (drawing a box and tweaking colors), but I'm less certain about emphasis (they strictly should be drawn between text and linethrough -- possibly just needs to be a second list of glyphs).

Summary of Benefits

  • reduced bandwidth: currently clients are expected to just send the text again for each shadow with the effects applied. Under this system they would just send a list of shadow effects. (There's some sites that apply like 4 shadows to all their text to get a certain effect)
  • a path for migrating implementation from gecko to webrender incrementally (start all decorations as blobs, then teach it basic lines, then dashed lines, then wavy lines, etc.)
  • more text decoration/shadow logic can be shared between gecko and servo via webrender (e.g. Servo devs will do my job for me :P)
@Gankra Gankra changed the title text decoration blob support plan: text decoration blob support Jun 22, 2017
@Gankra
Copy link
Contributor Author

@Gankra Gankra commented Jun 22, 2017

Clarification: drawTextWithEffect probably only forwards a subset of the effects. i.e. blurring of the shadow should be a finalization step, and not something each piece of the text does itself.

@Gankra
Copy link
Contributor Author

@Gankra Gankra commented Jun 30, 2017

Ran into an issue in implementation: "hello 👏 there" will often contain two fonts -- one for the text, one for the emoji (because emoji aren't in many fonts). Similar thing for kanji and friends. However "hello 👏 there" should have a single shadow -- in fact all the paragraphs in a single stacking context should have their shadows on the same "layer" behind the text, per:

https://drafts.csswg.org/css-text-decor-3/#text-shadow-property

The shadow effects are applied front-to-back: the first shadow is on top. The shadows may thus overlay each other, but they never overlay the text itself. The shadow must be painted at a stack level between the element’s border and/or background, if present, and the elements text and text decoration. UAs should avoid painting text shadows over text in adjacent elements belonging to the same stack level and stacking context. (This may mean that the exact stack level of the shadows depends on whether the element has a border or background: the exact stacking behavior of text shadows is thus UA-defined.) It is undefined whether a given shadow layer shadows each glyph or decoration independently or if the text and/or decorations are flattened and then shadowed.

Discussing with some of the folks it seemed like the best path forward would involve introducing some kind of non-stacking-context to group a bunch of elements and say "these should have shadows" so the shadows can be done all at once. This would also let us remove the decorations from the text and just have them as "normal" blob images.

I need to do more experiments to figure out exactly what Gecko's doing here.

@kvark
Copy link
Member

@kvark kvark commented Aug 17, 2017

Closing as per IRC discussion. The WR part is done for the most part.

@kvark kvark closed this Aug 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.