예제 #1
0
/**
 * @param typefaceName[in]  Name of the typeface.
 * @param pointSize[in]     Size of the font in points.
 *
 * Checks the global font cache for the named font and returns a reference to
 * it.  If the font is not in the cache, it gets loaded first.
 */
NoDice::Font& NoDice::
getFont(const std::string& typefaceName, unsigned int pointSize)
{
  typedef std::map<std::string, Font> FontCache;
  static FontCache s_fontCache;

  std::ostringstream ostr;
  ostr << typefaceName << '_' << pointSize;
  std::string fontKey = ostr.str();
  FontCache::iterator it = s_fontCache.find(fontKey);
  if (it != s_fontCache.end())
  {
    return  it->second;
  }

  // allow in-build-directory to take precedence
  std::string filename = "./assets/" + typefaceName + ".ttf";
  if (0 != access(filename.c_str(), R_OK))
  {
    filename = DATA_DIR + std::string("/") + typefaceName + ".ttf";
    if (0 != access(filename.c_str(), R_OK))
    {
      filename = typefaceName;
    }
  }
  std::pair<FontCache::iterator,bool> p = s_fontCache.insert(
                std::make_pair(fontKey, Font(filename, pointSize)));
  return p.first->second;
}
예제 #2
0
/**
 * Free everything allocated w.r.t. fonts.
 */
void UninitFreeType()
{
	for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
		FontCache *fc = FontCache::Get(fs);
		if (fc->HasParent()) delete fc;
	}

#ifdef WITH_FREETYPE
	FT_Done_FreeType(_library);
	_library = NULL;
#endif /* WITH_FREETYPE */
}
예제 #3
0
void
InitializeSystemFontCache(FontCache& fc, const string& fong_file,
	const string& font_dir)
{
	puts("Loading font files...");
	try
	{
		size_t nFileLoaded(fc.LoadTypefaces(fong_file) != 0);

		if(!font_dir.empty())
			//读取字体文件目录并载入目录下指定后缀名的字体文件。
			try
			{
				HDirectory dir{font_dir.c_str()};
				IO::PathNorm nm;

				std::for_each(FileIterator(&dir), FileIterator(),
					[&](const std::string& name){
					if(!nm.is_self(name) && !dir.IsDirectory()
						/*&& IsExtensionOf(ext, dir.GetName())*/)
					{
						FontPath path(font_dir + dir.GetName());

						if(path != fong_file)
							nFileLoaded += fc.LoadTypefaces(path) != 0;
					}
				});
			}
			catch(FileOperationFailure&)
			{}
		fc.InitializeDefaultTypeface();
		if(const auto nFaces = fc.GetFaces().size())
			std::printf("%u face(s) in %u font file(s)"
				" are loaded\nsuccessfully.\n", nFaces, nFileLoaded);
		else
			throw LoggedEvent("No fonts found.");
		puts("Setting default font face...");
		if(const auto* const pf = fc.GetDefaultTypefacePtr())
			std::printf("\"%s\":\"%s\",\nsuccessfully.\n",
				pf->GetFamilyName().c_str(), pf->GetStyleName().c_str());
		else
			throw LoggedEvent("Setting default font face failed.");
		return;
	}
	// TODO: Use %std::nested_exception.
	catch(std::exception& e)
	{
		puts(e.what());
	}
	throw FatalError("      Font Caching Failure      ",
		" Please make sure the fonts are\n"
		" stored in correct path.\n");
}
예제 #4
0
/**
 * (Re)initialize the freetype related things, i.e. load the non-sprite fonts.
 * @param monospace Whether to initialise the monospace or regular fonts.
 */
void InitFreeType(bool monospace)
{
	for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
		if (monospace != (fs == FS_MONO)) continue;

		FontCache *fc = FontCache::Get(fs);
		if (fc->HasParent()) delete fc;

#ifdef WITH_FREETYPE
		LoadFreeTypeFont(fs);
#endif
	}
}
예제 #5
0
PassRefPtr<SimpleFontData> FontFallbackIterator::uniqueSystemFontForHint(
    UChar32 hint) {
  // When we're asked for a fallback for the same characters again, we give up
  // because the shaper must have previously tried shaping with the font
  // already.
  if (!hint || m_previouslyAskedForHint.contains(hint))
    return nullptr;

  FontCache* fontCache = FontCache::fontCache();
  m_previouslyAskedForHint.add(hint);
  return fontCache->fallbackFontForCharacter(
      m_fontDescription, hint,
      m_fontFallbackList->primarySimpleFontData(m_fontDescription));
}
const PassRefPtr<SimpleFontData> FontFallbackIterator::uniqueSystemFontForHint(UChar32 hint)
{
    FontCache* fontCache = FontCache::fontCache();

    // When we're asked for a fallback for the same characters again, we give up
    // because the shaper must have previously tried shaping with the font
    // already.
    if (m_visitedSystemFonts.find(hint) != m_visitedSystemFonts.end()) {
        return nullptr;
    }

    RefPtr<SimpleFontData> fallbackFont = fontCache->fallbackFontForCharacter(m_fontDescription, hint, m_fontFallbackList->primarySimpleFontData(m_fontDescription));

    return m_visitedSystemFonts.add(hint, fallbackFont).storedValue->value;
}
예제 #7
0
TEST(FontCacheAndroid, fallbackFontForCharacter)
{
    // A Latin character in the common locale system font, but not in the
    // Chinese locale-preferred font.
    const UChar32 testChar = 228;

    FontDescription fontDescription;
    fontDescription.setScript(USCRIPT_SIMPLIFIED_HAN);
    fontDescription.setGenericFamily(FontDescription::StandardFamily);

    FontCache* fontCache = FontCache::fontCache();
    ASSERT_TRUE(fontCache);
    RefPtr<SimpleFontData> fontData = fontCache->fallbackFontForCharacter(fontDescription, testChar, 0);
    EXPECT_TRUE(fontData);
}
TEST(FontCache, getLastResortFallbackFont)
{
    FontCache* fontCache = FontCache::fontCache();
    ASSERT_TRUE(fontCache);

    EmptyPlatform platform;

    FontDescription fontDescription;
    fontDescription.setGenericFamily(FontDescription::StandardFamily);
    RefPtr<SimpleFontData> fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
    EXPECT_TRUE(fontData);

    fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
    fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
    EXPECT_TRUE(fontData);
}
예제 #9
0
TEST(FontCache, getLastResortFallbackFont)
{
    FontCache* fontCache = FontCache::fontCache();
    ASSERT_TRUE(fontCache);

    Platform* oldPlatform = Platform::current();
    OwnPtr<EmptyPlatform> platform = adoptPtr(new EmptyPlatform);
    Platform::initialize(platform.get());

    FontDescription fontDescription;
    fontDescription.setGenericFamily(FontDescription::StandardFamily);
    RefPtr<SimpleFontData> fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
    EXPECT_TRUE(fontData);

    fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
    fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
    EXPECT_TRUE(fontData);

    Platform::initialize(oldPlatform);
}
예제 #10
0
파일: MiniMui.cpp 프로젝트: Livit/moonpdf
namespace mui {

class FontCache {
    struct Entry{
        WCHAR *     name;
        float       size;
        FontStyle   style;
        Font *      font;

        bool operator==(Entry& other){
            return size == other.size && style == other.style && str::Eq(name, other.name);
        }
    };

    ScopedGdiPlus scope;
    Vec<Entry> cache;

public:
    FontCache() { }
    ~FontCache() {
        for (Entry *e = cache.IterStart(); e; e = cache.IterNext()) {
            free(e->name);
            ::delete e->font;
        }
    }

    Font *GetFont(const WCHAR *name, float size, FontStyle style) {
        Entry f = { (WCHAR *)name, size, style, NULL };
        for (Entry *e = cache.IterStart(); e; e = cache.IterNext()) {
            if (f == *e)
                return e->font;
        }

        f.font = ::new Font(name, size, style);
        if (!f.font) {
            // fall back to the default font, if a desired font can't be created
            f.font = ::new Font(L"Times New Roman", size, style);
            if (!f.font) {
                if (cache.Count() > 0)
                    return cache.At(0).font;
                return NULL;
            }
        }
        f.name = str::Dup(f.name);
        cache.Append(f);
        return f.font;
    }
};

static FontCache gFontCache;

Font *GetCachedFont(const WCHAR *name, float size, FontStyle style)
{
    return gFontCache.GetFont(name, size, style);
}

static void InitGraphicsMode(Graphics *g)
{
    g->SetCompositingQuality(CompositingQualityHighQuality);
    g->SetSmoothingMode(SmoothingModeAntiAlias);
    //g.SetSmoothingMode(SmoothingModeHighQuality);
    g->SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
    g->SetPageUnit(UnitPixel);
}

class GlobalGraphicsHack {
    ScopedGdiPlus scope;
    Bitmap bmp;
public:
    Graphics gfx;

