diff options
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 201 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.h | 23 | 
2 files changed, 105 insertions, 119 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index fa249902af..bab721615b 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -56,9 +56,9 @@  FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; -LLFontManager *gFontManagerp = NULL; +LLFontManager *gFontManagerp = nullptr; -FT_Library gFTLibrary = NULL; +FT_Library gFTLibrary = nullptr;  //static  void LLFontManager::initClass() @@ -73,7 +73,7 @@ void LLFontManager::initClass()  void LLFontManager::cleanupClass()  {      delete gFontManagerp; -    gFontManagerp = NULL; +    gFontManagerp = nullptr;  }  LLFontManager::LLFontManager() @@ -101,6 +101,7 @@ LLFontManager::LLFontManager()  LLFontManager::~LLFontManager()  {      FT_Done_FreeType(gFTLibrary); +    unloadAllFonts();  } @@ -139,12 +140,8 @@ LLFontFreetype::LLFontFreetype()      mAscender(0.f),      mDescender(0.f),      mLineHeight(0.f), -#ifdef LL_WINDOWS -    pFileStream(NULL), -    pFtStream(NULL), -#endif      mIsFallback(false), -    mFTFace(NULL), +    mFTFace(nullptr),      mRenderGlyphCount(0),      mAddGlyphCount(0),      mStyle(0), @@ -158,35 +155,16 @@ LLFontFreetype::~LLFontFreetype()      // Clean up freetype libs.      if (mFTFace)          FT_Done_Face(mFTFace); -    mFTFace = NULL; +    mFTFace = nullptr;      // Delete glyph info      std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());      mCharGlyphInfoMap.clear(); -#ifdef LL_WINDOWS -    delete pFileStream; // closed by FT_Done_Face -    delete pFtStream; -#endif      delete mFontBitmapCachep;      // mFallbackFonts cleaned up by LLPointer destructor  } -#ifdef LL_WINDOWS -unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { -    if (count <= 0) return count; -    llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); -    file_stream->seekg(offset, std::ios::beg); -    file_stream->read((char*)buffer, count); -    return (unsigned long)file_stream->gcount(); -} - -void ft_close_cb(FT_Stream stream) { -    llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); -    file_stream->close(); -} -#endif -  bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)  {      // Don't leak face objects.  This is also needed to deal with @@ -194,26 +172,21 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v      if (mFTFace)      {          FT_Done_Face(mFTFace); -        mFTFace = NULL; +        mFTFace = nullptr;      } -    int error; -#ifdef LL_WINDOWS -    error = ftOpenFace(filename, face_n); -#else -    error = FT_New_Face( gFTLibrary, -                         filename.c_str(), -                         0, -                         &mFTFace); -#endif +    FT_Open_Args openArgs; +    memset( &openArgs, 0, sizeof( openArgs ) ); +    openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); + +    if( !openArgs.memory_base ) +        return false; + +    openArgs.flags = FT_OPEN_MEMORY; +    int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace );      if (error) -    { -#ifdef LL_WINDOWS -        clearFontStreams(); -#endif          return false; -    }      mIsFallback = is_fallback;      F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi @@ -228,10 +201,8 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v      {          // Clean up freetype libs.          FT_Done_Face(mFTFace); -#ifdef LL_WINDOWS -        clearFontStreams(); -#endif -        mFTFace = NULL; + +        mFTFace = nullptr;          return false;      } @@ -287,73 +258,30 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename)      if (mFTFace)      {          FT_Done_Face(mFTFace); -        mFTFace = NULL; +        mFTFace = nullptr;      }      S32 num_faces = 1; -#ifdef LL_WINDOWS -    int error = ftOpenFace(filename, 0); +    FT_Open_Args openArgs; +    memset( &openArgs, 0, sizeof( openArgs ) ); +    openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); +    if( !openArgs.memory_base ) +        return 0; +    openArgs.flags = FT_OPEN_MEMORY; +    int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace );      if (error) -    {          return 0; -    }      else -    {          num_faces = mFTFace->num_faces; -    }      FT_Done_Face(mFTFace); -    clearFontStreams(); -    mFTFace = NULL; -#endif +    mFTFace = nullptr;      return num_faces;  } -#ifdef LL_WINDOWS -S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n) -{ -    S32 error = -1; -    pFileStream = new llifstream(filename, std::ios::binary); -    if (pFileStream->is_open()) -    { -        std::streampos beg = pFileStream->tellg(); -        pFileStream->seekg(0, std::ios::end); -        std::streampos end = pFileStream->tellg(); -        std::size_t file_size = end - beg; -        pFileStream->seekg(0, std::ios::beg); - -        pFtStream = new LLFT_Stream(); -        pFtStream->base = 0; -        pFtStream->pos = 0; -        pFtStream->size = static_cast<unsigned long>(file_size); -        pFtStream->descriptor.pointer = pFileStream; -        pFtStream->read = ft_read_cb; -        pFtStream->close = ft_close_cb; - -        FT_Open_Args args; -        args.flags = FT_OPEN_STREAM; -        args.stream = (FT_StreamRec*)pFtStream; -        error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace); -    } -    return error; -} - -void LLFontFreetype::clearFontStreams() -{ -    if (pFileStream) -    { -        pFileStream->close(); -    } -    delete pFileStream; -    delete pFtStream; -    pFileStream = NULL; -    pFtStream = NULL; -} -#endif -  void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font,                                       const char_functor_t& functor)  { @@ -377,7 +305,7 @@ F32 LLFontFreetype::getDescenderHeight() const  F32 LLFontFreetype::getXAdvance(llwchar wch) const  { -    if (mFTFace == NULL) +    if (mFTFace == nullptr)          return 0.0;      // Return existing info only if it is current @@ -401,7 +329,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const  F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const  { -    if (mFTFace == NULL) +    if (mFTFace == nullptr)          return 0.0;      return glyph->mXAdvance; @@ -409,7 +337,7 @@ F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const  F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const  { -    if (mFTFace == NULL) +    if (mFTFace == nullptr)          return 0.0;      //llassert(!mIsFallback); @@ -428,7 +356,7 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const  F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const  { -    if (mFTFace == NULL) +    if (mFTFace == nullptr)          return 0.0;      U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; @@ -451,7 +379,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type  {      if (!mFTFace)      { -        return NULL; +        return nullptr;      }      llassert(!mIsFallback); @@ -542,14 +470,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type      {          return addGlyphFromFont(this, wch, glyph_index, glyph_type);      } -    return NULL; +    return nullptr;  }  LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const  {      LL_PROFILE_ZONE_SCOPED; -    if (mFTFace == NULL) -        return NULL; +    if (mFTFace == nullptr) +        return nullptr;      llassert(!mIsFallback);      fontp->renderGlyph(requested_glyph_type, glyph_index, wch); @@ -602,7 +530,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l      {          U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;          S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; -        U8 *tmp_graydata = NULL; +        U8 *tmp_graydata = nullptr;          if (fontp->mFTFace->glyph->bitmap.pixel_mode              == FT_PIXEL_MODE_MONO) @@ -699,7 +627,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const  void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const  { -    if (mFTFace == NULL) +    if (mFTFace == nullptr)          return;      FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT; @@ -901,3 +829,58 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32      }  } + +namespace ll +{ +    namespace fonts +    { +        class LoadedFont +        { +            public: +            LoadedFont( std::string aName , std::string const &aAddress, std::size_t aSize ) +            : mAddress( aAddress ) +            { +                mName = aName; +                mSize = aSize; +                mRefs = 1; +            } +            std::string mName; +            std::string mAddress; +            std::size_t mSize; +            U32  mRefs; +        }; +    } +} + +U8 const* LLFontManager::loadFont( std::string const &aFilename, long &a_Size) +{ +    a_Size = 0; +    std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> >::iterator itr = m_LoadedFonts.find( aFilename ); +    if( itr != m_LoadedFonts.end() ) +    { +        ++itr->second->mRefs; +        // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits<long>::max() a few lines below. +        a_Size = static_cast<long>(itr->second->mSize); +        return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str()); +    } + +    auto strContent = LLFile::getContents(aFilename); + +    if( strContent.empty() ) +        return nullptr; + +    // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?) +    llassert_always( strContent.size() < std::numeric_limits<long>::max() ); + +    a_Size = static_cast<long>(strContent.size()); + +    auto pCache = std::make_shared<ll::fonts::LoadedFont>( aFilename,  strContent, a_Size ); +    itr = m_LoadedFonts.insert( std::make_pair( aFilename, pCache ) ).first; + +    return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str()); +} + +void LLFontManager::unloadAllFonts() +{ +    m_LoadedFonts.clear(); +} diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 1ad795060a..3977911fe5 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -43,15 +43,28 @@ typedef struct FT_FaceRec_* LLFT_Face;  struct FT_StreamRec_;  typedef struct FT_StreamRec_ LLFT_Stream; +namespace ll +{ +    namespace fonts +    { +        class LoadedFont; +    } +} +  class LLFontManager  {  public:      static void initClass();      static void cleanupClass(); +    U8 const *loadFont( std::string const &aFilename, long &a_Size ); +  private:      LLFontManager();      ~LLFontManager(); + +    void unloadAllFonts(); +    std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> > m_LoadedFonts;  };  struct LLFontGlyphInfo @@ -90,11 +103,6 @@ public:      S32 getNumFaces(const std::string& filename); -#ifdef LL_WINDOWS -    S32 ftOpenFace(const std::string& filename, S32 face_n); -    void clearFontStreams(); -#endif -      typedef std::function<bool(llwchar)> char_functor_t;      void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr); @@ -170,11 +178,6 @@ private:      LLFT_Face mFTFace; -#ifdef LL_WINDOWS -    llifstream *pFileStream; -    LLFT_Stream *pFtStream; -#endif -      bool mIsFallback;      typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;      typedef std::vector<fallback_font_t> fallback_font_vector_t;  | 
