/* * FTGL - OpenGL font library * * Copyright (c) 2001-2004 Henry Maddocks * Copyright (c) 2008 Sam Hocevar * * 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 "FTUnicode.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); } void FTFont::GlyphLoadFlags(FT_Int flags) { return impl->GlyphLoadFlags(flags); } 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::Render(mgVBO& vbo, const char * string, const int len, FTPoint position, FTPoint spacing, int renderMode) { return impl->Render(vbo, string, len, position, spacing, renderMode); } FTPoint FTFont::Render(mgVBO& vbo, const wchar_t * string, const int len, FTPoint position, FTPoint spacing, int renderMode) { return impl->Render(vbo, string, len, position, spacing, renderMode); } float FTFont::Advance(const char * string, const int len, FTPoint spacing) { return impl->Advance(string, len, spacing); } float FTFont::Advance(const wchar_t * string, const int len, FTPoint spacing) { return impl->Advance(string, len, 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), load_flags(FT_LOAD_DEFAULT), 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), load_flags(FT_LOAD_DEFAULT), 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) { ; } void FTFontImpl::GlyphLoadFlags(FT_Int flags) { load_flags = flags; } 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 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])) { // for multibyte - we can't rely on sizeof(T) == character FTUnicodeStringItr ustr(string); unsigned int thisChar = *ustr++; unsigned int nextChar = *ustr; if(CheckGlyph(thisChar)) { totalBBox = glyphList->BBox(thisChar); totalBBox += position; position += FTPoint(glyphList->Advance(thisChar, nextChar), 0.0); } /* Expand totalBox by each glyph in string */ for(int i = 1; (len < 0 && *ustr) || (len >= 0 && i < len); i++) { thisChar = *ustr++; nextChar = *ustr; if(CheckGlyph(thisChar)) { position += spacing; FTBBox tempBBox = glyphList->BBox(thisChar); tempBBox += position; totalBBox |= tempBBox; position += FTPoint(glyphList->Advance(thisChar, nextChar), 0.0); } } } 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 inline float FTFontImpl::AdvanceI(const T* string, const int len, FTPoint spacing) { float advance = 0.0f; FTUnicodeStringItr ustr(string); for(int i = 0; (len < 0 && *ustr) || (len >= 0 && i < len); i++) { unsigned int thisChar = *ustr++; unsigned int nextChar = *ustr; if(CheckGlyph(thisChar)) { advance += glyphList->Advance(thisChar, nextChar); } if(nextChar) { advance += spacing.Xf(); } } return advance; } float FTFontImpl::Advance(const char* string, const int len, FTPoint spacing) { /* The chars need to be unsigned because they are cast to int later */ return AdvanceI((const unsigned char *)string, len, spacing); } float FTFontImpl::Advance(const wchar_t* string, const int len, FTPoint spacing) { return AdvanceI(string, len, spacing); } template inline FTPoint FTFontImpl::RenderI(const T* string, const int len, FTPoint position, FTPoint spacing, int renderMode) { // for multibyte - we can't rely on sizeof(T) == character FTUnicodeStringItr ustr(string); for(int i = 0; (len < 0 && *ustr) || (len >= 0 && i < len); i++) { unsigned int thisChar = *ustr++; unsigned int nextChar = *ustr; if(CheckGlyph(thisChar)) { position += glyphList->Render(thisChar, nextChar, position, renderMode); } if(nextChar) { position += spacing; } } return position; } template inline FTPoint FTFontImpl::RenderI(mgVBO& vbo, const T* string, const int len, FTPoint position, FTPoint spacing, int renderMode) { // for multibyte - we can't rely on sizeof(T) == character FTUnicodeStringItr ustr(string); for(int i = 0; (len < 0 && *ustr) || (len >= 0 && i < len); i++) { unsigned int thisChar = *ustr++; unsigned int nextChar = *ustr; if(CheckGlyph(thisChar)) { position += glyphList->Render(vbo, thisChar, nextChar, position, renderMode); } if(nextChar) { 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); } FTPoint FTFontImpl::Render(mgVBO& vbo, const char * string, const int len, FTPoint position, FTPoint spacing, int renderMode) { return RenderI(vbo, (const unsigned char *)string, len, position, spacing, renderMode); } FTPoint FTFontImpl::Render(mgVBO& vbo, const wchar_t * string, const int len, FTPoint position, FTPoint spacing, int renderMode) { return RenderI(vbo, string, len, position, spacing, renderMode); } bool FTFontImpl::CheckGlyph(const unsigned int characterCode) { if(glyphList->Glyph(characterCode)) { return true; } unsigned int glyphIndex = glyphList->FontIndex(characterCode); FT_GlyphSlot ftSlot = face.Glyph(glyphIndex, load_flags); 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; }