[HN Gopher] Show HN: Dropflow, a CSS layout engine for node or <...
___________________________________________________________________
Show HN: Dropflow, a CSS layout engine for node or <canvas>
For the last 5 years I've been working on a layout engine that
targets CSS2 and some more modern properties. Live demo:
https://chearon.github.io/dropflow/ It matches browsers in all
cases I can find where they agree, and it's fast. It supports
`position`, `inline-block`, `z-index`, and complex properties like
`float` and `vertical-align`. It doesn't support high-level layout
like flexbox or grid yet, but you can get intrinsics to easily
divide space yourself and paint multiple layout trees. It has a
great text layout implementation, and supporting non-Latin scripts
is a top priority. I've wanted this to exist as far back as 2013,
and the desire kept coming up: for a way to get detailed
intrinsics, for high quality rich text layout to canvas and SVG,
and for server-side rich text. We currently use it in CellEngine
for our new canvas-based spreadsheet library to layout text in
hundreds of thousands of cells, and will be using it soon to render
PDFs with thousands of pages in a few seconds.
Author : chearon
Score : 267 points
Date : 2024-03-21 13:58 UTC (9 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| big_paps wrote:
| Well this looks like something useful. Can't imaging how much
| work is needed to first understand css and then to build a layout
| engine around it.
| troupo wrote:
| There's also Facebook's Yoga: https://github.com/facebook/yoga
| Rohansi wrote:
| Yoga is great but only really supports flexbox. For most
| cases that can be enough but inline content (as shown in the
| Dropflow demo) is difficult with only flexbox layouts
| available.
| lovegrenoble wrote:
| For anyone struggling with flexbox, you can use this tool to
| streamline the process of creating
|
| responsive layouts, removing the need to focus on multiple
| properties: https://flexboxcss.com
| airstrike wrote:
| thank you for this!
| undershirt wrote:
| thank you
| techscruggs wrote:
| This is the first site I've run in to that uses neumorphic
| design. Love the aesthetic -- just never seen in it the wild
| before.
| bobajeff wrote:
| This sounds close to what I've been wondering about lately. I was
| wondering if css and svg could be used as abstraction over
| graphics and UI libraries. This is my first time hearing of node-
| canvas looks like it fills the drawing part of the solution.
| While this may do the layout portion (which is all I need from a
| UI library).
|
| I wonder how hard it was to implement css. I've heard it can be
| pretty complex.
| chearon wrote:
| > wondering if css and svg could be used as abstraction over
| graphics and UI libraries
|
| There's another project called Sciter that uses CSS to target
| native graphics libraries: https://sciter.com
|
| > I wonder how hard it was to implement css. I've heard it can
| be pretty complex.
|
| It was hard, but the biggest barrier is the obscurity of the
| knowledge.
|
| Text layout is the hardest, because working with glyphs and
| iterating them in reverse for RTL is brain-breaking. And line
| wrapping gets really complicated. It's also the most obscure
| because nobody has written down everything you need to know in
| one place. After I finished block layout early on, I had to
| stop for a couple of years (only working a few hours a week
| though) and learn all of the ins, outs, dos, and don'ts around
| shaping and itemizing text. A lot of that I learned by reading
| Pango's [1] source code, and a lot I pieced together from
| Google searches.
|
| But other than that, the W3C specifications cover almost
| everything. The CSS2 standard [2] is one of the most beautiful
| things I've ever read. It's internally consistent, concise, and
| obviously the result of years of deliberation, trial and error.
| (CSS3 is great, but CSS2 is the bedrock for everything).
|
| [1] https://gitlab.gnome.org/GNOME/pango/
|
| [2] https://www.w3.org/TR/CSS22/
| jsunderland323 wrote:
| I'm curious if you've implemented a rich text editor with
| this. I think Google Docs uses canvas. I hate the browser
| APIs for rich text and wonder if this could be more a viable
| candidate than using contenteditable for future projects
| chearon wrote:
| Google Docs uses canvas, yeah, and last I looked it used an
| empty contentEditable just to receive [rich text] input. I
| do think you could use this to write a document editor like
| Docs and side-step many of the problems with
| contentEditable, but I haven't tried to.
|
| Every time someone releases a new rich text editor I'm
| disappointed to find that it uses contentEdtiable. Would be
| very interesting!
| c-smile wrote:
| > Every time someone releases a new rich text editor ...
| uses contentEdtiable
|
| Sciter is using its own implementation (obviously).
|
| contentEdtiable thing is indeed quite limited for general
| purpose WYSIWYG editor.
|
| For example Web platform is missing transactional update
| [1] mechanism that allows to put custom DOM mutation
| groups into unified undo/redo stack.
|
| Sciter's <htmlarea> element ( implement behavior:richtext
| - WYSIWYG ) allows to build specialized editors. For
| example it is used in Sciter.Notes [2].
|
| [1] https://docs.sciter.com/docs/behaviors/behavior-
| richtext#ric... [2] https://notes.sciter.com/
| Traubenfuchs wrote:
| > It's also the most obscure because nobody has written down
| everything you need to know in one place
|
| Your work might have been, or maybe still is, the worlds
| biggest chance for this to change!
| ape4 wrote:
| Its too bad browsers don't support this. // Do
| CSS layout in the regular document const doc = new
| CssLayout(document); doc.layout(...); // Do
| CSS layout on your own canvas const mycanvas = new
| CssLayout(document.getElementById('mycanvas'));
| mycanvas.layout(...);
| Sesse__ wrote:
| The security implications would be interesting, unless you
| tainted the canvas (which makes it instantly less useful).
| awesomekling wrote:
| Super cool! Nice job, chearon :)
| chearon wrote:
| Wow thanks! Seeing Ladybird progress kept me motivated!
| 1oooqooq wrote:
| why not ship a desktop application at this point with support for
| a special schema?
|
| i can understand the abuse for server side rendering, but at this
| poit you pretty much have a bad browser engine. running inside a
| 2d hack in a browser engine. sigh.
| Bjartr wrote:
| Why re-invent the wheel with a special schema when CSS2 is a
| solid standard and widely understood? Is there no room in the
| world for rendering implementations between nothing at all and
| full-spec web browser with all the bells and whistles?
| 1oooqooq wrote:
| I'm actually advocating against re-inventing the wheel
| (insider another wheel, no less)
|
| you can still follow css spec if you want. just get a better
| environment than a canvas.
| robbiejs wrote:
| This is a big achievement, congrats! A lot of time must have been
| put into this I am sure. And you are also making a spreadsheet
| product AND a PDF (preview?) product? How do you combine it?
| chearon wrote:
| With this and node-canvas, you have everything you need to
| generate PDFs. I'll add an example to the examples/ directory
| for that. The spreadsheet library and PDFs I talked about in OP
| were examples of how we use this in our application, but are
| closed-source.
| XCSme wrote:
| Could I use this together with Pixi.JS ?
| jasonjmcghee wrote:
| Are you planning to add support for the missing standard tags
| like img and table (both very useful for pdf rendering)?
| chearon wrote:
| Yes, definitely. In the meantime, you can still use this to get
| the intrinsic sizes of cells to create rows and columns, and
| you can use an empty inline-block and paint the image where
| it's laid out. I'll put something in the examples/ directory
| soon.
| AndriyKunitsyn wrote:
| I wonder if there's something opposite -- an abstraction for the
| Web to provide some layout rules that are more sane than CSS.
| usrusr wrote:
| Feels a bit like history repeating (well, rhyming) with the time
| back when Java was "the language of web applets" and then Sun
| created the Hotjava browser and confusion reached the point where
| minds simply blank out. Few technological novelties have been
| forgotten more decidedly than Hotjava. Despite marking an
| intersection of two technological fields (browsers and the JVM)
| that have shown extreme staying power through the last quarter
| century.
|
| But the idea of using html for text styling has stuck, Swing UI
| do text styling with html (and rudimentary css!) to this day.
| Html would not be a lingua franca if its use was limited to the
| equivalent of native speakers (browsers).
| eigenvalue wrote:
| I worry that this sort of technology is going to lead to webapps
| that aren't really what we've grown to think of as "the web" but
| which will instead be closer to a VNC window where you just see
| pixels and can't interact with anything or see how stuff works in
| devtools.
| jdiff wrote:
| Accessibility features would need to be added to canvases
| before that reality's possible, so we've got a ways to go yet
| before we need to worry too much about that.
| joelanman wrote:
| traditionally, lack of accessibility has unfortunately not
| held back people's use of tech, see Flash and most SPAs
| jdiff wrote:
| The people who would do this canvas trickery are the people
| that would be held back by the lack of accessibility.
| guhcampos wrote:
| Is it bad though? This is of course a rethoric question, I
| don't know myself if I think it's good or bad, yet.
|
| What I'm thinking is: there's been soo much discussion around
| "we have corrupted the Web", "Web standards were never made to
| build apps on", etc. with sometimes good and sometimes really
| bad arguments.
|
| If we can build viewports in canvas that behave more like just
| a desktop environment where apps can be built, maybe that could
| be good? It could mean a split between the informational web
| and the "apps on the browser" paradigm, and in a ideal scenario
| this could make things simpler and more organized for everyone?
| Or it could just mean more work, more standards, more rupture
| and more siloing. Honestly don't know.
| littlestymaar wrote:
| It wouldn't be bad if we were sure it wasn't going to be
| abused to make apps where ads cannot be blocked, consent
| extortion pop-up cannot be removed, content cannot be copy-
| pasted, etc. unfortunately, this is the way this industry is
| always going, so there's good reason to be scared.
|
| (It's also terrible for accessibility, for both disabled
| people or just regular users who expect to be able to
| navigate with the keyboard for instance, unless the framework
| re-implement everything itself, which I doubt)
| wizzwizz4 wrote:
| > _unless the framework re-implement everything itself_
|
| In which case, we're able to make an "inspect element"
| tool, which we could use to copy text out, and at the very
| least draw black rectangles on top of adverts.
| https://xkcd.com/2677/
| ttepasse wrote:
| A major point of the web for me back in the 90s was that
| everything was text. You could inspect it, you could change
| it, you could curl it. That's why Java and Flash and
| Silverlight were so annoying, they were blackboxes inside web
| pages. I can't help but see this today like those yesterday.
| danielvaughn wrote:
| I don't see this, or any other equivalent effort, taking off.
| It's neat, but CSS layout is a small part of the overall
| problem. Even setting side accessibility, which is a massive
| undertaking in and of itself, you have text rendering.
|
| To get an idea of what you'd have to emulate, here are _some_
| (not even all) issues related to rendering text:
| https://faultlore.com/blah/text-hates-you/
| dspillett wrote:
| Even without this that is happening in small ways. I've seen a
| few fairly visual pages (graphs & charts, etc.) where parts
| that could be done with plain HTML+CSS such as separate tables
| containing the data (or a subset thereof) displayed in the
| charts was also rendered on a canvas.
| abofh wrote:
| Every snake eats its own tail eventually - we went from bit
| blasting onto a frame buffer in 320x200 to bit blasting vector
| graphics onto a virtual frame buffer. (I leave out earlier
| steps and later steps, but every implementation eventually
| tries to implement its framework - it seems like the natural
| flow of things)
| nickpsecurity wrote:
| That's what a GUI app is, though. You could say it's the
| default way we interact with graphical apps. Web browsers,
| along with web-enabled platforms, add a bunch of extra stuff to
| that.
|
| Many of us just want good, GUI apps for many things. They were
| often faster and lighter. VS Code is the exception to the rule
| which I use regularly.
| lewisjoe wrote:
| This is an amazing piece of work. Thanks for making this open-
| source.
|
| The default way of generating beautiful PDFs in the backend these
| days is, running a headless browser and using browser APIs to
| turn HTML/CSS into PDFs. And apparently, it's a bit costly
| running instances of browser in the server and scale it properly
| for huge workloads.
|
| This is literally a game changer. Now it's possible to design
| PDFs using HTML/css and generate them without the browser
| overhead!
| bawolff wrote:
| As an aside its amazing how far the web has come, where the
| best way to make pretty pdf documents is to literally run a web
| browser on the server. This would have been so unthinkable back
| in the 90s & 2000s
| vanderZwan wrote:
| I'm _fairly_ certain that using a headless browser on the
| server is mainly about sandboxing all the security concerns
| that PDFs have, not aesthetics, but yes.
| bawolff wrote:
| Security of the pdf format is not relavent here. The
| headless browser outputs a PDF. It is not taking a user
| controlled pdf as input.
| vanderZwan wrote:
| Ah of course, my apologies. I misread the original post.
| menacingly wrote:
| it's actually because layout-via-code for arbitrary
| documents is a humblingly complex problem, so leveraging
| existing layout engines is preferred.
|
| This impressive effort looks far better than what I'd
| achieve, but when this approach has been tried before, it
| is eventually discovered that few organizations have the
| resources to maintain a rendering engine long-term.
| chearon wrote:
| I do think complexity could be part of why we don't have
| many options here, but I don't agree that a layout engine
| is too difficult to maintain. More of the issue is that
| CSS layout (and maybe layout in general) is not widely
| well-understood. I've almost _never_ come across people
| interested in layout because generally it's a few
| properties to get something working and then you move on.
|
| > few organizations have the resources to maintain a
| rendering engine long-term
|
| I'm curious are there other instances of this happening
| than Edge switching to Blink? That event was one of my
| main motivators; it felt like further consolidation of
| obscure knowledge.
| Sesse__ wrote:
| Opera switched from Presto to Blink, too.
|
| Very fun project! Did you ever consider integrating with
| web-platform-tests? It's shared between all the common
| browser vendors, and we're always interested in more
| contributors :-)
| rajh wrote:
| I needed to transform a 12MB HTML file into a PDF document
| and headless Chrome quickly ran out of memory (4GB+).
|
| We are now using a commercial alternative that seems be be
| using a custom engine that implements the HTML and CSS specs.
| The result is reduced memory usage (below 512MB during my
| tests) and the resulting PDF is much smaller, 3.3MB vs 42MB.
| phonon wrote:
| Did you try Weasyprint?
| ManBeardPc wrote:
| Have you tried Typst? It's like a modern version of LaTeX and
| allows to generate nice looking documents quickly. Can be
| called from the console and makes it easy to create templates
| and import resources like images, fonts and data (csv, json,
| toml, yaml, raw files, ...). Of course it is its own language
| instead of HTML/CSS but so far I found it quite pleasant to
| use.
| sciolistse wrote:
| Back around 2002 at least there were some products, ABCpdf is
| one I used a lot, which ran Internet Explorer on the server
| to generate PDFs from HTML. Worked pretty well from what I
| recall.
| pmx wrote:
| I've used this with good success
|
| https://ekoopmans.github.io/html2pdf.js/
| Pelerin wrote:
| I'm a little confused by your comment. I've been using the
| Prawn library to generate PDFs on the backend for a side
| project I am working on for quite sometime
| https://github.com/prawnpdf/prawn
|
| (Admittedly, the PDFs I generate are most certainly not
| beautiful, so maybe that's the difference)
| Lukas_Skywalker wrote:
| Prawn really is great. I use it to generate invoices and for
| exporting a billing overview in client projects. And it's
| quite fast as well, since it generates the PDF directly
| without the need to spin up a browser.
| lukew3 wrote:
| Lots of people are already really comfortable with html/css,
| so having the option to avoid learning an entirely new
| paradigm is helpful.
| ricardobeat wrote:
| > One thing Prawn is not, and will never be, is an HTML to
| PDF generator
| thekingshorses wrote:
| One of the benefits of using the browser is that the generated
| PDF will be using vectors/fonts etc whereas Canvas will be
| mostly an image in the PDF. Not a big deal for the most use
| cases.
| aidos wrote:
| I feel like it's probably not a leap to go from this to
| having a PDF renderer as a backend. The trickiness is in the
| layout, which this is already doing. Looks to be a lower
| level api and a way to render to absolutely positioned html.
| That gets you most of the way there.
| pietroppeter wrote:
| I would be very much interested in articles on how to write a CSS
| layout engine from scratch
| bawolff wrote:
| Not exactly what you are looking for, but if you haven't seen
| it, firefox has some really interesting blog posts about how
| their css engine works, e.g.
| https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-en...
| that i personally found really enlightening
| nicoburns wrote:
| I've been considering writing such a thing. Although I've only
| implemented Flexbox and CSS Grid so far. The CSS specifications
| for those algorithms are worth reading if you're interested in
| this kind of thing. They're a challenging read, but not an
| impossible one.
| joelanman wrote:
| this wouldn't be accessible would it? For example to screen
| readers, so just wondering what the use case is over accessible
| tech
| mattmar96 wrote:
| Oh wonderful. Thank you! I was looking for something like this
| for my project https://htwins.net/scale2 and others which use svg
| or canvas
| eob wrote:
| This is incredible --- @chearon thank you for open sourcing this!
|
| I think most folks probably don't realize how difficult it is to
| go from HTML -> PNG programmatically. You get hit with a thousand
| papercuts related to either Node<>Browser differences or
| HTML<>Canvas differences.
| shepherdjerred wrote:
| I've used satori [0] on the backend with TypeScript/Deno to
| render React JSX + tailwind CSS as an SVG (which is then rendered
| to a PNG). Of course you could use another flavor of JSX (or even
| plain HTML) or omit tailwind, but it's really cool that you can
| use the same stack as a typical frontend and render it as an
| image.
|
| Satori is meant for rendering Open Graph images (e.g. the little
| images that come up when you post a link on
| Twitter/Slack/Facebook), but I found that it works well for
| rendering arbitrary images. Satori has no native dependencies, so
| it kinda "just works" on the backend. It supports a subset of
| modern CSS, including flexbox.
|
| My use case is posting match reports for League of Legends into a
| Discord text channel, e.g. person X just played a match, here are
| their stats.
|
| It's quite nice because there are almost zero server-side native
| dependencies (the one exception is the library to convert svg ->
| png requires some native libraries).
|
| Here's what a match report looks like: [1]
|
| Here's an example of what the JSX looks like: [2]
|
| I also built a small project [3] that renders the JSX in a
| browser to make developing the images just as easy as developing
| a normal website.
|
| If others are interested in this, I would by happy to write a
| blog post about the process.
|
| [0]: https://github.com/vercel/satori
|
| [1]:
| https://github.com/shepherdjerred/glitter/blob/main/assets/p...
|
| [2]:
| https://github.com/shepherdjerred/glitter/blob/main/packages...
|
| [3]:
| https://github.com/shepherdjerred/glitter/tree/main/packages...
| LinguaBrowse wrote:
| Thanks for sharing this. I'll be checking its potential as a base
| element for something like NativeScript or Node.js.
|
| Text is about the most complex UI element that a UI framework
| offers, and if you've got Flow Layout working, that's very
| encouraging! Will be interested how far along things like
| gestures (particularly text highlighting) and IME integration
| are. In any case, kudos for opensourcing this!
| mwit2023 wrote:
| will give it a try for opengraph images, thank you!
| Vt71fcAqt7 wrote:
| This looks great. As you mention PDF, do you plan to support the
| various @page properties that add pagination? For example like
| pagedjs[0] but native? Major usecases are books and invoices
|
| [0] https://pagedjs.org/about/
| chearon wrote:
| Yes, this is pretty high up on my list. I've already done a
| little bit of work on pagination/fragmentation, but it will
| take me some time.
| wg0 wrote:
| This is pure craftsmanship. A heavy undertaking TBH, kind of
| reinventing browser flow on top of browser primitives.
| rrgok wrote:
| Perhaps I'm missing something, but why can't we render HTML
| directly onto the canvas in the browser? The parser is there, the
| layout engine is already implemented, and the calculation of box
| layout is already done. It should be doable without going in
| circles. If only the browser had a flag indicating which
| "surface" to render on.
|
| I was looking at Glide Grid the other day, and it renders so
| fast, even with 1 million rows; it's somehow responsive. There
| should be an easier way to render HTML to canvas without
| resorting to low-level primitives. Why is canvas faster than the
| "regular" DOM renderer?
| eeiaeaa wrote:
| Glide grid renders to canvas also.
| rrgok wrote:
| Perhaps I worded it wrong: I meant to bring Glide Grid as an
| example how fast we can render millions of items to canvas.
| duckfruit wrote:
| But if all you want to do is render HTML then why use <canvas>?
|
| I'm only speculating, but it doesn't seem surprising that
| regular DOM rendering logic - which has to handle approximately
| a bazillion different rules and special cases - is slower than
| a custom renderer written for a specific subset of HTML.
| hwillis wrote:
| If you want to do any kind of text or diegetic UI in webgl,
| you are _begging_ for DOM rendering to canvas (which is then
| sent to a texture)
| robbiejs wrote:
| Glide Grid is an amazing achievement I have to say!
|
| You can have a fast DOM without canvas, but it requires
| creative thinking. DataGridXL also renders millions of cells,
| but it does not use canvas as its main renderer
| (https://www.datagridxl.com/demos/one-million-cells).
|
| The way it works: only columns are their own DOM nodes. For
| browsers it's just too much to ask to re-render let's say
| (20rows*10cols) 200 DOM nodes while keeping scrolling at 60fps.
| spankalee wrote:
| > it's just too much to ask to re-render let's say
| (20rows*10cols) 200 DOM
|
| I don't think this is true with modern browsers and CSS. For
| a table, every cell and parents of the cells as much as
| possible, should be styled `contain: strict` and if possible,
| absolutely positioned.
| robbiejs wrote:
| It's still true. You might be able to get decent
| performance on a Macbook 3000 (doubtful even) but anything
| less than that, nope. That's why many grid components use
| canvas rendering. It would have been a lot easier for all
| these grid devs to work with DOM nodes if they could.
| dtf wrote:
| As far as I remember, it's down to security concerns.
|
| You can actually insert your HTML into a SVG foreignObject, and
| then drawImage() that onto your canvas. But your HTML-in-SVG
| document will need to load all its own resources, fonts, CSS
| etc.. which makes this process rather tedious.
| lloydatkinson wrote:
| It doesn't support flex box? I really can't tell what the purpose
| of this library is then.
| peer2pay wrote:
| I have nostalgia for a lot of things in webdev, hacking together
| floating layouts is not one of them. /s
|
| But congrats on the work! I can definitely see this being useful
| for text formatting and layouting PDFs. Neat!
| dohello1 wrote:
| verry
| justhw wrote:
| This looks great. I've been using html2canvas but it doesn't
| support the 'filter' property yet. This will be an awesome
| alternative.
| moron4hire wrote:
| This sounds great.
|
| In a past role, my job was to develop an immersive, online
| learning platform. We used Oculus Quest 2s to do foreign language
| training for DoD personnel. WebXR, Three.js, etc, because I had
| had enough Unity3D for one lifetime and we didn't want to submit
| to app store reviews. We had a fleet of our own devices, so it
| was fine.
|
| One of the biggest challenges with the project was creating a
| workflow for didactic content. By myself. I had an employee who I
| supervised working for me, but most of the work was of such high
| technical level that it was way over their head and we couldn't
| afford to hire anyone else. I eventually landed on having our
| actual language instructors use PowerPoint to create PDFs, use a
| bespoke editor I created to upload the PDF into a content
| database and position them in the training environments, and then
| used PDFJS to render them to canvas elements to then texture on a
| 3D quad.
|
| Something like this would have made it possible for me to avoid
| having people go out of band into PowerPoint to make those
| materials. The PowerPoint route did dramatically improve our
| workflow speed over a previous attempt to get people to author
| images in Photoshop. But if I could have built the "sign" editor
| into the app, it would have improved it even more by eliminating
| the "guess what will look good in the environment, export to PDF,
| upload to the database (oh, BTW, not a lot of people know how to
| keep files well organized), then find out how it really looks"
| cycle.
|
| Oh well. We didn't have a business development team or market
| department that knew anything about selling products instead of
| services, so I guess the point is moot anyway.
| vthommeret wrote:
| Does anyone have a similar solution for drawing graphs / charts
| in a Node environment without a browser dependency? Last time I
| explored this I couldn't find any good solutions.
| tills13 wrote:
| You could use https://github.com/vercel/satori which supports
| Node 16+.
| vthommeret wrote:
| Thanks. I've tried using Satori but I'm curious if you've
| used it to draw graphs specifically. E.g. Satori expects JSX
| / doesn't support HTML strings from d3-node with
| dangerouslySetInnerHTML.
| AaronFriel wrote:
| Unfortunately not for nested inline nodes, like spans of text
| with formatting. For a lot of uses, that will be OK - but for
| rendering say, markdown text, Satori won't work.
|
| The upstream layout engine handles flexbox layout, and it's
| unclear if Facebook needs inline layout or if Vercel would
| pick it up and close the gap:
| https://github.com/facebook/yoga
|
| Then again, for the main purpose Satori is advertised for -
| generating URL unfurl previews - Dropflow looks like it might
| be the answer.
| AaronFriel wrote:
| Does this depend on a browser? It looks like it doesn't - which
| is pretty impressive!
| foreigner wrote:
| What is the API to produce SVG?
___________________________________________________________________
(page generated 2024-03-21 23:00 UTC)