SVG Working Group Meeting Report — London

The SVG Working Group had a four day Face-to-Face meeting just before The Graphical Web conference in Winchester (UK). The meetings were hosted by Mozilla in their London office.

Here are some highlights of the meeting:

Day 1

Minutes

  • Symbol and marker placement shorthands:

    Map makers use symbols quite extensively. We decided at a previous meeting to add the ‘refX’ and ‘refY’ attributes (from <marker>) to <symbol> so that symbols can be aligned to a particular point on a map without having to do manual position adjustments. We have since been asked to provide ‘shorthand’ values for ‘refX’ and ‘refY’. I proposed adding ‘left’, ‘center’, and ‘right’ to ‘refX’ (defined as 0%, 50%, and 100%) of the view box as well as ‘top’, ‘center’, and ‘bottom’ to ‘refY’. These values follow those used in the ‘transform-origin’ property. We debated the usefulness and decided to postpone the decision until we had feedback from those using SVG for maps (see Day 4).

    For example, to center a symbol at the moment, one has to subtract off half the width and height from the ‘x’ and ‘y’ attributes of the <use> element:

      <symbol id="MySquare" viewBox="0 0 20 20">
        <rect width="100%" height="100%"
    	  style="fill:none;stroke:black;stroke-width:2px"/>
      </symbol>
      <use x="100" y="100" width="100" height="100"
           xlink:href="#MySquare"/>
    

    By using ‘refX’ and ‘refY’ set to ‘center’, one no longer needs to perform the manual calculations:

      <symbol id="MySquare" viewBox="0 0 20 20"
                      refX="center" refY="center">
        <rect width="100%" height="100%"
    	  style="fill:none;stroke:black;stroke-width:2px"/>
      </symbol>
      <use x="150" y="150" width="100" height="100"
                 xlink:href="#MySquare"/>
    
    A square symbol centered in an SVG.

    An example of a square <symbol> centered inside an SVG.

  • Marker and symbol overflow:

    One common ‘gotcha’ in using hand-written markers and symbols is that by default anything drawn outside the marker or symbol viewport is hidden. People sometimes naively draw a marker or symbol around the origin. Since this is the upper-left corner of the viewport, only one quarter of the marker or symbol is shown. We decided to change the default to not hide the region outside the viewport, however, if this is shown to break too much existing content, the change might be reverted (it is possible that some markers/symbols have hidden content outside the viewport).

  • Two triangle paths with markers on corners. Only one-fourth of each marker on the left path is shown.

    Example of markers drawn around origin point. Left: overflow=’hidden’ (default), right: overflow=”visible’.

  • Variable-stroke width:

    Having the ability to vary stroke width along a path is one of the most requested things for SVG. Inkscape has the Live Path Effect ‘Power Stroke’ extension that does just that. However, getting this into a standard is not a simple process. We must deal with all kinds of special cases. The most difficult part will be to decide how to handle line joins. (See my post from the Tokyo meeting for more details.) As a step towards moving this along, we need to decide how to interpolate between points. One method is to use a Centripital Catmull-Rom function. Johan Engelen quickly added this function as an option to Inkscape’ Power Stroke implementation (which he wrote) for us to test.

Day 2

Minutes

  • Path animations:

    In the context of discussing the possibility of having a canonical path decomposition into Bezier curves (for speed optimization) we briefly discussed allowing animation between paths with different structures. Currently, SVG path animations require the start and end paths to have the same structure (i.e. same types of path segments).

  • Catmull-Rom path segments.

    We had a lengthy discussion on the merits of Catmull-Rom path segments. The main advantage of Catmull-Rom paths is that the path goes through all the specified points (unlike Bezier path segments where the path does not go through the handles). There are some disadvantages… adding a new segment changes the shape of the previous segment, the paths tend not to be particularly pretty, and if one is connecting data points, the curves have the tendency to over/under shoot the data. The majority of the working group supports adding these curves although there is some rather strong dissent. The SVG 2 specification already contains Catmull-Rom paths text.

    After discussing the merits of Catmull-Rom path segments we turned to some technical discussions: what exact form of Catmull-Rom should we use, how should start and end segments be specified, how should Catmull-Rom segments interact with other segment types, how should paths be closed?

    Here is a demo of Catmull-Rom curves.

Day 3

Minutes

  • <tref> decission:

    One problem I see with the working group is that it is dominated by browser interests: Opera, Google (both Blink), Mozilla (Gecko), and Adobe (Blink, Webkit, Gecko). (Apple and Microsoft aren’t actively involved with the group although we did have a Microsoft rep at this meeting.) This leaves those using SVG for other purposes sometimes high and dry. Take the case of <tref>. This element is used in the air-traffic control industry to shadow text so it is visible on the screen over multi-color backgrounds. Admittedly, this is not the best way to do this (the new ‘paint-order’ property is a perfect fit for this) but the fact is that it is being used and flight-control software can’t be changed at a moments notice. Last year there was a discussion on the SVG email list about deprecating <tref> due to some security issues. From reading the thread, it appeared the conclusion was reached that <tref> should be kept around using the same security model that <use> has.

    Deprecating <tref> came up again a few weeks ago and it was decided to remove the feature altogether and not just deprecate it (unfortunately I missed the call). The specification was updated quickly and Blink removed the feature immediately (Firefox had never implemented it… probably due to an oversight). It has reached the point of no-return. It seems that Blink in particular is eager to remove as much cruft as possible… but one person’s cruft is someone else’s essential tool. (<tref> had other uses too, such as allowing localization of Web pages through a server.)

  • Blending on ‘fill’ and ‘stroke’:

    We have already decided to allow multiple paint servers (color, gradient, pattern, hatch) on fills and strokes. It has been proposed that blending be allowed. This would follow the model of the ‘background-blend-mode’ property. (Blending is already allowed between various element using the ‘mix-blend-mode’ property’, available in Firefox (nightly), Chrome, and the trunk version of Inkscape.)

  • CSS Layout Properties:

    The SVG attributes: ‘x’, ‘y’, ‘cx’, ‘cy’, ‘r’, ‘rx’, ‘ry’ have been promoted to properties (see SVG Layout Properties). This allows them to be set via CSS. There is an experimental implementation in Webkit (nightly). It also allows them to be animated via CSS animations.

