M5Paper: Support for multiple loaded TTF fonts



  • Currently the M5EPD library only supports a single loaded TTF font.
    For most applications this is fine, but for something like an eReader or web browser it is limiting, as it means you can't have bold/italic/monospaced text.
    For my own use, I've modified the library to allow multiple loaded TTF fonts, and I thought I'd share in case it is of use to anyone else.
    This is still very experimental, so there may be issues I haven't encountered yet.
    The way I've added this support to to use the textfont variable, which isn't currently used when TTF fonts are active. Calling setTextFont switches the currently active TTF font slot, and any subsequent loadFont/createRender/drawString calls will use that slot, until you change it again.
    Each loaded font has its own set of render caches, and you can render each font at multiple, different, sizes.
    You must call setTextSize each time you call setTextFont, as that is what selects the correct render for the font you have chosen.
    This works with either file fonts or header fonts.
    Example sketch:

    #include "M5EPD.h"
    
    #define USE_HEADER_FONTS 0
    
    #if USE_HEADER_FONTS
    #include "OpenSans_Regular.ttf.h"
    #include "OpenSans_ExtraBold.ttf.h"
    #include "OpenSans_Italic.ttf.h"
    #include "OpenSans_ExtraBoldItalic.ttf.h"
    
    std::vector<std::pair<const unsigned char*,uint32_t>> fonts = 
      {{OpenSans_Regular_ttf,sizeof(OpenSans_Regular_ttf)}
      ,{OpenSans_ExtraBold_ttf,sizeof(OpenSans_ExtraBold_ttf)}
      ,{OpenSans_Italic_ttf,sizeof(OpenSans_Italic_ttf)}
      ,{OpenSans_ExtraBoldItalic_ttf,sizeof(OpenSans_ExtraBoldItalic_ttf)}};
    #else
    std::vector<String> fonts = {"/Fonts/OpenSans-Regular.ttf","/Fonts/OpenSans-ExtraBold.ttf","/Fonts/OpenSans-Italic.ttf","/Fonts/OpenSans-ExtraBoldItalic.ttf"};
    #endif
    
    M5EPD_Canvas Canvas(&M5.EPD);
    
    void setup() { 
      M5.begin();
      M5.EPD.SetRotation(90);
      M5.EPD.Clear(true);
      M5.TP.SetRotation(90);
      M5.RTC.begin();
    
      Canvas.createCanvas(540,960);
    
      Canvas.useFreetypeFont(true);
      Canvas.setFreeFont(nullptr);
    
      for( int font = 1 ; font <= 4 ; font++ )
      {
        Canvas.setTextFont(font); 
    #if USE_HEADER_FONTS
        Canvas.loadFont(fonts[font-1].first,fonts[font-1].second); 
    #else
        Canvas.loadFont(fonts[font-1],SD); 
    #endif
        Canvas.createRender(48,32);
      }
    
      Canvas.setTextColor(15);
      Canvas.setTextDatum(TL_DATUM);
    
      int xPos = 64;
      for( int font = 1 ; font <= 4 ; font++ )
      {
        Canvas.setTextFont(font);
        Canvas.setTextSize(48);
        xPos += Canvas.drawString("Test ",xPos,64);
      }
      
      Canvas.pushCanvas(0,0,UPDATE_MODE_GC16);
    }
    
    void loop() {}
    

    In this example I have loaded each font and created its render together, and created all fonts before using any of them. Neither of those is required, you can load fonts and create renders at any time, as long as you select the correct textfont before each operation. You can also delete renders, unload fonts and load a new font into the slot, as long as no canvases are using that slot.

    Edit: The updated M5EPD library is available at https://github.com/murraypaul/M5EPD



  • great tnx !