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

Render text in wasm32-unknown-unknown #229

Closed
dabreegster opened this issue Feb 26, 2020 · 21 comments
Closed

Render text in wasm32-unknown-unknown #229

dabreegster opened this issue Feb 26, 2020 · 21 comments

Comments

@dabreegster
Copy link
Contributor

usvg currently works great in wasm environments as long as the optional "text" feature is disabled. I'd love to get text support working too. From my understanding so far, there are at least 3 issues:

The first two are relatively straightforward. As part of #202, design an API to feed a FontDB into usvg that can be instantiated many different ways, one of them just being raw bytes of a font file. (include_bytes! is a low-effort way to get this working in a wasm environment.)

The harfbuzz dependency seems harder. My requirements are limited to simple Latin left-to-right text; harfbuzz is overkill. I found font2svg and think it might be possible to make something much simpler. Before I go down this rabbit hole, I wanted to ask for your advice.

Background

I'm using usvg in A/B Street to turn both normal SVG files and text into paths for lyon, which then give me polygons. This does the usvg->lyon->my simple Polygon abstraction path, based off this example from lyon. I'm using this same pipeline for text as well. (There are many inefficient and silly things that the text pipeline does right now, like constantly re-load fonts.) In a few weeks, I'm hoping to properly split off my drawing, geometry, and GUI libraries as new crates for other people to use. These libraries attempt to give exactly the same experience on native and web -- not using system UI controls/style -- without any changes to user code needed for different platforms.

@RazrFalcon
Copy link
Collaborator

The harfbuzz dependency seems harder.

Believe me, I know =) https://github.com/RazrFalcon/rustybuzz

My requirements are limited to simple Latin left-to-right text; harfbuzz is overkill.

The harfbuzz dependency is mandatory. I do not plan reducing text rendering to Latin only, since this is against the SVG spec.

Anyway, Rust version will be way smaller.

like constantly re-load fonts

In your code or in usvg? Because usvg does this too.

Basically, the resvg 0.10 roadmap looks like this:

  1. Port harfbuzz. I hope I will finish in 2-3 month.
  2. Write a font query library (for TrueType fonts only for now). There are a lot of questions there also, like the caching, fontconfig integration and the API in general.
    Basically, you will be able to create a fonts storage (system, custom path, raw binary data) and then pass it to usvg.
  3. Keep only the raqote backend.

@dabreegster
Copy link
Contributor Author

dabreegster commented Feb 26, 2020

In your code or in usvg? Because usvg does this too.

In usvg; I meant that I'm calling usvg::Tree::from_str repeatedly, which loads fonts everytime.

It sounds like resvg 0.10 will exactly make wasm work. Let me know how I can help!

@RazrFalcon
Copy link
Collaborator

Yes, resvg/usvg were focused on correctness, spec conformance for now. And since I'm almost finished with the spec, I can start optimizing it bit by bit.

Right now, I'm implementing a zero-allocation variable fonts support in ttf-parser. Not sure if someone could actually help me with this task 😄
Anyway, I will let you know when the first version of "fontdb" became available for testing.

@khaledhosny
Copy link

HarfBuzz builds to WASM just fine, I have been using it for months, see https://github.com/harfbuzz/harfbuzzjs

@dabreegster
Copy link
Contributor Author

Oh? I'm not too familiar with the wasm/Rust interop, but there may be some way to get https://crates.io/crates/harfbuzz-sys to expose the JS bindings.

I'd personally prefer a pure Rust stack, so the work on rustybuzz is awesome.

@dabreegster
Copy link
Contributor Author

@RazrFalcon, I got text support in web working for the simple Latin LTR case, to unblock getting my project on the web. Before Rustybuzz is complete, do you think it's worth exposing this functionality to all users of usvg? The change is reasonably small: dabreegster@97ff395 and dabreegster/fontdb@04c8ffc. I can send PRs if you'd like. If it muddies up the API too much, I'm fine just pinning to my fork temporarily.

@RazrFalcon
Copy link
Collaborator

No, I thinks that a fork is the best solution for now.

As for rustybuzz, I have no idea when it became pure Rust. Sadly, I don't have time right now to work on it.

@RazrFalcon
Copy link
Collaborator

I guess it's fixed now.

@dabreegster
Copy link
Contributor Author

Congratulations on the rustybuzz release! There are a few small build changes to fontdb and usvg to avoid native dependencies like memmap; I'm preparing PRs now.

@RazrFalcon
Copy link
Collaborator

Oh, I've forgot about it. Since I've done with huge rewrites (tiny-skia, rustybuzz), I hope to release resvg/usvg more often.

@DerKarlos
Copy link

"usvg currently works great in wasm environments as long as the optional "text" feature is disabled."
How could I disable text? Do I have to build the lib myselve?
Could some one show me the shell command?

@RazrFalcon
Copy link
Collaborator

@DerKarlos Can you clarify what you want to do?

@DerKarlos
Copy link

Thank you for your fast replay!
This issue starts with this sentence. So I assume, there is a variated cradle of resvg or a way to build one, that does not render text but does compile with wasm-pack.
If I build resvg, memmap2 is included which does not build for WASM.

@dabreegster
Copy link
Contributor Author

The issue is fixed; usvg works just fine in wasm now. You need to disable the system-fonts feature. Something like this should help. If you want to see a quick demo of usvg rendering text on wasm, see here.

@DerKarlos
Copy link

That sounds good. But sorry, I am new to Rust and what ever I try, at last memmap2 gets used by wasm-pack and:
363 MmapInner::map_mut(self.get_len(file)?, file, self.offset, self.populate)
supplied 4 arguments, expected 3 arguments

The demo looks good but where to find the source? Or any example (with an Cargo.toml) to read SVC and write it to a byte array?

@RazrFalcon
Copy link
Collaborator

I assume this is what you want.

cargo build --target wasm32-unknown-unknown --no-default-features --features text

@DerKarlos
Copy link

Hm? To build my project, I use
wasm-pack build --target web --out-name web --out-dir ./pkg
If I use yours:
error: Package o2t v0.1.0 (/Users/karlos/Public/o2t) does not have the feature text

@dabreegster
Copy link
Contributor Author

The demo looks good but where to find the source?

https://github.com/a-b-street/abstreet/tree/master/widgetry_demo, and the widgetry crate has the library implementation. See https://a-b-street.github.io/docs/tech/dev/ui.html for design.

o2t v0.1.0 (/Users/karlos/Public/o2t) does not have the feature text

Is your repository online? No promises, but easier to help looking at your specific issue.

@DerKarlos
Copy link

You may see my code, I send you an invite.
I am puzzled: widgetry_demo does not use usvg
Still looking at your hints ...

@dabreegster
Copy link
Contributor Author

Thanks for the invitation, I'll take a look when I find time.

The demo crate pulls in the widgetry crate, where the work happens: https://github.com/a-b-street/abstreet/blob/c5671557defbd80ce749b8fa7faf7c166b3d23dd/widgetry/Cargo.toml#L9

@DerKarlos
Copy link

Sorry, I still don't see a way. The crux may be the tiny_skia.
I used your with resvg/examples/minimal.rs and was happy with the binary build.
But not with the build by wasm-pack: As memmap2 is used as soon as I ad usvg to the dependencies.
usvg reads the SVG syntax and calls lyon (but your example in lyon does not call ender( ... , pixmap

Your examples are just the "main.rs", no how to build. Bin is no problem but could you please add the files to build to WASM and how to call carto?
(The input file my be a path in the Web or a inline string constand. I do not need the output file, just the pixmap.data() )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants