Explorar el Código

STB Memory functions for fonts

Add the ability to read and write to a stream.
marauder2k7 hace 1 año
padre
commit
106346630d

+ 27 - 0
Engine/source/gfx/bitmap/gBitmap.cpp

@@ -1206,6 +1206,20 @@ bool  GBitmap::readBitmap(const String& bmType, const Torque::Path& path)
    return regInfo->readFunc(path, this);
 }
 
+bool GBitmap::readBitmapStream(const String& bmType, Stream& ioStream, U32 len)
+{
+   PROFILE_SCOPE(ResourceGBitmap_readBitmapStream);
+   const GBitmap::Registration* regInfo = GBitmap::sFindRegInfo(bmType);
+
+   if (regInfo == NULL)
+   {
+      Con::errorf("[GBitmap::readBitmap] unable to find registration for extension [%s]", bmType.c_str());
+      return false;
+   }
+
+   return regInfo->readStreamFunc(ioStream, this, len);
+}
+
 bool  GBitmap::writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel )
 {
    FileStream stream;
@@ -1230,6 +1244,19 @@ bool  GBitmap::writeBitmap( const String &bmType, const Torque::Path& path, U32
    return regInfo->writeFunc(path, this, (compressionLevel == U32_MAX) ? regInfo->defaultCompression : compressionLevel );
 }
 
+bool GBitmap::writeBitmapStream(const String& bmType, Stream& ioStream, U32 compressionLevel)
+{
+   const GBitmap::Registration* regInfo = GBitmap::sFindRegInfo(bmType);
+
+   if (regInfo == NULL)
+   {
+      Con::errorf("[GBitmap::writeBitmap] unable to find registration for extension [%s]", bmType.c_str());
+      return false;
+   }
+
+   return regInfo->writeStreamFunc(ioStream, this, (compressionLevel == U32_MAX) ? regInfo->defaultCompression : compressionLevel);
+}
+
 template<> void *Resource<GBitmap>::create(const Torque::Path &path)
 {
    PROFILE_SCOPE( ResourceGBitmap_create );

+ 23 - 13
Engine/source/gfx/bitmap/gBitmap.h

@@ -70,26 +70,31 @@ public:
 
    struct Registration
    {
-      /// The read function prototype.
+      /// The read functions prototype.
       typedef bool(*ReadFunc)(const Torque::Path& path, GBitmap* bitmap);
-
-      /// The write function prototype.  Compression levels are image-specific - see their registration declaration for details.
+      typedef bool(*ReadStreamFunc)(Stream& stream, GBitmap* bitmap, U32 len);
+      /// The write functions prototype.  Compression levels are image-specific - see their registration declaration for details.
       typedef bool(*WriteFunc)(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel);
-
+      typedef bool(*WriteStreamFunc)(Stream& stream, GBitmap* bitmap, U32 compressionLevel);
+      
       /// Used to sort the registrations so that 
       /// lookups occur in a fixed order.
       U32 priority;
-
       Vector<String>   extensions;     ///< the list of file extensions for this bitmap type [these should be lower case]
       
-      ReadFunc    readFunc;            ///< the read function to call for this bitmap type
-      WriteFunc   writeFunc;           ///< the write function to call for this bitmap type
-      U32         defaultCompression;  ///< the default compression level [levels are image-specific - see their registration declaration for details]
+      ReadFunc    readFunc;            ///< the read function to read from a file.
+      WriteFunc   writeFunc;           ///< the write function to write to a file.
+      ReadStreamFunc readStreamFunc;   ///< the read function to read from a stream.
+      WriteStreamFunc writeStreamFunc; ///< the write function to write to a stream.
+
+      U32 defaultCompression;          ///< the default compression level [levels are image-specific - see their registration declaration for details]
 
       Registration()
       {
          readFunc = NULL;
          writeFunc = NULL;
+         readStreamFunc = NULL;
+         writeStreamFunc = NULL;
          defaultCompression = 0;
          priority = 0;
          VECTOR_SET_ASSOCIATION( extensions );
@@ -238,19 +243,24 @@ public:
 
    //-------------------------------------- Input/Output interface
 
-   /// Read a bitmap from a stream
+   /// Read a bitmap from a file
    /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
    /// @param ioStream The stream to read from
-   bool  readBitmap(const String& bmType, const Torque::Path& path);
+   bool readBitmap(const String& bmType, const Torque::Path& path);
+
+   /// Sane as above but reads from a stream.
+   bool readBitmapStream(const String& bmType, Stream& ioStream, U32 len);
 
-   /// Write a bitmap to a stream
+   /// Write a bitmap to a file
    /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
    /// @param ioStream The stream to read from
    /// @param compressionLevel Image format specific compression level. For JPEG sets the quality level percentage, range 0 to 100.
    /// For PNG compression level is 0 - 10
    /// Not used for other image formats.
-   
-   bool  writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel = U32_MAX );
+   bool writeBitmap( const String &bmType, const Torque::Path& path, U32 compressionLevel = U32_MAX );
+
+   /// Sane as above but writes to a stream.
+   bool writeBitmapStream(const String& bmType, Stream& ioStream, U32 compressionLevel = U32_MAX);
 
    bool readMNG(Stream& io_rStream);               // located in bitmapMng.cc
    bool writeMNG(Stream& io_rStream) const;

+ 66 - 0
Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp

@@ -21,6 +21,7 @@
 //-----------------------------------------------------------------------------
 
 #include "platform/platform.h"
+#include "console/console.h"
 
 #include "core/stream/fileStream.h"
 #include "core/stream/memStream.h"
@@ -40,7 +41,10 @@
 #include "stb_image_write.h"
 
 static bool sReadSTB(const Torque::Path& path, GBitmap* bitmap);
+static bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len);
+
 static bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel);
+static bool sWriteStreamSTB(Stream& stream, GBitmap* bitmap, U32 compressionLevel);
 
 static struct _privateRegisterSTB
 {
@@ -58,8 +62,10 @@ static struct _privateRegisterSTB
       reg.extensions.push_back("tga");
 
       reg.readFunc = sReadSTB;
+      reg.readStreamFunc = sReadStreamSTB;
 
       reg.writeFunc = sWriteSTB;
+      reg.writeStreamFunc = sWriteStreamSTB;
 
       // for png only.
       reg.defaultCompression = 6;
@@ -194,6 +200,41 @@ bool sReadSTB(const Torque::Path& path, GBitmap* bitmap)
    return true;
 }
 
+bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len)
+{
+   PROFILE_SCOPE(sReadStreamSTB);
+   // only used for font at the moment.
+
+   U8* data = new U8[len];
+   stream.read(len, data);
+
+   S32 width, height, comp = 0;
+
+   unsigned char* pixelData = stbi_load_from_memory((const U8*)data, (int)len, &width, &height, &comp, 1);
+   if (!pixelData)
+   {
+      const char* stbErr = stbi_failure_reason();
+
+      if (!stbErr)
+         stbErr = "Unknown Error!";
+
+      Con::printf("sReadStreamSTB Error: %s", stbErr);
+      return false;
+   }
+   bitmap->deleteImage();
+
+   bitmap->allocateBitmap(256, 256, false, GFXFormatA8);
+
+   U8* pBase = bitmap->getWritableBits(0);
+   U32 rowBytes = bitmap->getByteSize();
+   dMemcpy(pBase, pixelData, rowBytes);
+
+   dFree(data);
+   dFree(pixelData);
+
+   return true;
+}
+
 /**
  * Write bitmap to an image file.
  *
@@ -269,3 +310,28 @@ bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel)
 
    return false;
 }
+
+bool sWriteStreamSTB(Stream& stream, GBitmap* bitmap, U32 compressionLevel)
+{
+   S32 len;
+   const U8* pData = bitmap->getBits();
+
+   unsigned char* png = stbi_write_png_to_mem(pData, 0, bitmap->getWidth(), bitmap->getHeight(), 1, &len);
+
+   if (!png)
+   {
+      const char* stbErr = stbi_failure_reason();
+
+      if (!stbErr)
+         stbErr = "Unknown Error!";
+
+      Con::printf("sReadStreamSTB Error: %s", stbErr);
+      return false;
+   }
+
+   stream.write(len);
+   stream.write(len, png);
+
+   dFree(png);
+   return true;
+}

+ 13 - 2
Engine/source/gfx/gFont.cpp

@@ -699,12 +699,21 @@ bool GFont::read(Stream& io_rStream)
    for(i = 0; i < numSheets; i++)
    {
        GBitmap *bmp = new GBitmap;
-       String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
+       /*String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
        if(!bmp->readBitmap("png", path))
        {
            delete bmp;
            return false;
+       }*/
+       U32 len;
+       io_rStream.read(&len);
+
+       if (!bmp->readBitmapStream("png", io_rStream, len))
+       {
+          delete bmp;
+          return false;
        }
+
        GFXTexHandle handle = GFXTexHandle(bmp, &GFXFontTextureProfile, true, avar("%s() - Read Font Sheet for %s %d (line %d)", __FUNCTION__, mFaceName.c_str(), mSize, __LINE__));
        //handle.setFilterNearest();
        mTextureSheets.push_back(handle);
@@ -779,7 +788,9 @@ bool GFont::write(Stream& stream)
    for (i = 0; i < mTextureSheets.size(); i++)
    {
       String path = String::ToString("%s/%s %d %d (%s).png", Con::getVariable("$GUI::fontCacheDirectory"), mFaceName.c_str(), mSize, i, getCharSetName(mCharSet));
-      mTextureSheets[i].getBitmap()->writeBitmap("png", path);
+      //mTextureSheets[i].getBitmap()->writeBitmap("png", path);
+
+      mTextureSheets[i].getBitmap()->writeBitmapStream("png", stream);
    }
 
    stream.write(mCurX);