Commit a6f07b94345ae4b99e11b9ddf448ff275a9bb329

sammy 2008-04-13T19:37:25

* Merged trunk commits [662] and [663], by patrick: + Added the FTBBox::Invalidate and FTBBox::IsValid methods. + Changed the FTFont::BBox to accept a range of indicies. Only characters with the range are checked. The previous funcitonality is preserved via inline methods that call the new implementation. + Kluged a fix for a bug where FTFont::BBox was returning bounding volumes where min > max. I don't know where the problem is originating, I just force the bounds to be correct. + Changed the FTFont::DoRender methods to accept an external FTPoint for the pen position. This enables FTLayout classes to use their own pen for rendering. + Added the FTLayout class as a friend of FTFont to allow layout managers to call private rendering functions and access private font information.

diff --git a/include/FTBBox.h b/include/FTBBox.h
index e5c2166..68e7fee 100644
--- a/include/FTBBox.h
+++ b/include/FTBBox.h
@@ -106,6 +106,26 @@ class FTGL_EXPORT FTBBox
         ~FTBBox()
         {}
         
+        /**
+         * Mark the bounds invalid by setting all lower dimensions greater
+         * than the upper dimensions.
+         */
+        void Invalidate() 
+        {
+            lowerX = lowerY = lowerZ = 1.0f;
+            upperX = upperY = upperZ = -1.0f;
+        }
+        
+        /**
+         * Determines if this bounding box is valid.
+         *
+         * @return True if all lower values are <= the corresponding
+         *         upper values.
+         */
+        bool IsValid()
+        {
+            return((lowerX <= upperX) && (lowerY <= upperY) && (lowerZ <= upperZ));
+        }
 
         /**
          * Move the Bounding Box by a vector.
diff --git a/include/FTFont.h b/include/FTFont.h
index c70f26e..f99d1dd 100644
--- a/include/FTFont.h
+++ b/include/FTFont.h
@@ -46,7 +46,7 @@
 
 class FTGlyphContainer;
 class FTGlyph;
-
+class FTLayout;
 
 /**
  * FTFont is the public interface for the FTGL library.
@@ -193,6 +193,44 @@ class FTGL_EXPORT FTFont
         /**
          * Get the bounding box for a string.
          *
+         * @param String    a char buffer
+         * @param StartIdx  The index of the first character of String
+         *                  to check.
+         * @param EndIdx    The index of the last character of String to
+         *                  check.  If < 0 then characters will be parsed
+         *                  until a '\0' is encountered.
+         * @param llx       lower left near x coord
+         * @param lly       lower left near y coord
+         * @param llz       lower left near z coord
+         * @param urx       upper right far x coord
+         * @param ury       upper right far y coord
+         * @param urz       upper right far z coord
+         */
+        void BBox(const char *String,const int StartIdx,const int EndIdx,
+                  float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+                  
+        /**
+         * Get the bounding box for a string.
+         *
+         * @param String    a wchar_t buffer
+         * @param StartIdx  The index of the first character of String
+         *                  to check.
+         * @param EndIdx    The index of the last character of String
+         *                  to check.    If < 0 then characters will
+         *                  be parsed until a '\0' is encountered.
+         * @param llx       lower left near x coord
+         * @param lly       lower left near y coord
+         * @param llz       lower left near z coord
+         * @param urx       upper right far x coord
+         * @param ury       upper right far y coord
+         * @param urz       upper right far z coord
+         */
+        void BBox(const wchar_t *String,const int StartIdx,const int EndIdx,
+                  float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+        
+        /**
+         * Get the bounding box for a string.
+         *
          * @param string    a char string
          * @param llx       lower left near x coord
          * @param lly       lower left near y coord
@@ -201,7 +239,8 @@ class FTGL_EXPORT FTFont
          * @param ury       upper right far y coord
          * @param urz       upper right far z coord
          */
-        void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+        void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+            { BBox(string,0,-1,llx,lly,llz,urx,ury,urz); }
 
         /**
          * Get the bounding box for a string.
@@ -214,8 +253,9 @@ class FTGL_EXPORT FTFont
          * @param ury       upper right far y coord
          * @param urz       upper right far z coord
          */
-        void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
-
+        void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+            { BBox(string,0,-1,llx,lly,llz,urx,ury,urz); }
+            
         /**
          * Get the advance width for a string.
          *
@@ -252,7 +292,6 @@ class FTGL_EXPORT FTFont
          * @return  The current error code.
          */
         FT_Error Error() const { return err;}
-
     protected:
         /**
          * Construct a glyph of the correct type.
@@ -289,6 +328,20 @@ class FTGL_EXPORT FTFont
         
     private:        
         /**
+         * Render a character.
+         * This function does an implicit conversion on its arguments.
+         *
+         * @param chr       current character
+         * @param nextChr   next character
+         * @param origin       The position of the origin of the character.
+         *                  After rendering the point referenced by origin 
+         *                  will be incremented by the kerning advance of 
+         *                  char and nextChr.
+         */
+        inline void DoRender(const unsigned int chr,
+                             const unsigned int nextChr, FTPoint &origin);
+
+        /**
          * Check that the glyph at <code>chr</code> exist. If not load it.
          *
          * @param chr  character index
@@ -305,7 +358,9 @@ class FTGL_EXPORT FTFont
          * Current pen or cursor position;
          */
         FTPoint pen;
-        
+
+        /* Allow FTLayout classes to access DoRender and CheckGlyph */
+        friend class FTLayout;
 };
 
 #endif //__cplusplus
diff --git a/src/FTFont.cpp b/src/FTFont.cpp
index f2772e1..6f308cb 100644
--- a/src/FTFont.cpp
+++ b/src/FTFont.cpp
@@ -168,77 +168,85 @@ float FTFont::LineHeight() const
     return charSize.Height();
 }
 
