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 MermaidJS diagrams #35

Closed
ghost opened this issue Nov 18, 2021 · 23 comments · Fixed by #60
Closed

Render MermaidJS diagrams #35

ghost opened this issue Nov 18, 2021 · 23 comments · Fixed by #60
Labels
enhancement New feature or request
Milestone

Comments

@ghost
Copy link

ghost commented Nov 18, 2021

Background

MermaidJS is a popular (38k ⭐) server-side rendering suite for translating text-based diagram descriptions into scalable vector graphics. No open source rendering library that I tried can render its diagrams (see issue). Kroki is a REST-based service for rendering text-based diagrams, including mermaid, as SVG.

Replicate

  1. Copy attached mermaid.svg.txt as samples/mermaid.svg (see Kroki render).
  2. Add the following method to SamplesRenderingTest.java:
    @Test
    public void testMermaid() throws TranscoderException, IOException {
    	test("samples/mermaid.svg");
    }
  3. Run the unit test method.

Expected

Diagram is rendered.

Actual

Exception while validating the XML: the <div> element is unexpected.

Work around

Comment out XML validation in SAXDocumentFactory.java:

  //parser.setFeature("http://xml.org/sax/features/validation", isValidating);
  //parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);

Continue

  1. Re-run the test.

Expected

The diagram renders.

Actual

<style> is expected to be <style type="text/css">.

Work around

Add the missing type attribute. Consider relaxing the DTD.

Continue

  1. Re-run the test.

Expected

Diagram is rendered.

Actual

Cannot parse the CSS.

Work around

None. At this point the CSS parser cannot handle the semi-colon. Specifically, in CSSParser.java, the handleSemicolon method fires an endOfPropertyDeclaration. Is parsing the double-quotes for "trebuchet ms" causing the parser to get into an invalid state?

Addendum

Using the W3C validator service, the document validates correctly as an SVG 1.1 document.

@ghost ghost changed the title mermaidjs produces unparsable vector graphics mermaid diagramming tool produces unparseable vector graphics Nov 18, 2021
@carlosame carlosame added the enhancement New feature or request label Nov 18, 2021
@carlosame
Copy link
Member

carlosame commented Nov 18, 2021

Thank you for your bug report, Dave.

Add the following method to SamplesRenderingTest.java:

@Test
public void testMermaid() throws TranscoderException, IOException {
	test("samples/mermaid.svg");
}

You want to use testNV("samples/mermaid.svg") which is a non-validating test, so you do not need to comment anything out nor add any attribute. Once I run that test, I directly get this:

The following stylesheet represents an invalid 
CSS document.
#mermaid-1637216322989 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-1637216322989 .error-icon{fill:#552222;}#mermaid-1637216322989 .error-text{fill:#552222;stroke:#552222;}#mermaid-1637216322989 .edge-thickness-normal{stroke-width:2px;}#mermaid-1637216322989 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1637216322989 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1637216322989 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1637216322989 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1637216322989 .marker{fill:#333333;stroke:#333333;}#mermaid-1637216322989 .marker.cross{stroke:#333333;}#mermaid-1637216322989 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-1637216322989 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-1637216322989 .cluster-label text{fill:#333;}#mermaid-1637216322989 .cluster-label span{color:#333;}#mermaid-1637216322989 .label text,#mermaid-1637216322989 span{fill:#333;color:#333;}#mermaid-1637216322989 .node rect,#mermaid-1637216322989 .node circle,#mermaid-1637216322989 .node ellipse,#mermaid-1637216322989 .node polygon,#mermaid-1637216322989 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-1637216322989 .node .label{text-align:center;}#mermaid-1637216322989 .node.clickable{cursor:pointer;}#mermaid-1637216322989 .arrowheadPath{fill:#333333;}#mermaid-1637216322989 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-1637216322989 .flowchart-link{stroke:#333333;fill:none;}#mermaid-1637216322989 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-1637216322989 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-1637216322989 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-1637216322989 .cluster text{fill:#333;}#mermaid-1637216322989 .cluster span{color:#333;}#mermaid-1637216322989 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1637216322989 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
Original message:
you try to use an empty method in Adapter-class