A pink square centered in SVG if attributes supported, nothing otherwise.

A test of support of ‘x’, ‘y’, ‘width’, and ‘height’ as properties. If supported, a pink square will be displayed on the center of the image.

Day 4

Minutes

  • Shared path segments (Superpaths):

    Sharing path segments between paths is quite useful. For example, the boundary between two countries could be given as one sub-path, shared between the paths of the two countries. Not only does this reduce the amount of data needed to describe a map but it also allows the renderer to optimize the aliasing between the regions. There is an example polyfill available.

    We discussed various syntax issues. One requirement is the ability to specify the direction of the inserted path. We settled for directly referencing the sub-path as d=”m 20,20 #subpath …” or d=”m 20,20 -#subpath…”, the latter for when the subpath should be reversed. We also decided that the subpath should be inserted into the path before any other operation takes place. This would nominally exclude having separate properties for each sub-path but it makes implementation easier.

  • Here, MySubpath is shared between two paths:

      <path id="MySubpath" d="m 150,80 c 20,20 -20,120 0,140"/>
      <path d="m 50,220 c -40,-30 -20,-120 10,-140 30,-20 80,-10
                       90,0 #MySubpath c 0,20 -60,30 -100,0 z"
    	style="fill:lightblue" />
      <path d="m 150,80 c 20,-14 30,-20 50,-20 20,0 50,40 50,90
                       0,50 -30,120 -100,70 -#MySubPath z"
    	style="fill:pink" />
    

    This SVG code would render as:

    Two closed paths sharing a common section.

    The two closed paths share a common section.

  • Stroke position:

    An often requested feature is to be able to position a stroke with some percentage inside or outside a path. We were going to punt this to a future edition of SVG but there seems to be quite a demand. The easiest way to implement this is to offset the path and then stroke that (remember, one has to be able to handle dashes, line joins, and end caps). If we can come up with a simple algorithm to offset a stroke we will add this to SVG 2. This is actually a challenging task as an offset of a Bezier curve is not a Bezier… thus some sort of approximation must be used. The Inkscape ‘Path->Linked Offset’ is one example of offsetting. So is the Inkscape Power Stroke Live Path Effect (available in trunk).

  • Symbol and marker placement shorthands, revisited:

    After feedback from mappers, we have decided to include the symbol and marker placement shorthands: ‘left’, ‘center’, ‘right’, ‘top’, and ‘bottom’.

  • Units in path data:

    Currently all path data is in User Units (pixels if untransformed). There is some desire to have the ability to specify a unit in the path data. Personally, I think this is mostly useless, especially as units (cm, mm, inch, etc.) are useless as there is no way to set a preferred pixel to inch ratio (and never will be). The one unit that could be useful is percent. In any case, we will be investigating this further.

Lots of other technical and administrative topics were discussed: improved DOM, embedding SVG in HTML, specification annotations, testing, etc.

Posted in CSS, SVG | 1 Comment

The ‘paint-order’ property in SVG 2

Introduction

SVG 2 has a new ‘paint-order’ property which can be used to select the order in which the fill, stroke, and markers are painted. This is of especially great use for text where having the stroke painted on top of the fill leads to distorted glyphs.

Sample text showing effect of paint-order.

Sample text showing the effect of the ‘paint-order’ property.

As of March 2014, Chrome and Firefox Nightly support the ‘paint-order’ property. Inkscape trunk also has rendering support for the property (if compiled in).

Test SVGs

Tests with different orders of 'fill', 'stroke', and 'markers'.

Each square has the indicated value of the ‘paint-order’ property.

Tests with different orders of 'fill', 'stroke', and 'markers'.

Each line of text has the indicated value of the ‘paint-order’ property.

Posted in Inkscape, SVG | Comments Off

Blending coming to an SVG renderer near you! (Including Inkscape)

SVG has supported a limited set of blend modes through the use of SVG filters. Now SVG (and HTML) are getting a full set of blend modes that can be directly applied to all graphical objects. Chrome already has some support for the new blending method.

Here is a snippet of SVG from the specification CSS Blending and Compositing Level 1:

<svg>
  <rect width="120" height="120" fill="black"/>
  <circle cx="40" cy="40" r="40" fill="red"/>
  <circle cx="80" cy="40" r="40" fill="lime"/>
  <circle cx="60" cy="80" r="40" fill="blue"/>
</svg>

Normally, SVG uses the painter’s model where each element is painted on top of the previous. So the above SVG gets rendered as (actual inline SVG):

Inlined SVG. Circles drawn using painter’s model.

With CSS blending, one can specify how the blending between the elements is done by setting the ‘mix-blend-mode’ property. The following style rule:

circle { mix-blend-mode: screen; }

yields the following figure:

Inlined SVG. Circles blended with ‘mix-blend-mode’ = ‘screen’.

which in a browser (recent Chrome) that supports CSS blending should look like this:

Red, lime, and blue overlapping circles, blended with 'screen' mode.

PNG.

Why the black background? If the background was white, the circles would not be visible. This is because the circles blend not only with each other but also with the background. (With the ‘screen’ blending mode, any color blended with a white background results in white.) To stop blending with the background, one can use the ‘isolation’ property. By wrapping the three circles in a group and setting the ‘isolation’ property to ‘isolate’, the three circles are first blended onto a transparent, black background and then the resulting image is painted normally. The code looks like this:

<svg>
  <g>
    <circle cx="40" cy="40" r="40" fill="red"/>
    <circle cx="80" cy="40" r="40" fill="lime"/>
    <circle cx="60" cy="80" r="40" fill="blue"/>
  </g>
</svg>

and the CSS:

circle { mix-blend-mode: screen; }
g { isolation: isolate; }

The resulting image should look like this:

Red, green, and blue overlapping circles, blended with 'screen' mode.

PNG.

I wasn’t able to get the ‘isolation’ property to work with Chrome (which should support it), thus I used a PNG in the above figure.

