Search code examples
javascriptfont-awesomeglyphiconspdfmake

Use Glyphicons or Font-Awesome in pdfmake prints


I am developing a webapp using pdfmake for the printing. In more recent days I started using Glyphicons and Font-Awesome-Icons in my project, now I need those in the printout as well.

But I can't really imagine what would be the best way to achieve this.

I see two possibilities:

  1. Include the respective Font in pdfmake and create something like a map which determines the Icons font-representation by it's class name (because this is what is used in the app). In this case I could still use the font colors for the Icons

  2. I could use something like phantomJS to generate Images of the Icons, but I don't really like this idea, because I would loose the possibility to easily change the icon's color and i would have to maintain this picture collection somehow.

Any Ideas, Comments or solutions? I would really appreciate it :)


Solution

  • I solved the problem as follows:
    (I decided to use the first approach and narrowed the icons down to use Font-Awesome only)

    1. Find the symbol by its css-class
      I was quite unhappy with the idea of fetching data from e.g. https://fortawesome.github.io/Font-Awesome/cheatsheet/, so I did as a co-worker suggested: I parsed the symbol directly from the stylesheet:

    FontAwesomeMap = {
      findSymbolForClass: findSymbolForClass
    };
    
    /**
     * Looks through all Stylesheets for css-selectors. Returns the content of the 
     * first match.
     *
     * @param   {string} selector The complete selector or part of it 
     *                            (e.g. 'user-md' for '.fa-user-md')
     * @returns {string}          The content of the 'content' attribute of the 
     *                            matching css-rule <br>
     *                            or '' if nothing has been found
     */
    function findSymbolForClass(selector) {
      var result = '';
      var sheets = document.styleSheets;
    
      for (var sheetNr = 0; sheetNr < sheets.length; sheetNr++) {
        var content = findCSSRuleContent(sheets[sheetNr], selector);
    
        if (content) {
          result = stripQuotes(content);
          break;
        }
      }
    
      return result;
    }
    
    /**
     * Finds the first css-rule with a selectorText containing the given selector.
     *
     * @param   {CSSStyleSheet} mySheet  The stylesheet to examine
     * @param   {string}        selector The selector to match (or part of it)
     * @returns {string}                 The content of the matching rule <br>
     *                                   or '' if nothing has been found
     */
    function findCSSRuleContent(mySheet, selector) {
      var ruleContent = '';
      var rules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
    
      for (var i = 0; i < rules.length; i++) {
        var text = rules[i].selectorText;
        if (text && text.indexOf(selector) >= 0) {
          ruleContent = rules[i].style.content;
          break;
        }
      }
    
      return ruleContent;
    }
    
    /**
     * Strips one leading and one trailing Character from the given String.
     *
     * The 'content'-Tag is assigned by a quoted String, which will als be returned 
     * with those quotes.
     * So we need to strip them, if we want to access the real content
     *
     * @param   {String} string original quoted content
     * @returns {String}        unquoted content
     */
    function stripQuotes(string) {
      var len = string.length;
      return string.slice(1, len - 1);
    }

    1. Import the Font in pdfMake Now I had to get pdfMake to know the Font, thus I needed to convert the .ttf to base64.
      I used the .ttf from github and converted it here
      Afterwards I updated the vfs_fonts.js as described on github:
      (stripped the base64s)

    window.pdfMake = window.pdfMake || {};
    window.pdfMake.vfs = {
      "LICENSE.txt"       : "...",
      "Roboto-Italic.ttf" : "...",
      "Roboto-Medium.ttf" : "...",
      "Roboto-Regular.ttf": "...",
      "sampleImage.jpg"   : "...",
      "FontAwesome.ttf"   : "..."
    };
    
    window.pdfMake.fonts = {
      Roboto     : {
        normal     : 'Roboto-Regular.ttf',
        bold       : 'Roboto-Medium.ttf',
        italics    : 'Roboto-Italic.ttf',
        bolditalics: 'Roboto-Italic.ttf'
      },
      FontAwesome: {
        normal     : 'FontAwesome.ttf',
        bold       : 'FontAwesome.ttf',
        italics    : 'FontAwesome.ttf',
        bolditalics: 'FontAwesome.ttf'
      }
    };

    1. Set proper style-informations
      Last but not least, the font-information has to be set, so I made a simple style for that:

    styles = {
      /*...*/
      symbol: {
        font: 'FontAwesome'
      },
      /*...*/
    }

    edit as @nicfo pointed out, I missed to show the actual use of all together:
    4. Use the symbols in pdfmake

    value = {
        text : FontAwesomeMap.findSymbolForClass(symbol) + '',
        style: ['symbol']
    };

    where the magic FontAwesomeMap.findSymbolForClass(symbol) ist the one mentioned above

    That's all. Not exactly easy, but it's worth the effort.

    I'm pretty sure the same works for Glyphicons.