XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

SVG and Typography: Bells and Whistles

SVG and Typography: Bells and Whistles

June 02, 2004

In this installment of our discussion of SVG and typography, we make a departure from the sobriety of the typographic strategies we've been discussing so far and go for the other half of the fun: the bells and whistles of effects, distortions, coloring, and other unusual treatments of type.

We will create reusable code (basically a cookbook) of common typographic treatments implemented in SVG. The idea is to recreate some of the most famous effects you would expect from a design book in SVG:

  • Blur
  • Outer Shadow
  • Image within Type
  • Type within Image
  • Stroke
  • Dilate
  • Bevel
  • Gradients
  • Spacing
  • Skew
  • Mixing

This article is intended as a little arsenal of typographic treatments implemented in SVG, not as a tutorial on filters, which is something I will do in future columns. However, for some techniques we take the opportunity to briefly discuss some relevant aspect of SVG style and syntax.

Blur

Figure 1. Blur

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" version="1.1">
  <defs>
    <filter id="blur" x="0" y="0" width="150" height="150">
      <feGaussianBlur in="SourceGraphic" stdDeviation="2" />
    </filter>
  </defs>
<rect x="0" y="0" width="150" height="150" style="fill:#F1B813;" />
<text filter="url(#blur)" 
      x="40" y="85" 
      style="font-family:Arial; font-size: 30pt; fill:red;">blur</text>
</svg>

Listing 1. blur.svg

Blur is a good starting point because it is based on just one primitive filter, predefined in SVG. As you can see from the code above, we define filters inside the defs element. Inside each filter we can define series of operations and their combinations; in our case we are doing only one operation, a gaussian blur identified by the primitive feGaussianBlur.

Then, on the text element itself, we apply the defined filter by providing its location as the value of the filter attribute. Note that because of the way they are defined, in order to use any of the effects in this page all you have to do is copy and paste its definition in your document.

Drop Shadow

Figure 2. Drop Shadow

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" version="1.1">
  <defs>
    <filter id="dropShadow" x="0" y="0" width="150" height="150">
      <feOffset in="SourceGraphic" dx="0" dy="0" result="topCopy" />
      <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="shadow" />
      <feOffset in="shadow" dx="3" dy="3" result="movedShadow" />
      <feMerge>
        <feMergeNode in="topCopy" />
        <feMergeNode in="movedShadow" />
      </feMerge>
    </filter>
  </defs>

<g filter="url(#dropShadow)" >
<text x="10" y="45" 
      style="font-family:Verdana; font-size: 20pt; fill:green;">Shadows</text>
<text x="10" y="65" 
      style="font-family:Verdana; font-size: 20pt; fill:green;">and</text>
<text x="10" y="85" 
      style="font-family:Verdana; font-size: 20pt; fill:green;">Tall Trees</text>
</g>

</svg>

Listing 2. outershadow.svg

For the drop shadow effect we use a slightly more elaborate filter. This time we use three operations: first we create a copy of the source graphic, then we blur the source, and then we move the result of the blur 3 pixels to the right and 3 pixels down.

Note that in order to specify the result of a primitive as the input of another we use the result and in attributes.

At the end of the description of our filter we merge the two layers (copy and shadow) to create the final output. Finally, the filter can be applied not only to individual elements but also to groups.

Type Within Image

For the type-within-image effect we use a mask, not a filter. Masks allow you to define a region through which other elements are visible.

Figure 3. type within Image

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" version="1.1">
 <defs>
 <mask id="star">
  <polygon points="155.5,45.6146 181.334,119.935 260,121.538 197.3,169.074 
                   220.085,244.385 155.5,199.444 90.9154,244.385 113.7,169.074 
                   51,121.538 129.666,119.935"
      transform="matrix(1 0 0 1.04643 1.9873e-014 -6.73254) 
                 translate(-52.381 -37.9218)"
      style="fill:rgb(255,255,255);stroke:rgb(0,0,0);stroke-width:1" />
 </mask>
 </defs>

<g mask="url(#star)" style="font-family:Verdana; font-size: 10pt; fill:red;">
<text x="80" y="80" 
      style="font-size:24pt; fill:pink;">the</text>
<text x="0" y="130" 
      style="font-size: 60pt; fill:pink;">Girlie</text>
<text x="20" y="190" 
      style="font-size: 60pt; fill:pink;">Show</text>

<g>
<text x="30" y="20" >Bye bye baby bye bye</text>
<!-- other text -->
</g>

</svg>

Listing 3. typeinimage.svg

As you can see, in the defs element we define a mask, in this case a polygon (the star). We give it a name which we use later on in the g element to refer to the mask.

Pages: 1, 2, 3

Next Pagearrow