/** ** Free OpenGL fonts */ void FreeOpenGLFonts() { for (FontMap::iterator it = Fonts.begin(); it != Fonts.end(); ++it) { CFont &font = *it->second; font.FreeOpenGL(); } }
/** ** Reload OpenGL fonts */ void ReloadFonts() { for (FontMap::iterator it = Fonts.begin(); it != Fonts.end(); ++it) { CFont &font = *it->second; font.Reload(); } }
/** ** Load all fonts. */ void LoadFonts() { for (FontMap::iterator it = Fonts.begin(); it != Fonts.end(); ++it) { CFont &font = *it->second; font.Load(); } // TODO: remove this SmallFont = CFont::Get("small"); GameFont = CFont::Get("game"); }
/** ** Get a font ** ** @param ident Font identifier ** ** @return The font */ /* static */ CFont *CFont::Get(const std::string &ident) { std::map<std::string, CFont *>::iterator it = Fonts.find(ident); if (it == Fonts.end()) { DebugPrint("font not found: %s\n" _C_ ident.c_str()); return nullptr; } CFont *font = it->second; if (font == nullptr) { DebugPrint("font not found: %s\n" _C_ ident.c_str()); return nullptr; } return font; }
Font *Font::Create(TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative,bool inInitRef) { FontInfo info(inFormat,inScale,inRotation,inNative); Font *font = 0; FontMap::iterator fit = sgFontMap.find(info); if (fit!=sgFontMap.end()) { font = fit->second; if (inInitRef) font->IncRef(); return font; } FontFace *face = 0; AutoGCRoot *bytes = 0; FontBytesMap::iterator fbit = sgRegisteredFonts.find(WideToUTF8(inFormat.font).c_str()); if (fbit!=sgRegisteredFonts.end()) { bytes = fbit->second; } if (bytes != NULL) face = FontFace::CreateFreeType(inFormat,inScale,bytes); if (!face) face = FontFace::CreateCFFIFont(inFormat,inScale); if (!face && inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) face = FontFace::CreateFreeType(inFormat,inScale,NULL); if (!face && !inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) return 0; font = new Font(face,info.height,inRotation,inInitRef); // Store for Ron ... font->IncRef(); sgFontMap[info] = font; return font; }
/** ** Clean up the font module. */ void CleanFonts() { for (FontMap::iterator it = Fonts.begin(); it != Fonts.end(); ++it) { CFont *font = it->second; font->Clean(); delete font; } if (UseOpenGL) { FontColorGraphics.clear(); } Fonts.clear(); for (FontColorMap::iterator it = FontColors.begin(); it != FontColors.end(); ++it) { delete it->second; } FontColors.clear(); SmallFont = NULL; GameFont = NULL; }
/** ** Clean up the font module. */ void CleanFonts() { for (FontMap::iterator it = Fonts.begin(); it != Fonts.end(); ++it) { CFont *font = it->second; font->Clean(); delete font; } #if defined(USE_OPENGL) || defined(USE_GLES) if (UseOpenGL) { FontColorGraphics.clear(); } #endif Fonts.clear(); for (FontColorMap::iterator it = FontColors.begin(); it != FontColors.end(); ++it) { delete it->second; } FontColors.clear(); SmallFont = nullptr; GameFont = nullptr; }
Font *Font::Create(TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative,bool inInitRef) { FontInfo info(inFormat,inScale,inRotation,inNative); Font *font = 0; FontMap::iterator fit = sgFontMap.find(info); if (fit!=sgFontMap.end()) { font = fit->second; if (inInitRef) font->IncRef(); return font; } FontFace *face = 0; if (inNative) face = FontFace::CreateNative(inFormat,inScale); #ifndef IPHONE if (!face) face = FontFace::CreateFreeType(inFormat,inScale); #endif if (!face && !inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) return 0; font = new Font(face,info.height,inRotation,inInitRef); // Store for Ron ... font->IncRef(); sgFontMap[info] = font; return font; }
/** * Create a new paragraph layouter. * @param buffer The characters of the paragraph. * @param length The length of the paragraph. * @param runs The font mapping of this paragraph. */ FallbackParagraphLayout::FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs) : buffer_begin(buffer), buffer(buffer), runs(runs) { assert(runs.End()[-1].first == length); }
Font *Font::Create(TextFormat &inFormat,double inScale,bool inNative,bool inInitRef) { FontInfo info(inFormat,inScale,inNative); Font *font = 0; FontMap::iterator fit = sgFontMap.find(info); if (fit!=sgFontMap.end()) { font = fit->second; if (inInitRef) font->IncRef(); return font; } FontFace *face = 0; AutoGCRoot *bytes = 0; FontBytesMap::iterator fbit = sgRegisteredFonts.find(WideToUTF8(inFormat.font).c_str()); if (fbit!=sgRegisteredFonts.end()) { bytes = fbit->second; } if (bytes != NULL) face = FontFace::CreateFreeType(inFormat,inScale,bytes); if (!face) face = FontFace::CreateCFFIFont(inFormat,inScale); if (!face && inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) face = FontFace::CreateFreeType(inFormat,inScale,NULL); if (!face && !inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) return 0; font = new Font(face,info.height,inInitRef); // Store for Ron ... font->IncRef(); sgFontMap[info] = font; // Clear out any old fonts for (FontMap::iterator fit = sgFontMap.begin(); fit!=sgFontMap.end();) { if (fit->second->GetRefCount()==1) { fit->second->DecRef(); FontMap::iterator next = fit; next++; sgFontMap.erase(fit); fit = next; } else ++fit; } return font; }
namespace nme { Font::Font(FontFace *inFace, int inPixelHeight, GlyphRotation inRotation,bool inInitRef) : Object(inInitRef), mFace(inFace), mPixelHeight(inPixelHeight) { mRotation = inRotation; mCurrentSheet = -1; } Font::~Font() { for(int i=0;i<mSheets.size();i++) mSheets[i]->DecRef(); } Tile Font::GetGlyph(int inCharacter,int &outAdvance) { bool use_default = false; Glyph &glyph = inCharacter < 128 ? mGlyph[inCharacter] : mExtendedGlyph[inCharacter]; if (glyph.sheet<0) { int gw,gh,adv,ox,oy; bool ok = mFace->GetGlyphInfo(inCharacter,gw,gh,adv,ox,oy); if (!ok) { if (inCharacter=='?') { gw = mPixelHeight; gh = mPixelHeight; ox = oy = 0; adv = mPixelHeight; use_default = true; } else { Tile result = GetGlyph('?',outAdvance); glyph = mGlyph['?']; return result; } } int orig_w = gw; int orig_h = gh; switch(mRotation) { case gr270: std::swap(gw,gh); std::swap(ox,oy); oy = -gh-oy; break; case gr180: ox = -gw-ox; oy = -gh-oy; break; case gr90: std::swap(gw,gh); std::swap(ox,oy); ox = -gw-ox; break; } while(1) { // Allocate new sheet? if (mCurrentSheet<0) { int rows = mPixelHeight > 128 ? 1 : mPixelHeight > 64 ? 2 : mPixelHeight>32 ? 4 : 5; int h = 4; while(h<mPixelHeight*rows) h*=2; int w = h; while(w<orig_w) w*=2; if (mRotation!=gr0 && mRotation!=gr180) std::swap(w,h); Tilesheet *sheet = new Tilesheet(w,h,pfAlpha,true); mCurrentSheet = mSheets.size(); mSheets.push_back(sheet); } int tid = mSheets[mCurrentSheet]->AllocRect(gw,gh,ox,oy); if (tid>=0) { glyph.sheet = mCurrentSheet; glyph.tile = tid; glyph.advance = adv; break; } // Need new sheet... mCurrentSheet = -1; } // Now fill rect... Tile tile = mSheets[glyph.sheet]->GetTile(glyph.tile); // SharpenText(bitmap); RenderTarget target = tile.mSurface->BeginRender(tile.mRect); if (use_default) { for(int y=0; y<target.mRect.h; y++) { uint8 *dest = (uint8 *)target.Row(y + target.mRect.y) + target.mRect.x; for(int x=0; x<target.mRect.w; x++) *dest++ = 0xff; } } else if (mRotation==gr0) mFace->RenderGlyph(inCharacter,target); else { SimpleSurface *buf = new SimpleSurface(orig_w,orig_h,pfAlpha,true); buf->IncRef(); { AutoSurfaceRender renderer(buf); mFace->RenderGlyph(inCharacter,renderer.Target()); } const uint8 *src; for(int y=0; y<target.mRect.h; y++) { uint8 *dest = (uint8 *)target.Row(y + target.mRect.y) + target.mRect.x; switch(mRotation) { case gr270: src = buf->Row(0) + buf->Width() -1 - y; for(int x=0; x<target.mRect.w; x++) { *dest++ = *src; src += buf->GetStride(); } break; case gr180: src = buf->Row(buf->Height()-1-y) + buf->Width() -1; for(int x=0; x<target.mRect.w; x++) *dest++ = *src--; break; case gr90: src = buf->Row(buf->Height()-1) + y; for(int x=0; x<target.mRect.w; x++) { *dest++ = *src; src -= buf->GetStride(); } break; } } buf->DecRef(); } tile.mSurface->EndRender(); outAdvance = glyph.advance; return tile; } outAdvance = glyph.advance; return mSheets[glyph.sheet]->GetTile(glyph.tile); } void Font::UpdateMetrics(TextLineMetrics &ioMetrics) { if (mFace) mFace->UpdateMetrics(ioMetrics); } int Font::Height() { if (!mFace) return 12; return mFace->Height(); } // --- CharGroup --------------------------------------------- void CharGroup::UpdateMetrics(TextLineMetrics &ioMetrics) { if (mFont) mFont->UpdateMetrics(ioMetrics); } int CharGroup::Height() { return mFont ? mFont->Height() : 12; } // --- Create font from TextFormat ---------------------------------------------------- struct FontInfo { FontInfo(const TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative) { name = inFormat.font; height = (int )(inFormat.size*inScale + 0.5); flags = 0; native = inNative; if (inFormat.bold) flags |= ffBold; if (inFormat.italic) flags |= ffItalic; rotation = inRotation; } bool operator<(const FontInfo &inRHS) const { if (name < inRHS.name) return true; if (name > inRHS.name) return false; if (height < inRHS.height) return true; if (height > inRHS.height) return false; if (!native && inRHS.native) return true; if (native && !inRHS.native) return false; if (rotation < inRHS.rotation) return true; if (rotation > inRHS.rotation) return false; return flags < inRHS.flags; } WString name; bool native; int height; unsigned int flags; GlyphRotation rotation; }; typedef std::map<FontInfo, Font *> FontMap; FontMap sgFontMap; Font *Font::Create(TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative,bool inInitRef) { FontInfo info(inFormat,inScale,inRotation,inNative); Font *font = 0; FontMap::iterator fit = sgFontMap.find(info); if (fit!=sgFontMap.end()) { font = fit->second; if (inInitRef) font->IncRef(); return font; } FontFace *face = 0; if (inNative) face = FontFace::CreateNative(inFormat,inScale); #ifndef IPHONE if (!face) face = FontFace::CreateFreeType(inFormat,inScale); #endif if (!face && !inNative) face = FontFace::CreateNative(inFormat,inScale); if (!face) return 0; font = new Font(face,info.height,inRotation,inInitRef); // Store for Ron ... font->IncRef(); sgFontMap[info] = font; return font; } } // end namespace nme