Using svglite with web fonts by @ellis2013nz

Share Tweet

OK, no stats today, just fidgeting about with graphics devices and type faces. Caveat – the details of graphics formats and typefaces is not my area of real expertise, this blog post is me noting down things that I found useful and others might too. As always, corrections and comments are very welcome.

There are two main types of computer graphic formats:

  • vector graphics, where the file is basically a set of instructions (start at x, draw a line at 30 degrees angle for y units, draw a circle of radius w centred at z, etc). Like something you generated with Inkscape or Adobe Illustrator.
  • raster or bitmap graphics which are basically an array of numbers telling the computer which how to colour each pixel. Like a digital photograph.

Generally vector formats are far superior if you have the choice but large complex graphics (eg with millions of points, or maps with many fiddly bits) can be slow to render (and large to store). And until relatively recently many users’ web browsers could only show bitmap graphics. Internet Explorer 8 was the last high-use browser of this sort we had to worry about.

For my blog I work almost purely with Scalable Vector Graphic (SVG) format by choice, and PNG (a relatively efficient and high quality bitmap format) when I have to.

My graphics workflow for this blog is generally:

  1. Write the graphic to a Scalable Vector Graphic (SVG)
  2. Convert the SVGs to PNGs in batches using ImageMagick

I use the SVGs on the web pages that make up this blog; I need the PNG copies for posting on Twitter, Facebook and LinkedIn which don’t take SVGs, and also for some complex objects that would be too large as SVGs.

A quick aside on anti-aliasing

To get in the groove of thinking about graphics I’m going to start with the concept of anti-aliasing. Here are three closeups of a straight line in a computer graphic, generated in R by three different graphics devices. From left to right these were generated by CairoSVG(), CairoPNG() and png().

Aliasing (in graphics) refers to the jagged staircase-like bits of an image from approximating an ideal shape with crude collections of pixels. Anti-aliasing is basically the smoothing or blurring process to try to make the problem less obvious.

On a Windows machine (where I spend nearly all my working time), the png() device, no matter high a resolution you specify, will not use anti-aliasing and close ups of the image will reveal jagged bits like that in the right of the three options above. At the opposite end, a graphic that has been saved as SVG won’t have any aliasing at all coming from the file format itself; any jaggedness comes from the final rendering of the information in the file onto the screen (in the end, everything has to become pixels to get on the screen), not from how you generated the file.

The Cairo option in the middle has anti-aliasing taking place when the PNG file itself was generated. Files generated with CairoPNG() look much better than those from png(), but still can’t compete with the vector format even when the PNG is high resolution (eg 720 or more dots per inch).

Here’s the code that generated these examples

library(Cairo) library(svglite) library(frs) library(clipr) png("0150-antialias-none.png", 8 * 600, 4 * 600, res = 600) plot(1:2, 1:2, type = "l", bty = "n", main = "No anti-alias png() device") dev.off() CairoPNG("0150-antialias-cairo.png", 8 * 600, 4 * 600, dpi = 600) plot(1:2, 1:2, type = "l", bty = "n", main = "Anti-aliased CairoPNG device") dev.off() CairoSVG("0150-antialias-cairo.svg", 8, 4) plot(1:2, 1:2, type = "l", bty = "n", main = "CairoSVG device") dev.off()

Potentially useful whimsical tip: once your awareness is raised about the need for anti-aliasing, you might become painfully aware of those unprofessional looking jagged bits in graphics. When working interactively in RStudio on Windows, all the graphics in your plot pane will look this way. If this hurts you like it hurts me, you can bring up a anti-aliased window with CairoWin() and plots will be rendered nicely on that window, and look much better than the crude default renditions. If you’re using two screens it’s also convenient for placing on your second screen.

Different flavours of SVG

Until recently I’ve been generating my SVG files with CairoSVG(). However, I’ve gotten very disatisfied with how text is rendered by that format. It’s hard to put my finger on what is wrong, but it looks blurry, particularly when it’s about 10 point in size which of course is nearly all the time in statistical graphics. Sometimes the problem goes away when you zoom in, but that isn’t really the point.

I eventually solved this problem by moving to the excellent svglite package by Hadley Wickham, Lionel Henry, T Jake Luciani, Matthieu Decorde and Vaudor Lis. svglite creates smaller and faster SVGs and has a much better treatment of text in particular. But svglite alone wasn’t enough for the way I needed typefaces treated – I’ll get to that later.

To go into this further, here are three different SVG files, rendered in this web page as images, created by Cairo::CairoSVG(), grDevices::svg() and svglite::svglite().



The first two approaches are very similar, but the svglite philosophy is quite different. CairoSVG and svg take text and turn it into many tiny shapes to draw; whereas svglite keeps the text as text in the SVG file and leaves it to the end user’s computer to render it. Zoom in close on any of those images above and the text will magnify nicely; but something about the relatively complicated approach of the first two makes them look a little blurred and complex when they’re looked at from a distance. This is the process of turning the text into individual shapes, interacting with the final rendering on the screen in some way that I don’t want to have to understand.

SVG files are just text files (in XML format) so we can look at the actual code (a huge advantage of SVG over other formats). Here’s the full text of the SVG generated by CairoSVG:

 
    
    
 
    
     
     
     xmlns= 
     
     "http://www.w3.org/2000/svg" 
     
     xmlns:xlink= 
     
     "http://www.w3.org/1999/xlink" 
     
     width= 
     
     "432pt" 
     
     height= 
     
     "432pt" 
     
     viewBox= 
     
     "0 0 432 432" 
     
     version= 
     
     "1.1" 
     
     > 
     
      
      
       
     
      
      
       
     
      
      
       
       
       overflow= 
       
       "visible" 
       
       id= 
       
       "glyph0-0" 
       
       > 
       
        
        
         
         
         style= 
         
         "stroke:none;" 
         
         d= 
         
         "M 2.921875 0 L 2.921875 -26.128906 L 6.378906 -26.128906 L 6.378906 -15.398438 L 19.960938 -15.398438 L 19.960938 -26.128906 L 23.417969 -26.128906 L 23.417969 0 L 19.960938 0 L 19.960938 -12.316406 L 6.378906 -12.316406 L 6.378906 0 Z M 2.921875 0 " 
         
         /> 
         
          
         
          
          
           
           
           overflow= 
           
           "visible" 
           
           id= 
           
           "glyph0-1" 
           
           > 
           
            
            
             
             
             style= 
             
             "stroke:none;" 
             
             d= 
             
             "M 15.363281 -6.09375 L 18.679688 -5.683594 C 18.15625 -3.746094 17.1875 -2.242188 15.773438 -1.175781 C 14.359375 -0.105469 12.550781 0.425781 10.355469 0.429688 C 7.582031 0.425781 5.386719 -0.421875 3.769531 -2.128906 C 2.144531 -3.832031 1.335938 -6.226563 1.335938 -9.304688 C 1.335938 -12.484375 2.152344 -14.953125 3.792969 -16.714844 C 5.429688 -18.472656 7.558594 -19.351563 10.175781 -19.355469 C 12.703125 -19.351563 14.769531 -18.492188 16.378906 -16.769531 C 17.980469 -15.046875 18.785156 -12.621094 18.785156 -9.5 C 18.785156 -9.304688 18.777344 -9.019531 18.765625 -8.644531 L 4.652344 -8.644531 C 4.769531 -6.558594 5.355469 -4.96875 6.414063 -3.867188 C 7.472656 -2.761719 8.792969 -2.207031 10.371094 -2.210938 C 11.546875 -2.207031 12.550781 -2.515625 13.382813 -3.136719 C 14.214844 -3.75 14.875 -4.738281 15.363281 -6.09375 Z M 4.828125 -11.28125 L 15.398438 -11.28125 C 15.253906 -12.867188 14.847656 -14.0625 14.1875 -14.863281 C 13.160156 -16.097656 11.835938 -16.714844 10.210938 -16.71875 C 8.738281 -16.714844 7.5 -16.222656 6.496094 -15.238281 C 5.492188 -14.25 4.9375 -12.929688 4.828125 -11.28125 Z M 4.828125 -11.28125 " 
             
             /> 
             
              
             
              
              
               
               
               overflow= 
               
               "visible" 
               
               id= 
               
               "glyph0-2" 
               
               > 
               
                
                
                 
                 
                 style= 
                 
                 "stroke:none;" 
                 
                 d= 
                 
                 "M 2.335938 0 L 2.335938 -26.128906 L 5.542969 -26.128906 L 5.542969 0 Z M 2.335938 0 " 
                 
                 /> 
                 
                  
                 
                  
                  
                   
                   
                   overflow= 
                   
                   "visible" 
                   
                   id= 
                   
                   "glyph0-3" 
                   
                   > 
                   
                    
                    
                     
                     
                     style= 
                     
                     "stroke:none;" 
                     
                     d= 
                     
                     "M 1.210938 -9.464844 C 1.207031 -12.964844 2.179688 -15.5625 4.132813 -17.25 C 5.757813 -18.652344 7.742188 -19.351563 10.085938 -19.355469 C 12.6875 -19.351563 14.816406 -18.5 16.46875 -16.796875 C 18.117188 -15.089844 18.941406 -12.734375 18.945313 -9.730469 C 18.941406 -7.292969 18.578125 -5.378906 17.847656 -3.984375 C 17.117188 -2.585938 16.054688 -1.5 14.660156 -0.730469 C 13.261719 0.0429688 11.734375 0.425781 10.085938 0.429688 C 7.433594 0.425781 5.292969 -0.417969 3.660156 -2.117188 C 2.023438 -3.8125 1.207031 -6.261719 1.210938 -9.464844 Z M 4.507813 -9.464844 C 4.503906 -7.035156 5.035156 -5.222656 6.09375 -4.019531 C 7.148438 -2.8125 8.476563 -2.207031 10.085938 -2.210938 C 11.675781 -2.207031 13.003906 -2.8125 14.0625 -4.027344 C 15.117188 -5.234375 15.644531 -7.082031 15.648438 -9.570313 C 15.644531 -11.90625 15.113281 -13.679688 14.050781 -14.890625 C 12.988281 -16.09375 11.664063 -16.699219 10.085938 -16.699219 C 8.476563 -16.699219 7.148438 -16.097656 6.09375 -14.898438 C 5.035156 -13.695313 4.503906 -11.882813 4.507813 -9.464844 Z M 4.507813 -9.464844 " 
                     
                     /> 
                     
                      
                     
                      
                      
                       
                       
                       overflow= 
                       
                       "visible" 
                       
                       id= 
                       
                       "glyph0-4" 
                       
                       > 
                       
                        
                        
                         
                         
                         style= 
                         
                         "stroke:none;" 
                         
                         d= 
                         
                         "" 
                         
                         /> 
                         
                          
                         
                          
                          
                           
                           
                           overflow= 
                           
                           "visible" 
                           
                           id= 
                           
                           "glyph0-5" 
                           
                           > 
                           
                            
                            
                             
                             
                             style= 
                             
                             "stroke:none;" 
                             
                             d= 
                             
                             "M 5.898438 0 L 0.105469 -18.925781 L 3.421875 -18.925781 L 6.433594 -8.003906 L 7.554688 -3.9375 C 7.601563 -4.140625 7.929688 -5.441406 8.535156 -7.84375 L 11.546875 -18.925781 L 14.847656 -18.925781 L 17.679688 -7.949219 L 18.625 -4.332031 L 19.710938 -7.984375 L 22.953125 -18.925781 L 26.074219 -18.925781 L 20.15625 0 L 16.824219 0 L 13.8125 -11.335938 L 13.082031 -14.5625 L 9.25 0 Z M 5.898438 0 " 
                             
                             /> 
                             
                              
                             
                              
                              
                               
                               
                               overflow= 
                               
                               "visible" 
                               
                               id= 
                               
                               "glyph0-6" 
                               
                               > 
                               
                                
                                
                                 
                                 
                                 style= 
                                 
                                 "stroke:none;" 
                                 
                                 d= 
                                 
                                 "M 2.371094 0 L 2.371094 -18.925781 L 5.257813 -18.925781 L 5.257813 -16.058594 C 5.992188 -17.398438 6.671875 -18.28125 7.296875 -18.710938 C 7.917969 -19.136719 8.605469 -19.351563 9.355469 -19.355469 C 10.433594 -19.351563 11.53125 -19.007813 12.652344 -18.320313 L 11.546875 -15.34375 C 10.761719 -15.804688 9.976563 -16.035156 9.195313 -16.039063 C 8.492188 -16.035156 7.863281 -15.824219 7.304688 -15.40625 C 6.746094 -14.980469 6.347656 -14.398438 6.113281 -13.652344 C 5.753906 -12.511719 5.578125 -11.261719 5.578125 -9.910156 L 5.578125 0 Z M 2.371094 0 " 
                                 
                                 /> 
                                 
                                  
                                 
                                  
                                  
                                   
                                   
                                   overflow= 
                                   
                                   "visible" 
                                   
                                   id= 
                                   
                                   "glyph0-7" 
                                   
                                   > 
                                   
                                    
                                    
                                     
                                     
                                     style= 
                                     
                                     "stroke:none;" 
                                     
                                     d= 
                                     
                                     "M 14.6875 0 L 14.6875 -2.386719 C 13.484375 -0.507813 11.71875 0.425781 9.390625 0.429688 C 7.878906 0.425781 6.492188 0.015625 5.230469 -0.816406 C 3.960938 -1.644531 2.980469 -2.808594 2.289063 -4.300781 C 1.589844 -5.792969 1.242188 -7.507813 1.246094 -9.445313 C 1.242188 -11.335938 1.558594 -13.046875 2.191406 -14.585938 C 2.820313 -16.121094 3.761719 -17.300781 5.023438 -18.125 C 6.28125 -18.941406 7.691406 -19.351563 9.25 -19.355469 C 10.386719 -19.351563 11.402344 -19.113281 12.296875 -18.632813 C 13.183594 -18.148438 13.910156 -17.519531 14.472656 -16.753906 L 14.472656 -26.128906 L 17.660156 -26.128906 L 17.660156 0 Z M 4.542969 -9.445313 C 4.539063 -7.019531 5.050781 -5.207031 6.074219 -4.007813 C 7.09375 -2.808594 8.300781 -2.207031 9.695313 -2.210938 C 11.09375 -2.207031 12.285156 -2.78125 13.265625 -3.929688 C 14.246094 -5.074219 14.734375 -6.824219 14.738281 -9.179688 C 14.734375 -11.765625 14.238281 -13.664063 13.242188 -14.878906 C 12.242188 -16.089844 11.011719 -16.699219 9.554688 -16.699219 C 8.125 -16.699219 6.933594 -16.117188 5.976563 -14.953125 C 5.019531 -13.789063 4.539063 -11.953125 4.542969 -9.445313 Z M 4.542969 -9.445313 " 
                                     
                                     /> 
                                     
                                      
                                     
                                      
                                     
                                      
                                      
                                       
                                       
                                       id= 
                                       
                                       "clip1" 
                                       
                                       > 
                                       
                                        
                                        
                                         
                                         
                                         d= 
                                         
                                         "M 177.121094 177.121094 L 342.28125 177.121094 L 342.28125 212.679688 L 177.121094 212.679688 Z M 177.121094 177.121094 " 
                                         
                                         /> 
                                         
                                          
                                         
                                          
                                         
                                          
                                          
                                           
                                           
                                           id= 
                                           
                                           "surface16" 
                                           
                                           > 
                                           
                                            
                                            
                                             
                                             
                                             clip-path= 
                                             
                                             "url(#clip1)" 
                                             
                                             clip-rule= 
                                             
                                             "nonzero" 
                                             
                                             > 
                                             
                                              
                                              
                                               
                                               
                                               style= 
                                               
                                               "fill:rgb(0%,0%,0%);fill-opacity:1;" 
                                               
                                               > 
                                               
                                                
                                                
                                                 
                                                 
                                                 xlink:href= 
                                                 
                                                 "#glyph0-0" 
                                                 
                                                 x= 
                                                 
                                                 "168.929688" 
                                                 
                                                 y= 
                                                 
                                                 "207.25" 
                                                 
                                                 /> 
                                                 
                                                  
                                                  
                                                   
                                                   
                                                   xlink:href= 
                                                   
                                                   "#glyph0-1" 
                                                   
                                                   x= 
                                                   
                                                   "195.288818" 
                                                   
                                                   y= 
                                                   
                                                   "207.25" 
                                                   
                                                   /> 
                                                   
                                                    
                                                    
                                                     
                                                     
                                                     xlink:href= 
                                                     
                                                     "#glyph0-2" 
                                                     
                                                     x= 
                                                     
                                                     "215.588379" 
                                                     
                                                     y= 
                                                     
                                                     "207.25" 
                                                     
                                                     /> 
                                                     
                                                      
                                                      
                                                       
                                                       
                                                       xlink:href= 
                                                       
                                                       "#glyph0-2" 
                                                       
                                                       x= 
                                                       
                                                       "223.69751" 
                                                       
                                                       y= 
                                                       
                                                       "207.25" 
                                                       
                                                       /> 
                                                       
                                                        
                                                        
                                                         
                                                         
                                                         xlink:href= 
                                                         
                                                         "#glyph0-3" 
                                                         
                                                         x= 
                                                         
                                                         "231.806641" 
                                                         
                                                         y= 
                                                         
                                                         "207.25" 
                                                         
                                                         /> 
                                                         
                                                          
                                                          
                                                           
                                                           
                                                           xlink:href= 
                                                           
                                                           "#glyph0-4" 
                                                           
                                                           x= 
                                                           
                                                           "252.106201" 
                                                           
                                                           y= 
                                                           
                                                           "207.25" 
                                                           
                                                           /> 
                                                           
                                                            
                                                            
                                                             
                                                             
                                                             xlink:href= 
                                                             
                                                             "#glyph0-5" 
                                                             
                                                             x= 
                                                             
                                                             "262.24707" 
                                                             
                                                             y= 
                                                             
                                                             "207.25" 
                                                             
                                                             /> 
                                                             
                                                              
                                                              
                                                               
                                                               
                                                               xlink:href= 
                                                               
                                                               "#glyph0-3" 
                                                               
                                                               x= 
                                                               
                                                               "288.606201" 
                                                               
                                                               y= 
                                                               
                                                               "207.25" 
                                                               
                                                               /> 
                                                               
                                                                
                                                                
                                                                 
                                                                 
                                                                 xlink:href= 
                                                                 
                                                                 "#glyph0-6" 
                                                                 
                                                                 x= 
                                                                 
                                                                 "308.905762" 
                                                                 
                                                                 y= 
                                                                 
                                                                 "207.25" 
                                                                 
                                                                 /> 
                                                                 
                                                                  
                                                                  
                                                                   
                                                                   
                                                                   xlink:href= 
                                                                   
                                                                   "#glyph0-2" 
                                                                   
                                                                   x= 
                                                                   
                                                                   "321.060547" 
                                                                   
                                                                   y= 
                                                                   
                                                                   "207.25" 
                                                                   
                                                                   /> 
                                                                   
                                                                    
                                                                    
                                                                     
                                                                     
                                                                     xlink:href= 
                                                                     
                                                                     "#glyph0-7" 
                                                                     
                                                                     x= 
                                                                     
                                                                     "329.169678" 
                                                                     
                                                                     y= 
                                                                     
                                                                     "207.25" 
                                                                     
                                                                     /> 
                                                                     
                                                                      
                                                                     
                                                                      
                                                                     
                                                                      
                                                                     
                                                                      
                                                                    
                                                                     
                                                                  
                                                                   
                                                                
                                                                 
                                                              
                                                               
                                                            
                                                             
                                                          
                                                           
                                                        
                                                         
                                                      
                                                       
                                                    
                                                     
                                                  
                                                   
                                                
                                                 
                                              
                                               
                                            
                                             
                                          
                                           
                                        
                                         
                                      
                                       
                                    
                                     
                                  
                                   
                                
                                 
                              
                               
                            
                             
                          
                           
                        
                         
                      
                       
                    
                     
                  
                   
                
                 
              
               
            
             
          
           
        
         
      
       
    
    

