Edit

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

Branch :

  • Show log

    Commit

  • Author : dtremenak
    Date : 2008-05-06 06:38:37
    Hash : eb45c699
    Message : VC build fixes from bzflag revs 17848-17852. * size_t consistency * avoid coercing from int to bool * make casts from double to float explicit rather than implicit, mostly by way of a few new getter functions in FTPoint, or avoid if possible.

  • 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()
    {
        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();
    }
    
    
    void FTFont::Render(const wchar_t* string)
    {
        return impl->Render(string);
    }
    
    
    void FTFont::Render(const char * string)
    {
        return impl->Render(string);
    }
    
    
    void FTFont::Render(const char * string, int renderMode)
    {
        return impl->Render(string, renderMode);
    }
    
    
    void FTFont::Render(const wchar_t* string, int renderMode)
    {
        return impl->Render(string, renderMode);
    }
    
    
    float FTFont::Advance(const wchar_t* string)
    {
        return impl->Advance(string);
    }
    
    
    float FTFont::Advance(const char* string)
    {
        return impl->Advance(string);
    }
    
    
    void FTFont::BBox(const char* string, const int start, const int end,
                      float& llx, float& lly, float& llz,
                      float& urx, float& ury, float& urz)
    {
        return impl->BBox(string, start, end, llx, lly, llz, urx, ury, urz);
    }
    
    
    void FTFont::BBox(const wchar_t* string, const int start, const int end,
                      float& llx, float& lly, float& llz,
                      float& urx, float& ury, float& urz)
    {
        return impl->BBox(string, start, end, llx, lly, llz, urx, ury, urz);
    }
    
    
    void FTFont::BBox(const char* string, float& llx, float& lly, float& llz,
                      float& urx, float& ury, float& urz)
    {
        return impl->BBox(string, 0, -1, llx, lly, llz, urx, ury, urz);
    }
    
    
    void FTFont::BBox(const wchar_t* string, float& llx, float& lly, float& llz,
                      float& urx, float& ury, float& urz)
    {
        return impl->BBox(string, 0, -1, llx, lly, llz, urx, ury, urz);
    }
    
    
    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;
        }
    }
    
    
    /* FIXME: DoRender should disappear, see commit [853]. */
    void FTFontImpl::DoRender(const unsigned int chr, const unsigned int nextChr,
                              FTPoint &origin, int renderMode)
    {
        if(CheckGlyph(chr))
        {
            FTPoint kernAdvance = glyphList->Render(chr, nextChr, origin, renderMode);
            origin += kernAdvance;
        }
    }
    
    
    template <typename T>
    inline void FTFontImpl::RenderI(const T* string, int renderMode)
    {
        const T* c = string;
        pen = FTPoint(0., 0.);
    
        while(*c)
        {
            DoRender(*c, *(c + 1), pen, renderMode);
            ++c;
        }
    }
    
    
    void FTFontImpl::Render(const char * string)
    {
        RenderI((const unsigned char *)string,
                FTGL::RENDER_FRONT | FTGL::RENDER_BACK | FTGL::RENDER_SIDE);
    }
    
    
    void FTFontImpl::Render(const wchar_t* string)
    {
        RenderI(string, FTGL::RENDER_FRONT | FTGL::RENDER_BACK | FTGL::RENDER_SIDE);
    }
    
    
    void FTFontImpl::Render(const char * string, int renderMode)
    {
        RenderI((const unsigned char *)string, renderMode);
    }
    
    
    void FTFontImpl::Render(const wchar_t* string, int renderMode)
    {
        RenderI(string, renderMode);
    }
    
    
    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()
    {
        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 void FTFontImpl::BBoxI(const T* string, const int start, const int end,
                                  float& llx, float& lly, float& llz,
                                  float& urx, float& ury, float& urz)
    {
        FTBBox totalBBox;
    
        /* Only compute the bounds if string is non-empty. */
        if(string && ('\0' != string[start]))
        {
            float advance = 0;
    
            if(CheckGlyph(string[start]))
            {
                totalBBox = glyphList->BBox(string[start]);
                advance = glyphList->Advance(string[start], string[start + 1]);
            }
    
            /* Expand totalBox by each glyph in String (for idx) */
            for(int i = start + 1; (end < 0 && string[i])
                                     || (end >= 0 && i < end); i++)
            {
                if(CheckGlyph(string[i]))
                {
                    FTBBox tempBBox = glyphList->BBox(string[i]);
                    tempBBox.Move(FTPoint(advance, 0.0f, 0.0f));
    
                    totalBBox += tempBBox;
                    advance += glyphList->Advance(string[i], string[i + 1]);
                }
            }
        }
    
        // TODO: The Z values do not follow the proper ordering.  I'm not sure why.
        llx = totalBBox.Lower().Xf() < totalBBox.Upper().Xf() ? totalBBox.Lower().Xf() : totalBBox.Upper().Xf();
        lly = totalBBox.Lower().Yf() < totalBBox.Upper().Yf() ? totalBBox.Lower().Yf() : totalBBox.Upper().Yf();
        llz = totalBBox.Lower().Zf() < totalBBox.Upper().Zf() ? totalBBox.Lower().Zf() : totalBBox.Upper().Zf();
        urx = totalBBox.Lower().Xf() > totalBBox.Upper().Xf() ? totalBBox.Lower().Xf() : totalBBox.Upper().Xf();
        ury = totalBBox.Lower().Yf() > totalBBox.Upper().Yf() ? totalBBox.Lower().Yf() : totalBBox.Upper().Yf();
        urz = totalBBox.Lower().Zf() > totalBBox.Upper().Zf() ? totalBBox.Lower().Zf() : totalBBox.Upper().Zf();
    }
    
    
    void FTFontImpl::BBox(const char* string, const int start, const int end,
                          float& llx, float& lly, float& llz,
                          float& urx, float& ury, float& urz)
    {
        /* The chars need to be unsigned because they are cast to int later */
        return BBoxI((const unsigned char *)string, start, end,
                     llx, lly, llz, urx, ury, urz);
    }
    
    
    void FTFontImpl::BBox(const wchar_t* string, const int start, const int end,
                          float& llx, float& lly, float& llz,
                          float& urx, float& ury, float& urz)
    {
        return BBoxI(string, start, end, llx, lly, llz, urx, ury, urz);
    }
    
    
    template <typename T>
    inline float FTFontImpl::AdvanceI(const T* string)
    {
        const T* c = string;
        float width = 0.0f;
    
        while(*c)
        {
            if(CheckGlyph(*c))
            {
                width += glyphList->Advance(*c, *(c + 1));
            }
            ++c;
        }
    
        return width;
    }
    
    
    float FTFontImpl::Advance(const char* string)
    {
        /* The chars need to be unsigned because they are cast to int later */
        return AdvanceI((const unsigned char *)string);
    }
    
    
    float FTFontImpl::Advance(const wchar_t* string)
    {
        return AdvanceI(string);
    }
    
    
    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;
    }