5

I would like to take a multiline block of text and display it in SVG. I would like to keep the lines as lines. Is there a proper way to do this?

I am using Inkscape for my base drawing and Batik for my rendering. It seems the two do not agree on how to do this.

Inkscape is creating a structure like this:

<flowRoot
       xml:space="preserve"
       id="flowRoot3089"
       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       transform="translate(19.71875,334.88681)">
   <flowRegion id="flowRegion3091">
        <rect id="rect3093" width="50.78125" height="75" x="34.765625" y="155.89932"/>
   </flowRegion>

    <flowPara id="flowPara3123">Item 1</flowPara>
    <flowPara id="flowPara3137">Item 2</flowPara>
    <flowPara id="flowPara3139">Item 3</flowPara>
</flowRoot>

However, this is not acceptable to Batik for some reason.

JeffV
  • 52,985
  • 32
  • 103
  • 124

4 Answers4

5

Inkscape sets the SVG version of the document to 1.1 instead of 1.2, but still uses flowing text.

The simple solution for you is to edit your svg document and change the SVG version attribute to 1.2. Inkscape will not change it back to 1.1 and it handles the 1.2 version specifier fine.

Batik will then be happy to provide most functionality, however you'll also run into another Inkscape bug if you mess with pretty much any of the text attributes within the flow root that Inkscape creates. It sets the background color to the selected foreground color for the text, which means if you set the text color to red in Inkscape, when batik renders it, you'll see a red square ... the text is there, but its red too, so not really visible. This an Inkscape bug and is clearly visible in the code for the flowRegion -> rect element.

The solution is to manually edit your flowRect attributes after tweaking them with inkscape.

Batik also seems to do better if you use the standard svg output rather than inkscape svg output.

David
  • 76
  • 1
  • 4
  • Has anyone tried this? I tried setting version="1.2" on an SVG document containing flowRoot/flowPara elements and batik-rasterizer.jar simply didn't render the flowable text (Inkscape does). It also issued a warning about `"text-align: justify"`, which is valid in 1.2. I tried also setting `baseProfile="tiny"` and `"full"`. Also, http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Scalable_Vector_Graphics) says that Batik doesn't support any 1.2-full, only partial 1.2-tiny. – Jim Pivarski Jul 09 '13 at 20:57
  • Just as a really late FYI: https://xmlgraphics.apache.org/batik/status.html - Whats supported in general https://xmlgraphics.apache.org/batik/dev/svg12.html - SVG 1.2 support - notes on flowing text – David Mar 12 '14 at 13:48
4

This is not acceptable since flow* elements are non-standard elements. It comes from an SVG1.2 draft that has never been accepted and it is designed to wrap text in custom shapes. Only Inkscape and some builds of Opera support it. So, don't use it, at least for the moment.

If you don't need text wrapping (and you don't seem to, but I don't understand what you mean by "I would like to keep the lines as lines"), I suggest you use the basic <text/> element.

Tangui
  • 3,626
  • 2
  • 26
  • 28
  • Opera has never supported the flow* elements. It does however support the SVG Tiny 1.2 textArea element. All this can be seen by the documentation here: http://opera.com/docs/specs – Erik Dahlström Oct 13 '10 at 17:55
  • I think you're right @Tangui. The text/tspan technique is awkward as well. I need to create and provide spacing for the tspan elements on the fly adding much complication. (I am inserting the text in Java from Batik. The amount of Text is not know until runtime.) – JeffV Oct 13 '10 at 23:58
  • Unfortunately, you can't use XHtml via foreignObject since Batik doesn't support it. You may also use the SVG DOM to get the text length (with the getComputedLength/getStartPositionOfChar/getEndPositionOfChar methods) but I'm not sure this is compatible with your use of Batik. – Tangui Oct 14 '10 at 01:30
2

I'd suggest <text> with <tspan> children. Inkscape can generate that for you quite easily, just don't click and drag an area but instead just click where you want the text and start writing, press return where you want a new line.

Erik Dahlström
  • 59,452
  • 12
  • 120
  • 139
1

Alternatively, foreignObject will allow you to include html:

<svg:foreignObject><html:body><div>text here</html:div></html:body></svg:foreignObject>

Doesn't seem to work in Opera or IE, though.

Marcin
  • 48,559
  • 18
  • 128
  • 201