    GlobalGraphicsHack() : bmp(1, 1, PixelFormat32bppARGB), gfx(&bmp) {
        // cf. EbookEngine::RenderPage
        gfx.SetCompositingQuality(CompositingQualityHighQuality);
        gfx.SetSmoothingMode(SmoothingModeAntiAlias);
        gfx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
        gfx.SetPageUnit(UnitPixel);
    }
};

static GlobalGraphicsHack gGH;

Graphics *AllocGraphicsForMeasureText()
{
    return &gGH.gfx;
}

void FreeGraphicsForMeasureText(Graphics *g) { }

}
예제 #11
0
파일: MiniMui.cpp 프로젝트: Livit/moonpdf
Font *GetCachedFont(const WCHAR *name, float size, FontStyle style)
{
    return gFontCache.GetFont(name, size, style);
}
예제 #12
0
/**
 * @param FontName Name of the font to load
 */
void Font::Load(string FontName)
{
	VFile* fontfile;
	Uint16 wpos;
	Uint16 hpos;
	Uint16 cdata;
	Uint16 nchars;
	Uint8 fnheight;
	Uint8 fnmaxw;
	Uint32 fntotalw;
	Uint32 ypos;
	Uint32 pos;
	Uint32 curchar;
	Uint8		data;
	SDL_Surface* OrgFonImg = 0;



	this->fontname = FontName;

#ifdef USE_FONTCACHE
	if (fontCache.Get (this->fontname, &this->fontimg, this->chrdest)){
		return;
	}
#endif //USE_FONTCACHE

	//logger->debug("%s line %i: Load the font: %s\n\n", __FILE__, __LINE__, FontName.c_str());
	fontfile = VFSUtils::VFS_Open(fontname.c_str());
	if (0 == fontfile) {
		string s("Unable to load font ");
		s += fontname;
		throw(runtime_error(s));
	}

	fontfile->seekSet(8);
	fontfile->readWord(&wpos, 1);
	fontfile->readWord(&cdata, 1);
	fontfile->readWord(&hpos, 1);
	fontfile->seekCur(2);
	fontfile->readWord(&nchars, 1);
	nchars = SDL_Swap16(nchars); // Yes, even on LE systems.
	fontfile->readByte(&fnheight, 1);
	fontfile->readByte(&fnmaxw, 1);

	nchars++;

	vector<Uint8> wchar(nchars);
	vector<Uint8> hchar(nchars<<1);

	vector<Uint16> dataoffsets(nchars);
	fontfile->readWord(&dataoffsets[0], nchars);

	fontfile->seekSet(wpos);
	fontfile->readByte(&wchar[0], nchars);
	fontfile->seekSet(hpos);
	fontfile->readByte(&hchar[0], nchars<<1);

	chrdest.resize(nchars);

	fntotalw = 0;
	for(unsigned int i = 0 ; i < nchars; i++)
    {
		chrdest[i].x = fntotalw;
		chrdest[i].y = 0;
		chrdest[i].h = fnheight;
		chrdest[i].w = wchar[i];
		fntotalw += wchar[i];
	}
	vector<Uint8> chardata(fnheight*fntotalw);

	for( curchar = 0; curchar < nchars; curchar++ )
    {
		fontfile->seekSet(dataoffsets[curchar]);
		for( ypos = hchar[curchar<<1]; ypos < (Uint32)(hchar[curchar<<1]+hchar[(curchar<<1)+1]); ypos++ )
        {
			pos = chrdest[curchar].x+ypos*fntotalw;
			for(unsigned int i = 0; i < wchar[curchar]; i+=2 )
            {
				fontfile->readByte( &data, 1 );
#if 1
				/* Each 4 bits contain a index to the pallete */
				chardata[pos+i] = data&0xf;
				if( i+1<wchar[curchar] )
					chardata[pos+i+1] = (data>>4);
#else
				/* Each 4 bits contain a index to the pallete, convert them to 0 or 1 */
				chardata[pos+i] = (data&0xb)!=0?1:0;
				if( i+1<wchar[curchar] )
					chardata[pos+i+1] = (data>>4)!=0?1:0;
			//printf ("Data = %i\n", chardata[pos+i+1]);
#endif
			}
		}
	}

	SDL_FreeSurface(fontimg);
	fontimg = NULL;

	OrgFonImg = SDL_CreateRGBSurfaceFrom(&chardata[0], fntotalw, fnheight, 8, fntotalw, 0, 0, 0, 0);

	if (this->fontname == "6point.fnt" || this->fontname == "8point.fnt" || this->fontname == "3point.fnt")
		SDL_SetColors(OrgFonImg, font_pal2, 0, 16);
	else if ( this->fontname == "12metfnt.fnt")
		SDL_SetColors(OrgFonImg, font_pal3, 0, 16);
	else
		SDL_SetColors(OrgFonImg, font_pal1, 0, 16);

//	SDL_SetColorKey(OrgFonImg, SDL_SRCCOLORKEY, 0);

	fontimg = SDL_DisplayFormat(OrgFonImg);

	SDL_FreeSurface(OrgFonImg);
	OrgFonImg = NULL;


#ifdef USE_FONTCACHE
	fontCache.Add (this->fontname, this->fontimg,  chrdest);
#endif
	VFSUtils::VFS_Close(fontfile);
}
const FontDataForRangeSet FontFallbackIterator::next(const Vector<UChar32>& hintList)
{
    if (m_fallbackStage == OutOfLuck)
        return FontDataForRangeSet();

    if (m_fallbackStage == FallbackPriorityFonts) {
        // Only try one fallback priority font,
        // then proceed to regular system fallback.
        m_fallbackStage = SystemFonts;
        FontDataForRangeSet fallbackPriorityFontRange(fallbackPriorityFont(hintList[0]));
        if (fallbackPriorityFontRange.hasFontData())
            return fallbackPriorityFontRange;
        return next(hintList);
    }

    if (m_fallbackStage == SystemFonts) {
        // We've reached pref + system fallback.
        ASSERT(hintList.size());
        RefPtr<SimpleFontData> systemFont = uniqueSystemFontForHint(hintList[0]);
        if (systemFont)
            return FontDataForRangeSet(systemFont);

        // If we don't have options from the system fallback anymore or had
        // previously returned them, we only have the last resort font left.
        // TODO: crbug.com/42217 Improve this by doing the last run with a last
        // resort font that has glyphs for everything, for example the Unicode
        // LastResort font, not just Times or Arial.
        FontCache* fontCache = FontCache::fontCache();
        m_fallbackStage = OutOfLuck;
        RefPtr<SimpleFontData> lastResort = fontCache->getLastResortFallbackFont(m_fontDescription).get();
        RELEASE_ASSERT(lastResort);
        return FontDataForRangeSet(lastResort);
    }

    ASSERT(m_fallbackStage == FontGroupFonts
        || m_fallbackStage == SegmentedFace);
    const FontData* fontData = m_fontFallbackList->fontDataAt(
        m_fontDescription, m_currentFontDataIndex);

    if (!fontData) {
        // If there is no fontData coming from the fallback list, it means
        // we are now looking at system fonts, either for prioritized symbol
        // or emoji fonts or by calling system fallback API.
        m_fallbackStage = isNonTextFallbackPriority(m_fontFallbackPriority)
            ? FallbackPriorityFonts
            : SystemFonts;
        return next(hintList);
    }

    // Otherwise we've received a fontData from the font-family: set of fonts,
    // and a non-segmented one in this case.
    if (!fontData->isSegmented()) {
        // Skip forward to the next font family for the next call to next().
        m_currentFontDataIndex++;
        if (!fontData->isLoading()) {
            RefPtr<SimpleFontData> nonSegmented = const_cast<SimpleFontData*>(toSimpleFontData(fontData));
            return FontDataForRangeSet(nonSegmented);
        }
        return next(hintList);
    }

    // Iterate over ranges of a segmented font below.

    const SegmentedFontData* segmented = toSegmentedFontData(fontData);
    if (m_fallbackStage != SegmentedFace) {
        m_segmentedFaceIndex = 0;
        m_fallbackStage = SegmentedFace;
    }

    ASSERT(m_segmentedFaceIndex < segmented->numFaces());
    FontDataForRangeSet currentSegmentedFace = segmented->faceAt(m_segmentedFaceIndex);
    m_segmentedFaceIndex++;

    if (m_segmentedFaceIndex == segmented->numFaces()) {
        // Switch from iterating over a segmented face to the next family from
        // the font-family: group of fonts.
        m_fallbackStage = FontGroupFonts;
        m_currentFontDataIndex++;
    }

    if (rangeSetContributesForHint(hintList, currentSegmentedFace)) {
        if (currentSegmentedFace.fontData()->customFontData())
            currentSegmentedFace.fontData()->customFontData()->beginLoadIfNeeded();
        if (!currentSegmentedFace.fontData()->isLoading())
            return currentSegmentedFace;
        m_trackedLoadingRangeSets.append(currentSegmentedFace);
    }

    return next(hintList);
}
예제 #14
0
void CEngineSurface :: drawPrintText( const char* text, int textLen )
{
	static bool hasColor = 0;
	static int numColor = 7;

	if( !text || !_hCurrentFont || _drawTextColor[3] >= 255 )
		return;

	int x = _drawTextPos[0] + _translateX;
	int y = _drawTextPos[1] + _translateY;

	int iTall = _hCurrentFont->getTall();

	int j, iTotalWidth = 0;
	int curTextColor[4];

	//  HACKHACK: allow color strings in VGUI
	if( numColor != 7 && vgui_colorstrings->integer )
	{
		for( j = 0; j < 3; j++ ) // grab predefined color
			curTextColor[j] = g_color_table[numColor][j];
          }
          else
          {
		for( j = 0; j < 3; j++ ) // revert default color
			curTextColor[j] = _drawTextColor[j];
	}
	curTextColor[3] = _drawTextColor[3]; // copy alpha

	if( textLen == 1 && vgui_colorstrings->integer )
	{
		if( *text == '^' )
		{
			hasColor = true;
			return; // skip '^'
		}
		else if( hasColor && isdigit( *text ))
		{
			numColor = ColorIndex( *text );
			hasColor = false; // handled
			return; // skip colornum
		}
		else hasColor = false;
	}

	for( int i = 0; i < textLen; i++ )
	{
		char ch = text[i];

		int abcA,abcB,abcC;
		_hCurrentFont->getCharABCwide( ch, abcA, abcB, abcC );

		iTotalWidth += abcA;
		int iWide = abcB;

		if( !iswspace( ch ))
		{
			// get the character texture from the cache
			int iTexId = 0;
			float *texCoords = NULL;

			if( !g_FontCache.GetTextureForChar( _hCurrentFont, ch, &iTexId, &texCoords ))
				continue;

			Assert( texCoords != NULL );

			vpoint_t ul, lr;

			ul.point[0] = x + iTotalWidth;
			ul.point[1] = y;
			lr.point[0] = ul.point[0] + iWide;
			lr.point[1] = ul.point[1] + iTall;

			// gets at the texture coords for this character in its texture page
			ul.coord[0] = texCoords[0];
			ul.coord[1] = texCoords[1];
			lr.coord[0] = texCoords[2];
			lr.coord[1] = texCoords[3];

			vpoint_t clippedRect[2];

			if( !ClipRect( ul, lr, &clippedRect[0], &clippedRect[1] ))
				continue;
                                        
			drawSetTexture( iTexId );
			VGUI_SetupDrawingText( curTextColor );
			VGUI_DrawQuad(  &clippedRect[0], &clippedRect[1] ); // draw the letter
		}

		iTotalWidth += iWide + abcC;
	}

	_drawTextPos[0] += iTotalWidth;
}
예제 #15
0
namespace mui {

class FontCache {
    struct Entry {
        WCHAR *     name;
        float       size;
        FontStyle   style;
        Font *      font;