which is caused by the custom property --mermaid-font-family.

Neither EchoSVG nor Batik support custom properties (which implies supporting var()). So this issue could be reformulated as "please support custom properties".

My long-term intention is to land an alternative SVGOM implementation in EchoSVG, based on CSS4J's native DOM. Native DOM fully supports var(), calc(), etc. (in fact it even supports calc computations that are spec-compliant but that browsers do not support yet).

To write that thing I was waiting for Houdini's TypedOM to be implemented by a browser so I could use a supported standard CSSOM API (the CSS Object Model that EchoSVG/Batik implement is deprecated and no browser supports it). However, I may still write a SVGOM implementation inheriting from native DOM, one that does not implement any TypedOM yet; that thing would allow people to render SVG that includes advanced CSS like var() and calc(). No promises at all though.

@ghost
Copy link
Author

ghost commented Nov 18, 2021

Consider renaming testNV to testNonValidating because the acronym wasn't clear to me at first blush.

@ghost ghost changed the title mermaid diagramming tool produces unparseable vector graphics Support custom properties Nov 18, 2021
@ghost
Copy link
Author

ghost commented Nov 28, 2021

@carlosame
Copy link
Member

Found a few implementations:

Typed OM is a work in progress (see https://github.com/w3c/css-houdini-drafts/issues to have an idea, you'll find even one issue that I opened in May) and for example the color API is still immature. The following link lists Chrome's "supported properties" but even those properties are featuring a subset of a full typed-om API:

https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/core/css/cssom/README.md

See also the Typed OM feature Chrome Status.

https://chromium.googlesource.com/chromium/src.git/+/369fded22b179d683bd949e34592becc897f3c08/third_party/WebKit/Source/core/css/cssom

The actual implementation is here: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/core/css/cssom/

Note that I'm always talking about a Typed OM implementation that's usable from Javascript (which is Typed OM's target and what the above classes provide).

There's also CodeGen, a transpiler for C++/Java:

CSS4J already has its own full-featured typed-value Object Model. It has problematic legacy stuff like CSSValue.setCssText() which is inadequate for Javascript. In any case it is not standard, and that's where Typed OM enters.

What I meant in my previous post is that I wanted to provide a Typed OM front-end to my own typed object model, one that can be used from Javascript, but Typed OM isn't ready yet. I do not think that your SVG files use Typed OM at all, therefore —as I said in my previous post— I could implement a rendering process that uses advanced CSS, but without exposing (immature) Typed OM to Javascript.

Hope that my intent is clearer now.

@ghost
Copy link
Author

ghost commented Jan 18, 2022

Have you looked into CSSelly?

Maybe there's some room for collaboration?

@carlosame
Copy link
Member

Have you looked into CSSelly?

* https://lagarto.jodd.org/csselly/csselly

Seems a competing project to CSS4J, allowing a subset of what CSS4J supports. IMHO the combination of the validator.nu htmlparser and CSS4J is far more functional (and API-standard) than the whole Jodd Lagarto suite.

See https://css4j.github.io/usage.html for details about the usage of CSS4J with htmlparser.

Maybe there's some room for collaboration?

Why? It is a competing project offering a small fraction of what CSS4J (which is what EchoSVG uses) gives. What feature are you finding there that you miss in CSS4J?

CSS4J has all the features needed to implement this issue, it is EchoSVG (Batik) which needs to be changed. For example, I need to change the Batik transcoding API so one can render a specific <svg> element in a document, and also provide a more generic style computation API that fits both the current Batik stuff and other arbitrary style-computation providers (BTW including CSS4J's native DOM). I have to change several things to achieve the former, and plan to use one of the Houdini's Typed OM interfaces for the latter.

All of this takes time, please be patient.

@carlosame
Copy link
Member

All of this takes time, please be patient.

To be more specific, the level of refactor required to support arbitrary CSS style computation providers in EchoSVG/Batik amounts practically to a rewrite. The current code is too closely tied to the way that Batik does CSS (which in turn is tied to old CSS APIs), and refactoring classes and interfaces in a way that CSS becomes really pluggable is going to be hard.

This could take more than a year or may not be done at all.

@carlosame
Copy link
Member

I opened issues #39 and #40 which describe more precisely my intentions about upgrading this project to more recent SVG and CSS, please feel free to comment there if you have something to add.

As I know that some of you are eagerly waiting news about this issue, here is a status update albeit a disappointing one: I haven't worked on this nor do I have expectations to do that in the foreseeable future.

A reminder of the scale of this project: according to EchoSVG's OpenHub page, EchoSVG is over 170K lines of code (LoC). In case you want to compare it to Batik beware that LoC are being counted twice there, the real figure would be like 220K LoC; the difference with EchoSVG is mostly due to the CSS parser and the old testing framework having been removed (this project uses CSS4J which in turn is 180K LoC).

Meanwhile, if anyone is willing to contribute patches I'll be happy to review and eventually merge them.

carlosame added a commit that referenced this issue Aug 11, 2022
If a user agent finds something that it does not support, should ignore it and
proceed. See https://www.w3.org/TR/CSS22/syndata.html#parsing-errors

"User agents must ignore a declaration with an unknown property."

See also #35.
@carlosame
Copy link
Member

When EchoSVG finds a style that it does not support, should ignore it. That's what user agents are supposed to do, this way authors can create style sheets that are valid for both modern and legacy user agents.

I just applied a patch that ignores declarations of custom properties. More changes of this kind need to be done to the codebase, but at least with said patch I can produce this:

mermaid2

It has to be investigated why the texts aren't being drawn, but it is a beginning.

Furthermore, there is a relatively easy workaround that can be applied: I'm preparing an example of how to combine CSS4J and EchoSVG to produce images that use modern CSS like var() or calc(). No need to wait for EchoSVG to support it natively (but EchoSVG needs to ignore what it does not support).

carlosame added a commit that referenced this issue Aug 11, 2022
This is used by FontAwesome which in turn is used by Mermaid.

Related to #35
@carlosame
Copy link
Member

Custom properties aren't the real problem here, so I'll modify the title of this issue. The real problem is that foreign HTML elements are being used and EchoSVG does not support that. However, I managed to create a workaround that allows the transcoding of SVG images that use advanced CSS and also foreign HTML elements.

I'm not done yet, but this is a Mermaid diagram that I rendered today with EchoSVG:

mermaid

What I do is to take the complex, unrenderable document and transform it into something that EchoSVG can understand. The thing isn't perfect but should be enough to get the work done most of the times.

@carlosame carlosame changed the title Support custom properties Render MermaidJS diagrams Aug 21, 2022
@carlosame carlosame added this to the 0.2.1 milestone Aug 21, 2022
@carlosame
Copy link
Member

Here is the main javadoc description of the utility that I created. Comments are welcome (for example do you like the class name?):

CSSTranscodingHelper

Utility for transcoding documents that use modern CSS, bypassing the EchoSVG style computations.

To obtain the best results, your document should define style properties in a style sheet or the style attribute, instead of using style-like attributes like font-size.

For example it is preferable:

<text style="font-size: 20px;">  

to:

<text font-size="20">  

Supported CSS

Modern CSS is allowed, with most of the following specifications being supported:

• Selectors Level 4
• Values and Units Level 4 (calc(), viewport-based units)
• Values and Units Level 5 (advanced attr())
• Color Level 4 (color(display-p3 -0.61 1.09 -0.22)).
• Custom properties Level 1 (var()).
• Properties and Values API Level 1 (@property rule).
• Media Queries Level 4 (@media screen and (400px <= width <= 700px)).
• Conditional Rules Level 3 (@supports (color: lch(45% 30 60))).

Configuring for Media Queries

Media Queries use the SVG viewport dimensions by default, but you can set the dimensions used by queries by setting the SVGAbstractTranscoder.KEY_WIDTH and SVGAbstractTranscoder.KEY_HEIGHT transcoding hints. And the target medium (screen, print, etc.) can be set via the SVGAbstractTranscoder.KEY_MEDIA hint.

For example:

   Transcoder transcoder = new PNGTranscoder();

   CSSTranscodingHelper helper = new CSSTranscodingHelper(transcoder);

   helper.getTranscoder().addTranscodingHint(SVGAbstractTranscoder.KEY_MEDIA, "screen");
   helper.getTranscoder().addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, 450);
   helper.getTranscoder().addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, 500);

   String uri = "https://www.example.com/my_image.svg";
   java.io.Reader re = ... [SVG document reader]
   java.io.OutputStream os = ... [where to write the image]

   TranscoderOutput dst = new TranscoderOutput(os);

   helper.transcode(re, uri, dst, null);

Using a selector

You can also render <svg> elements that are located inside an HTML document. By default, the first <svg> element (in document order) will be used, but you can point to a specific one using a CSS selector. For example:

 helper.transcode(re, uri, dst, "#mySvg");

Foreign Elements

The processing of foreign elements is performed via SVG 1.2 features. Therefore, if a document contains foreign elements, the <svg> element should either not have a version attribute, or that attribute's value must be 1.2 or 2.

@carlosame
Copy link
Member

I could not find this issue in the open list, and it was because it was closed automatically when I merged the PR. Anyway, if there are cases where the workaround is not giving the expected results, a new issue could be opened.

@carlosame
Copy link
Member

Were you able to use the new transcoding helper, @DaveJarvis ? Did it work with your use case?

@ghost
Copy link
Author

ghost commented Sep 5, 2022

Here's the code KeenWrite uses to transcode SVG documents into BufferedImage instances (see the SvgRasterizer class for details):

  /**
   * Creates a rasterized image of the given source document.
   *
   * @param input The source document to transcode.
   * @param key   Transcoding hint key.
   * @param width Transcoding hint value.
   * @return A new {@link BufferedImageTranscoder} instance with the given
   * transcoding hint applied.
   */
  private static BufferedImage rasterize(
    final TranscoderInput input, final Key key, final float width )
    throws TranscoderException {
    final var transcoder = new BufferedImageTranscoder();

    transcoder.setErrorHandler( sErrorHandler );
    transcoder.addTranscodingHint( key, width );
    transcoder.transcode( input, null );

    return transcoder.getImage();
  }

From KeenWrite's perspective, this is:

  • Input: SVG Document
  • Output: BufferedImage

Whether the SVG document requires CSS transcoding is really an implementation detail that, preferably, applications would need not be forced to consider. If there are performance trade-offs, then perhaps the helper class could be enabled using a transcoding hint, such as:

    final var transcoder = new BufferedImageTranscoder();

    transcoder.setErrorHandler( sErrorHandler );

    // Always enable CSS transcoding (used by MermaidJS).
    transcoder.addTranscodingHint( KEY_CSS_TRANSCODER, new BooleanKey( true ) );
    transcoder.addTranscodingHint( key, width );
    transcoder.transcode( input, null );

    return transcoder.getImage();

This would be backwards compatible, as well. That is, if the SVG transcoder receives an SVG document that does not require the CSS transcoder helper, then we'd expect the BufferedImage to be created as usual.

Using this approach, the name CSSTranscodingHelper doesn't bleed into applications, making the name (mostly) irrelevant from an API standpoint.

Conversely, if we wanted the SVG transcoding to "just work", we could make KEY_CSS_TRANSCODER be true by default and people would have to disable as per their requirements. In effect, this would mean that no code would have to change: swap Batik for EchoSVG and you get MermaidJS diagrams for free.

I've switched to EchoSVG with KeenWrite. Looking forward to seeing the reduced footprint!

To answer your question: No, it doesn't really work with my use case, as it stands.

@ghost
Copy link
Author

ghost commented Sep 5, 2022

FWIW, it's quite exciting to see these changes come to fruition. This will be the first non-browser-based SVG implementation that can rasterize MermaidJS diagrams (that I know of). The gargantuan amount of effort gone into getting the code to this point is very much appreciated. I'm looking forward to trying out the demo diagrams simply by adding the following lines in a document:

``` diagram-mermaid
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
```

@carlosame
Copy link
Member

This would be backwards compatible, as well. That is, if the SVG transcoder receives an SVG document that does not require the CSS transcoder helper, then we'd expect the BufferedImage to be created as usual.

Using this approach, the name CSSTranscodingHelper doesn't bleed into applications, making the name (mostly) irrelevant from an API standpoint.

Conversely, if we wanted the SVG transcoding to "just work", we could make KEY_CSS_TRANSCODER be true by default and people would have to disable as per their requirements. In effect, this would mean that no code would have to change: swap Batik for EchoSVG and you get MermaidJS diagrams for free.

This is something that you could have commented before the pull request was merged and/or the release published. But please consider these points:

  1. The CSS and foreign-element support that CSSTranscodingHelper brings is not natively built into EchoSVG. It is a hack, a workaround. I explained that in a previous comment:

What I do is to take the complex, unrenderable document and transform it into something that EchoSVG can understand. The thing isn't perfect but should be enough to get the work done most of the times.

  1. Even when only CSS2 is used, the renders produced by the Helper are sometimes slightly different to those produced by EchoSVG/Batik natively. The Helper output often resembles more what a modern web browser draws, but in any case this is a backwards incompatibility.

  2. You are using a DOM document that you build yourself as a TranscoderInput, but the Helper requires building a css4j native DOM document to be used as the real input (that's why it always takes a Reader as argument). So building your own document to use with the Helper is a lost step, inefficient. If I just add a hint, developers would be unaware of what's going on under the hood and would believe that their performance and efficiency is fine.

I want people to be aware of the previous points, and that is more easily achieved if they use a separate CSSTranscodingHelper located in a helper package. That said, if there is user feedback about using a hint, that could be implemented as well.

To answer your question: No, it doesn't really work with my use case, as it stands.

Instead of

transcoder.transcode( input, null );

you would have:

CSSTranscodingHelper helper = new CSSTranscodingHelper(transcoder);
helper.transcode(new StringReader(xml), uri, null, null);

and that would work.

@carlosame
Copy link
Member

FWIW, it's quite exciting to see these changes come to fruition. This will be the first non-browser-based SVG implementation that can rasterize MermaidJS diagrams (that I know of). The gargantuan amount of effort gone into getting the code to this point is very much appreciated.

Thank you, but the core of the Helper was written in like a day. Native support is going to be much harder, and may never happen. Updating Batik/EchoSVG to browser-level spec compliance is a task for a team of full-time developers during years.

I'm looking forward to trying out the demo diagrams simply by adding the following lines in a document:

``` diagram-mermaid
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!

One of the planned features is to support triggering DOM events in the Helper, so in principle mermaid.js could be called from a script.

@ghost
Copy link
Author

ghost commented Sep 6, 2022

CSSTranscodingHelper helper = new CSSTranscodingHelper(transcoder);
helper.transcode(new StringReader(xml), uri, null, null);

Can the URI be derived from the TranscoderInput document?

  private static BufferedImage rasterize(
    final TranscoderInput input, final Key key, final float width )
    throws TranscoderException {
    final var transcoder = new BufferedImageTranscoder();

    transcoder.setErrorHandler( sErrorHandler );
    transcoder.addTranscodingHint( key, width );

    final var helper = new CSSTranscodingHelper( transcoder );
    helper.transcode( input,  null, null );

    return transcoder.getImage();
  }

@ghost
Copy link
Author

ghost commented Sep 6, 2022

Also, would it be possible to wrap the IOException in a TranscoderException?

public void transcode(Reader reader, String documentURI, TranscoderOutput output, String selector) throws TranscoderException {

@ghost
Copy link
Author

ghost commented Sep 6, 2022

Here's the revised code:

  private static BufferedImage rasterize(
    final TranscoderInput input, final Key key, final float width )
    throws TranscoderException {
    final var transcoder = new BufferedImageTranscoder();

    transcoder.setErrorHandler( sErrorHandler );
    transcoder.addTranscodingHint( key, width );

    try {
      final var helper = new CSSTranscodingHelper( transcoder );
      helper.transcode( input.getReader(), input.getURI(), null, null );
    }
    catch(final IOException ex) {
      throw new TranscoderException( ex );
    }

    return transcoder.getImage();
  }

Unfortunately, this doesn't work. No regular SVG images are rendered. It may be that Mermaid diagrams work, but both need to work with the same API calls. KeenWrite doesn't distinguish between different types of TranscoderInput documents (i.e., MermaidJS vs regular SVG diagrams).

One of the planned features is to support triggering DOM events in the Helper, so in principle mermaid.js could be called from a script.

Oof. One of the reasons I went with FlyingSaucer was to avoid having to bundle the JavaScript engine Rhino into my application. It feels like the tech stack for SVG images is moving in the wrong direction if JavaScript is now a requirement to rasterize SVG documents (that's a mermaid complaint, btw, EchoSVG is awesome). Hopefully there will be a way to "opt out" so that EchoSVG library users can still get partial rendering of SVG without the overhead of pulling in an entire JavaScript engine.

@carlosame
Copy link
Member

Can the URI be derived from the TranscoderInput document?

Not unless you put it there first.

Also, would it be possible to wrap the IOException in a TranscoderException?

I'd rather not. It is generally better to handle possibly transient exceptions (like IOException) separately.

Unfortunately, this doesn't work.

That's because you aren't providing a real input.

It feels like the tech stack for SVG images is moving in the wrong direction if JavaScript is now a requirement to rasterize SVG

Javascript is not a requirement. Both Batik and EchoSVG carry Rhino as an optional dependency. Scripts are supported but not mandatory.

@ghost
Copy link
Author

ghost commented Sep 7, 2022

Maybe a little more background would be useful on what I'm trying to accomplish. KeenWrite rasterizes SVG images from the following sources:

  • A URI (e.g., Kroki diagrams over HTTP, which can include Mermaid, GraphViz, and PlantUML diagrams; local .svg files; or any other SVG resource).
  • An in-memory SVG Document instance generated from TeX macros (see SvgDomGraphics2D for details).

Both of these scenarios currently render using the same underlying code. This is why I first convert the SVG into a TranscoderInput instance, regardless of its origin:

  public static BufferedImage rasterize(
    final Document svg, final int width ) throws TranscoderException {
    return rasterize(
      new TranscoderInput( svg ),
      KEY_WIDTH,
      fit( svg.getDocumentElement(), width )
    );
  }

  public static BufferedImage rasterize(
    final InputStream svg, final float dpi ) throws TranscoderException {
    return rasterize(
      new TranscoderInput( svg ),
      KEY_PIXEL_UNIT_TO_MILLIMETER,
      1f / dpi * 25.4f
    );
  }

The TranscoderInput should have everything CSSTranscodingHelper needs to perform rasterization, including a Document and a URI. In effect:

public class CSSTranscodingHelper {
  public void transcode(TranscoderInput input, OutputStream out) throws TranscoderException {
    assert input != null;

    final var uri = input.getUR();
    final var doc = input.getDocument();
    if( doc != null ) {
      transcode( doc, uri, out );
    }
    else {
      final var reader = input.getReader();
      if( reader != null ) {
        transcode( reader, uri, out );
      }
    }
  }
}

Something like that would allow for parsing the DOM when needed (via the Reader instance) or using an existing DOM when provided.

@carlosame
Copy link
Member

Please see #64 for why I did not use TranscoderInput in the new Helper interface. However, I could add a new method which takes a css4j DOMDocument as input. That would be a bold move because it would mean that css4j classes become part of the EchoSVG public API, but we'll see.

Please create a new discussion if you want to keep this conversation going. Quite a few people subscribed to this thread and we do not want to spam them.

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

Successfully merging a pull request may close this issue.

1 participant