I'd like to be able to have text shrink to fit a multi-line text box. The box will have a default font (say 20px Sans) and if the text fits in the box it will not adjust the font. However, if the text would overflow, it will reduce the font-size until it no longer overflows.
Just to be clear, I know Inkscape (and SVG in general) doesn't do this by default. However, since I am generating the SVG programatically and then using Inkscape as a converter (to PDF), I believe this is possible if I know the algorithm that Inkscape uses for text flow and how it calculates font-metrics, etc.
So, I suppose my first question is: has anyone done this? I've seen approaches online that use the browser's DOM to do it in Javascript, and I've seen how to do it with ImageMagick. I know that it can be inefficient, but that's not a huge deal for me. Has anyone done something like this Inkscape?
Here's a simple FlowRoot that hold a full alphabet across and is three lines high. Adding even a space to the first line would cause it to wrap to four lines and therefore need to shrink fonts. To make this work, I THINK I would need to do the following:
- Grab the height and widthof the box (applying any scaling in the transform on the FlowRoot, there is none in this example)
- Calculate the number of rows that currently fit with the default font (74.483658 / (20 * 1.25) ~= 3 (oddly, it's just BELOW 3 which means it should wrap... but doesn't - WHY?)
- Count the number of <flowPara> elements in the <flowRoot> since that is the minimum number of rows I'll need.
- For each <flowPara> follow Inkscape's text-wrapping algorithm using the same fontMetrics that it uses [HELP] figuring out how many MORE rows I'll need.
- If that total number of rows is > the number of rows that fit, adjust the font size and re-calculate the split <flowPara>s until it does fit (I will use a Binary Search here starting with the default font and shrinking it.
- Documentation (or a pointer to code) for Inkscape's Text Wrapping code
- Descriptions of how to calculate the FontMetrics. Specifically, can I use ImageMagick's FontMetrics (which I have in PHP) and get equivalent information? If not, I'd like ideas (fontserver?)
- Explanation of why the text didn't wrap in the example below even though it says it will hold < 3 rows (do I not count line spacing at the top and bottom?)
I'd really appreciate any help on this matter - this would make a huge difference in my project.
Thank you!
Bill
Sample Code
Code: Select all
<flowRoot
xml:space="preserve"
id="flowRoot2985"
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
transform="translate(-80.257425,41.559833)"><flowRegion
id="flowRegion2987"><rect
id="rect2989"
width="359.05862"
height="74.483658"
x="154.28572"
y="198.07646"
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans" /></flowRegion><flowPara
id="flowPara2991">ABCDEFGHIJKLMNOPQRSTUVWXYZ</flowPara><flowPara
id="flowPara2993">Line 2</flowPara><flowPara
id="flowPara2995">Line 3</flowPara></flowRoot>