4

See this demo on jsFiddle (or hosted here):

  • I have an svg path that is rougly (99.99%) circular
  • Along this path, I place text, using a 'textpath' svg element
  • I want the end of the text to meet with the beginning as accurately as possible (ideally pixel-perfectly) so as to make a continuous text loop

Here's an excerpt of the code (stripped down of all text values):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" viewBox="0 0 480 480" preserveAspectRatio="xMidYMid" height="100%"
width="100%">
    <defs>
        <style type="text/css">
            /* for some reason, SVG font import doesn't work in Chrome or Firefox! */
            @font-face {
                font-family: Libertine;
                src: url(LinLibertine_R.svg#LinLibertineO);
            }
            @font-face {
                font-family: Libertine2;
                src: url(LinLibertine_Rah.ttf);
            }
            /* Chrome seems to round to the nearest 0.5 em; also, does not display em-widths consistently with Firefox (though px-widths are consistent) */
            .ex1 {
                font: 0.85em Libertine2;
            }
            .measurement {
                font: 1.0em monospace;
            }
        </style>
        <text id="day1">...</text>
        <text id="day2">...</text>
        <text id="day3">...</text>
        <text id="day4">...</text>
        <text id="day5">...</text>
        <text id="day6">...</text>
        <text id="day7">...</text>
    </defs>
    <g transform="translate(240,240)">
        <g transform="translate(-240,-240)">
            <circle r="1" cx="240" cy="27" fill="black" />
            <path id="circle" d="M 240,20 a 220,220, 0 1,1 -0.0001,0.0000 Z"
            fill="none" stroke="red" stroke-width="0" />
            <path id="inner-circle" d="M 240,40 a 200,200, 0 1,1 -0.0001,0.0000 Z"
            fill="none" stroke="red" stroke-width="0" />
            <text class="ex1" fill="black">
                <!-- this RTL text-along-path is displayed backwards (ie sdrawkcab) in
                Chrome; manual CSS overrides (e.g. unicode-bidi) cause blank/white screen
                -->
                <textPath xlink:href="#circle" method="stretch">...</textPath>
            </text>
            <text class="measurement" fill="grey">
                <textPath xlink:href="#inner-circle" method="stretch">A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 G0 G1 G2 G3 G4 G5 G6 G8 G9</textPath>
            </text>
        </g>
    </g>
</svg>

So far, the best I can do is import a font via CSS, which roughly standardizes the width across browsers.

Note that Chrome does not read fine-tuned font-size values (e.g. it seems to round 0.87em to 0.85em), and seems to have a different text-rendering engine than Firefox, even when the font-sizes are consistent. For example, a font-size of 1em renders the inner 'measurement circle' in the above example to the F in tick 'F9' in Firefox, where Chrome renders nearly to the beginning of tick 'F4', a problem which is reduced to a single-character-width-difference when px units are used in font-size.

You'll also notice that Chrome renders Right-to-Left (RTL) text incorrectly, and manual CSS overrides (using 'unicode-bidi' and 'direction' directives) have caused complete failure (no SVG rendering at all).

It goes without saying — there are lots of problems. So far, this has been a fun experiment, but any help in standardization would be greatly appreciated.

As far as my own solutions; I am thinking of specifying the location of each character manually using the font specifications in the LinuxLibertine svg-font, which is a very tacky alternative to figuring out the root of the rendering inconsistencies.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Romi
  • 123
  • 10

1 Answers1

1

The problem with depending purely on SVG and TTF ONLY, is that you're going to run into pixel perfection issues in non webkit browsers. Some of them won't even render at all. (Stoopid IE7). While it's not 100% perfect, Fontsquirrel's generator get's me 99% there most times with my webfonts.

http://www.fontsquirrel.com/tools/webfont-generator

My rule of thumb is to use the following formats for specific browsers. It seems like 2x the work of just using SVG/TTF but it's really not, and will save you so much headache when it comes to pixel perfection.

TTF - Good for most browsers, but lacks on IE and iOS Safari.
EOT - IE only.
WOFF - Compressed, emerging standard.
SVG - iPhone/iPad.

This CSS will cover all the formats in one family:

@font-face {
    font-family: 'Libertine';
    src: url('Libertine-webfont.eot');
    src: url('Libertine-webfont.eot?#iefix') format('embedded-opentype'),
         url('Libertine-webfont.woff') format('woff'),
         url('Libertine-webfont.ttf') format('truetype'),
         url('Libertine-webfont.svg#LibertineRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}

and then the connecting HTML:

<style type="text/css" media="screen">
    .ex1 {font: 18px/27px 'Libertine', Arial, sans-serif;}
    }
</style>

Hope this helps, or didn't just confuse you further. :/ I tend to do that.

Daveable
  • 53
  • 1
  • 9