[haiku-commits] r40186 - in haiku/trunk/src/servers/app: . drawing/Painter

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 9 Jan 2011 22:24:09 +0100 (CET)

Author: mmlr
Date: 2011-01-09 22:24:09 +0100 (Sun, 09 Jan 2011)
New Revision: 40186
Changeset: http://dev.haiku-os.org/changeset/40186

Modified:
   haiku/trunk/src/servers/app/FontCacheEntry.cpp
   haiku/trunk/src/servers/app/FontCacheEntry.h
   haiku/trunk/src/servers/app/GlyphLayoutEngine.h
   haiku/trunk/src/servers/app/drawing/Painter/AGGTextRenderer.cpp
Log:
Create uncached glyphs on demand instead of checking glyph availability upfront.
This safes a HasGlyphs() call which would convert the whole string to glyph
codes and look each of the glyphs up in the cache entry, just to do the same
again during the loop where they are actually used. Instead we now simply switch
to the write lock and look up the fallback entry when hitting the first uncached
glyph. This benefits the normal case of having all glyphs cached without any
drawbacks.


Modified: haiku/trunk/src/servers/app/FontCacheEntry.cpp
===================================================================
--- haiku/trunk/src/servers/app/FontCacheEntry.cpp      2011-01-09 21:03:37 UTC 
(rev 40185)
+++ haiku/trunk/src/servers/app/FontCacheEntry.cpp      2011-01-09 21:24:09 UTC 
(rev 40186)
@@ -256,8 +256,16 @@
 
 
 const GlyphCache*
-FontCacheEntry::Glyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
+FontCacheEntry::CachedGlyph(uint32 glyphCode)
 {
+       // Only requires a read lock.
+       return fGlyphCache->FindGlyph(glyphCode);
+}
+
+
+const GlyphCache*
+FontCacheEntry::CreateGlyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
+{
        // We cache the glyph by the requested glyphCode. The FontEngine of this
        // FontCacheEntry may not contain a glyph for the given code, in which 
case
        // we ask the fallbackEntry for the code to index translation and let it

Modified: haiku/trunk/src/servers/app/FontCacheEntry.h
===================================================================
--- haiku/trunk/src/servers/app/FontCacheEntry.h        2011-01-09 21:03:37 UTC 
(rev 40185)
+++ haiku/trunk/src/servers/app/FontCacheEntry.h        2011-01-09 21:24:09 UTC 
(rev 40186)
@@ -103,7 +103,8 @@
                        bool                            HasGlyphs(const char* 
utf8String,
                                                                        ssize_t 
glyphCount) const;
 
-                       const GlyphCache*       Glyph(uint32 glyphCode,
+                       const GlyphCache*       CachedGlyph(uint32 glyphCode);
+                       const GlyphCache*       CreateGlyph(uint32 glyphCode,
                                                                        
FontCacheEntry* fallbackEntry = NULL);
 
                        void                            InitAdaptors(const 
GlyphCache* glyph,

Modified: haiku/trunk/src/servers/app/GlyphLayoutEngine.h
===================================================================
--- haiku/trunk/src/servers/app/GlyphLayoutEngine.h     2011-01-09 21:03:37 UTC 
(rev 40185)
+++ haiku/trunk/src/servers/app/GlyphLayoutEngine.h     2011-01-09 21:24:09 UTC 
(rev 40186)
@@ -97,6 +97,14 @@
                                                                        
FontCacheReference* cacheReference = NULL);
 
 private:
+       static  bool                            
_WriteLockAndAcquireFallbackEntry(
+                                                                       
FontCacheReference& cacheReference,
+                                                                       
FontCacheEntry* entry,
+                                                                       const 
ServerFont& font,
+                                                                       const 
char* utf8String, int32 length,
+                                                                       
FontCacheReference& fallbackCacheReference,
+                                                                       
FontCacheEntry*& fallbackEntry);
+
                                                                
GlyphLayoutEngine();
        virtual                                         ~GlyphLayoutEngine();
 };
@@ -189,52 +197,6 @@
 
                if (entry == NULL)
                        return false;
-
-               // See if the entry already has the glyphs cached. Switch to a 
write
-               // lock if not.
-               bool needsWriteLock = !entry->HasGlyphs(utf8String, length);
-               if (needsWriteLock) {
-                       // This also means we need the fallback font, since 
potentially,
-                       // we have to obtain missing glyphs from it. We need to 
obtain
-                       // the fallback font while we have not locked anything, 
since
-                       // locking the FontManager with the write-lock held can 
obvisouly
-                       // lead to a deadlock.
-
-                       cacheReference.SetTo(NULL, false);
-                       entry->ReadUnlock();
-
-                       if (gFontManager->Lock()) {
-                               // TODO: We always get the fallback glyphs from 
VL Gothic at the
-                               // moment, but of course the fallback font 
should a) contain the
-                               // missing glyphs at all and b) be similar to 
the original font.
-                               // So there should be a mapping of some kind to 
know the most
-                               // suitable fallback font.
-                               FontStyle* fallbackStyle = 
gFontManager->GetStyleByIndex(
-                                       "VL Gothic", 0);
-                               if (fallbackStyle != NULL) {
-                                       ServerFont fallbackFont(*fallbackStyle, 
font.Size());
-                                       gFontManager->Unlock();
-                                       // Force the write-lock on the fallback 
entry, since we
-                                       // don't transfer or copy GlyphCache 
objects from one cache
-                                       // to the other, but create new glyphs 
which are stored in
-                                       // "entry" in any case, which requires 
the write cache for
-                                       // sure (used FontEngine of 
fallbackEntry).
-                                       fallbackEntry = 
FontCacheEntryFor(fallbackFont, entry,
-                                               utf8String, length, 
fallbackCacheReference, true);
-                                       // NOTE: We don't care if fallbackEntry 
is NULL, fetching
-                                       // alternate glyphs will simply not 
work.
-                               } else
-                                       gFontManager->Unlock();
-                       }
-
-                       if (!entry->WriteLock()) {
-                               FontCache::Default()->Recycle(entry);
-                               return false;
-                       }
-
-                       // Update the FontCacheReference, since the locking 
kind changed.
-                       cacheReference.SetTo(entry, needsWriteLock);
-               }
        } // else the entry was already used and is still locked
 
        consumer.Start();