-void FTFont::BBox( const char* string,
-                   float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+void FTFont::BBox(const char* string, const int start, const int end,
+                  float& llx, float& lly, float& llz,
+                  float& urx, float& ury, float& urz)
 {
     FTBBox totalBBox;
 
-    if((NULL != string) && ('\0' != *string))
+    /* Only compute the bounds if string is non-empty. */
+    if(string && ('\0' != string[start]))
     {
-        const unsigned char* c = (unsigned char*)string;
         float advance = 0;
 
-        if(CheckGlyph( *c))
+        if(CheckGlyph(string[start]))
         {
-            totalBBox = glyphList->BBox( *c);
-            advance = glyphList->Advance( *c, *(c + 1));
+            totalBBox = glyphList->BBox(string[start]);
+            advance = glyphList->Advance(string[start], string[start + 1]);
         }
-                
-        while( *++c)
+
+        /* Expand totalBox by each glyph in String (for idx) */
+        for(int i = start + 1; (end < 0 && string[i]) || end >= 0; i++)
         {
-            if(CheckGlyph( *c))
+            if(CheckGlyph(string[i]))
             {
-                FTBBox tempBBox = glyphList->BBox( *c);
-                tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+                FTBBox tempBBox = glyphList->BBox(string[i]);
+                tempBBox.Move(FTPoint(advance, 0.0f, 0.0f));
+
                 totalBBox += tempBBox;
-                advance += glyphList->Advance( *c, *(c + 1));
+                advance += glyphList->Advance(string[i], string[i + 1]);
             }
         }
     }
 
-    llx = totalBBox.lowerX;
-    lly = totalBBox.lowerY;
-    llz = totalBBox.lowerZ;
-    urx = totalBBox.upperX;
-    ury = totalBBox.upperY;
-    urz = totalBBox.upperZ;
+    // TODO: The Z values do not follow the proper ordering.  I'm not sure why.
+    llx = totalBBox.lowerX < totalBBox.upperX ? totalBBox.lowerX : totalBBox.upperX;
+    lly = totalBBox.lowerY < totalBBox.upperY ? totalBBox.lowerY : totalBBox.upperY;
+    llz = totalBBox.lowerZ < totalBBox.upperZ ? totalBBox.lowerZ : totalBBox.upperZ;
+    urx = totalBBox.lowerX > totalBBox.upperX ? totalBBox.lowerX : totalBBox.upperX;
+    ury = totalBBox.lowerY > totalBBox.upperY ? totalBBox.lowerY : totalBBox.upperY;
+    urz = totalBBox.lowerZ > totalBBox.upperZ ? totalBBox.lowerZ : totalBBox.upperZ;
 }
 
 
-void FTFont::BBox( const wchar_t* string,
-                   float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+void FTFont::BBox(const wchar_t* string, const int start, const int end,
+                  float& llx, float& lly, float& llz,
+                  float& urx, float& ury, float& urz)
 {
     FTBBox totalBBox;
 
-    if((NULL != string) && ('\0' != *string))
+    /* Only compute the bounds if string is non-empty. */
+    if(string && ('\0' != string[start]))
     {
-        const wchar_t* c = string;
         float advance = 0;
 
-        if(CheckGlyph( *c))
+        if(CheckGlyph(string[start]))
         {
-            totalBBox = glyphList->BBox( *c);
-            advance = glyphList->Advance( *c, *(c + 1));
+            totalBBox = glyphList->BBox(string[start]);
+            advance = glyphList->Advance(string[start], string[start + 1]);
         }
-        
-        while( *++c)
+
+        /* Expand totalBox by each glyph in String (for idx) */
+        for(int i = start + 1; (end < 0 && string[i]) || end >= 0; i++)
         {
-            if(CheckGlyph( *c))
+            if(CheckGlyph(string[i]))
             {
-                FTBBox tempBBox = glyphList->BBox( *c);
-                tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+                FTBBox tempBBox = glyphList->BBox(string[i]);
+                tempBBox.Move(FTPoint(advance, 0.0f, 0.0f));
+
                 totalBBox += tempBBox;
-                advance += glyphList->Advance( *c, *(c + 1));
+                advance += glyphList->Advance(string[i], string[i + 1]);
             }
         }
     }
 
-    llx = totalBBox.lowerX;
-    lly = totalBBox.lowerY;
-    llz = totalBBox.lowerZ;
-    urx = totalBBox.upperX;
-    ury = totalBBox.upperY;
-    urz = totalBBox.upperZ;
+    // TODO: The Z values do not follow the proper ordering.  I'm not sure why.
+    llx = totalBBox.lowerX < totalBBox.upperX ? totalBBox.lowerX : totalBBox.upperX;
+    lly = totalBBox.lowerY < totalBBox.upperY ? totalBBox.lowerY : totalBBox.upperY;
+    llz = totalBBox.lowerZ < totalBBox.upperZ ? totalBBox.lowerZ : totalBBox.upperZ;
+    urx = totalBBox.lowerX > totalBBox.upperX ? totalBBox.lowerX : totalBBox.upperX;
+    ury = totalBBox.lowerY > totalBBox.upperY ? totalBBox.lowerY : totalBBox.upperY;
+    urz = totalBBox.lowerZ > totalBBox.upperZ ? totalBBox.lowerZ : totalBBox.upperZ;
 }
 
 
@@ -278,6 +286,18 @@ float FTFont::Advance( const char* string)
 }
 
 
+/* FIXME: DoRender should disappear, see commit [853]. */
+void FTFont::DoRender(const unsigned int chr,
+                      const unsigned int nextChr, FTPoint &origin)
+{
+    if(CheckGlyph(chr))
+    {
+        FTPoint kernAdvance = glyphList->Render(chr, nextChr, origin);
+        origin += kernAdvance;
+    }
+}
+
+
 void FTFont::Render( const char* string )
 {
     const unsigned char* c = (unsigned char*)string;