At the SVG Working Group meeting last week, the group approved moving the CSS Compositing and Blending Level 1 to a Candidate Recommendation. Since this a joint specification, the CSS Working group must also give their approval. A Candidate Recommendation is the last step before becoming a Recommendation (i.e. an official W3C specification). During this last step two things must happen. First a comprehensive test suite must be written and second at least two different implementations must pass the tests for each feature in the specification. This latter requirement ensures that the specification is clear enough that it can be implemented (and also demonstrates there is a real interest in the specification).

Chrome already implements the specification so just one more implementation is needed. It is expected that Firefox will soon support the specification. There is also a test plan that includes SVG tests. So we are well on the way to getting this through the last step.

In addition, I’ve also just added support for CSS Blending to Inscape trunk. For the moment, a compile time flag must be set to enable the support. There is no GUI (other than the XML editor) and there is still a bit of work to be done (the Inkscape canvas background needs to be isolated from the drawing and I’ve seen a bug when part of the drawing is cached.

The CSS Compositing and Blending Level 1 specification also include a full set of Porter-Duff compositing operators. For the moment, they only apply to Canvas. It was intended that they apply to HTML and SVG but the rendering models used by browsers cannot yet accomodate them. They will be included in the next version of the specification, CSS Compositing and Blending Level 2. The SVG working group approved the start on the next level at the last meeting.

Blending and compositing has been included in SVG filters from the beginning. However, only a limited set of blending modes and compositing operators are available in SVG filters. Unfortunately, CSS Filters Level 1 has not extended filters to include the new blending modes and compositing operators despite being trivial to implement once the original set has been implemented (it took me all of an hour to add them to Inkscape trunk). Again the motivation is to speed up approval of the level 1 specification; level 2 will include them. Work on level 2 is expected to begin early next year.

If you are interested in playing with then new blending modes and compositing modes in Inkscape, check out Inkscape trunk and set the flags WITH_CSSBLEND and/or WITH_CSSCOMPOSITE (see the file configure.ac). As mentioned above, there is no GUI for the new non-filter based blending modes. The new blending modes and compositing operators for filters are available through the Filters dialog.

You can also have a look at my Blending Test Page.

Posted in CSS, Inkscape, SVG | Tagged , | 6 Comments

SVG Working Group Meeting Report — Tokyo

The SVG Working Group had a three day Face-to-Face meeting in Tokyo at the beginning of June. The first two days (hosted by Mozilla) were devoted to SVG proper while the third day (hosted by Google) was a joint meeting with the CSS Working Group. As typical, a lot of time was devoted to nitty-gritty details that only browser coders could love but there were still plenty of things of interest for artists and their brethren:

  • Wrapped text:

    I presented a proposal based on using the CSS Exclusions and CSS Shapes specifications. As I wrote earlier, the current Level 1 version of these specifications are missing the exact features we need, namely “shape-inside” (to provide a wrapping context) and references to SVG elements; both were recently removed. However, when we met with the CSS working group we were told that they would be back in the Level 2 specs. Alan Stearns promised to get the Level 2 drafts out soon so we have something to reference.

    Doug Schepers presented his idea on a simple way to provide a rectangular wrapping context which would not require CSS Exclusions or CSS Shapes:

     <text x="20" y="30" width="200"
        font-size="20px"
        alignment-baseline="top">This text wraps at 200 pixels.<text>
    
    Horizontally wrapped text inside box 200 px wide.

    Horizontally wrapped text.

    Or for vertical text:

     <text x="20" y="30" height="200"
        font-size="20px"
        alignment-baseline="text-before-edge">テキストは
           10文字の後に折り返されます。<text>
    
    Vertically wrapped text inside box 200 px high.

    Vertically wrapped text.

    Specifying only the “width” or the “height” creates an infinitely long rectangle for wrapping text. Specifying both creates a finite rectangle. The visibility of text that overflows this finite rectangle is controlled by the overflow property.

    One small problem with Doug’s proposal is that the values of “x” and “y” normally refer to the baseline of the first line of text and not the upper left corner of the rectangle wrapping area. This can be changed by specifying the “alignment-baseline” property to top or text-before-edge.

    Note that Doug’s proposal and my proposal are not mutually exclusive and we will mostly like incorporate both.

    Both the SVG and CSS working groups are amenable to the proposals. There are some details to work out. For example, in my initial proposal one would specify that text should flow sequentially into two different objects by giving a comma separated list: shape-inside=”url(#shape1), url(#shape2)”. This, I am told, won’t work as in CSS it indicates that the text should flow into the two shapes as if they were one shape. Instead, it has been suggested that either CSS Regions and/or CSS Fragments be used. This, however, seems overly complex.

  • Variable width stroke:

    We discussed various aspects of variable width strokes. It is clear that it will take some work to come up with a good specification. Problems include: how to specify positions, widths, smoothing, line joins, and end caps. Whether or not this gets into SVG 2 will depend on how fast these issues are resolved and in the timing of SVG 2. It it doesn’t get into SVG 2, it certainly will get into the next version.

    For example, here are some possible ways of drawing a “round” stroke-linejoin:

    Possible ways to draw a “round” stroke-linejoin when there is a discontinuity in line width at a corner node. Top: using a “pen” with diameter of the smallest width. Bottom: using an ellipse.

    Circles and ellipses work well when the two line segments intersect at 90 degrees. At other angles or when the line widths are changing they aren’t as useful. Here is an attempt at using a Bezier with a handle length chosen so that it matches a “round” stroke-linejoin when the width is constant.

    Possible way to draw a “round” stroke-linejoin: using a Bezier curve. The handle length is calculated so that it reduces to a circular arc when the width is constant (length is 0.552 × angle between tangents in degrees / 90 × distance from end to intersection of tangents). The handles are shown in purple.

    Here is a challenge: Come up with a method that produces a suitable “round” stroke-linejoin in each of the following cases:

    Figures with various angles between the two path sections.

    A triangle shape is applied to a path with two sections. The angle between the two sections is changed from figure to figure. How would you construct a “round” stroke-linejoin between the two sections that works in all cases?

  • Marker rendering issues:

    SVG renderers differ on how markers are rendered for corner cases such as a polyline with one point (see: http://paullebeau.com/svg2/markers/). We sorted out the details. As part of the discussion, we agreed that markers should apply to rectangles, ellipses, and circles (and in the future stars). The basic rule, is that markers are drawn as if these shapes were rendered as paths. We explicitly decided that circles and ellipses would have four markers.

    Marks shown on a rectangle, rounded rectangle, circle, and ellipse.

    Markers drawn on various shapes.

  • New value for the marker property orient: “auto-start-reverse”:

    This value indicates that a marker should be reversed if it is at the start of a path. This is so that one needs to define only one marker (like an arrowhead) and use it both as a start and an end marker (like a double-headed arrow). This has already been added to the spec and is in the process of being implemented in Firefox.

      <defs>
       <marker id="MyArrowHead"
          viewBox="0 0 10 10" refX="0" refY="5"
          markerUnits="strokeWidth"
          markerWidth="4" markerHeight="3"
          orient="auto-start-reverse"
          fill="black">
          <path d="M 0 0 L 10 5 L 0 10 z" />
        </marker>
      </defs>
      <path marker-start="url(#MyArrowHead)"
            marker-end="url(#MyArrowHead)"
           d="m 75,75 150,0" />
    
    Double headed arrow using auto-start-reverse.

    Path with just one defined marker using orient=”auto-start-reverse”.

  • Hatch patterns:

    I recently added hatch patterns to the SVG 2 specification. The work was approved with a few small changes (renaming a property and specifying that only solid colors can be used… no hatches inside hatches!).

  • Multiple fill and stroke properties:

    As part of our discussion of hatch patterns, we discussed the ability to specify multiple fill and stroke properties. This is useful, for example, to draw a hatch over a gradient fill, or in drawing cross-hatching. We agreed to how this would be specified. This is a first step to allowing things like multiple stroke widths and colors on paths but at the moment there is some resistance to handling these more complicated cases. The feeling is that we need to start limiting what is being added to SVG 2 so that we can get it finished.

      <defs>
       <hatch id="MyHatch1" ... >
       <hatch id="MyHatch2" ... >
      </defs>
      <rect x="50" y="50" width="200" height="200"
         fill="url(#MyHatch1),url(#MyHatch2),#a0a0ff"</rect>
    
    A simple cross hatch over a light blue fill.

    A multiple fill consisting of two hatch patterns over a solid light blue fill”.

  • Filter compositing: feBlend:

    As anybody who has used the feBlend filter primitive to blend an element with transparency with a background image knows that the background gets added twice, once with the blending and once when the blend result is composited with the background. (See my example.) We can’t change the behavior of feBlend as there is too much content out there that uses it. We did agree to add a new attribute that will allow turning off compositing.

Posted in SVG | 1 Comment

Flowed text in SVG: One step forward, one step back.

Background

The ability to flow text into an arbitrary shape or even a simple box has been a feature long in demand in SVG. Thus it is on the list of required features for SVG 2.[1] The SVG 1.2 draft specification[2] included the ablility to flow text (and graphics!) into arbitrary shapes. Unfortunately, SVG 1.2 never got off the ground and only Inkscape and Batik seem to have implemented parts of flowed text.

Inkscape’s implementation supports text flowed into arbitrary paths. If the path has a hole, text will wrap around it. Inkscape also supports text flowed into multiple shapes. Inkscape (nor Batik) implemented flowing images or some of the fancier elements that control line and paragraph breaks.

Text flowed inside a Chinese coin. Text wraps around hole.

Text flowed into a Chinese Coin. Done in Inkscape.

Text flowed into three circles.

Text flowed into three circles. Done in Inkscape.

Flowed text in SVG 1.2 does have some problems. First, it is complicated. There are eleven separate elements (Inkscape supports five, Batik seven). Second, there is some missing functionality. For example, there is no way to set a margin (as seen in the above examples). Third, the reality is that none of the browsers will implement SVG 1.2 flowed text even if it were part of SVG 2. They want a solution that works for both HTML and SVG.

Enter CSS and a step forward

Almost nine years after the SVG 1.2 draft came out, interest in flowing text into and around shapes has made it to HTML. The CSS working group has produced a draft specification[3] for text flowing and wrapping. The specification is fairly simple and straight forward. One specifies shapes to flow text into (‘shape-inside’) and shapes to flow text around (‘shape-ouside’). Then one specifies how the text should wrap (e.g. only wrap on the left side of a ‘shape-outside’ shape) and how close the text should come to the shapes (‘wrap-margin’ for outside shapes and ‘wrap-padding’ for inside shapes). There are a set of canned shapes defined (rectangle, circle, ellipse, or polygon) or one can link to an SVG shape or path. One can also use the alpha value of an image to generate a shape.

With this, 95% of the work for getting text wrapping in SVG is done. A few small changes are needed to adapt to the spec to SVG. For example, in HTML, one always has a box to provide a ‘wrapping-context’. In SVG you must supply the wrapping context using the ‘shape-outside’ property. In SVG, you might want to limit shapes to actual SVG shapes or paths (rather than using the canned shapes). SVG would need to add the value ‘justified’ to ‘text-align’ and add the property ‘line-height’ (already defined in CSS). The ‘x’ and ‘y’ attributes on <text> and <tspan> would be ignored (but left for use as a fallback). The trickiest part is figuring out how SVG would specify linebreaks and paragraphs since SVG does not have the <br/> and <p></p> elements.

Here is a simple example of how CSS Exclusions might work in SVG:

<def>
  <circle id="mycircle" cx="150" cy="150" r="125"/>
</def>
<text x="100" y="100" font-size="18px" text-align="justified"
       line-height="125%" wrap-margin="25"
       shape-inside="url(#myshape)">This is a mockup of...</text>
Text flowed using CSS Exclusions.

Text flowed into circle using CSS Exclusions.

And one step back

I just knocked off adding hatches to SVG 2 this week and was ready to take a closer look at text wrapping so I could present a plan for its specification at the upcoming SVG Working Group meeting. I looked at the lastest CSS Exclusions public working draft and started formulating a plan. Things looked easy. But then, a few days ago, it was announced on the CSS Working Group mailing list that the CSS Exclusions draft had been split into an Exclusions specification[4] and a Shapes specifications[5]. This seemed OK at first but in looking at the current editor’s drafts (a step before publishing a public working draft) I noticed two problems. In the Exclusions editors draft ‘shape-inside’ had been removed, to be postponed to a future specification; and in the Shapes draft, it was no longer possible to reference SVG shapes and paths. These are the VERY two things that are most required for having flowed text in SVG are gone. Hopefully we can get these back.

  1. SVG 2 Requirement.
  2. SVG 1.2 Working Draft (27 October 2004.
  3. CSS Exclusions Working Draft (3 May 2013).
  4. CSS Exclusions Editor’s draft (22 May 2013).
  5. CSS Shapes Editor’s draft (20 May 2013).
Posted in CSS, Inkscape, SVG | 2 Comments

Inkscape and Font Faces, a drama featuring SVG, Pango, and others.

I have just disabled “faux” or “synthesized” font faces in Inkscape trunk. The post explains why.

Background

Fonts often come in groups of related faces that all belong to the same family. For example, the group for the family ‘Nimbus Roman No9 L’ consists of the faces Regular, Regular Italic, Medium, and Medium Italic.[1]

Four lines of text showing the four different faces.

The four faces of ‘Nimbus Roman No9 L’. From top to bottom: Regular, Regular Italic, Medium, and Medium Italic.

Font designers take a lot of time to create the different faces. This can be illustrated by comparing individual characters between the faces.

Comparison of the letters 'a', 'f', 'l', 'v', 'z', and 'Q'.

Comparison between the Regular and Regular Italic faces of ‘Nimbus Roman No9 L’. Note how the font designer customized the different characters.

Comparison of the letters 'O', 'X'.

Comparison between the Regular and Medium faces of ‘Nimbus Roman No9 L’. Note that the Medium glyphs (black) are not just thickened versions of the Regular glyphs (red outline). In fact, the top and bottom of the bolder ‘O’ are actually thinner.

Font Faces and SVG

Since Inkscape uses SVG as its native file format, we need to take a quick look at how SVG describes font faces. SVG 1.1 (which for fonts is basically the same as CSS 2.1 ) defines the following font-selection properties:

  • font-family.
  • font-style: normal, italic, oblique.
  • font-variant: normal, small-caps.
  • font-weight: normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900.
  • font-stretch: normal, wider, narrower, ultra-condensed, extra-condensed, condensed, semi-condensed, semi-expanded, expanded, extra-expanded, ultra-expanded.

In the past, most software offered only a choice of four faces: Regular, Italic, Bold, and Bold-Italic. This was a limitation set by Microsoft Windows as it only supported four faces inside one font file.[2] The creation of faux faces ensures that each of these four faces are present even if only one true face is available. But font foundries typically offer more than four faces in a family. For example, ‘Helvetica’ from Linotype has 34 faces, ‘DejaVu Sans’ has nine. SVG and CSS, recognizing this, allow access to more faces. But still there are limitations. For example, SVG and CSS only supports nine weight variants, the numbers 100, 200, …, 900 but some faces have a weight of 1000 (as supported by FontLab).[3] Since Inkscape relies on SVG, it cannot directly support a weight of 1000. Also, SVG and CSS have no way to distinguish between two faces in the same font-family that differ in away not described by the above properties (e.g. Pochoir Regular and Pochoir Sprayed). One should note that the Bold and Italic buttons in the Inkscape text toolbar have recently been replaced by a drop-down list to accommodate more face options.

There is a new CSS3 Font module being written. The main change from CSS2 is that the property font-variant is being changed from a font-selection property to a font-feature property with expanded functionality. It will allow one to select between various glyphs in a single font face. Small caps will no longer be found in a separate face but be embedded into a “normal” face. As of now, CSS3 Fonts does not add the font weight 1000. (If you think that this is important, tell them!)

Font Faces and Pango/Cairo/FreeType/Fontconfig

Inkscape interfaces to the fonts on a system through Pango. There is surprisingly little documentation on how this works. If a font does not have an Italic/Oblique or a Bold face, Pango will still indicate that it does. At some point along the line synthesized faces are created. A little bit of sleuthing finds that Pango can create an Oblique face from a Regular face in the Pango/Cairo interface code but does not appear to be able to embolden a face. The Oblique face is made by skewing the “Regular” glyphs by 25%.[4] The style name is set to “Oblique”. This doesn’t appear to be what is happening with Inkscape.

Hunting further, one finds that Cairo has functions that interact with FreeType to request synthesized fonts. The enumeration “cairo_ft_synthesize_t” can have the values (from the documentation):

  • CAIRO_FT_SYNTHESIZE_BOLD: Embolden the glyphs (redraw with a pixel offset).
  • CAIRO_FT_SYNTHESIZE_OBLIQUE: Slant the glyph outline by 12 degrees to the right.

FreeType has functions that create faux faces.[5] However, a close examination shows that the faux Italic faces in Inkscape are not skewed by 12 degrees.

On Linux, font configuring is handled by Fontconfig. On my Fedora box, all the configuration options for synthesized faces are located in the file /etc/fonts/conf.d/90-synthetic.conf. This file dictates that fonts without a slanted face (Italic or Oblique) should have a faux face created with a skew of 20%. This is exactly what I saw when I examined a faux Italic face in Inkscape.

Taking a step back, one finds that Pango has routines that directly interact with Fontconfig. It is one of the supported back ends (the others being Uniscribe on MS Windows and CoreText on MacOS X). In the function pango_fc_list_faces() one finds the source of the names for the faux faces: “Regular”, “Bold”, “Italic”, “Bold Italic”. So we have found the source of the faux faces in Inkscape (at least on Linux).

On Linux, you can disable faux font faces by removing the 90-synthetic.conf configuration file (however, this does not disable faux faces in Chrome). This is probably not what you want to do. For programs that consume content, such such as Web browers, the Italic and Bold faux faces would probably be missed. The different faces are often used to highlight important information. In addition, browsers use font fallbacks to replace missing glyphs. A faux face might be a better fallback than a distantly related font face. As the glyphs are typically rendered small, you probably won’t notice much the inferior design. In the future, when a web designer wants more control over the use of faux faces, CSS3 Fonts will have a property to disable font synthesization. It doesn’t appear that any browser supports this yet.

Font Faces and Inkscape

Inkscape has happily provided the user with synthesized font faces without warning. These faces are at best imitations of the properly designed faces. Here is an example of the font face “Impact Condensed” as displayed by Chrome:

Two lines of text using Impact.

The top line is the normal (condensed) face while the bottom line is a faux bold face. Notice how the space between the dot and the base of the ‘i’ has disappeared, there is no longer a gap in the ‘e’, and how some letters overlap others.

The Firefox version is even worse! Who in their right mind would want to use a faux bold Impact face? For programs that create content, like Inkscape, the usefulness of faux faces is questionable.

Fortunately, Inkscape did not actually render faux bold faces on the canvas (although they did appear in the style lists and the preview section of the Text and Font dialog). The faux Italic/Oblique faces were rendered on the Inkscape canvas. This doesn’t seem so bad at first since the rendering quality of a faux Italic/Oblique face is not nearly as bad as a faux Bold face. However, it too was not so desirable:

  • The artist was not made aware that they were using a poor imitation of a real Italic font.
  • There was a good chance the face won’t be rendered correctly downstream. At least on Linux, PDF and Postscript output will show the regular face rather than the faux Italic face (but quite perversely, will show the faux Bold face).
  • Different operating systems may create the faux fonts in different ways. On Linux, the faux faces were created by the Fontconfig backend.
  • Only one each of faux Italic, Bold, and Bold-Italic faces were created per font-family even if more than one “regular” face exists (for example, a face with four weights would have just one faux Italic face created).

One could have tracked down and fixed the faux face rendering problems for all three Pango backends, and one could have added a warning in the Inkscape Text toolbar and Text and Font dialog that one is using a faux face, but it didn’t seem like it was worth the amount of effort it would have taken. The simplest solution (and the best in my view and the majority of those who have commented on this in the Inkscape Developer’s mailing list) was to disable faux font faces in Inkscape. It was a one line fix.

Work-arounds

How to work around not having the faux font faces if you find you really need them?

  • The easiest solution is to choose another font-family that does have the faces you need. There are an incredible number of font-families out there.
  • One is still able to type “Italic” or “Bold” in the Text toolbar Style entry box. (The rendering problems remain unchanged but the styling will be saved in the SVG.)
  • A faux Italic face can be simulated by skewing a text object. The only problem with this method is that multiline text won’t be lined up properly. The Transform dialog can be used to set a precise amount of skewing.
  • A faux Bold face can be simulated by adding a stroke to the text. The text may then need to be shrunk and shifted slightly to account for the added width and height with the stroke, and the distance between the glyphs may need to be adjusted; there is an entry in the Text toolbar that allows one to adjust glyph spacing.

Footnotes

Posted in CSS, Inkscape, SVG | Tagged , , , | 3 Comments

Spec Writing Madness

Hidden image for G+.

In the last SVG Working Group teleconference we discussed some aspects of CSS clipping. This discussion highlighted the sometimes unintended consequences of what seems to be a series of simple rational choices.

First, some background. Chunks of the SVG specification are being pulled out of the spec in order that they can be shared between SVG and CSS. This is overall a good thing. Web designers gains new features that are consistent across both SVG and HTML; things like filter effects, transforms, animation, etc. Web browser vendors are more motivated to perfect their implementation of old SVG features and implement new ones if they are also used in HTML. But this modularization process has its problems. The CSS forces are stronger than the SVG forces and their interests sometimes overwhelm those who see SVG as more of a pure drawing specification.

CSS clipping is part of the CSS Masking spec. With this spec, it is possible to define masks and clip paths in terms of the bounding box of the object that is being masked or clipped. Three ways to determine the bounding box are specified:

  • ‘border-box’
  • ‘padding-box’
  • ‘content-box’

Note that these terms are rooted in the CSS box model.

Image from the CSS2 specification showing a series of boxes within each other.

The CSS2 box model as shown in the CSS2 specification.

Equivalent SVG based terms might be:

  • ‘painted-box’ (includes fill, stroke, markers)
  • ‘stroke-box’ (includes fill, stroke)
  • ‘geometric-box’ (includes fill)
Triangle with fill but no stroke.

The dashed line is the bounding box for ‘geometric-box’.

Triangle with fill and stroke.

The dashed line is the bounding box for ‘stroke-box’.

Triangle with fill, stroke, and markers.

The dashed line is the bounding box for ‘painted-box’.

The default value is ‘border-box’. This may make perfect sense in HTML space.

For consistency, the default value should be the same for masking and for clipping and it should be the same for HTML and SVG.

During our meeting, we discussed what would make the most sense for SVG. Most people (including me) would find it very strange if the clipping of an object depended on what we would consider styling, thus ‘geometric-box’ would make the most sense. It might be possible to have the default style sheet set to that value for SVG but it is not clear this is what the SVG WG will choose to do. If they don’t, then by default, a clip path will depend on styling. Which can lead to some strange effects.

Suppose you have a triangle with a stroke. The ‘stroke-box’ and ‘painted-box’ depend on the thickness of that stroke, the line-join type, and in the case of miter join, the miter-join limit. OK, we can do the calculation to find the resulting bounding box, its just a few CPU cycles. Next lets add a dash pattern to the stroke. I was surprised to learn, that some people think that the dash pattern should effect the ‘stroke-box’ and that many graphics libraries are programmed that way. The box changes depending on if a dash hits a corner or not.

Triangle with fill, and dashed stroke.

The dashed line is the bounding box for ‘stroke-box’.

Now let’s go way out, suppose we animate the dash pattern (something you can so in SVG). As the dashes march around the triangle the bounding box will change. And since the clip path depends on the bounding box, it too will change… Probably not something that you would have expected or actually wanted.

A triangle showing an animated dash pattern marching around the triangle.

Note how the bounding box changes as the dash pattern moves.

Posted in CSS, Inkscape, SVG | 1 Comment

Color Interpolation in SVG

I recently added support for the value linearRGB on SVG property color-interpolation-filters to Inkscape. Here is a short post on what that means:

SVG 1.1 specifies two possible values for the color space used while compositing or while interpolating between two color values (as in a gradient or animation). The values are linearRGB and sRGB. The first, linearRGB, as the name suggests, describes a color space where the brightness (intensity) of a color is proportional to the numerical value that describes that color. This seems at first like an obvious choice. If shining one lamp on a surface produces an intensity of 100 lux, shining two identical lamps produces an intensity of 200 lux. But it turns out that this doesn’t match human vision very well. The eye’s sensors (rods and cones) and the circuitry (neurons) that process the signals are not linear. Doubling the intensity does not appear to the eye as doubling the brightness. When you have only eight bits (or 256 levels) per color channel to store brightness levels you want to maximize the usefulness of those bits. As the eye can distinguish between closer values of brightness at lower values than higher it is better to use a non-linear color space for recording brightness. One way of doing this is to use gamma correction. This can be described by the function:

Vout = A Vinɣ

where Vout is the intensity to be displayed, A is a constant, Vin is the input level. Typical values of ɣ are around 2.2 to 2.4 for TV and computer monitor signals. A secondary motivation for using a ɣ around those values was that it is close to the typical brightness response to the applied voltage of the electron gun in CRTs, making manufacturing of CRTs easier. (With LCD screens, which have very non-linear response functions, the gamma correction is handled by circuitry.)

The sRGB color space uses an effective ɣ of about 2.2. The exact formula is a bit more complicated than that shown above but it is close enough for the purposes here. Below is a comparison between linearRGB and sRGB. The linearRGB example is encoded with an inverse gamma correction so when your display applies the sRGB conversion the result is a linear brightness. Key points: an sRGB value of 0.5 (on a scale of 0 to 1) corresponds to a brightness of about 20% of that for a value of 1 and a brightness of 50% corresponds to an sRGB value of about 0.73.

Two lines with blocks of different brightness.

The top row consists of blocks with linear steps in brightness. The bottom row consists of blocks with even steps in sRGB color space. Note the rather large perceived step in brightness in the top row between the two darkest blocks and the rather small difference in the two lightest. How different the blocks look will depend on how your screen is calibrated (or not calibrated).

When interpolating between colors, which color space should one use?

Consider a linear gradient between red and blue. If one interpolates between the two colors using sRGB, the middle of the gradient appears dark. This is easy to understand. Consider one color component (red or blue) where the maximum value is 1. At the middle, the interpolated value is half the maximum value (0.5). If the interpolation is done in sRGB, this corresponds to a brightness of about 20% of the maximum value, not the 50% one would first expect. To get the expected value, one needs to interpolate in linearRGB space and then encode that value in sRGB color space (0.73 as discussed above). Clearly, using linearRGB while interpolating gives a better result.

Two gradients using different color spaces for interpolation.

The top gradient was created using interpolation in the sRGB color space while the bottom was created using linearRGB.

So why not use linearRGB in SVG drawings? The primary one is that browsers don’t support it! In addition most (all?) graphics libraries don’t support it. It is not part of the PostScript and PDF standards nor the Cairo rendering library that Inkscape (as of version 0.49) uses for rendering. The Batik based SVG viewer Squiggle does implement linearRGB interpolation for gradients but not for compositing. Here is a simple test:

Three gradients using different values of 'color-interpolation'.

SVG test file. The top gradient uses the SVG default interpolation (sRGB), the middle gradient uses sRGB interpolation, and the bottom uses linearRGB. If the bottom gradient looks like the other two then your browser doesn’t implement linearRGB interpolation.

Using linearRGB would also slow down rendering as objects would have to be converted from sRGB colorspace to linearRGB for compositing and the back to sRGB for display. And, for most purposed, using sRGB for compositing works well enough.

There is one place where browers do support linearRGB and that is in filters. In fact, the default color space for SVG 1.1 filters is linearRGB. I don’t know for sure why the writers of the original SVG specification chose to make that the default color space for filters while using sRGB for everything else. Perhaps it was viewed that filters would be used most frequently to build up complex effects that simulate point light sources shining on protrusions which would naturally call for using a linear color space. The introductory example filter in the SVG 1.1 specification shows just such an effect.

Up until now, Inkscape rendered all filters using the sRGB color space. This lead to rendering differences between browers and Inkscape for non-Inkscape created filters (Inkscape for some time now has set color-interpolation-filters to sRGB when using an Inkscape stock filter effect or when creating a filter effect inside Inkscape).

Should you expect Inkscape to support linearRGB outside of filters? Probably not. Filters are always rendered as bitmaps and it was fairly easy to add code to track the color space of the intermediate bitmap surfaces used while building up a filter effect and make the necessary conversions. Outside of filters, Inkscape uses direct calls to the Cairo rendering library and Cairo knows nothing about color spaces so it would be quite difficult to implement mixed color spaces (using sRGB some places and linearRGB other places). And as browers don’t currently support linearRGB, it would not be all that useful.

A variety of squares with tests for sRGB and linearRGB interpolation in filters.

SVG test file. For each tested filter primitive there are two sets of squares; ‘color-interpolation-filters’ is set to sRGB on the left and linearRGB on the right. A test passes if only one large square is seen. It fails if the inner square is a different color than the outer. Several of the tests rely on feFlood be rendered correctly. There is some discussion as to how the color in feFlood (as well as the lighting primitives) should be rendered so not all the tests may be valid. There may also be artifacts if the image isn’t viewed at a 100% scale and even at 100% the two vertical lines in the feConvolveMatrix filter are expected.

Posted in Inkscape, SVG | 1 Comment

SVG Path Morphing

As usual, if you are reading this in a blog aggregator and the images don’t display correctly, try viewing on my blog website. Aggregators don’t play well with SVG.


Four different Batman logos.

I have a project where I want to morph some paths. To experiment a bit, I looked for something simple to start with. I came across a poster of Batman logos over time. What a perfect thing to morph, I thought. I then looked a little bit further and saw that the designer actually got their idea from someone who had already produced a video of morphing Batman logos. Well, I still though it would be interesting to do in SVG so I continued.

I wanted to use SMIL animation as this is simpler than JavaScript and will work where JavaScript is disabled due to security concerns. SMIL works in all the major browsers except IE. Here is the result:

Morphing Batman logos.

A variety of Batman logos, animated with SMIL.

I used Inkscape to trace the paths and then extracted the path data using the XML Editor. I pasted the data into a hand-written SVG file. Inkscape’s SVG is rather verbose and adding animation inside Inkscape is not so simple.

Here is a very simple animation of a short path. Note how the <animate> element is inserted in between opening and closing <path> element tags. The d attribute is animated with the values attribute containing the required path data.

  <path d="M 100,50 100,250 300,250">
    <animate dur="5s" repeatCount="indefinite"
             attributeName="d"
	     values="M 100,50 300, 50 300,250;
		     M 100,50 100,250 300,250;
		     M 100,50 300, 50 300,250;"/>
  </path>

Here are a few notes about the process:

  • The paths must have the exact same structure. I took a look at the various logos and decided on a set that shared the same topological features so they would use the same number of Bezier curves. I choose to use all Cubic Bezier curves since they can simulate straight lines too.
  • In the Inkscape Preferences dialog under the SVG output tab, I disabled the use of relative paths. Inkscape can choose to use relative path data if it results in a shorter path string. This can result in inconsistent path structure. At the same time I reduced the numeric precision to three decimal places, I wasn’t so interested in getting the logos perfectly exact.
  • For each new logo, I copied the path from the previous logo to insure the same structure. I then deleted the right half of the path, adjusting only the left half to match the new logo. To get the right half, I duplicated the path and flipped the copy horizontally and moved it into place. I then combined the two halves into one path, merging the end nodes. I tried to use the same procedure each time to keep the path syntax the same. Occasionally, I ended up with a path that required flipping horizontally to get the starting point at the right place.
  • The animation part is rather straight forward. A few things to know: One has to repeat the first path at the end. I repeated each path twice so there would be a bit of a pause between morphs. I put each path on its own line so I could spot errors quicker. The most common error I made was forgetting the semicolon at the end of each path. Chrome has a bug where space after the last quote mark kills the animation. I am sure a person with more SMIL fu could come up with a better way of handling the morphing and the text fades but this SVG file does what I set out to do.
Posted in Inkscape, SVG | 6 Comments

Transportation and Passenger Symbols

I poked around the Internet for a set of symbols to add to Inkscape for use in the new Symbols Dialog. I was looking for a set that was more artistic than the typical symbol sets used for diagramming (I already added logic symbols as an example). I found that there are surprisingly few sets of high quality symbols available for free. Search results are dominated by commercial companies (who are happy to sell you symbols that are in the public domain). I rather quickly settled on the AIGA (American Institute of Graphic Arts) symbol set. This set was commissioned by the US Department of Transportation (DOT) in the 1970′s to create a standard set of symbols for use in airports and other transportation hubs. You will have to have lived your entire life as a hermit to have never seen the symbols in use. This symbol set served as the basis of other symbols sets like the NPS symbol set for maps, the Japanese ECOMO Public Information symbol set, and the ISO 7001 standard symbol set.

Examples of AIGA symbols.

Some common AIGA symbols (Toilets, Smoking, Immigration, Telephone).

The AIGA symbols have held up well over time (the symbols are almost 40 years old!). Only one symbol is really outdated (the Gift Shop symbol with a pipe) and one symbol never caught on (exit).

Examples of AIGA symbols.

Example of an outdated symbol (Shops) and an unused symbol (Exit).

I chose to redraw the symbols using the EPS files from the AIGA website as templates. This allowed me to optimize the SVG, aligning nodes where practical on pixel boundaries as well as using SVG elements like <circle> where possible. Redrawing the 50+ symbols gives one an insight into their design. The symbols were designed to be easily recognizable from a distance thus they use simple lines, circles, and circular arcs. Bodies are represented without feet or hands. The symbols were drawn in a pre-CAD era. This may explain some anomalies like figures not being accurately centered and small inconsistencies (i.e. the key in the Baggage Lockers symbol scaled differently than the one in the Car Rental symbol). Cut and paste meant a different thing in the 1970s.

The NPS symbol style is based on the AIGA style with some minor changes. The changes were probably motivated by the different target use of the two sets; the AIGA symbols targeted signs while the NPS symbols are for maps. In retrospect, the NPS set might have been a better choice to have added to Inkscape. The NPS set also has the advantage of being regularly updated.

Examples of AIGA vs NPS symbols.

Comparison of AIGA (left) vs NPS (right) symbols. Note how in the NPS version the fork has been simplified and how the separation between the legs/arms and bodies has been increased.

Both the ECOMO and ISO 7001 symbols sets are obviously inspired by the AIGA set. These sets, however, have the appearance of being designed by committee. There are style inconsistencies between various symbols, and those symbols that have obvious roots in AIGA seem to have often been changed for just the sake of change. Comparisons between the sets are complicated since the ISO standard is not freely available on the Web.

Examples of AIGA vs ECOMO and ISO symbols.

Comparison of AIGA (left), ISO 7001 (middle), and ECOMO (right) symbols.

One symbol that is conspicuously missing from the AIGA set is a symbol for Handicap Access; handicap access just wasn’t as an important issue among transportation planners back in the 1970s. The International Symbol of Access (ISA) was created in 1968. The original symbol left a lot to be desired from an artistic/design point of view. It basically looks like a stick figure with a head thrown on… and this is exactly how it was created. The original designer, a student, created a headless stick figure sitting in an oversized wheelchair. The head was added by the director the Swedish Handicap Institute to humanize the figure. The organization Rehabilitation International (RI) worked to get the symbol accepted by the ISO. This symbol is currently part of the ISO 7000 standard. A version more consistent with the style of the AIGA symbols is in the ISO 7001 standard as well as the 1996 NPS symbols set. A version with feet (not as consistent with the AIGA style) is in the current NPS symbol set. All these versions of the Handicap Access symbol have been subject to critique as it shows a disabled person sitting passively (helplessly?) in a wheelchair. A newer version, showing an active wheelchair user has been created but not widely adopted (in fact, RI appears to be hostile to it). And even this new symbol is subject to criticism because it represents only one kind of handicap access.

Examples of handicap access symbols.

Comparison of various Handicap Access symbols. From left to right: original (ISO 7000), NPS (1996) and ISO 7001, NPS (current), active version (quasi AIGA style).

Posted in Inkscape | 2 Comments