cdave1 / ftgles

A truetype font rendering library for OpenGL ES on iOS devices (iPad and iPhone)
http://cdave1.github.io/ftgles/
MIT License
142 stars 36 forks source link

Issue with storing cache in FTSimpleLayout #7

Open blake-r opened 13 years ago

blake-r commented 13 years ago

Hi.

There are two issues in cache realization in FTSimpleLayout:

My patch to fix this:

From f33041e830d791cfaee2ef5847584429965efea8 Mon Sep 17 00:00:00 2001
From: Oleg aka Blake-R <blake-r@mail.ru>
Date: Thu, 25 Aug 2011 09:09:13 +0400
Subject: [PATCH] Fix cache store and it's invalidation on change layout
 parameters.

---
 ftgles/src/FTLayout/FTSimpleLayout.cpp   |   60 ++++++++++++++++++++---------
 ftgles/src/FTLayout/FTSimpleLayoutImpl.h |    6 ++-
 2 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/ftgles/src/FTLayout/FTSimpleLayout.cpp b/ftgles/src/FTLayout/FTSimpleLayout.cpp
index ff2ec11..050d231 100755
--- a/ftgles/src/FTLayout/FTSimpleLayout.cpp
+++ b/ftgles/src/FTLayout/FTSimpleLayout.cpp
@@ -81,6 +81,7 @@ void FTSimpleLayout::Render(const wchar_t* string, const int len, FTPoint pos,
 void FTSimpleLayout::SetFont(FTFont *fontInit)
 {
     dynamic_cast<FTSimpleLayoutImpl*>(impl)->currentFont = fontInit;
+    dynamic_cast<FTSimpleLayoutImpl*>(impl)->invalidate();
 }

@@ -93,6 +94,7 @@ FTFont *FTSimpleLayout::GetFont()
 void FTSimpleLayout::SetLineLength(const float LineLength)
 {
     dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineLength = LineLength;
+    dynamic_cast<FTSimpleLayoutImpl*>(impl)->invalidate();
 }

@@ -105,6 +107,7 @@ float FTSimpleLayout::GetLineLength() const
 void FTSimpleLayout::SetAlignment(const FTGL::TextAlignment Alignment)
 {
     dynamic_cast<FTSimpleLayoutImpl*>(impl)->alignment = Alignment;
+    dynamic_cast<FTSimpleLayoutImpl*>(impl)->invalidate();
 }

@@ -117,6 +120,7 @@ FTGL::TextAlignment FTSimpleLayout::GetAlignment() const
 void FTSimpleLayout::SetLineSpacing(const float LineSpacing)
 {
     dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineSpacing = LineSpacing;
+    dynamic_cast<FTSimpleLayoutImpl*>(impl)->invalidate();
 }

@@ -137,6 +141,21 @@ FTSimpleLayoutImpl::FTSimpleLayoutImpl()
     lineLength = 100.0f;
     alignment = FTGL::ALIGN_LEFT;
     lineSpacing = 1.0f;
+   stringCache = NULL;
+   stringCacheCount = 0;
+}
+
+
+FTSimpleLayoutImpl::~FTSimpleLayoutImpl()
+{
+   free(stringCache);
+   stringCache = NULL;
+   stringCacheCount = 0;
+}
+
+
+inline void FTSimpleLayoutImpl::invalidate()
+{
    stringCacheCount = 0;
 }