        Entry(WCHAR *name=NULL, float size=0.0f, FontStyle style=FontStyleRegular, Font *font=NULL) :
            name(name), size(size), style(style), font(font) { }
        bool operator==(const Entry& other) const {
            return size == other.size && style == other.style && str::Eq(name, other.name);
        }
    };

    ScopedGdiPlus scope;
    Vec<Entry> cache;

public:
    FontCache() { }
    ~FontCache() {
        for (Entry *e = cache.IterStart(); e; e = cache.IterNext()) {
            free(e->name);
            ::delete e->font;
        }
    }

    Font *GetFont(const WCHAR *name, float size, FontStyle style) {
        int idx = cache.Find(Entry((WCHAR *)name, size, style));
        if (idx != -1)
            return cache.At(idx).font;

        Font *font = ::new Font(name, size, style);
        if (!font) {
            // fall back to the default font, if a desired font can't be created
            font = ::new Font(L"Times New Roman", size, style);
            if (!font) {
                return cache.Count() > 0 ? cache.At(0).font : NULL;
            }
        }
        cache.Append(Entry(str::Dup(name), size, style, font));
        return font;
    }
};

static FontCache gFontCache;

Font *GetCachedFont(const WCHAR *name, float size, FontStyle style)
{
    return gFontCache.GetFont(name, size, style);
}

class GlobalGraphicsHack {
    ScopedGdiPlus scope;
    Bitmap bmp;
public:
    Graphics gfx;

    GlobalGraphicsHack() : bmp(1, 1, PixelFormat32bppARGB), gfx(&bmp) {
        // cf. EbookEngine::RenderPage
        gfx.SetCompositingQuality(CompositingQualityHighQuality);
        gfx.SetSmoothingMode(SmoothingModeAntiAlias);
        gfx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
        gfx.SetPageUnit(UnitPixel);
    }
};

static GlobalGraphicsHack gGH;

Graphics *AllocGraphicsForMeasureText()
{
    return &gGH.gfx;
}

void FreeGraphicsForMeasureText(Graphics *g) { }

}