… and here it is for the SVG generated by svglite:

 
    
    
 
    
     
     
     xmlns= 
     
     'http://www.w3.org/2000/svg' 
     
     xmlns:xlink= 
     
     'http://www.w3.org/1999/xlink' 
     
     viewBox= 
     
     '0 0 720.00 576.00' 
     
     > 
     
      
      
       
     
      
      
       
       
       type= 
       
       'text/css' 
       
       > 
       
        line, polyline, path, rect, circle { fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 10.00; } ]]></span><span class="nt"></style></span> <span class="nt"></defs></span> <span class="nt"><rect</span> <span class="na">width=</span><span class="s">'100%'</span> <span class="na">height=</span><span class="s">'100%'</span> <span class="na">style=</span><span class="s">'stroke: none; fill: #FFFFFF;'</span><span class="nt">/></span> <span class="nt"><defs></span> <span class="nt"><clipPath</span> <span class="na">id=</span><span class="s">'cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy'</span><span class="nt">></span> <span class="nt"><rect</span> <span class="na">x=</span><span class="s">'177.12'</span> <span class="na">y=</span><span class="s">'177.12'</span> <span class="na">width=</span><span class="s">'452.16'</span> <span class="na">height=</span><span class="s">'178.56'</span> <span class="nt">/></span> <span class="nt"></clipPath></span> <span class="nt"></defs></span> <span class="nt"><g</span> <span class="na">clip-path=</span><span class="s">'url(#cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy)'</span><span class="nt">><text</span> <span class="na">x=</span><span class="s">'318.96'</span> <span class="na">y=</span><span class="s">'278.15'</span> <span class="na">style=</span><span class="s">'font-size: 60.00px; font-family: Indie Flower;'</span> <span class="na">textLength=</span><span class="s">'168.48px'</span> <span class="na">lengthAdjust=</span><span class="s">'spacingAndGlyphs'</span><span class="nt">></span>Hello world<span class="nt"></text></g></span> <span class="nt"></svg></span></code></pre> </figure> <p>The <code class="highlighter-rouge">svglite</code> version is <em>much</em> shorter because instead of describing exactly how each character looks, it just says “write ‘Hello world’ in the middle of the graphic, at 60 points in size, using the Indie Flower font family”.</p> <p>That last point – “using the Indie Flower font family” is important too. It means that this font family needs to be available at the point the SVG file is rendered on-screen ie the end user’s machine. Whereas in <code class="highlighter-rouge">CairoSVG</code> and <code class="highlighter-rouge">svg</code>, no font family is recorded in the SVG file itself, the font family is taken into account at the generation of the SVG and has to be available on the developer’s machine.</p> <p>As it happens, the “Indie Flower” type face isn’t installed on my computer and probably isn’t on yours either. When R encountered an instruction to use a typeface it didn’t know, it fell back on Arial and that’s how the two images on the left were generated. When a web browser encounters such an instruction, it falls back (at least if it’s Chrome or Edge) on Times New Roman or equivalent. This is why the image on the right looks different to the other two – it’s a question of a web browsers fall-back type face, compared to R’s.</p> <p>Here’s the code that produced those three images and got the code from the SVG files to put in this blog post:</p> <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="n">CairoSVG</span><span class="p">(</span><span class="s2">"0150-cairo-svg.svg"</span><span class="p">)</span><span class="w"> </span><span class="n">par</span><span class="p">(</span><span class="n">family</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Indie Flower"</span><span class="p">,</span><span class="w"> </span><span class="n">cex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">3</span><span class="p">)</span><span class="w"> </span><span class="n">plot.new</span><span class="p">()</span><span class="w"> </span><span class="n">text</span><span class="p">(</span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="s2">"Hello world"</span><span class="p">)</span><span class="w"> </span><span class="n">dev.off</span><span class="p">()</span><span class="w"> </span><span class="n">svg</span><span class="p">(</span><span class="s2">"0150-svg.svg"</span><span class="p">)</span><span class="w"> </span><span class="n">par</span><span class="p">(</span><span class="n">family</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Indie Flower"</span><span class="p">,</span><span class="w"> </span><span class="n">cex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">3</span><span class="p">)</span><span class="w"> </span><span class="n">plot.new</span><span class="p">()</span><span class="w"> </span><span class="n">text</span><span class="p">(</span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="s2">"Hello world"</span><span class="p">)</span><span class="w"> </span><span class="n">dev.off</span><span class="p">()</span><span class="w"> </span><span class="n">svglite</span><span class="p">(</span><span class="s2">"0150-svglite.svg"</span><span class="p">)</span><span class="w"> </span><span class="n">par</span><span class="p">(</span><span class="n">family</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Indie Flower"</span><span class="p">,</span><span class="w"> </span><span class="n">cex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">3</span><span class="p">)</span><span class="w"> </span><span class="n">plot.new</span><span class="p">()</span><span class="w"> </span><span class="n">text</span><span class="p">(</span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="s2">"Hello world"</span><span class="p">)</span><span class="w"> </span><span class="n">dev.off</span><span class="p">()</span><span class="w"> </span><span class="n">print_to_screen</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="k">function</span><span class="p">(</span><span class="n">fn</span><span class="p">){</span><span class="w"> </span><span class="n">txt</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">readChar</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span><span class="w"> </span><span class="n">file.info</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span><span class="o">$</span><span class="n">size</span><span class="p">)</span><span class="w"> </span><span class="n">write_clip</span><span class="p">(</span><span class="n">txt</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="n">print_to_screen</span><span class="p">(</span><span class="s2">"..http://freerangestats.info/img/0150-cairo-svg.svg"</span><span class="p">)</span><span class="w"> </span><span class="n">print_to_screen</span><span class="p">(</span><span class="s2">"..http://freerangestats.info/img/0150-svglite.svg"</span><span class="p">)</span></code></pre> </figure> <h2 id="solving-the-web-font-problem-for-svglite">Solving the web font problem for svglite</h2> <p>So, I much preferred the smaller size, faster creation and download, and better look for text from <code class="highlighter-rouge">svglite</code> – but I had a new problem, of how to get custom fonts rendering reliably. I use web fonts from Google for my web page to get my HTML/CSS consistent with the graphic images, so in practice I need a way to render Google web fonts in SVGs, regardless of whether the user has them on their end computer or not.</p> <p><code class="highlighter-rouge">svglite</code> has a <code class="highlighter-rouge">user_fonts</code> argument that is meant to embed fonts that are on the developer’s machine inside the SVG if desired, but <a href="https://github.com/r-lib/svglite/issues/95" rel="nofollow" target="_blank">as far as I can tell it doesn’t work</a>. So I forced myself to look a bit into how the SVG format works, and after wading through a number of out of date bits of info on the web eventually realised that I just needed the line <code class="highlighter-rouge">@import url('https://fonts.googleapis.com/css?family=Indie Flower:400,400i,700,700i');</code> added (for the Indie Flower case). So the <code class="highlighter-rouge">svglite</code> file above just needs to become as follows:</p> <figure class="highlight"> <pre><code class="language-xml" data-lang="xml"><span class="cp"><?xml version='1.0' encoding='UTF-8' ?></span> <span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">'http://www.w3.org/2000/svg'</span> <span class="na">xmlns:xlink=</span><span class="s">'http://www.w3.org/1999/xlink'</span> <span class="na">viewBox=</span><span class="s">'0 0 720.00 576.00'</span><span class="nt">></span> <span class="nt"><defs></span> <span class="nt"><style</span> <span class="na">type=</span><span class="s">'text/css'</span><span class="nt">></span><span class="cp"><![CDATA[ line, polyline, path, rect, circle { fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 10.00; } ]]></span><span class="nt"></style></span> <span class="nt"><style></span> @import url('https://fonts.googleapis.com/css?family=Indie Flower:400,400i,700,700i'); <span class="nt"></style></span> <span class="nt"></defs></span> <span class="nt"><rect</span> <span class="na">width=</span><span class="s">'100%'</span> <span class="na">height=</span><span class="s">'100%'</span> <span class="na">style=</span><span class="s">'stroke: none; fill: #FFFFFF;'</span><span class="nt">/></span> <span class="nt"><defs></span> <span class="nt"><clipPath</span> <span class="na">id=</span><span class="s">'cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy'</span><span class="nt">></span> <span class="nt"><rect</span> <span class="na">x=</span><span class="s">'177.12'</span> <span class="na">y=</span><span class="s">'177.12'</span> <span class="na">width=</span><span class="s">'452.16'</span> <span class="na">height=</span><span class="s">'178.56'</span> <span class="nt">/></span> <span class="nt"></clipPath></span> <span class="nt"></defs></span> <span class="nt"><g</span> <span class="na">clip-path=</span><span class="s">'url(#cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy)'</span><span class="nt">><text</span> <span class="na">x=</span><span class="s">'318.96'</span> <span class="na">y=</span><span class="s">'278.15'</span> <span class="na">style=</span><span class="s">'font-size: 60.00px; font-family: Indie Flower;'</span> <span class="na">textLength=</span><span class="s">'168.48px'</span> <span class="na">lengthAdjust=</span><span class="s">'spacingAndGlyphs'</span><span class="nt">></span>Hello world<span class="nt"></text></g></span> <span class="nt"></svg></span></code></pre> </figure> <p>This renders nicely, with the correct typeface and all:</p> <p><object type="image/svg+xml" data="https://freerangestats.info/img/0150-svglite-with-fonts.svg" width="50%"></object></p> <p>… albeit with one last change necessary to how I organise my blog. I used to include my SVG files in the blog using the <code class="highlighter-rouge"><img></code> tag, such as:</p> <figure class="highlight"> <pre><code class="language-html" data-lang="html"><span class="nt"><img</span> <span class="na">src=</span><span class="s">'http://freerangestats.info/img/0150-svglite-with-fonts.svg'</span> <span class="na">width=</span><span class="s">'50%'</span><span class="nt">></span></code></pre> </figure> <p>An SVG file that is called into a webpage by <code class="highlighter-rouge"><img></code> is not allowed to get information from external sites. It has to instead be included with an <code class="highlighter-rouge"><object></code> tag as follows:</p> <figure class="highlight"> <pre><code class="language-html" data-lang="html"><span class="nt"><object</span> <span class="na">type=</span><span class="s">"image/svg+xml"</span> <span class="na">data=</span><span class="s">'http://freerangestats.info/img/0150-svglite-with-fonts.svg'</span> <span class="na">width=</span><span class="s">'50%'</span><span class="nt">></object></span></code></pre> </figure> <p>This has the disadvantage that a user can no longer right-click on the image and save it. They can still view the “frame source”, copy it into a text editor and save it from there, but that’s going to put off a lot of users who aren’t used to thinking of an image as being fully represented by a bunch of code that can be pasted into Notepad! I imagine I’ll think of something to get around this.</p> <p>Embedding my SVGs with <code class="highlighter-rouge"><object></code> is also necessary if I want to incorporate interactivity (eg tooltips or more), so it’s probably a good habit to get into.</p> <p>I knocked up a <a href="https://github.com/ellisp/frs-r-package/blob/master/pkg/R/svg_googlefonts.R" rel="nofollow" target="_blank">quick and probably non-robust hack of a function <code class="highlighter-rouge">svg_googlefonts()</code></a> to add the necessary font imports in <code class="highlighter-rouge"><style></code> tags to an SVG generated by <code class="highlighter-rouge">svglite</code>. Usage is exceptionally simple. It takes a previously created SVG file (in this case, the “0150-svglite.svg” file created earlier in this post), the name of the Google fonts (one or more) to insert, and saves as a new version (or over the original, which is the convenient default for how I’ll be using it):</p> <figure class="highlight"> <pre><code class="language-r" data-lang="r"><span class="n">svg_googlefonts</span><span class="p">(</span><span class="s2">"0150-svglite.svg"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Indie Flower"</span><span class="p">,</span><span class="w"> </span><span class="n">new_svgfile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"0150-svglite-with-fonts.svg"</span><span class="p">)</span></code></pre> </figure> <p>That’s now in my <code class="highlighter-rouge">frs</code> R package of convenient utilities associated with this blog.</p> <p>That’s all for now. In summary:</p> <ul> <li><code class="highlighter-rouge">svglite</code> makes fast, small, well-rendered SVG images which treat text the way SVG is designed to</li> <li>but if you want to use typefaces that aren’t going to be on every user’s machine you need to embed them in the SVG or have the SVG import them. My <code class="highlighter-rouge">svg_googlefonts()</code> function helps you with the latter, and the resulting SVG files need to be included in web pages with the <code class="highlighter-rouge"><object></code> tag.</li> </ul> <script type='text/javascript'> var vglnk = { key: '949efb41171ac6ec1bf7f206d57e90b8' }; (function(d, t) { var s = d.createElement(t); s.type = 'text/javascript'; s.async = true; s.src = '//cdn.viglink.com/api/vglnk.js'; var r = d.getElementsByTagName(t)[0]; r.parentNode.insertBefore(s, r); }(document, 'script')); </script> <div > <h3 class="jp-relatedposts-headline"><em>Related</em></h3> </div><aside class="mashsb-container mashsb-main mashsb-stretched"><div class="mashsb-box"><div class="mashsb-buttons"><a class="mashicon-facebook mash-small mash-center mashsb-noshadow" href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F" target="_blank" rel="nofollow"><span class="icon"></span><span class="text">Share</span></a><a class="mashicon-twitter mash-small mash-center mashsb-noshadow" href="https://twitter.com/intent/tweet?text=Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz&url=https://www.r-bloggers.com/using-svglite-with-web-fonts-by-ellis2013nz/&via=Rbloggers" target="_blank" rel="nofollow"><span class="icon"></span><span class="text">Tweet</span></a><div class="onoffswitch2 mash-small mashsb-noshadow" style="display:none;"></div></div> </div> <div style="clear:both;"></div></aside> <!-- Share buttons by mashshare.net - Version: 3.6.1--> <p class="syndicated-attribution"> <div style="border: 1px solid; background: none repeat scroll 0 0 #EDEDED; margin: 1px; font-size: 13px;"> <div style="text-align: center;">To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://freerangestats.info/blog/2019/04/07/fonts-and-stuff"> free range statistics - R</a></strong>.</div> <hr /> <a href="https://www.r-bloggers.com/" rel="nofollow">R-bloggers.com</a> offers <strong><a href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers" rel="nofollow">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" href="https://www.r-project.org/" rel="nofollow">R</a> news and <a title="R tutorials" href="https://www.r-bloggers.com/search/tutorial" rel="nofollow">tutorials</a> on topics such as: <a title="Data science" href="https://www.r-bloggers.com/search/data%20science" rel="nofollow">Data science</a>, <a title="Big Data" href="https://www.r-bloggers.com/search/Big%20Data" rel="nofollow">Big Data, <a title="R jobs" href="https://www.r-users.com/" rel="nofollow">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" href="https://www.r-bloggers.com/search/ggplot2" rel="nofollow">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" href="https://www.r-bloggers.com/search/boxplot" rel="nofollow">Boxplots</a>, <a title="Maps and gis" href="https://www.r-bloggers.com/search/map" rel="nofollow">maps</a>, <a title="Animation in R" href="https://www.r-bloggers.com/search/animation" rel="nofollow">animation</a>), programming (<a title="RStudio IDE for R" href="https://www.r-bloggers.com/search/RStudio" rel="nofollow">RStudio</a>, <a title="Sweave and literate programming" href="https://www.r-bloggers.com/search/sweave" rel="nofollow">Sweave</a>, <a title="LaTeX in R" href="https://www.r-bloggers.com/search/LaTeX" rel="nofollow">LaTeX</a>, <a title="SQL and databases" href="https://www.r-bloggers.com/search/SQL" rel="nofollow">SQL</a>, <a title="Eclipse IDE for R" href="https://www.r-bloggers.com/search/eclipse" rel="nofollow">Eclipse</a>, <a title="git and github, Version Control System" href="https://www.r-bloggers.com/search/git" rel="nofollow">git</a>, <a title="Large data in R using Hadoop" href="https://www.r-bloggers.com/search/hadoop" rel="nofollow">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" href="https://www.r-bloggers.com/search/Web+Scraping" rel="nofollow">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" href="https://www.r-bloggers.com/search/regression" rel="nofollow">regression</a>, <a title="principal component analysis tutorial" href="https://www.r-bloggers.com/search/PCA" rel="nofollow">PCA</a>, <a title="Time series" href="https://www.r-bloggers.com/search/time+series" rel="nofollow">time series</a>, <a title="finance trading" href="https://www.r-bloggers.com/search/trading" rel="nofollow">trading</a>) and more... </div></p><hr /><hr /> <div style="border: 1px solid #EB9349; background: none repeat scroll 0 0 #FDEADA; text-align: center; margin: 10px; font-size: 16px;"> If you got this far, why not <strong><u>subscribe for updates</u> </strong>from the site? Choose your flavor: <a href="http://feedburner.google.com/fb/a/mailverify?uri=RBloggers" rel="nofollow">e-mail</a>, <a href="https://twitter.com/#!/rbloggers" rel="nofollow">twitter</a>, <a href="http://feeds.feedburner.com/RBloggers" rel="nofollow">RSS</a>, or <a href="http://www.facebook.com/pages/R-bloggers/191414254890" rel="nofollow">facebook</a>... </div><div class="social4i" style="height:29px;"><div class="social4in" style="height:29px;float: left;"><div class="socialicons s4fblike" style="float:left;margin-right: 10px;"><div class="fb-like" data-href="https://www.r-bloggers.com/using-svglite-with-web-fonts-by-ellis2013nz/" data-send="true" data-layout="button_count" data-width="100" data-height="21" data-show-faces="false"></div></div><div class="socialicons s4twitter" style="float:left;margin-right: 10px;"><a href="https://twitter.com/share" data-url="https://www.r-bloggers.com/using-svglite-with-web-fonts-by-ellis2013nz/" data-counturl="https://www.r-bloggers.com/using-svglite-with-web-fonts-by-ellis2013nz/" data-text="Using svglite with web fonts by @ellis2013nz" class="twitter-share-button" data-count="horizontal" data-via="rbloggers"></a></div><div class="socialicons s4linkedin" style="float:left;margin-right: 10px;"><script type="in/share" data-url="https://www.r-bloggers.com/using-svglite-with-web-fonts-by-ellis2013nz/" data-counter="right"></script></div></div><div style="clear:both"></div></div></div> </div><!-- #post-## --> <div id="comments"> <div id="comment-user-details"> <p class="nocomments">Comments are closed.</p> </div> </div><!-- #comments --> </div> <!-- begin second sidebar --> <div id="secondsidebar"> <div class="side-widget"><h2>Search R-bloggers</h2> <div class="textwidget"><p><script> (function() { var cx = '005359090438081006639:paz69t-s8ua'; var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true; gcse.src = 'https://cse.google.com/cse.js?cx=' + cx; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gcse, s); })(); </script><br /> <gcse:searchbox-only></gcse:searchbox-only></p> </div> </div><div class="side-widget"><h2>Recent popular posts</h2><ul> <li> <a href="https://www.r-bloggers.com/coke-vs-pepsi-data-table-vs-tidy-examining-consumption-preferences-for-data-scientists/" class="bump-view" data-bump-view="tp"> Coke vs. Pepsi? data.table vs. tidy? Examining Consumption Preferences for Data Scientists </a> </li> <li> <a href="https://www.r-bloggers.com/ibreakdown-faster-prettier-and-more-precise-explanations-for-predictive-models-with-interactions/" class="bump-view" data-bump-view="tp"> iBreakDown: faster, prettier and more precise explanations for predictive models (with interactions) </a> </li> <li> <a href="https://www.r-bloggers.com/martingale-strategies-dont-work-but-we-knew-that-simulation-analysis-in-r/" class="bump-view" data-bump-view="tp"> Martingale strategies don’t work, but we knew that – Simulation analysis in R </a> </li> <li> <a href="https://www.r-bloggers.com/winners-of-the-1st-shiny-contest/" class="bump-view" data-bump-view="tp"> Winners of the 1st Shiny Contest </a> </li> <li> <a href="https://www.r-bloggers.com/why-rcppdynprog-is-written-in-c/" class="bump-view" data-bump-view="tp"> Why RcppDynProg is Written in C++ </a> </li> </ul></div><div class="side-widget"><h2>Most visited articles of the week</h2> <ol > <li><a href='https://www.r-bloggers.com/data-science-software-used-in-journals-stat-packages-declining-including-r-ai-ml-software-growing/' title='Data Science Software Used in Journals: Stat Packages Declining (including R), AI/ML Software Growing'>Data Science Software Used in Journals: Stat Packages Declining (including R), AI/ML Software Growing</a></li> <li><a href='https://www.r-bloggers.com/how-to-write-the-first-for-loop-in-r/' title='How to write the first for loop in R'>How to write the first for loop in R</a></li> <li><a href='https://www.r-bloggers.com/5-ways-to-subset-a-data-frame-in-r/' title='5 Ways to Subset a Data Frame in R'>5 Ways to Subset a Data Frame in R</a></li> <li><a href='https://www.r-bloggers.com/what-are-the-popular-r-packages/' title='What are the Popular R Packages?'>What are the Popular R Packages?</a></li> <li><a href='https://www.r-bloggers.com/how-to-share-r-visualizations-in-microsoft-powerpoint/' title='How to share R visualizations in Microsoft PowerPoint'>How to share R visualizations in Microsoft PowerPoint</a></li> <li><a href='https://www.r-bloggers.com/r-sorting-a-data-frame-by-the-contents-of-a-column/' title='R – Sorting a data frame by the contents of a column'>R – Sorting a data frame by the contents of a column</a></li> <li><a href='https://www.r-bloggers.com/installing-r-packages/' title='Installing R packages'>Installing R packages</a></li> <li><a href='https://www.r-bloggers.com/what-is-a-permutation-test/' title='What is a Permutation Test?'>What is a Permutation Test?</a></li> <li><a href='https://www.r-bloggers.com/using-apply-sapply-lapply-in-r/' title='Using apply, sapply, lapply in R'>Using apply, sapply, lapply in R</a></li> </ol> </div><div class="side-widget"><h2>Sponsors</h2> <div class="textwidget"><script data-cfasync="false" type="text/javascript"> // https://support.cloudflare.com/hc/en-us/articles/200169436-How-can-I-have-Rocket-Loader-ignore-my-script-s-in-Automatic-Mode- // this must be placed higher. Otherwise it doesn't work. // data-cfasync="false" is for making sure cloudflares' rocketcache doesn't interfeare with this // in this case it only works because it was used at the original script in the text widget function createCookie(name,value,days) { var expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + (days*24*60*60*1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + value + expires + "; path=/"; } function readCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } return null; } function eraseCookie(name) { createCookie(name,"",-1); } async function readTextFile(file) { // Helps people browse between pages without the need to keep downloading the same // ads txt page everytime. This way, it allows them to use their browser's cache. var random_number = readCookie("ad_random_number_cookie"); if(random_number == null) { var random_number = Math.floor(Math.random()*100*(new Date().getTime()/10000000000)); createCookie("ad_random_number_cookie",random_number,1) } file += '?t='+random_number; var rawFile = new XMLHttpRequest(); rawFile.onreadystatechange = function () { if(rawFile.readyState === 4) { if(rawFile.status === 200 || rawFile.status == 0) { // var allText = rawFile.responseText; // document.write(allText); document.write(rawFile.responseText); } } } rawFile.open("GET", file, false); rawFile.send(null); } // readTextFile('https://raw.githubusercontent.com/Raynos/file-store/master/temp.txt'); readTextFile("https://www.r-bloggers.com/wp-content/uploads/text-widget_anti-cache.txt"); </script> </div> </div><div class="side-widget"><h2><a class="rsswidget" href="https://feeds.feedburner.com/Rjobs"><img class="rss-widget-icon" style="border:0" width="14" height="14" src="https://www.r-bloggers.com/wp-includes/images/rss.png" alt="RSS" /></a> <a class="rsswidget" href="https://www.r-users.com/">Jobs for R users</a></h2><ul><li><a href='http://feedproxy.google.com/~r/RJobs/~3/yCXCB5zlaPs/'>Economic Modeler @ Sophie, BluePath Solutions</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/i4uk70yuhKY/'>Movement Building Analyst</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/RTB4njQFmOs/'>Business Intelligence Analyst</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/PJ4UUBxiKB4/'>Innovation Fellow</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/nMdd0zTCIdE/'>Postdoctoral position Stats, Comp. Biol. @ Madrid, Spain.</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/_0NJUzBfMrQ/'>Lead Data Scientist @ Washington, District of Columbia, U.S.</a></li><li><a href='http://feedproxy.google.com/~r/RJobs/~3/y06JZPbLOoU/'>PhD Fellowship @ Wallace University, US</a></li></ul></div><div class="side-widget"> <div class="textwidget"><strong><a href="https://www.r-bloggers.com/blogs-list/">Full list of contributing R-bloggers</a></strong></div> </div> </div> <!-- end second sidebar --></div> <!-- begin footer --> <div id="footer"> <strong><a href="https://www.r-bloggers.com">R-bloggers</a></strong> was founded by <a href="http://www.r-statistics.com/about/">Tal Galili</a>, with gratitude to the <a href="http://www.r-project.org/">R</a> community. <br /> Is powered by <a href="http://www.wordpress.org">WordPress</a> using a <a href="http://themes.bavotasan.com" rel="nofollow">bavotasan.com</a> design.<br /> Copyright © 2019 <strong>R-bloggers</strong>. All Rights Reserved. <a href="http://www.r-bloggers.com/terms/">Terms and Conditions</a> for this website<br /> </div> <!-- TPC! Memory Usage (http://webjawns.com) Memory Usage: 80074656 Memory Peak Usage: 81103208 WP Memory Limit: 820M PHP Memory Limit: 800M Checkpoints: 9 --> <div class="wpusb wpusb-buttons wpusb-fixed-right wpusb-fixed wpusb-layout-buttons-content wpusb-fixed-position_fixed" id="wpusb-container-fixed" data-element-url="https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share" data-element-title="Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz" data-attr-reference="179906" data-is-term="0" data-element="fixed" data-attr-nonce="67fbd43ffc" data-disabled-share-counts="1" data-wpusb-component="counter-social-share"> <div data-element="buttons" class="wpusb-fixed-right-container "> <div class="wpusb-item wpusb-facebook "> <a href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share" target="_blank" data-action="open-popup" class="wpusb-layout-buttons wpusb-button wpusb-btn " title="Share on Facebook" rel="nofollow"> <i class="wpusb-icon-facebook-buttons "></i> </a> </div> <div class="wpusb-item wpusb-twitter "> <a href="https://twitter.com/share?url=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share&text=Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz #rstats #datascience&via=rbloggers" target="_blank" data-action="open-popup" class="wpusb-layout-buttons wpusb-button wpusb-btn " title="Tweet" rel="nofollow"> <i class="wpusb-icon-twitter-buttons "></i> </a> </div> <div class="wpusb-item wpusb-linkedin "> <a href="https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share&title=Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz" target="_blank" data-action="open-popup" class="wpusb-layout-buttons wpusb-button wpusb-btn " title="Share on Linkedin" rel="nofollow"> <i class="wpusb-icon-linkedin-buttons "></i> </a> </div> <div class="wpusb-item wpusb-email "> <a href="mailto:?subject=Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz&body=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share %0A%0AUsing%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz%0A%0AOK%2C%20no%20stats%20today%2C%20just%20fidgeting%20about%20with%20graphics%20devices%20and%20type%20faces.%20Caveat%20-%20the%20details%20of%20graphics%20formats%20and%20typefaces%20is%20not%20my%20area%20of%20real%20expertise%2C%20this%20blog%20post%20is%20me%20noting%20down%20things%20that%20I%20found%20useful%20and%20others%20might%20too.%20As%20always%2C%20corrections%20and%20comments%20are%20very%20welcome.%0A%0AThere%20are%20two%20main%20types%20of%20computer%20graphic%20formats%3A%0A%0A%0A%20%20vector%20graphics%2C%20where%20the%20file%20is%20basically%20a%20set%20of%20instructions%20%28start%20at%20x%2C%20draw%20a%20line%20at%2030%20degrees%20angle%20for%20y%20units%2C%20draw%20a%20circle%20of%20radius%20w%20centred%20at%20z%2C%20etc%29.%20Like%20something%20you%20generated%20with%20Inkscape%20or%20Adobe%20Illustrator.%0A%20%20raster%20or%20bitmap%20graphics%20which%20are%20basically%20an%20array%20of%20numbers%20telling%20the%20computer%20which%20how%20to%20colour%20each%20pixel.%20Like%20a%20digital%20photograph.%0A%0A%0AGenerally%20vector%20formats%20are%20far%20superior%20if%20you%20have%20the%20choice%20but%20large%20complex%20graphics%20%28eg%20with%20millions%20of%20points%2C%20or%20maps%20with%20many%20fiddly%20bits%29%20can%20be%20slow%20to%20render%20%28and%20large%20to%20store%29.%20And%20until%20relatively%20recently%20many%20users%E2%80%99%20web%20browsers%20could%20only%20show%20bitmap%20graphics.%20Internet%20Explorer%208%20was%20the%20last%20high-use%20browser%20of%20this%20sort%20we%20had%20to%20worry%20about.%0A%0AFor%20my%20blog%20I%20work%20almost%20purely%20with%20Scalable%20Vector%20Graphic%20%28SVG%29%20format%20by%20choice%2C%20and%20PNG%20%28a%20relatively%20efficient%20and%20high%20quality%20bitmap%20format%29%20when%20I%20have%20to.%0A%0AMy%20graphics%20workflow%20for%20this%20blog%20is%20generally%3A%0A%0A%0A%20%20Write%20the%20graphic%20to%20a%20Scalable%20Vector%20Graphic%20%28SVG%29%0A%20%20Convert%20the%20SVGs%20to%20PNGs%20in%20batches%20using%20ImageMagick%0A%0A%0AI%20use%20the%20SVGs%20on%20the%20web%20pages%20that%20make%20up%20this%20blog%3B%20I%20need%20the%20PNG%20copies%20for%20posting%20on%20Twitter%2C%20Facebook%20and%20LinkedIn%20which%20don%E2%80%99t%20take%20SVGs%2C%20and%20also%20for%20some%20complex%20objects%20that%20would%20be%20too%20large%20as%20SVGs.%0A%0AA%20quick%20aside%20on%20anti-aliasing%0A%0ATo%20get%20in%20the%20groove%20of%20thinking%20about%20graphics%20I%E2%80%99m%20going%20to%20start%20with%20the%20concept%20of%20anti-aliasing.%20Here%20are%20three%20closeups%20of%20a%20straight%20line%20in%20a%20computer%20graphic%2C%20generated%20in%20R%20by%20three%20different%20graphics%20devices.%20From%20left%20to%20right%20these%20were%20generated%20by%20CairoSVG%28%29%2C%20CairoPNG%28%29%20and%20png%28%29.%0A%0A%0A%0AAliasing%20%28in%20graphics%29%20refers%20to%20the%20jagged%20staircase-like%20bits%20of%20an%20image%20from%20approximating%20an%20ideal%20shape%20with%20crude%20collections%20of%20pixels.%20Anti-aliasing%20is%20basically%20the%20smoothing%20or%20blurring%20process%20to%20try%20to%20make%20the%20problem%20less%20obvious.%0A%0AOn%20a%20Windows%20machine%20%28where%20I%20spend%20nearly%20all%20my%20working%20time%29%2C%20the%20png%28%29%20device%2C%20no%20matter%20high%20a%20resolution%20you%20specify%2C%20will%20not%20use%20anti-aliasing%20and%20close%20ups%20of%20the%20image%20will%20reveal%20jagged%20bits%20like%20that%20in%20the%20right%20of%20the%20three%20options%20above.%20At%20the%20opposite%20end%2C%20a%20graphic%20that%20has%20been%20saved%20as%20SVG%20won%E2%80%99t%20have%20any%20aliasing%20at%20all%20coming%20from%20the%20file%20format%20itself%3B%20any%20jaggedness%20comes%20from%20the%20final%20rendering%20of%20the%20information%20in%20the%20file%20onto%20the%20screen%20%28in%20the%20end%2C%20everything%20has%20to%20become%20pixels%20to%20get%20on%20the%20screen%29%2C%20not%20from%20how%20you%20generated%20the%20file.%0A%0AThe%20Cairo%20option%20in%20the%20middle%20has%20anti-aliasing%20taking%20place%20when%20the%20PNG%20file%20itself%20was%20generated.%20Files%20generated%20with%20CairoPNG%28%29%20look%20much%20better%20than%20those%20from%20png%28%29%2C%20but%20still%20can%E2%80%99t%20compete%20with%20the%20vector%20format%20even%20when%20the%20PNG%20is%20high%20resolution%20%28eg%20720%20or%20more%20dots%20per%20inch%29.%0A%0AHere%E2%80%99s%20the%20code%20that%20generated%20these%20examples%0A%0Alibrary%28Cairo%29%0Alibrary%28svglite%29%0Alibrary%28frs%29%0Alibrary%28clipr%29%0A%0Apng%28%220150-antialias-none.png%22%2C%208%20%2A%20600%2C%204%20%2A%20600%2C%20res%20%3D%20600%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22No%20anti-alias%20png%28%29%20device%22%29%0Adev.off%28%29%0A%0ACairoPNG%28%220150-antialias-cairo.png%22%2C%208%20%2A%20600%2C%204%20%2A%20600%2C%20dpi%20%3D%20600%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22Anti-aliased%20CairoPNG%20device%22%29%0Adev.off%28%29%0A%0ACairoSVG%28%220150-antialias-cairo.svg%22%2C%208%2C%204%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22CairoSVG%20device%22%29%0Adev.off%28%29%0A%0A%0A%20%20Potentially%20useful%20whimsical%20tip%3A%20once%20your%20awareness%20is%20raised%20about%20the%20need%20for%20anti-aliasing%2C%20you%20might%20become%20painfully%20aware%20of%20those%20unprofessional%20looking%20jagged%20bits%20in%20graphics.%20When%20working%20interactively%20in%20RStudio%20on%20Windows%2C%20all%20the%20graphics%20in%20your%20plot%20pane%20will%20look%20this%20way.%20If%20this%20hurts%20you%20like%20it%20hurts%20me%2C%20you%20can%20bring%20up%20a%20anti-aliased%20window%20with%20CairoWin%28%29%20and%20plots%20will%20be%20rendered%20nicely%20on%20that%20window%2C%20and%20look%20much%20better%20than%20the%20crude%20default%20renditions.%20If%20you%E2%80%99re%20using%20two%20screens%20it%E2%80%99s%20also%20convenient%20for%20placing%20on%20your%20second%20screen.%0A%0A%0ADifferent%20flavours%20of%20SVG%0A%0AUntil%20recently%20I%E2%80%99ve%20been%20generating%20my%20SVG%20files%20with%20CairoSVG%28%29.%20However%2C%20I%E2%80%99ve%20gotten%20very%20disatisfied%20with%20how%20text%20is%20rendered%20by%20that%20format.%20It%E2%80%99s%20hard%20to%20put%20my%20finger%20on%20what%20is%20wrong%2C%20but%20it%20looks%20blurry%2C%20particularly%20when%20it%E2%80%99s%20about%2010%20point%20in%20size%20which%20of%20course%20is%20nearly%20all%20the%20time%20in%20statistical%20graphics.%20Sometimes%20the%20problem%20goes%20away%20when%20you%20zoom%20in%2C%20but%20that%20isn%E2%80%99t%20really%20the%20point.%0A%0AI%20eventually%20solved%20this%20problem%20by%20moving%20to%20the%20excellent%20svglite%20package%20by%20Hadley%20Wickham%2C%20Lionel%20Henry%2C%20T%20Jake%20Luciani%2C%20Matthieu%20Decorde%20and%20Vaudor%20Lis.%20svglite%20creates%20smaller%20and%20faster%20SVGs%20and%20has%20a%20much%20better%20treatment%20of%20text%20in%20particular.%20But%20svglite%20alone%20wasn%E2%80%99t%20enough%20for%20the%20way%20I%20needed%20typefaces%20treated%20-%20I%E2%80%99ll%20get%20to%20that%20later.%0A%0ATo%20go%20into%20this%20further%2C%20here%20are%20three%20different%20SVG%20files%2C%20rendered%20in%20this%20web%20page%20as%20images%2C%20created%20by%20Cairo%3A%3ACairoSVG%28%29%2C%20grDevices%3A%3Asvg%28%29%20and%20svglite%3A%3Asvglite%28%29.%0A%0A%0A%0A%0A%0AThe%20first%20two%20approaches%20are%20very%20similar%2C%20but%20the%20svglite%20philosophy%20is%20quite%20different.%20CairoSVG%20and%20svg%20take%20text%20and%20turn%20it%20into%20many%20tiny%20shapes%20to%20draw%3B%20whereas%20svglite%20keeps%20the%20text%20as%20text%20in%20the%20SVG%20file%20and%20leaves%20it%20to%20the%20end%20user%E2%80%99s%20computer%20to%20render%20it.%20Zoom%20in%20close%20on%20any%20of%20those%20images%20above%20and%20the%20text%20will%20magnify%20nicely%3B%20but%20something%20about%20the%20relatively%20complicated%20approach%20of%20the%20first%20two%20makes%20them%20look%20a%20little%20blurred%20and%20complex%20when%20they%E2%80%99re%20looked%20at%20from%20a%20distance.%20This%20is%20the%20process%20of%20turning%20the%20text%20into%20individual%20shapes%2C%20interacting%20with%20the%20final%20rendering%20on%20the%20screen%20in%20some%20way%20that%20I%20don%E2%80%99t%20want%20to%20have%20to%20understand.%0A%0ASVG%20files%20are%20just%20text%20files%20%28in%20XML%20format%29%20so%20we%20can%20look%20at%20the%20actual%20code%20%28a%20huge%20advantage%20of%20SVG%20over%20other%20formats%29.%20Here%E2%80%99s%20the%20full%20text%20of%20the%20SVG%20generated%20by%20CairoSVG%3A%0A%0A%26lt%3B%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%22432pt%22%20height%3D%22432pt%22%20viewBox%3D%220%200%20432%20432%22%20version%3D%221.1%22%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%26lt%3Bg%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-0%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.921875%200%20L%202.921875%20-26.128906%20L%206.378906%20-26.128906%20L%206.378906%20-15.398438%20L%2019.960938%20-15.398438%20L%2019.960938%20-26.128906%20L%2023.417969%20-26.128906%20L%2023.417969%200%20L%2019.960938%200%20L%2019.960938%20-12.316406%20L%206.378906%20-12.316406%20L%206.378906%200%20Z%20M%202.921875%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-1%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%2015.363281%20-6.09375%20L%2018.679688%20-5.683594%20C%2018.15625%20-3.746094%2017.1875%20-2.242188%2015.773438%20-1.175781%20C%2014.359375%20-0.105469%2012.550781%200.425781%2010.355469%200.429688%20C%207.582031%200.425781%205.386719%20-0.421875%203.769531%20-2.128906%20C%202.144531%20-3.832031%201.335938%20-6.226563%201.335938%20-9.304688%20C%201.335938%20-12.484375%202.152344%20-14.953125%203.792969%20-16.714844%20C%205.429688%20-18.472656%207.558594%20-19.351563%2010.175781%20-19.355469%20C%2012.703125%20-19.351563%2014.769531%20-18.492188%2016.378906%20-16.769531%20C%2017.980469%20-15.046875%2018.785156%20-12.621094%2018.785156%20-9.5%20C%2018.785156%20-9.304688%2018.777344%20-9.019531%2018.765625%20-8.644531%20L%204.652344%20-8.644531%20C%204.769531%20-6.558594%205.355469%20-4.96875%206.414063%20-3.867188%20C%207.472656%20-2.761719%208.792969%20-2.207031%2010.371094%20-2.210938%20C%2011.546875%20-2.207031%2012.550781%20-2.515625%2013.382813%20-3.136719%20C%2014.214844%20-3.75%2014.875%20-4.738281%2015.363281%20-6.09375%20Z%20M%204.828125%20-11.28125%20L%2015.398438%20-11.28125%20C%2015.253906%20-12.867188%2014.847656%20-14.0625%2014.1875%20-14.863281%20C%2013.160156%20-16.097656%2011.835938%20-16.714844%2010.210938%20-16.71875%20C%208.738281%20-16.714844%207.5%20-16.222656%206.496094%20-15.238281%20C%205.492188%20-14.25%204.9375%20-12.929688%204.828125%20-11.28125%20Z%20M%204.828125%20-11.28125%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-2%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.335938%200%20L%202.335938%20-26.128906%20L%205.542969%20-26.128906%20L%205.542969%200%20Z%20M%202.335938%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-3%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%201.210938%20-9.464844%20C%201.207031%20-12.964844%202.179688%20-15.5625%204.132813%20-17.25%20C%205.757813%20-18.652344%207.742188%20-19.351563%2010.085938%20-19.355469%20C%2012.6875%20-19.351563%2014.816406%20-18.5%2016.46875%20-16.796875%20C%2018.117188%20-15.089844%2018.941406%20-12.734375%2018.945313%20-9.730469%20C%2018.941406%20-7.292969%2018.578125%20-5.378906%2017.847656%20-3.984375%20C%2017.117188%20-2.585938%2016.054688%20-1.5%2014.660156%20-0.730469%20C%2013.261719%200.0429688%2011.734375%200.425781%2010.085938%200.429688%20C%207.433594%200.425781%205.292969%20-0.417969%203.660156%20-2.117188%20C%202.023438%20-3.8125%201.207031%20-6.261719%201.210938%20-9.464844%20Z%20M%204.507813%20-9.464844%20C%204.503906%20-7.035156%205.035156%20-5.222656%206.09375%20-4.019531%20C%207.148438%20-2.8125%208.476563%20-2.207031%2010.085938%20-2.210938%20C%2011.675781%20-2.207031%2013.003906%20-2.8125%2014.0625%20-4.027344%20C%2015.117188%20-5.234375%2015.644531%20-7.082031%2015.648438%20-9.570313%20C%2015.644531%20-11.90625%2015.113281%20-13.679688%2014.050781%20-14.890625%20C%2012.988281%20-16.09375%2011.664063%20-16.699219%2010.085938%20-16.699219%20C%208.476563%20-16.699219%207.148438%20-16.097656%206.09375%20-14.898438%20C%205.035156%20-13.695313%204.503906%20-11.882813%204.507813%20-9.464844%20Z%20M%204.507813%20-9.464844%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-4%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-5%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%205.898438%200%20L%200.105469%20-18.925781%20L%203.421875%20-18.925781%20L%206.433594%20-8.003906%20L%207.554688%20-3.9375%20C%207.601563%20-4.140625%207.929688%20-5.441406%208.535156%20-7.84375%20L%2011.546875%20-18.925781%20L%2014.847656%20-18.925781%20L%2017.679688%20-7.949219%20L%2018.625%20-4.332031%20L%2019.710938%20-7.984375%20L%2022.953125%20-18.925781%20L%2026.074219%20-18.925781%20L%2020.15625%200%20L%2016.824219%200%20L%2013.8125%20-11.335938%20L%2013.082031%20-14.5625%20L%209.25%200%20Z%20M%205.898438%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-6%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.371094%200%20L%202.371094%20-18.925781%20L%205.257813%20-18.925781%20L%205.257813%20-16.058594%20C%205.992188%20-17.398438%206.671875%20-18.28125%207.296875%20-18.710938%20C%207.917969%20-19.136719%208.605469%20-19.351563%209.355469%20-19.355469%20C%2010.433594%20-19.351563%2011.53125%20-19.007813%2012.652344%20-18.320313%20L%2011.546875%20-15.34375%20C%2010.761719%20-15.804688%209.976563%20-16.035156%209.195313%20-16.039063%20C%208.492188%20-16.035156%207.863281%20-15.824219%207.304688%20-15.40625%20C%206.746094%20-14.980469%206.347656%20-14.398438%206.113281%20-13.652344%20C%205.753906%20-12.511719%205.578125%20-11.261719%205.578125%20-9.910156%20L%205.578125%200%20Z%20M%202.371094%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-7%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%2014.6875%200%20L%2014.6875%20-2.386719%20C%2013.484375%20-0.507813%2011.71875%200.425781%209.390625%200.429688%20C%207.878906%200.425781%206.492188%200.015625%205.230469%20-0.816406%20C%203.960938%20-1.644531%202.980469%20-2.808594%202.289063%20-4.300781%20C%201.589844%20-5.792969%201.242188%20-7.507813%201.246094%20-9.445313%20C%201.242188%20-11.335938%201.558594%20-13.046875%202.191406%20-14.585938%20C%202.820313%20-16.121094%203.761719%20-17.300781%205.023438%20-18.125%20C%206.28125%20-18.941406%207.691406%20-19.351563%209.25%20-19.355469%20C%2010.386719%20-19.351563%2011.402344%20-19.113281%2012.296875%20-18.632813%20C%2013.183594%20-18.148438%2013.910156%20-17.519531%2014.472656%20-16.753906%20L%2014.472656%20-26.128906%20L%2017.660156%20-26.128906%20L%2017.660156%200%20Z%20M%204.542969%20-9.445313%20C%204.539063%20-7.019531%205.050781%20-5.207031%206.074219%20-4.007813%20C%207.09375%20-2.808594%208.300781%20-2.207031%209.695313%20-2.210938%20C%2011.09375%20-2.207031%2012.285156%20-2.78125%2013.265625%20-3.929688%20C%2014.246094%20-5.074219%2014.734375%20-6.824219%2014.738281%20-9.179688%20C%2014.734375%20-11.765625%2014.238281%20-13.664063%2013.242188%20-14.878906%20C%2012.242188%20-16.089844%2011.011719%20-16.699219%209.554688%20-16.699219%20C%208.125%20-16.699219%206.933594%20-16.117188%205.976563%20-14.953125%20C%205.019531%20-13.789063%204.539063%20-11.953125%204.542969%20-9.445313%20Z%20M%204.542969%20-9.445313%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3BclipPath%20id%3D%22clip1%22%26gt%3B%0A%20%20%26lt%3Bpath%20d%3D%22M%20177.121094%20177.121094%20L%20342.28125%20177.121094%20L%20342.28125%20212.679688%20L%20177.121094%20212.679688%20Z%20M%20177.121094%20177.121094%20%22%2F%26gt%3B%0A%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20id%3D%22surface16%22%26gt%3B%0A%26lt%3Bg%20clip-path%3D%22url%28%23clip1%29%22%20clip-rule%3D%22nonzero%22%26gt%3B%0A%26lt%3Bg%20style%3D%22fill%3Argb%280%25%2C0%25%2C0%25%29%3Bfill-opacity%3A1%3B%22%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-0%22%20x%3D%22168.929688%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-1%22%20x%3D%22195.288818%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22215.588379%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22223.69751%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-3%22%20x%3D%22231.806641%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-4%22%20x%3D%22252.106201%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-5%22%20x%3D%22262.24707%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-3%22%20x%3D%22288.606201%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-6%22%20x%3D%22308.905762%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22321.060547%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-7%22%20x%3D%22329.169678%22%20y%3D%22207.25%22%2F%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0A%E2%80%A6%20and%20here%20it%20is%20for%20the%20SVG%20generated%20by%20svglite%3A%0A%0A%26lt%3B%3Fxml%20version%3D%271.0%27%20encoding%3D%27UTF-8%27%20%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20viewBox%3D%270%200%20720.00%20576.00%27%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3Bstyle%20type%3D%27text%2Fcss%27%26gt%3B%26lt%3B%21%5BCDATA%5B%0A%20%20%20%20line%2C%20polyline%2C%20path%2C%20rect%2C%20circle%20%7B%0A%20%20%20%20%20%20fill%3A%20none%3B%0A%20%20%20%20%20%20stroke%3A%20%23000000%3B%0A%20%20%20%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%20%20%20stroke-linejoin%3A%20round%3B%0A%20%20%20%20%20%20stroke-miterlimit%3A%2010.00%3B%0A%20%20%20%20%7D%0A%20%20%5D%5D%26gt%3B%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Brect%20width%3D%27100%25%27%20height%3D%27100%25%27%20style%3D%27stroke%3A%20none%3B%20fill%3A%20%23FFFFFF%3B%27%2F%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3BclipPath%20id%3D%27cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%27%26gt%3B%0A%20%20%20%20%26lt%3Brect%20x%3D%27177.12%27%20y%3D%27177.12%27%20width%3D%27452.16%27%20height%3D%27178.56%27%20%2F%26gt%3B%0A%20%20%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20clip-path%3D%27url%28%23cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%29%27%26gt%3B%26lt%3Btext%20x%3D%27318.96%27%20y%3D%27278.15%27%20style%3D%27font-size%3A%2060.00px%3B%20font-family%3A%20Indie%20Flower%3B%27%20textLength%3D%27168.48px%27%20lengthAdjust%3D%27spacingAndGlyphs%27%26gt%3BHello%20world%26lt%3B%2Ftext%26gt%3B%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0AThe%20svglite%20version%20is%20much%20shorter%20because%20instead%20of%20describing%20exactly%20how%20each%20character%20looks%2C%20it%20just%20says%20%E2%80%9Cwrite%20%E2%80%98Hello%20world%E2%80%99%20in%20the%20middle%20of%20the%20graphic%2C%20at%2060%20points%20in%20size%2C%20using%20the%20Indie%20Flower%20font%20family%E2%80%9D.%0A%0AThat%20last%20point%20-%20%E2%80%9Cusing%20the%20Indie%20Flower%20font%20family%E2%80%9D%20is%20important%20too.%20It%20means%20that%20this%20font%20family%20needs%20to%20be%20available%20at%20the%20point%20the%20SVG%20file%20is%20rendered%20on-screen%20ie%20the%20end%20user%E2%80%99s%20machine.%20Whereas%20in%20CairoSVG%20and%20svg%2C%20no%20font%20family%20is%20recorded%20in%20the%20SVG%20file%20itself%2C%20the%20font%20family%20is%20taken%20into%20account%20at%20the%20generation%20of%20the%20SVG%20and%20has%20to%20be%20available%20on%20the%20developer%E2%80%99s%20machine.%0A%0AAs%20it%20happens%2C%20the%20%E2%80%9CIndie%20Flower%E2%80%9D%20type%20face%20isn%E2%80%99t%20installed%20on%20my%20computer%20and%20probably%20isn%E2%80%99t%20on%20yours%20either.%20When%20R%20encountered%20an%20instruction%20to%20use%20a%20typeface%20it%20didn%E2%80%99t%20know%2C%20it%20fell%20back%20on%20Arial%20and%20that%E2%80%99s%20how%20the%20two%20images%20on%20the%20left%20were%20generated.%20When%20a%20web%20browser%20encounters%20such%20an%20instruction%2C%20it%20falls%20back%20%28at%20least%20if%20it%E2%80%99s%20Chrome%20or%20Edge%29%20on%20Times%20New%20Roman%20or%20equivalent.%20This%20is%20why%20the%20image%20on%20the%20right%20looks%20different%20to%20the%20other%20two%20-%20it%E2%80%99s%20a%20question%20of%20a%20web%20browsers%20fall-back%20type%20face%2C%20compared%20to%20R%E2%80%99s.%0A%0AHere%E2%80%99s%20the%20code%20that%20produced%20those%20three%20images%20and%20got%20the%20code%20from%20the%20SVG%20files%20to%20put%20in%20this%20blog%20post%3A%0A%0ACairoSVG%28%220150-cairo-svg.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0Asvg%28%220150-svg.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0Asvglite%28%220150-svglite.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0A%0Aprint_to_screen%20%26lt%3B-%20function%28fn%29%7B%0A%20%20txt%20%26lt%3B-%20readChar%28fn%2C%20file.info%28fn%29%24size%29%0A%20%20write_clip%28txt%29%0A%7D%0A%0Aprint_to_screen%28%22..http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-cairo-svg.svg%22%29%0Aprint_to_screen%28%22..http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite.svg%22%29%0A%0ASolving%20the%20web%20font%20problem%20for%20svglite%0A%0ASo%2C%20I%20much%20preferred%20the%20smaller%20size%2C%20faster%20creation%20and%20download%2C%20and%20better%20look%20for%20text%20from%20svglite%20-%20but%20I%20had%20a%20new%20problem%2C%20of%20how%20to%20get%20custom%20fonts%20rendering%20reliably.%20I%20use%20web%20fonts%20from%20Google%20for%20my%20web%20page%20to%20get%20my%20HTML%2FCSS%20consistent%20with%20the%20graphic%20images%2C%20so%20in%20practice%20I%20need%20a%20way%20to%20render%20Google%20web%20fonts%20in%20SVGs%2C%20regardless%20of%20whether%20the%20user%20has%20them%20on%20their%20end%20computer%20or%20not.%0A%0Asvglite%20has%20a%20user_fonts%20argument%20that%20is%20meant%20to%20embed%20fonts%20that%20are%20on%20the%20developer%E2%80%99s%20machine%20inside%20the%20SVG%20if%20desired%2C%20but%20as%20far%20as%20I%20can%20tell%20it%20doesn%E2%80%99t%20work.%20So%20I%20forced%20myself%20to%20look%20a%20bit%20into%20how%20the%20SVG%20format%20works%2C%20and%20after%20wading%20through%20a%20number%20of%20out%20of%20date%20bits%20of%20info%20on%20the%20web%20eventually%20realised%20that%20I%20just%20needed%20the%20line%20%40import%20url%28%27https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DIndie%20Flower%3A400%2C400i%2C700%2C700i%27%29%3B%20added%20%28for%20the%20Indie%20Flower%20case%29.%20So%20the%20svglite%20file%20above%20just%20needs%20to%20become%20as%20follows%3A%0A%0A%26lt%3B%3Fxml%20version%3D%271.0%27%20encoding%3D%27UTF-8%27%20%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20viewBox%3D%270%200%20720.00%20576.00%27%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3Bstyle%20type%3D%27text%2Fcss%27%26gt%3B%26lt%3B%21%5BCDATA%5B%0A%20%20%20%20line%2C%20polyline%2C%20path%2C%20rect%2C%20circle%20%7B%0A%20%20%20%20%20%20fill%3A%20none%3B%0A%20%20%20%20%20%20stroke%3A%20%23000000%3B%0A%20%20%20%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%20%20%20stroke-linejoin%3A%20round%3B%0A%20%20%20%20%20%20stroke-miterlimit%3A%2010.00%3B%0A%20%20%20%20%7D%0A%20%20%5D%5D%26gt%3B%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3Bstyle%26gt%3B%0A%20%20%40import%20url%28%27https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DIndie%20Flower%3A400%2C400i%2C700%2C700i%27%29%3B%0A%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Brect%20width%3D%27100%25%27%20height%3D%27100%25%27%20style%3D%27stroke%3A%20none%3B%20fill%3A%20%23FFFFFF%3B%27%2F%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3BclipPath%20id%3D%27cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%27%26gt%3B%0A%20%20%20%20%26lt%3Brect%20x%3D%27177.12%27%20y%3D%27177.12%27%20width%3D%27452.16%27%20height%3D%27178.56%27%20%2F%26gt%3B%0A%20%20%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20clip-path%3D%27url%28%23cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%29%27%26gt%3B%26lt%3Btext%20x%3D%27318.96%27%20y%3D%27278.15%27%20style%3D%27font-size%3A%2060.00px%3B%20font-family%3A%20Indie%20Flower%3B%27%20textLength%3D%27168.48px%27%20lengthAdjust%3D%27spacingAndGlyphs%27%26gt%3BHello%20world%26lt%3B%2Ftext%26gt%3B%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0AThis%20renders%20nicely%2C%20with%20the%20correct%20typeface%20and%20all%3A%0A%0A%0A%0A%E2%80%A6%20albeit%20with%20one%20last%20change%20necessary%20to%20how%20I%20organise%20my%20blog.%20I%20used%20to%20include%20my%20SVG%20files%20in%20the%20blog%20using%20the%20%26lt%3Bimg%26gt%3B%20tag%2C%20such%20as%3A%0A%0A%26lt%3Bimg%20src%3D%27http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite-with-fonts.svg%27%20width%3D%2750%25%27%26gt%3B%0A%0AAn%20SVG%20file%20that%20is%20called%20into%20a%20webpage%20by%20%26lt%3Bimg%26gt%3B%20is%20not%20allowed%20to%20get%20information%20from%20external%20sites.%20It%20has%20to%20instead%20be%20included%20with%20an%20%26lt%3Bobject%26gt%3B%20tag%20as%20follows%3A%0A%0A%26lt%3Bobject%20type%3D%22image%2Fsvg%2Bxml%22%20data%3D%27http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite-with-fonts.svg%27%20width%3D%2750%25%27%26gt%3B%26lt%3B%2Fobject%26gt%3B%0A%0AThis%20has%20the%20disadvantage%20that%20a%20user%20can%20no%20longer%20right-click%20on%20the%20image%20and%20save%20it.%20They%20can%20still%20view%20the%20%E2%80%9Cframe%20source%E2%80%9D%2C%20copy%20it%20into%20a%20text%20editor%20and%20save%20it%20from%20there%2C%20but%20that%E2%80%99s%20going%20to%20put%20off%20a%20lot%20of%20users%20who%20aren%E2%80%99t%20used%20to%20thinking%20of%20an%20image%20as%20being%20fully%20represented%20by%20a%20bunch%20of%20code%20that%20can%20be%20pasted%20into%20Notepad%21%20I%20imagine%20I%E2%80%99ll%20think%20of%20something%20to%20get%20around%20this.%0A%0AEmbedding%20my%20SVGs%20with%20%26lt%3Bobject%26gt%3B%20is%20also%20necessary%20if%20I%20want%20to%20incorporate%20interactivity%20%28eg%20tooltips%20or%20more%29%2C%20so%20it%E2%80%99s%20probably%20a%20good%20habit%20to%20get%20into.%0A%0AI%20knocked%20up%20a%20quick%20and%20probably%20non-robust%20hack%20of%20a%20function%20svg_googlefonts%28%29%20to%20add%20the%20necessary%20font%20imports%20in%20%26lt%3Bstyle%26gt%3B%20tags%20to%20an%20SVG%20generated%20by%20svglite.%20Usage%20is%20exceptionally%20simple.%20It%20takes%20a%20previously%20created%20SVG%20file%20%28in%20this%20case%2C%20the%20%E2%80%9C0150-svglite.svg%E2%80%9D%20file%20created%20earlier%20in%20this%20post%29%2C%20the%20name%20of%20the%20Google%20fonts%20%28one%20or%20more%29%20to%20insert%2C%20and%20saves%20as%20a%20new%20version%20%28or%20over%20the%20original%2C%20which%20is%20the%20convenient%20default%20for%20how%20I%E2%80%99ll%20be%20using%20it%29%3A%0A%0Asvg_googlefonts%28%220150-svglite.svg%22%2C%20%22Indie%20Flower%22%2C%20new_svgfile%20%3D%20%220150-svglite-with-fonts.svg%22%29%0A%0AThat%E2%80%99s%20now%20in%20my%20frs%20R%20package%20of%20convenient%20utilities%20associated%20with%20this%20blog.%0A%0AThat%E2%80%99s%20all%20for%20now.%20In%20summary%3A%0A%0A%0A%20%20svglite%20makes%20fast%2C%20small%2C%20well-rendered%20SVG%20images%20which%20treat%20text%20the%20way%20SVG%20is%20designed%20to%0A%20%20but%20if%20you%20want%20to%20use%20typefaces%20that%20aren%E2%80%99t%20going%20to%20be%20on%20every%20user%E2%80%99s%20machine%20you%20need%20to%20embed%20them%20in%20the%20SVG%20or%20have%20the%20SVG%20import%20them.%20My%20svg_googlefonts%28%29%20function%20helps%20you%20with%20the%20latter%2C%20and%20the%20resulting%20SVG%20files%20need%20to%20be%20included%20in%20web%20pages%20with%20the%20%26lt%3Bobject%26gt%3B%20tag.%0A" target="_self" class="wpusb-layout-buttons wpusb-button wpusb-btn " title="Send by email" rel="nofollow"> <i class="wpusb-icon-email-buttons "></i> </a> </div> <div class="wpusb-item wpusb-gmail "> <a href="https://mail.google.com/mail/u/0/?view=cm&fs=1&su=Using%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz&body=https%3A%2F%2Fwww.r-bloggers.com%2Fusing-svglite-with-web-fonts-by-ellis2013nz%2F%3Futm_source%3Dshare_buttons%26utm_medium%3Dsocial_media%26utm_campaign%3Dsocial_share %0A%0AUsing%20svglite%20with%20web%20fonts%20by%20%40ellis2013nz%0A%0AOK%2C%20no%20stats%20today%2C%20just%20fidgeting%20about%20with%20graphics%20devices%20and%20type%20faces.%20Caveat%20-%20the%20details%20of%20graphics%20formats%20and%20typefaces%20is%20not%20my%20area%20of%20real%20expertise%2C%20this%20blog%20post%20is%20me%20noting%20down%20things%20that%20I%20found%20useful%20and%20others%20might%20too.%20As%20always%2C%20corrections%20and%20comments%20are%20very%20welcome.%0A%0AThere%20are%20two%20main%20types%20of%20computer%20graphic%20formats%3A%0A%0A%0A%20%20vector%20graphics%2C%20where%20the%20file%20is%20basically%20a%20set%20of%20instructions%20%28start%20at%20x%2C%20draw%20a%20line%20at%2030%20degrees%20angle%20for%20y%20units%2C%20draw%20a%20circle%20of%20radius%20w%20centred%20at%20z%2C%20etc%29.%20Like%20something%20you%20generated%20with%20Inkscape%20or%20Adobe%20Illustrator.%0A%20%20raster%20or%20bitmap%20graphics%20which%20are%20basically%20an%20array%20of%20numbers%20telling%20the%20computer%20which%20how%20to%20colour%20each%20pixel.%20Like%20a%20digital%20photograph.%0A%0A%0AGenerally%20vector%20formats%20are%20far%20superior%20if%20you%20have%20the%20choice%20but%20large%20complex%20graphics%20%28eg%20with%20millions%20of%20points%2C%20or%20maps%20with%20many%20fiddly%20bits%29%20can%20be%20slow%20to%20render%20%28and%20large%20to%20store%29.%20And%20until%20relatively%20recently%20many%20users%E2%80%99%20web%20browsers%20could%20only%20show%20bitmap%20graphics.%20Internet%20Explorer%208%20was%20the%20last%20high-use%20browser%20of%20this%20sort%20we%20had%20to%20worry%20about.%0A%0AFor%20my%20blog%20I%20work%20almost%20purely%20with%20Scalable%20Vector%20Graphic%20%28SVG%29%20format%20by%20choice%2C%20and%20PNG%20%28a%20relatively%20efficient%20and%20high%20quality%20bitmap%20format%29%20when%20I%20have%20to.%0A%0AMy%20graphics%20workflow%20for%20this%20blog%20is%20generally%3A%0A%0A%0A%20%20Write%20the%20graphic%20to%20a%20Scalable%20Vector%20Graphic%20%28SVG%29%0A%20%20Convert%20the%20SVGs%20to%20PNGs%20in%20batches%20using%20ImageMagick%0A%0A%0AI%20use%20the%20SVGs%20on%20the%20web%20pages%20that%20make%20up%20this%20blog%3B%20I%20need%20the%20PNG%20copies%20for%20posting%20on%20Twitter%2C%20Facebook%20and%20LinkedIn%20which%20don%E2%80%99t%20take%20SVGs%2C%20and%20also%20for%20some%20complex%20objects%20that%20would%20be%20too%20large%20as%20SVGs.%0A%0AA%20quick%20aside%20on%20anti-aliasing%0A%0ATo%20get%20in%20the%20groove%20of%20thinking%20about%20graphics%20I%E2%80%99m%20going%20to%20start%20with%20the%20concept%20of%20anti-aliasing.%20Here%20are%20three%20closeups%20of%20a%20straight%20line%20in%20a%20computer%20graphic%2C%20generated%20in%20R%20by%20three%20different%20graphics%20devices.%20From%20left%20to%20right%20these%20were%20generated%20by%20CairoSVG%28%29%2C%20CairoPNG%28%29%20and%20png%28%29.%0A%0A%0A%0AAliasing%20%28in%20graphics%29%20refers%20to%20the%20jagged%20staircase-like%20bits%20of%20an%20image%20from%20approximating%20an%20ideal%20shape%20with%20crude%20collections%20of%20pixels.%20Anti-aliasing%20is%20basically%20the%20smoothing%20or%20blurring%20process%20to%20try%20to%20make%20the%20problem%20less%20obvious.%0A%0AOn%20a%20Windows%20machine%20%28where%20I%20spend%20nearly%20all%20my%20working%20time%29%2C%20the%20png%28%29%20device%2C%20no%20matter%20high%20a%20resolution%20you%20specify%2C%20will%20not%20use%20anti-aliasing%20and%20close%20ups%20of%20the%20image%20will%20reveal%20jagged%20bits%20like%20that%20in%20the%20right%20of%20the%20three%20options%20above.%20At%20the%20opposite%20end%2C%20a%20graphic%20that%20has%20been%20saved%20as%20SVG%20won%E2%80%99t%20have%20any%20aliasing%20at%20all%20coming%20from%20the%20file%20format%20itself%3B%20any%20jaggedness%20comes%20from%20the%20final%20rendering%20of%20the%20information%20in%20the%20file%20onto%20the%20screen%20%28in%20the%20end%2C%20everything%20has%20to%20become%20pixels%20to%20get%20on%20the%20screen%29%2C%20not%20from%20how%20you%20generated%20the%20file.%0A%0AThe%20Cairo%20option%20in%20the%20middle%20has%20anti-aliasing%20taking%20place%20when%20the%20PNG%20file%20itself%20was%20generated.%20Files%20generated%20with%20CairoPNG%28%29%20look%20much%20better%20than%20those%20from%20png%28%29%2C%20but%20still%20can%E2%80%99t%20compete%20with%20the%20vector%20format%20even%20when%20the%20PNG%20is%20high%20resolution%20%28eg%20720%20or%20more%20dots%20per%20inch%29.%0A%0AHere%E2%80%99s%20the%20code%20that%20generated%20these%20examples%0A%0Alibrary%28Cairo%29%0Alibrary%28svglite%29%0Alibrary%28frs%29%0Alibrary%28clipr%29%0A%0Apng%28%220150-antialias-none.png%22%2C%208%20%2A%20600%2C%204%20%2A%20600%2C%20res%20%3D%20600%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22No%20anti-alias%20png%28%29%20device%22%29%0Adev.off%28%29%0A%0ACairoPNG%28%220150-antialias-cairo.png%22%2C%208%20%2A%20600%2C%204%20%2A%20600%2C%20dpi%20%3D%20600%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22Anti-aliased%20CairoPNG%20device%22%29%0Adev.off%28%29%0A%0ACairoSVG%28%220150-antialias-cairo.svg%22%2C%208%2C%204%29%0Aplot%281%3A2%2C%201%3A2%2C%20type%20%3D%20%22l%22%2C%20bty%20%3D%20%22n%22%2C%20main%20%3D%20%22CairoSVG%20device%22%29%0Adev.off%28%29%0A%0A%0A%20%20Potentially%20useful%20whimsical%20tip%3A%20once%20your%20awareness%20is%20raised%20about%20the%20need%20for%20anti-aliasing%2C%20you%20might%20become%20painfully%20aware%20of%20those%20unprofessional%20looking%20jagged%20bits%20in%20graphics.%20When%20working%20interactively%20in%20RStudio%20on%20Windows%2C%20all%20the%20graphics%20in%20your%20plot%20pane%20will%20look%20this%20way.%20If%20this%20hurts%20you%20like%20it%20hurts%20me%2C%20you%20can%20bring%20up%20a%20anti-aliased%20window%20with%20CairoWin%28%29%20and%20plots%20will%20be%20rendered%20nicely%20on%20that%20window%2C%20and%20look%20much%20better%20than%20the%20crude%20default%20renditions.%20If%20you%E2%80%99re%20using%20two%20screens%20it%E2%80%99s%20also%20convenient%20for%20placing%20on%20your%20second%20screen.%0A%0A%0ADifferent%20flavours%20of%20SVG%0A%0AUntil%20recently%20I%E2%80%99ve%20been%20generating%20my%20SVG%20files%20with%20CairoSVG%28%29.%20However%2C%20I%E2%80%99ve%20gotten%20very%20disatisfied%20with%20how%20text%20is%20rendered%20by%20that%20format.%20It%E2%80%99s%20hard%20to%20put%20my%20finger%20on%20what%20is%20wrong%2C%20but%20it%20looks%20blurry%2C%20particularly%20when%20it%E2%80%99s%20about%2010%20point%20in%20size%20which%20of%20course%20is%20nearly%20all%20the%20time%20in%20statistical%20graphics.%20Sometimes%20the%20problem%20goes%20away%20when%20you%20zoom%20in%2C%20but%20that%20isn%E2%80%99t%20really%20the%20point.%0A%0AI%20eventually%20solved%20this%20problem%20by%20moving%20to%20the%20excellent%20svglite%20package%20by%20Hadley%20Wickham%2C%20Lionel%20Henry%2C%20T%20Jake%20Luciani%2C%20Matthieu%20Decorde%20and%20Vaudor%20Lis.%20svglite%20creates%20smaller%20and%20faster%20SVGs%20and%20has%20a%20much%20better%20treatment%20of%20text%20in%20particular.%20But%20svglite%20alone%20wasn%E2%80%99t%20enough%20for%20the%20way%20I%20needed%20typefaces%20treated%20-%20I%E2%80%99ll%20get%20to%20that%20later.%0A%0ATo%20go%20into%20this%20further%2C%20here%20are%20three%20different%20SVG%20files%2C%20rendered%20in%20this%20web%20page%20as%20images%2C%20created%20by%20Cairo%3A%3ACairoSVG%28%29%2C%20grDevices%3A%3Asvg%28%29%20and%20svglite%3A%3Asvglite%28%29.%0A%0A%0A%0A%0A%0AThe%20first%20two%20approaches%20are%20very%20similar%2C%20but%20the%20svglite%20philosophy%20is%20quite%20different.%20CairoSVG%20and%20svg%20take%20text%20and%20turn%20it%20into%20many%20tiny%20shapes%20to%20draw%3B%20whereas%20svglite%20keeps%20the%20text%20as%20text%20in%20the%20SVG%20file%20and%20leaves%20it%20to%20the%20end%20user%E2%80%99s%20computer%20to%20render%20it.%20Zoom%20in%20close%20on%20any%20of%20those%20images%20above%20and%20the%20text%20will%20magnify%20nicely%3B%20but%20something%20about%20the%20relatively%20complicated%20approach%20of%20the%20first%20two%20makes%20them%20look%20a%20little%20blurred%20and%20complex%20when%20they%E2%80%99re%20looked%20at%20from%20a%20distance.%20This%20is%20the%20process%20of%20turning%20the%20text%20into%20individual%20shapes%2C%20interacting%20with%20the%20final%20rendering%20on%20the%20screen%20in%20some%20way%20that%20I%20don%E2%80%99t%20want%20to%20have%20to%20understand.%0A%0ASVG%20files%20are%20just%20text%20files%20%28in%20XML%20format%29%20so%20we%20can%20look%20at%20the%20actual%20code%20%28a%20huge%20advantage%20of%20SVG%20over%20other%20formats%29.%20Here%E2%80%99s%20the%20full%20text%20of%20the%20SVG%20generated%20by%20CairoSVG%3A%0A%0A%26lt%3B%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%22432pt%22%20height%3D%22432pt%22%20viewBox%3D%220%200%20432%20432%22%20version%3D%221.1%22%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%26lt%3Bg%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-0%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.921875%200%20L%202.921875%20-26.128906%20L%206.378906%20-26.128906%20L%206.378906%20-15.398438%20L%2019.960938%20-15.398438%20L%2019.960938%20-26.128906%20L%2023.417969%20-26.128906%20L%2023.417969%200%20L%2019.960938%200%20L%2019.960938%20-12.316406%20L%206.378906%20-12.316406%20L%206.378906%200%20Z%20M%202.921875%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-1%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%2015.363281%20-6.09375%20L%2018.679688%20-5.683594%20C%2018.15625%20-3.746094%2017.1875%20-2.242188%2015.773438%20-1.175781%20C%2014.359375%20-0.105469%2012.550781%200.425781%2010.355469%200.429688%20C%207.582031%200.425781%205.386719%20-0.421875%203.769531%20-2.128906%20C%202.144531%20-3.832031%201.335938%20-6.226563%201.335938%20-9.304688%20C%201.335938%20-12.484375%202.152344%20-14.953125%203.792969%20-16.714844%20C%205.429688%20-18.472656%207.558594%20-19.351563%2010.175781%20-19.355469%20C%2012.703125%20-19.351563%2014.769531%20-18.492188%2016.378906%20-16.769531%20C%2017.980469%20-15.046875%2018.785156%20-12.621094%2018.785156%20-9.5%20C%2018.785156%20-9.304688%2018.777344%20-9.019531%2018.765625%20-8.644531%20L%204.652344%20-8.644531%20C%204.769531%20-6.558594%205.355469%20-4.96875%206.414063%20-3.867188%20C%207.472656%20-2.761719%208.792969%20-2.207031%2010.371094%20-2.210938%20C%2011.546875%20-2.207031%2012.550781%20-2.515625%2013.382813%20-3.136719%20C%2014.214844%20-3.75%2014.875%20-4.738281%2015.363281%20-6.09375%20Z%20M%204.828125%20-11.28125%20L%2015.398438%20-11.28125%20C%2015.253906%20-12.867188%2014.847656%20-14.0625%2014.1875%20-14.863281%20C%2013.160156%20-16.097656%2011.835938%20-16.714844%2010.210938%20-16.71875%20C%208.738281%20-16.714844%207.5%20-16.222656%206.496094%20-15.238281%20C%205.492188%20-14.25%204.9375%20-12.929688%204.828125%20-11.28125%20Z%20M%204.828125%20-11.28125%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-2%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.335938%200%20L%202.335938%20-26.128906%20L%205.542969%20-26.128906%20L%205.542969%200%20Z%20M%202.335938%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-3%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%201.210938%20-9.464844%20C%201.207031%20-12.964844%202.179688%20-15.5625%204.132813%20-17.25%20C%205.757813%20-18.652344%207.742188%20-19.351563%2010.085938%20-19.355469%20C%2012.6875%20-19.351563%2014.816406%20-18.5%2016.46875%20-16.796875%20C%2018.117188%20-15.089844%2018.941406%20-12.734375%2018.945313%20-9.730469%20C%2018.941406%20-7.292969%2018.578125%20-5.378906%2017.847656%20-3.984375%20C%2017.117188%20-2.585938%2016.054688%20-1.5%2014.660156%20-0.730469%20C%2013.261719%200.0429688%2011.734375%200.425781%2010.085938%200.429688%20C%207.433594%200.425781%205.292969%20-0.417969%203.660156%20-2.117188%20C%202.023438%20-3.8125%201.207031%20-6.261719%201.210938%20-9.464844%20Z%20M%204.507813%20-9.464844%20C%204.503906%20-7.035156%205.035156%20-5.222656%206.09375%20-4.019531%20C%207.148438%20-2.8125%208.476563%20-2.207031%2010.085938%20-2.210938%20C%2011.675781%20-2.207031%2013.003906%20-2.8125%2014.0625%20-4.027344%20C%2015.117188%20-5.234375%2015.644531%20-7.082031%2015.648438%20-9.570313%20C%2015.644531%20-11.90625%2015.113281%20-13.679688%2014.050781%20-14.890625%20C%2012.988281%20-16.09375%2011.664063%20-16.699219%2010.085938%20-16.699219%20C%208.476563%20-16.699219%207.148438%20-16.097656%206.09375%20-14.898438%20C%205.035156%20-13.695313%204.503906%20-11.882813%204.507813%20-9.464844%20Z%20M%204.507813%20-9.464844%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-4%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-5%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%205.898438%200%20L%200.105469%20-18.925781%20L%203.421875%20-18.925781%20L%206.433594%20-8.003906%20L%207.554688%20-3.9375%20C%207.601563%20-4.140625%207.929688%20-5.441406%208.535156%20-7.84375%20L%2011.546875%20-18.925781%20L%2014.847656%20-18.925781%20L%2017.679688%20-7.949219%20L%2018.625%20-4.332031%20L%2019.710938%20-7.984375%20L%2022.953125%20-18.925781%20L%2026.074219%20-18.925781%20L%2020.15625%200%20L%2016.824219%200%20L%2013.8125%20-11.335938%20L%2013.082031%20-14.5625%20L%209.25%200%20Z%20M%205.898438%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-6%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%202.371094%200%20L%202.371094%20-18.925781%20L%205.257813%20-18.925781%20L%205.257813%20-16.058594%20C%205.992188%20-17.398438%206.671875%20-18.28125%207.296875%20-18.710938%20C%207.917969%20-19.136719%208.605469%20-19.351563%209.355469%20-19.355469%20C%2010.433594%20-19.351563%2011.53125%20-19.007813%2012.652344%20-18.320313%20L%2011.546875%20-15.34375%20C%2010.761719%20-15.804688%209.976563%20-16.035156%209.195313%20-16.039063%20C%208.492188%20-16.035156%207.863281%20-15.824219%207.304688%20-15.40625%20C%206.746094%20-14.980469%206.347656%20-14.398438%206.113281%20-13.652344%20C%205.753906%20-12.511719%205.578125%20-11.261719%205.578125%20-9.910156%20L%205.578125%200%20Z%20M%202.371094%200%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3Bsymbol%20overflow%3D%22visible%22%20id%3D%22glyph0-7%22%26gt%3B%0A%26lt%3Bpath%20style%3D%22stroke%3Anone%3B%22%20d%3D%22M%2014.6875%200%20L%2014.6875%20-2.386719%20C%2013.484375%20-0.507813%2011.71875%200.425781%209.390625%200.429688%20C%207.878906%200.425781%206.492188%200.015625%205.230469%20-0.816406%20C%203.960938%20-1.644531%202.980469%20-2.808594%202.289063%20-4.300781%20C%201.589844%20-5.792969%201.242188%20-7.507813%201.246094%20-9.445313%20C%201.242188%20-11.335938%201.558594%20-13.046875%202.191406%20-14.585938%20C%202.820313%20-16.121094%203.761719%20-17.300781%205.023438%20-18.125%20C%206.28125%20-18.941406%207.691406%20-19.351563%209.25%20-19.355469%20C%2010.386719%20-19.351563%2011.402344%20-19.113281%2012.296875%20-18.632813%20C%2013.183594%20-18.148438%2013.910156%20-17.519531%2014.472656%20-16.753906%20L%2014.472656%20-26.128906%20L%2017.660156%20-26.128906%20L%2017.660156%200%20Z%20M%204.542969%20-9.445313%20C%204.539063%20-7.019531%205.050781%20-5.207031%206.074219%20-4.007813%20C%207.09375%20-2.808594%208.300781%20-2.207031%209.695313%20-2.210938%20C%2011.09375%20-2.207031%2012.285156%20-2.78125%2013.265625%20-3.929688%20C%2014.246094%20-5.074219%2014.734375%20-6.824219%2014.738281%20-9.179688%20C%2014.734375%20-11.765625%2014.238281%20-13.664063%2013.242188%20-14.878906%20C%2012.242188%20-16.089844%2011.011719%20-16.699219%209.554688%20-16.699219%20C%208.125%20-16.699219%206.933594%20-16.117188%205.976563%20-14.953125%20C%205.019531%20-13.789063%204.539063%20-11.953125%204.542969%20-9.445313%20Z%20M%204.542969%20-9.445313%20%22%2F%26gt%3B%0A%26lt%3B%2Fsymbol%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3BclipPath%20id%3D%22clip1%22%26gt%3B%0A%20%20%26lt%3Bpath%20d%3D%22M%20177.121094%20177.121094%20L%20342.28125%20177.121094%20L%20342.28125%20212.679688%20L%20177.121094%20212.679688%20Z%20M%20177.121094%20177.121094%20%22%2F%26gt%3B%0A%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20id%3D%22surface16%22%26gt%3B%0A%26lt%3Bg%20clip-path%3D%22url%28%23clip1%29%22%20clip-rule%3D%22nonzero%22%26gt%3B%0A%26lt%3Bg%20style%3D%22fill%3Argb%280%25%2C0%25%2C0%25%29%3Bfill-opacity%3A1%3B%22%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-0%22%20x%3D%22168.929688%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-1%22%20x%3D%22195.288818%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22215.588379%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22223.69751%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-3%22%20x%3D%22231.806641%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-4%22%20x%3D%22252.106201%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-5%22%20x%3D%22262.24707%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-3%22%20x%3D%22288.606201%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-6%22%20x%3D%22308.905762%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-2%22%20x%3D%22321.060547%22%20y%3D%22207.25%22%2F%26gt%3B%0A%20%20%26lt%3Buse%20xlink%3Ahref%3D%22%23glyph0-7%22%20x%3D%22329.169678%22%20y%3D%22207.25%22%2F%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0A%E2%80%A6%20and%20here%20it%20is%20for%20the%20SVG%20generated%20by%20svglite%3A%0A%0A%26lt%3B%3Fxml%20version%3D%271.0%27%20encoding%3D%27UTF-8%27%20%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20viewBox%3D%270%200%20720.00%20576.00%27%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3Bstyle%20type%3D%27text%2Fcss%27%26gt%3B%26lt%3B%21%5BCDATA%5B%0A%20%20%20%20line%2C%20polyline%2C%20path%2C%20rect%2C%20circle%20%7B%0A%20%20%20%20%20%20fill%3A%20none%3B%0A%20%20%20%20%20%20stroke%3A%20%23000000%3B%0A%20%20%20%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%20%20%20stroke-linejoin%3A%20round%3B%0A%20%20%20%20%20%20stroke-miterlimit%3A%2010.00%3B%0A%20%20%20%20%7D%0A%20%20%5D%5D%26gt%3B%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Brect%20width%3D%27100%25%27%20height%3D%27100%25%27%20style%3D%27stroke%3A%20none%3B%20fill%3A%20%23FFFFFF%3B%27%2F%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3BclipPath%20id%3D%27cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%27%26gt%3B%0A%20%20%20%20%26lt%3Brect%20x%3D%27177.12%27%20y%3D%27177.12%27%20width%3D%27452.16%27%20height%3D%27178.56%27%20%2F%26gt%3B%0A%20%20%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20clip-path%3D%27url%28%23cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%29%27%26gt%3B%26lt%3Btext%20x%3D%27318.96%27%20y%3D%27278.15%27%20style%3D%27font-size%3A%2060.00px%3B%20font-family%3A%20Indie%20Flower%3B%27%20textLength%3D%27168.48px%27%20lengthAdjust%3D%27spacingAndGlyphs%27%26gt%3BHello%20world%26lt%3B%2Ftext%26gt%3B%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0AThe%20svglite%20version%20is%20much%20shorter%20because%20instead%20of%20describing%20exactly%20how%20each%20character%20looks%2C%20it%20just%20says%20%E2%80%9Cwrite%20%E2%80%98Hello%20world%E2%80%99%20in%20the%20middle%20of%20the%20graphic%2C%20at%2060%20points%20in%20size%2C%20using%20the%20Indie%20Flower%20font%20family%E2%80%9D.%0A%0AThat%20last%20point%20-%20%E2%80%9Cusing%20the%20Indie%20Flower%20font%20family%E2%80%9D%20is%20important%20too.%20It%20means%20that%20this%20font%20family%20needs%20to%20be%20available%20at%20the%20point%20the%20SVG%20file%20is%20rendered%20on-screen%20ie%20the%20end%20user%E2%80%99s%20machine.%20Whereas%20in%20CairoSVG%20and%20svg%2C%20no%20font%20family%20is%20recorded%20in%20the%20SVG%20file%20itself%2C%20the%20font%20family%20is%20taken%20into%20account%20at%20the%20generation%20of%20the%20SVG%20and%20has%20to%20be%20available%20on%20the%20developer%E2%80%99s%20machine.%0A%0AAs%20it%20happens%2C%20the%20%E2%80%9CIndie%20Flower%E2%80%9D%20type%20face%20isn%E2%80%99t%20installed%20on%20my%20computer%20and%20probably%20isn%E2%80%99t%20on%20yours%20either.%20When%20R%20encountered%20an%20instruction%20to%20use%20a%20typeface%20it%20didn%E2%80%99t%20know%2C%20it%20fell%20back%20on%20Arial%20and%20that%E2%80%99s%20how%20the%20two%20images%20on%20the%20left%20were%20generated.%20When%20a%20web%20browser%20encounters%20such%20an%20instruction%2C%20it%20falls%20back%20%28at%20least%20if%20it%E2%80%99s%20Chrome%20or%20Edge%29%20on%20Times%20New%20Roman%20or%20equivalent.%20This%20is%20why%20the%20image%20on%20the%20right%20looks%20different%20to%20the%20other%20two%20-%20it%E2%80%99s%20a%20question%20of%20a%20web%20browsers%20fall-back%20type%20face%2C%20compared%20to%20R%E2%80%99s.%0A%0AHere%E2%80%99s%20the%20code%20that%20produced%20those%20three%20images%20and%20got%20the%20code%20from%20the%20SVG%20files%20to%20put%20in%20this%20blog%20post%3A%0A%0ACairoSVG%28%220150-cairo-svg.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0Asvg%28%220150-svg.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0Asvglite%28%220150-svglite.svg%22%29%0Apar%28family%20%3D%20%22Indie%20Flower%22%2C%20cex%20%3D%203%29%0Aplot.new%28%29%0Atext%280.5%2C%200.5%2C%20%22Hello%20world%22%29%0Adev.off%28%29%0A%0A%0Aprint_to_screen%20%26lt%3B-%20function%28fn%29%7B%0A%20%20txt%20%26lt%3B-%20readChar%28fn%2C%20file.info%28fn%29%24size%29%0A%20%20write_clip%28txt%29%0A%7D%0A%0Aprint_to_screen%28%22..http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-cairo-svg.svg%22%29%0Aprint_to_screen%28%22..http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite.svg%22%29%0A%0ASolving%20the%20web%20font%20problem%20for%20svglite%0A%0ASo%2C%20I%20much%20preferred%20the%20smaller%20size%2C%20faster%20creation%20and%20download%2C%20and%20better%20look%20for%20text%20from%20svglite%20-%20but%20I%20had%20a%20new%20problem%2C%20of%20how%20to%20get%20custom%20fonts%20rendering%20reliably.%20I%20use%20web%20fonts%20from%20Google%20for%20my%20web%20page%20to%20get%20my%20HTML%2FCSS%20consistent%20with%20the%20graphic%20images%2C%20so%20in%20practice%20I%20need%20a%20way%20to%20render%20Google%20web%20fonts%20in%20SVGs%2C%20regardless%20of%20whether%20the%20user%20has%20them%20on%20their%20end%20computer%20or%20not.%0A%0Asvglite%20has%20a%20user_fonts%20argument%20that%20is%20meant%20to%20embed%20fonts%20that%20are%20on%20the%20developer%E2%80%99s%20machine%20inside%20the%20SVG%20if%20desired%2C%20but%20as%20far%20as%20I%20can%20tell%20it%20doesn%E2%80%99t%20work.%20So%20I%20forced%20myself%20to%20look%20a%20bit%20into%20how%20the%20SVG%20format%20works%2C%20and%20after%20wading%20through%20a%20number%20of%20out%20of%20date%20bits%20of%20info%20on%20the%20web%20eventually%20realised%20that%20I%20just%20needed%20the%20line%20%40import%20url%28%27https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DIndie%20Flower%3A400%2C400i%2C700%2C700i%27%29%3B%20added%20%28for%20the%20Indie%20Flower%20case%29.%20So%20the%20svglite%20file%20above%20just%20needs%20to%20become%20as%20follows%3A%0A%0A%26lt%3B%3Fxml%20version%3D%271.0%27%20encoding%3D%27UTF-8%27%20%3F%26gt%3B%0A%26lt%3Bsvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20viewBox%3D%270%200%20720.00%20576.00%27%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3Bstyle%20type%3D%27text%2Fcss%27%26gt%3B%26lt%3B%21%5BCDATA%5B%0A%20%20%20%20line%2C%20polyline%2C%20path%2C%20rect%2C%20circle%20%7B%0A%20%20%20%20%20%20fill%3A%20none%3B%0A%20%20%20%20%20%20stroke%3A%20%23000000%3B%0A%20%20%20%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%20%20%20stroke-linejoin%3A%20round%3B%0A%20%20%20%20%20%20stroke-miterlimit%3A%2010.00%3B%0A%20%20%20%20%7D%0A%20%20%5D%5D%26gt%3B%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3Bstyle%26gt%3B%0A%20%20%40import%20url%28%27https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DIndie%20Flower%3A400%2C400i%2C700%2C700i%27%29%3B%0A%26lt%3B%2Fstyle%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Brect%20width%3D%27100%25%27%20height%3D%27100%25%27%20style%3D%27stroke%3A%20none%3B%20fill%3A%20%23FFFFFF%3B%27%2F%26gt%3B%0A%26lt%3Bdefs%26gt%3B%0A%20%20%26lt%3BclipPath%20id%3D%27cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%27%26gt%3B%0A%20%20%20%20%26lt%3Brect%20x%3D%27177.12%27%20y%3D%27177.12%27%20width%3D%27452.16%27%20height%3D%27178.56%27%20%2F%26gt%3B%0A%20%20%26lt%3B%2FclipPath%26gt%3B%0A%26lt%3B%2Fdefs%26gt%3B%0A%26lt%3Bg%20clip-path%3D%27url%28%23cpMTc3LjEyfDYyOS4yOHwzNTUuNjh8MTc3LjEy%29%27%26gt%3B%26lt%3Btext%20x%3D%27318.96%27%20y%3D%27278.15%27%20style%3D%27font-size%3A%2060.00px%3B%20font-family%3A%20Indie%20Flower%3B%27%20textLength%3D%27168.48px%27%20lengthAdjust%3D%27spacingAndGlyphs%27%26gt%3BHello%20world%26lt%3B%2Ftext%26gt%3B%26lt%3B%2Fg%26gt%3B%0A%26lt%3B%2Fsvg%26gt%3B%0A%0AThis%20renders%20nicely%2C%20with%20the%20correct%20typeface%20and%20all%3A%0A%0A%0A%0A%E2%80%A6%20albeit%20with%20one%20last%20change%20necessary%20to%20how%20I%20organise%20my%20blog.%20I%20used%20to%20include%20my%20SVG%20files%20in%20the%20blog%20using%20the%20%26lt%3Bimg%26gt%3B%20tag%2C%20such%20as%3A%0A%0A%26lt%3Bimg%20src%3D%27http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite-with-fonts.svg%27%20width%3D%2750%25%27%26gt%3B%0A%0AAn%20SVG%20file%20that%20is%20called%20into%20a%20webpage%20by%20%26lt%3Bimg%26gt%3B%20is%20not%20allowed%20to%20get%20information%20from%20external%20sites.%20It%20has%20to%20instead%20be%20included%20with%20an%20%26lt%3Bobject%26gt%3B%20tag%20as%20follows%3A%0A%0A%26lt%3Bobject%20type%3D%22image%2Fsvg%2Bxml%22%20data%3D%27http%3A%2F%2Ffreerangestats.info%2Fimg%2F0150-svglite-with-fonts.svg%27%20width%3D%2750%25%27%26gt%3B%26lt%3B%2Fobject%26gt%3B%0A%0AThis%20has%20the%20disadvantage%20that%20a%20user%20can%20no%20longer%20right-click%20on%20the%20image%20and%20save%20it.%20They%20can%20still%20view%20the%20%E2%80%9Cframe%20source%E2%80%9D%2C%20copy%20it%20into%20a%20text%20editor%20and%20save%20it%20from%20there%2C%20but%20that%E2%80%99s%20going%20to%20put%20off%20a%20lot%20of%20users%20who%20aren%E2%80%99t%20used%20to%20thinking%20of%20an%20image%20as%20being%20fully%20represented%20by%20a%20bunch%20of%20code%20that%20can%20be%20pasted%20into%20Notepad%21%20I%20imagine%20I%E2%80%99ll%20think%20of%20something%20to%20get%20around%20this.%0A%0AEmbedding%20my%20SVGs%20with%20%26lt%3Bobject%26gt%3B%20is%20also%20necessary%20if%20I%20want%20to%20incorporate%20interactivity%20%28eg%20tooltips%20or%20more%29%2C%20so%20it%E2%80%99s%20probably%20a%20good%20habit%20to%20get%20into.%0A%0AI%20knocked%20up%20a%20quick%20and%20probably%20non-robust%20hack%20of%20a%20function%20svg_googlefonts%28%29%20to%20add%20the%20necessary%20font%20imports%20in%20%26lt%3Bstyle%26gt%3B%20tags%20to%20an%20SVG%20generated%20by%20svglite.%20Usage%20is%20exceptionally%20simple.%20It%20takes%20a%20previously%20created%20SVG%20file%20%28in%20this%20case%2C%20the%20%E2%80%9C0150-svglite.svg%E2%80%9D%20file%20created%20earlier%20in%20this%20post%29%2C%20the%20name%20of%20the%20Google%20fonts%20%28one%20or%20more%29%20to%20insert%2C%20and%20saves%20as%20a%20new%20version%20%28or%20over%20the%20original%2C%20which%20is%20the%20convenient%20default%20for%20how%20I%E2%80%99ll%20be%20using%20it%29%3A%0A%0Asvg_googlefonts%28%220150-svglite.svg%22%2C%20%22Indie%20Flower%22%2C%20new_svgfile%20%3D%20%220150-svglite-with-fonts.svg%22%29%0A%0AThat%E2%80%99s%20now%20in%20my%20frs%20R%20package%20of%20convenient%20utilities%20associated%20with%20this%20blog.%0A%0AThat%E2%80%99s%20all%20for%20now.%20In%20summary%3A%0A%0A%0A%20%20svglite%20makes%20fast%2C%20small%2C%20well-rendered%20SVG%20images%20which%20treat%20text%20the%20way%20SVG%20is%20designed%20to%0A%20%20but%20if%20you%20want%20to%20use%20typefaces%20that%20aren%E2%80%99t%20going%20to%20be%20on%20every%20user%E2%80%99s%20machine%20you%20need%20to%20embed%20them%20in%20the%20SVG%20or%20have%20the%20SVG%20import%20them.%20My%20svg_googlefonts%28%29%20function%20helps%20you%20with%20the%20latter%2C%20and%20the%20resulting%20SVG%20files%20need%20to%20be%20included%20in%20web%20pages%20with%20the%20%26lt%3Bobject%26gt%3B%20tag.%0A&tf=1" target="_blank" data-action="open-popup" class="wpusb-layout-buttons wpusb-button wpusb-btn " title="Send by Gmail" rel="nofollow"> <i class="wpusb-icon-gmail-buttons "></i> </a> </div> </div> <span class="wpusb-toggle" data-action="close-buttons"></span> </div> <script> var snp_f = []; var snp_hostname = new RegExp(location.host); var snp_http = new RegExp("^(http|https)://", "i"); var snp_cookie_prefix = ''; var snp_separate_cookies = false; var snp_ajax_url = 'https://www.r-bloggers.com/wp-admin/admin-ajax.php'; var snp_ajax_nonce = '4e57ab8a48'; var snp_ignore_cookies = false; var snp_enable_analytics_events = false; var snp_enable_mobile = false; var snp_use_in_all = false; var snp_excluded_urls = []; snp_excluded_urls.push(''); </script> <div class="snp-root"> <input type="hidden" id="snp_popup" value="" /> <input type="hidden" id="snp_popup_id" value="" /> <input type="hidden" id="snp_popup_theme" value="" /> <input type="hidden" id="snp_exithref" value="" /> <input type="hidden" id="snp_exittarget" value="" /> <div id="snppopup-welcome" class="snp-pop-109583 snppopup"><input type="hidden" class="snp_open" value="scroll" /><input type="hidden" class="snp_show_on_exit" value="2" /><input type="hidden" class="snp_exit_js_alert_text" value="" /><input type="hidden" class="snp_exit_scroll_down" value="" /><input type="hidden" class="snp_exit_scroll_up" value="" /><input type="hidden" class="snp_open_scroll" value="50" /><input type="hidden" class="snp_optin_redirect_url" value="" /><input type="hidden" class="snp_show_cb_button" value="yes" /><input type="hidden" class="snp_popup_id" value="109583" /><input type="hidden" class="snp_popup_theme" value="theme6" /><input type="hidden" class="snp_overlay" value="disabled" /><input type="hidden" class="snp_cookie_conversion" value="30" /><input type="hidden" class="snp_cookie_close" value="180" /><div class="snp-fb snp-theme6"> <div class="snp-subscribe-inner"> <h1 class="snp-header"><i>Never miss an update! </i> <br/> <strong>Subscribe to R-bloggers</strong> to receive <br/>e-mails with the latest R posts.<br/> <small>(You will not see this message again.)</small></h1> <div class="snp-form"> <form action="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers" method="post" class="snp-subscribeform snp_subscribeform"> <fieldset> <div class="snp-field"> <input type="text" name="email" id="snp_email" placeholder="Your E-mail..." class="snp-field snp-field-email" /> </div> <button type="submit" class="snp-submit">Submit</button> </fieldset> </form> </div> <a href="#" class="snp_nothanks snp-close">Click here to close (This popup will not appear again)</a> </div> </div> <style>.snp-pop-109583 .snp-theme6 { max-} .snp-pop-109583 .snp-theme6 h1 {font-size: 17px;} .snp-pop-109583 .snp-theme6 { color: #a0a4a9;} .snp-pop-109583 .snp-theme6 .snp-field ::-webkit-input-placeholder { color: #a0a4a9;} .snp-pop-109583 .snp-theme6 .snp-field :-moz-placeholder { color: #a0a4a9;} .snp-pop-109583 .snp-theme6 .snp-field :-ms-input-placeholder { color: #a0a4a9;} .snp-pop-109583 .snp-theme6 .snp-field input { border: 1px solid #a0a4a9;} .snp-pop-109583 .snp-theme6 .snp-field { color: #000000;} .snp-pop-109583 .snp-theme6 { background: #f2f2f2;} </style><script> jQuery(document).ready(function() { }); </script> </div> <script type="text/javascript"> var CaptchaCallback = function() { jQuery('.g-recaptcha').each(function(index, el) { grecaptcha.render(el, { 'sitekey' : '' }); }); }; </script> </div> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shCore.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushAS3.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushBash.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushColdFusion.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushClojure.js?ver=20090602'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCpp.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCSharp.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCss.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushDelphi.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushDiff.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushErlang.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushFSharp.js?ver=20091003'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushGroovy.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJava.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJavaFX.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJScript.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushLatex.js?ver=20090613'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushMatlabKey.js?ver=20091209'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushObjC.js?ver=20091207'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPerl.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPhp.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPlain.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPowerShell.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPython.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/third-party-brushes/shBrushR.js?ver=20100919'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushRuby.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushScala.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushSql.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushVb.js?ver=3.0.9b'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushXml.js?ver=3.0.9b'></script> <script type='text/javascript'> (function(){ var corecss = document.createElement('link'); var themecss = document.createElement('link'); var corecssurl = "https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shCore.css?ver=3.0.9b"; if ( corecss.setAttribute ) { corecss.setAttribute( "rel", "stylesheet" ); corecss.setAttribute( "type", "text/css" ); corecss.setAttribute( "href", corecssurl ); } else { corecss.rel = "stylesheet"; corecss.href = corecssurl; } document.getElementsByTagName("head")[0].insertBefore( corecss, document.getElementById("syntaxhighlighteranchor") ); var themecssurl = "https://www.r-bloggers.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shThemeDefault.css?ver=3.0.9b"; if ( themecss.setAttribute ) { themecss.setAttribute( "rel", "stylesheet" ); themecss.setAttribute( "type", "text/css" ); themecss.setAttribute( "href", themecssurl ); } else { themecss.rel = "stylesheet"; themecss.href = themecssurl; } //document.getElementById("syntaxhighlighteranchor").appendChild(themecss); document.getElementsByTagName("head")[0].insertBefore( themecss, document.getElementById("syntaxhighlighteranchor") ); })(); SyntaxHighlighter.config.strings.expandSource = '+ expand source'; SyntaxHighlighter.config.strings.help = '?'; SyntaxHighlighter.config.strings.alert = 'SyntaxHighlighter\n\n'; SyntaxHighlighter.config.strings.noBrush = 'Can\'t find brush for: '; SyntaxHighlighter.config.strings.brushNotHtmlScript = 'Brush wasn\'t configured for html-script option: '; SyntaxHighlighter.defaults['pad-line-numbers'] = false; SyntaxHighlighter.defaults['toolbar'] = false; SyntaxHighlighter.all(); // Infinite scroll support if ( typeof( jQuery ) !== 'undefined' ) { jQuery( function( $ ) { $( document.body ).on( 'post-load', function() { SyntaxHighlighter.highlight(); } ); } ); } </script> <link rel='stylesheet' href='https://www.r-bloggers.com/wp-content/plugins/wpupper-share-buttons/assets/stylesheets/style.css?ver=1552759553' type='text/css' media='all' /> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/arscode-ninja-popups/js/jquery.ck.min.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/arscode-ninja-popups/js/dialog_trigger.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/arscode-ninja-popups/js/ninjapopups.min.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/arscode-ninja-popups/fancybox2/jquery.fancybox.min.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-includes/js/comment-reply.min.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/themes/magazine-basic/js/effects.js?ver=4.9.7'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/jetpack/_inc/build/photon/photon.min.js?ver=20130122'></script> <script type='text/javascript' src='https://s0.wp.com/wp-content/js/devicepx-jetpack.js?ver=201914'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/lazy-load/js/jquery.sonar.min.js?ver=0.6.1'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-content/plugins/lazy-load/js/lazy-load.js?ver=0.6.1'></script> <script type='text/javascript' src='https://www.r-bloggers.com/wp-includes/js/wp-embed.min.js?ver=4.9.7'></script> <div id="fb-root"></div> <script type="text/javascript" src="https://platform.twitter.com/widgets.js"></script><script type="text/javascript" src="//connect.facebook.net/en_US/all.js#xfbml=1"></script><script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script><script type="text/javascript" src="https://platform.linkedin.com/in.js"></script><script type='text/javascript' src='https://stats.wp.com/e-201914.js' async='async' defer='defer'></script> <script type='text/javascript'> _stq = window._stq || []; _stq.push([ 'view', {v:'ext',j:'1:7.1.1',blog:'11524731',post:'179906',tz:'-6',srv:'www.r-bloggers.com'} ]); _stq.push([ 'clickTrackerInit', '11524731', '179906' ]); </script> <script type="text/javascript" src="https://www.r-bloggers.com/wp-content/themes/magazine-basic/js/effects.js"></script> <script type="text/javascript"> /* <![CDATA[ */ jQuery(function(){ jQuery("ul.sf-menu").supersubs({ minWidth: 12, maxWidth: 27, extraWidth: 1 }).superfish({ delay: 100, speed: 250 }); }); /* */ 
        
         
        
         
        
         
      
       
    
    
__data