Edit

kc3-lang/ftgl/src/FTFont/FTFont.cpp

Branch :

  • Show log

    Commit

  • Author : sammy
    Date : 2008-05-11 11:29:17
    Hash : 32ef6d1e
    Message : * Get rid of FTFontImpl::DoRender(), one of the oldest TODOs.

  • src/FTFont/FTFont.cpp
  • /*
     * FTGL - OpenGL font library
     *
     * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz>
     *
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be
     * included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */
    
    #include "config.h"
    
    #include "FTInternals.h"
    
    #include "FTFontImpl.h"
    
    #include "FTBitmapFontImpl.h"
    #include "FTExtrudeFontImpl.h"
    #include "FTOutlineFontImpl.h"
    #include "FTPixmapFontImpl.h"
    #include "FTPolygonFontImpl.h"
    #include "FTTextureFontImpl.h"
    
    #include "FTGlyphContainer.h"
    #include "FTFace.h"
    
    
    //
    //  FTFont
    //
    
    
    FTFont::FTFont(char const *fontFilePath)
    {
        impl = new FTFontImpl(this, fontFilePath);
    }
    
    
    FTFont::FTFont(const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
    {
        impl = new FTFontImpl(this, pBufferBytes, bufferSizeInBytes);
    }
    
    
    FTFont::FTFont(FTFontImpl *pImpl)
    {
        impl = pImpl;
    }
    
    
    FTFont::~FTFont()
    {
        delete impl;
    }
    
    
    bool FTFont::Attach(const char* fontFilePath)
    {
        return impl->Attach(fontFilePath);
    }
    
    
    bool FTFont::Attach(const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
    {
        return impl->Attach(pBufferBytes, bufferSizeInBytes);
    }
    
    
    bool FTFont::FaceSize(const unsigned int size, const unsigned int res)
    {
        return impl->FaceSize(size, res);
    }
    
    
    unsigned int FTFont::FaceSize() const
    {
        return impl->FaceSize();
    }
    
    
    void FTFont::Depth(float depth)
    {
        return impl->Depth(depth);
    }
    
    
    void FTFont::Outset(float outset)
    {
        return impl->Outset(outset);
    }
    
    
    void FTFont::Outset(float front, float back)
    {
        return impl->Outset(front, back);
    }
    
    
    bool FTFont::CharMap(FT_Encoding encoding)
    {
        return impl->CharMap(encoding);
    }
    
    
    unsigned int FTFont::CharMapCount() const
    {
        return impl->CharMapCount();
    }
    
    
    FT_Encoding* FTFont::CharMapList()
    {
        return impl->CharMapList();
    }
    
    
    void FTFont::UseDisplayList(bool useList)
    {
        return impl->UseDisplayList(useList);
    }
    
    
    float FTFont::Ascender() const
    {
        return impl->Ascender();
    }
    
    
    float FTFont::Descender() const
    {
        return impl->Descender();
    }
    
    
    float FTFont::LineHeight() const
    {
        return impl->LineHeight();
    }
    
    
    FTPoint FTFont::Render(const char * string, const int len,
                           FTPoint position, FTPoint spacing, int renderMode)
    {
        return impl->Render(string, len, position, spacing, renderMode);
    }
    
    
    FTPoint FTFont::Render(const wchar_t * string, const int len,
                           FTPoint position, FTPoint spacing, int renderMode)
    {
        return impl->Render(string, len, position, spacing, renderMode);
    }
    
    
    FTPoint FTFont::Advance(const char * string, const int len,
                            FTPoint position, FTPoint spacing)
    {
        return impl->Advance(string, len, position, spacing);
    }
    
    
    FTPoint FTFont::Advance(const wchar_t * string, const int len,
                            FTPoint position, FTPoint spacing)
    {
        return impl->Advance(string, len, position, spacing);
    }
    
    
    FTBBox FTFont::BBox(const char *string, const int len,
                        FTPoint position, FTPoint spacing)
    {
        return impl->BBox(string, len, position, spacing);
    }
    
    
    FTBBox FTFont::BBox(const wchar_t *string, const int len,
                        FTPoint position, FTPoint spacing)
    {
        return impl->BBox(string, len, position, spacing);
    }
    
    
    FT_Error FTFont::Error() const
    {
        return impl->err;
    }
    
    
    //
    //  FTFontImpl
    //
    
    
    FTFontImpl::FTFontImpl(FTFont *ftFont, char const *fontFilePath) :
        face(fontFilePath),
        useDisplayLists(true),
        intf(ftFont),
        glyphList(0)
    {
        err = face.Error();
        if(err == 0)
        {
            glyphList = new FTGlyphContainer(&face);
        }
    }
    
    
    FTFontImpl::FTFontImpl(FTFont *ftFont, const unsigned char *pBufferBytes,
                           size_t bufferSizeInBytes) :
        face(pBufferBytes, bufferSizeInBytes),
        useDisplayLists(true),
        intf(ftFont),
        glyphList(0)
    {
        err = face.Error();
        if(err == 0)
        {
            glyphList = new FTGlyphContainer(&face);
        }
    }
    
    
    FTFontImpl::~FTFontImpl()
    {
        if(glyphList)
        {
            delete glyphList;
        }
    }
    
    
    bool FTFontImpl::Attach(const char* fontFilePath)
    {
        if(!face.Attach(fontFilePath))
        {
            err = face.Error();
            return false;
        }
    
        err = 0;
        return true;
    }
    
    
    bool FTFontImpl::Attach(const unsigned char *pBufferBytes,
                            size_t bufferSizeInBytes)
    {
        if(!face.Attach(pBufferBytes, bufferSizeInBytes))
        {
            err = face.Error();
            return false;
        }
    
        err = 0;
        return true;
    }
    
    
    bool FTFontImpl::FaceSize(const unsigned int size, const unsigned int res)
    {
        if(glyphList != NULL)
        {
            delete glyphList;
            glyphList = NULL;
        }
    
        charSize = face.Size(size, res);
        err = face.Error();
    
        if(err != 0)
        {
            return false;
        }
    
        glyphList = new FTGlyphContainer(&face);
        return true;
    }
    
    
    unsigned int FTFontImpl::FaceSize() const
    {
        return charSize.CharSize();
    }
    
    
    void FTFontImpl::Depth(float depth)
    {
        ;
    }
    
    
    void FTFontImpl::Outset(float outset)
    {
        ;
    }
    
    
    void FTFontImpl::Outset(float front, float back)
    {
        ;
    }
    
    
    bool FTFontImpl::CharMap(FT_Encoding encoding)
    {
        bool result = glyphList->CharMap(encoding);
        err = glyphList->Error();
        return result;
    }
    
    
    unsigned int FTFontImpl::CharMapCount() const
    {
        return face.CharMapCount();
    }
    
    
    FT_Encoding* FTFontImpl::CharMapList()
    {
        return face.CharMapList();
    }
    
    
    void FTFontImpl::UseDisplayList(bool useList)
    {
        useDisplayLists = useList;
    }
    
    
    float FTFontImpl::Ascender() const
    {
        return charSize.Ascender();
    }
    
    
    float FTFontImpl::Descender() const
    {
        return charSize.Descender();
    }
    
    
    float FTFontImpl::LineHeight() const
    {
        return charSize.Height();
    }
    
    
    template <typename T>
    inline FTBBox FTFontImpl::BBoxI(const T* string, const int len,
                                    FTPoint position, FTPoint spacing)
    {
        FTBBox totalBBox;
    
        /* Only compute the bounds if string is non-empty. */
        if(string && ('\0' != string[0]))
        {
            if(CheckGlyph(string[0]))
            {
                totalBBox = glyphList->BBox(string[0]);
                position += glyphList->Advance(string[0], string[1]);
            }
    
            /* Expand totalBox by each glyph in string */
            for(int i = 1; (len < 0 && string[i]) || (len >= 0 && i < len); i++)
            {
                if(CheckGlyph(string[i]))
                {
                    position += spacing;
    
                    FTBBox tempBBox = glyphList->BBox(string[i]);
                    tempBBox += position;
                    totalBBox |= tempBBox;
    
                    position += glyphList->Advance(string[i], string[i + 1]);
                }
            }
        }
    
        return totalBBox;
    }
    
    
    FTBBox FTFontImpl::BBox(const char *string, const int len,
                            FTPoint position, FTPoint spacing)
    {
        /* The chars need to be unsigned because they are cast to int later */
        return BBoxI((const unsigned char *)string, len, position, spacing);
    }
    
    
    FTBBox FTFontImpl::BBox(const wchar_t *string, const int len,
                            FTPoint position, FTPoint spacing)
    {
        return BBoxI(string, len, position, spacing);
    }
    
    
    template <typename T>
    inline FTPoint FTFontImpl::AdvanceI(const T* string, const int len,
                                        FTPoint position, FTPoint spacing)
    {
        for(int i = 0; (len < 0 && string[i]) || (len >= 0 && i < len); i++)
        {
            if(CheckGlyph(string[i]))
            {
                position += glyphList->Advance((unsigned int)string[i],
                                               (unsigned int)string[i + 1]);
            }
    
            if(string[i + 1])
            {
                position += spacing;
            }
        }
    
        return position;
    }
    
    
    FTPoint FTFontImpl::Advance(const char* string, const int len,
                                FTPoint position, FTPoint spacing)
    {
        /* The chars need to be unsigned because they are cast to int later */
        return AdvanceI((const unsigned char *)string,
                        len, position, spacing);
    }
    
    
    FTPoint FTFontImpl::Advance(const wchar_t* string, const int len,
                                FTPoint position, FTPoint spacing)
    {
        return AdvanceI(string, len, position, spacing);
    }
    
    
    template <typename T>
    inline FTPoint FTFontImpl::RenderI(const T* string, const int len,
                                       FTPoint position, FTPoint spacing,
                                       int renderMode)
    {
        for(int i = 0; (len < 0 && string[i]) || (len >= 0 && i < len); i++)
        {
            if(CheckGlyph(string[i]))
            {
                position += glyphList->Render((unsigned int)string[i],
                                              (unsigned int)string[i + 1],
                                              position, renderMode);
            }
    
            if(string[i + 1])
            {
                position += spacing;
            }
        }
    
        return position;
    }
    
    
    FTPoint FTFontImpl::Render(const char * string, const int len,
                               FTPoint position, FTPoint spacing, int renderMode)
    {
        return RenderI((const unsigned char *)string,
                       len, position, spacing, renderMode);
    }
    
    
    FTPoint FTFontImpl::Render(const wchar_t * string, const int len,
                               FTPoint position, FTPoint spacing, int renderMode)
    {
        return RenderI(string, len, position, spacing, renderMode);
    }
    
    
    bool FTFontImpl::CheckGlyph(const unsigned int characterCode)
    {
        if(glyphList->Glyph(characterCode))
        {
            return true;
        }
    
        /*
         * FIXME: load options are not the same for all subclasses:
         *  FTBitmapGlyph: FT_LOAD_DEFAULT
         *  FTExtrudeGlyph: FT_LOAD_NO_HINTING
         *  FTOutlineGlyph: FT_LOAD_NO_HINTING
         *  FTPixmapGlyph: FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
         *  FTPolygonGlyph: FT_LOAD_NO_HINTING
         *  FTTextureGlyph: FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
         */
        unsigned int glyphIndex = glyphList->FontIndex(characterCode);
        FT_GlyphSlot ftSlot = face.Glyph(glyphIndex, FT_LOAD_NO_HINTING);
        if(!ftSlot)
        {
            err = face.Error();
            return false;
        }
    
        FTGlyph* tempGlyph = intf->MakeGlyph(ftSlot);
        if(!tempGlyph)
        {
            if(0 == err)
            {
                err = 0x13;
            }
    
            return false;
        }
    
        glyphList->Add(tempGlyph, characterCode);
    
        return true;
    }