@@ -252,6 +214,7 @@
        uint32 lastCharCode = 0;
        uint32 charCode;
        int32 index = 0;
+       bool writeLocked = false;
        const char* start = utf8String;
        while ((charCode = UTF8ToCharCode(&utf8String))) {
 
@@ -273,8 +236,23 @@
                                x += IsWhiteSpace(charCode) ? delta->space : 
delta->nonspace;
                }
 
-               const GlyphCache* glyph = entry->Glyph(charCode, fallbackEntry);
+               const GlyphCache* glyph = entry->CachedGlyph(charCode);
                if (glyph == NULL) {
+                       // The glyph has not been cached yet, switch to a write 
lock,
+                       // acquire the fallback entry and create the glyph. 
Note that
+                       // the write lock will persist (in the cacheReference) 
so that
+                       // we only have to do this switch once for the whole 
string.
+                       if (!writeLocked) {
+                               writeLocked = 
_WriteLockAndAcquireFallbackEntry(cacheReference,
+                                       entry, font, utf8String, length, 
fallbackCacheReference,
+                                       fallbackEntry);
+                       }
+
+                       if (writeLocked)
+                               glyph = entry->CreateGlyph(charCode, 
fallbackEntry);
+               }
+
+               if (glyph == NULL) {
                        consumer.ConsumeEmptyGlyph(index++, charCode, x, y);
                        advanceX = 0;
                        advanceY = 0;
@@ -312,4 +290,53 @@
 }
 
 
+inline bool
+GlyphLayoutEngine::_WriteLockAndAcquireFallbackEntry(
+       FontCacheReference& cacheReference, FontCacheEntry* entry,
+       const ServerFont& font, const char* utf8String, int32 length,
+       FontCacheReference& fallbackCacheReference, FontCacheEntry*& 
fallbackEntry)
+{
+       // We need the fallback font, since potentially, we have to obtain 
missing
+       // glyphs from it. We need to obtain the fallback font while we have not
+       // locked anything, since locking the FontManager with the write-lock 
held
+       // can obvisouly lead to a deadlock.
+
+       cacheReference.SetTo(NULL, false);
+       entry->ReadUnlock();
+
+       if (gFontManager->Lock()) {
+               // TODO: We always get the fallback glyphs from VL Gothic at the
+               // moment, but of course the fallback font should a) contain the
+               // missing glyphs at all and b) be similar to the original font.
+               // So there should be a mapping of some kind to know the most
+               // suitable fallback font.
+               FontStyle* fallbackStyle = gFontManager->GetStyleByIndex(
+                       "VL Gothic", 0);
+               if (fallbackStyle != NULL) {
+                       ServerFont fallbackFont(*fallbackStyle, font.Size());
+                       gFontManager->Unlock();
+                       // Force the write-lock on the fallback entry, since we
+                       // don't transfer or copy GlyphCache objects from one 
cache
+                       // to the other, but create new glyphs which are stored 
in
+                       // "entry" in any case, which requires the write cache 
for
+                       // sure (used FontEngine of fallbackEntry).
+                       fallbackEntry = FontCacheEntryFor(fallbackFont, entry,
+                               utf8String, length, fallbackCacheReference, 
true);
+                       // NOTE: We don't care if fallbackEntry is NULL, 
fetching
+                       // alternate glyphs will simply not work.
+               } else
+                       gFontManager->Unlock();
+       }
+
+       if (!entry->WriteLock()) {
+               FontCache::Default()->Recycle(entry);
+               return false;
+       }
+
+       // Update the FontCacheReference, since the locking kind changed.
+       cacheReference.SetTo(entry, true);
+       return true;
+}
+
+
 #endif // GLYPH_LAYOUT_ENGINE_H

Modified: haiku/trunk/src/servers/app/drawing/Painter/AGGTextRenderer.cpp
===================================================================
--- haiku/trunk/src/servers/app/drawing/Painter/AGGTextRenderer.cpp     
2011-01-09 21:03:37 UTC (rev 40185)
+++ haiku/trunk/src/servers/app/drawing/Painter/AGGTextRenderer.cpp     
2011-01-09 21:24:09 UTC (rev 40186)
@@ -146,6 +146,7 @@
                fRenderer.fRasterizer.reset();
                fRenderer.fSubpixRasterizer.reset();
        }
+
        void Finish(double x, double y)
        {
                if (fVector) {


Other related posts:

  • » [haiku-commits] r40186 - in haiku/trunk/src/servers/app: . drawing/Painter - mmlr