@@ -209,6 +228,7 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
 {
     FTUnicodeStringItr<T> breakItr(buf);          // points to the last break character
     FTUnicodeStringItr<T> lineStart(buf);         // points to the line start
+   unsigned int new_stringCacheCount = 0;        // length of buffer
     float nextStart = 0.0;     // total width of the current line
     float breakWidth = 0.0;    // width of the line up to the last word break
     float currentWidth = 0.0;  // width of all characters on the current line
@@ -228,31 +248,33 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
     {
        bounds->Invalidate();
     }
-   
+
+   {
+       FTUnicodeStringItr<T> itr(buf);
+       for (; *itr; ++itr) {}
+       new_stringCacheCount = itr.getBufferFromHere() - buf + sizeof(T)/*terminator*/;
+   }
+
    // Check if the incoming string is different to the previously
    // cached string.
-   unsigned int i = 0;
-   for (FTUnicodeStringItr<T> itr(buf); *itr; itr++)
-   {
-       if (i >= stringCacheCount ||
-           stringCache[i++] != (unsigned int)*itr)
-       {
-           refresh = true;
-           break;
-       }
+   if (stringCache && stringCacheCount == new_stringCacheCount) refresh = !!memcmp(stringCache, buf, stringCacheCount);
+   else {
+       refresh = true;
+       stringCacheCount = new_stringCacheCount;
+       if (!stringCache) stringCache = (unsigned char *)malloc(stringCacheCount);
+       else stringCache = (unsigned char *)realloc(stringCache, stringCacheCount);
+       if (!stringCache) throw std::bad_alloc();
    }
-   
+
    if (refresh)
    {
-       stringCacheCount = 0;
+       memcpy(stringCache, buf, stringCacheCount);
         layoutGlyphCache.clear();

        // Scan the input for all characters that need output
        FTUnicodeStringItr<T> prevItr(buf);
        for (FTUnicodeStringItr<T> itr(buf); *itr; prevItr = itr++, charCount++)
-       {
-           stringCache[stringCacheCount++] = (unsigned int)*itr;
-           
+       {   
            // Find the width of the current glyph
            glyphBounds = currentFont->BBox(itr.getBufferFromHere(), 1);
            glyphWidth = glyphBounds.Upper().Xf() - glyphBounds.Lower().Xf();
@@ -296,7 +318,7 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
                }

                layoutGlyphCacheItem_t cacheItem;
-               cacheItem.buf = (T*)lineStart.getBufferFromHere();
+               cacheItem.buf = stringCache + ptrdiff_t(lineStart.getBufferFromHere() - buf);
                cacheItem.charCount = breakCharCount;
                cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
                cacheItem.remainingWidth = remainingWidth;
@@ -331,7 +353,7 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
                wordLength += advance;
            }
        }
-       
+
        float remainingWidth = lineLength - currentWidth;
        // Render any remaining text on the last line
        // Disable justification for the last row
@@ -339,7 +361,7 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
        {
            alignment = FTGL::ALIGN_LEFT;
            layoutGlyphCacheItem_t cacheItem;
-           cacheItem.buf = (T *)lineStart.getBufferFromHere();
+           cacheItem.buf = stringCache + ptrdiff_t(lineStart.getBufferFromHere() - buf);
            cacheItem.charCount = -1;
            cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
            cacheItem.penDiff = FTPoint(0,0,0);
@@ -350,7 +372,7 @@ inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
        else
        {
            layoutGlyphCacheItem_t cacheItem;
-           cacheItem.buf = (T *)lineStart.getBufferFromHere();
+           cacheItem.buf = stringCache + ptrdiff_t(lineStart.getBufferFromHere() - buf);
            cacheItem.charCount = -1;
            cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
            cacheItem.penDiff = FTPoint(0,0,0);
diff --git a/ftgles/src/FTLayout/FTSimpleLayoutImpl.h b/ftgles/src/FTLayout/FTSimpleLayoutImpl.h
index 63b56cc..dd84234 100755
--- a/ftgles/src/FTLayout/FTSimpleLayoutImpl.h
+++ b/ftgles/src/FTLayout/FTSimpleLayoutImpl.h
@@ -50,7 +50,7 @@ class FTSimpleLayoutImpl : public FTLayoutImpl
 protected:
    FTSimpleLayoutImpl();

-   virtual ~FTSimpleLayoutImpl() {};
+   virtual ~FTSimpleLayoutImpl();

    virtual FTBBox BBox(const char* string, const int len,
                        FTPoint position);
@@ -211,10 +211,12 @@ private:
     */
     std::list<layoutGlyphCacheItem_t> layoutGlyphCache;

-   unsigned int stringCache[4096];
+   unsigned char * stringCache;

    unsigned int stringCacheCount;
+

+   void invalidate();

    /* Internal generic BBox() implementation */
    template <typename T>
-- 
1.7.6.1
blake-r commented 13 years ago

Patch updated, make cache allocable instead of restricted.