fs/ras/fsBmfFnt.cpp

Go to the documentation of this file.
00001 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
00002 /*                          _______      ______    ______          __      */
00003 /*  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~    / ____(_)___ / ___ /)  / ____/___  ____/ /__    */
00004 /*     [fsBmfFnt]         / /_  / / __ \\__ \|/  / /   / __ \/ __  / _ \   */
00005 /*       rev. 3          / __/ / / /_/ /__/ /   / /___/ /_/ / /_/ /  __/   */
00006 /*    14th Feb 2007     /_/   /_/ ,___/____/    \____/\____/\__,_/\___/    */
00007 /*     [ ] stable              /_/ (c) 2006-7 Filip STOKLAS (FipS)         */
00008 /*  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~       http://HOLE.4FipS.com/fips_code.php          */
00009 /*                                                                         */
00010 /* This code is free for personal and commercial use. You may redistribute */
00011 /* it by any means. If you use the code for your own projects please give  */
00012 /* me credit. Please send a bug report. Don't alter or remove this header! */
00013 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
00014 #include <fs/ras/fsBmfFnt.h>
00015 
00016 // >>> COMMON SUPPORT BLOCK (rev. 6)
00017 #if defined(FS_HAS_FSASSERT)
00018 #   include <fs/sys/fsAssert.h>
00019 #else
00020 #   include <cassert>
00021 #   if !defined(FS_ASSERT)
00022 #       define FS_ASSERT(exp) assert(exp)
00023 #   endif
00024 #   if !defined(FS_ASSERT_MSG)
00025 #       define FS_ASSERT_MSG(exp, msg) assert(exp && msg)
00026 #   endif
00027 #   if !defined(FS_VERIFY)
00028 #       define FS_VERIFY(exp) \
00029         { bool bExp = !!(exp); assert(bExp && #exp); bExp; }
00030 #   endif
00031 #   if !defined(FS_VERIFY_MSG)
00032 #       define FS_VERIFY_MSG(exp, msg) \
00033         { bool bExp = !!(exp); assert(bExp && #exp && msg); bExp; }
00034 #   endif
00035 #   if !defined(FS_STATIC_ASSERT)
00036 #       define FS_STATIC_ASSERT(exp) { char error[(exp) ? 1 : 0]; error; }
00037 #   endif
00038 #endif
00039 #if !defined(FS_VERIFY_RETURN)
00040 #   define FS_VERIFY_RETURN(exp) \
00041     if(!(exp)) { FS_ASSERT_MSG(0, #exp "<return>"); return; }
00042 #endif
00043 #if !defined(FS_VERIFY_RETURN_VAL)
00044 #   define FS_VERIFY_RETURN_VAL(exp, ret) \
00045     if(!(exp)) { FS_ASSERT_MSG(0, #exp "<returns:>" #ret); return (ret); }
00046 #endif
00047 // <<< COMMON SUPPORT BLOCK (rev. 6)
00048 
00049 #include <vector>
00050 
00051 // provide detailed memory tracking information
00052 #if defined(FS_HAS_FSMEMMGR)
00053 #   include <fs/sys/fsMemMgr.h>
00054 #endif
00055 //---------------------------------------------------------------------------
00056 #if (_MSC_VER >= 1400) // MSVC8
00057 #   pragma warning(disable : 4996) // function was marked as deprecated
00058 #endif
00059 //---------------------------------------------------------------------------
00060 using namespace fs::ras;
00061 //---------------------------------------------------------------------------
00062 //--- ANONYMOUS NAMESPACE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00063 //---------------------------------------------------------------------------
00064 namespace {
00065 //---------------------------------------------------------------------------
00066 //--- CLASS BmfFntImpl_t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00067 //---------------------------------------------------------------------------
00068 class BmfFntImpl_t
00069 {
00070  public:
00071             
00072     explicit BmfFntImpl_t(const char *pszFile);
00073     bool IsValid() const;
00074     
00075     void Print(int nX, int nY, const char *pszText, BmfFnt_t::PxFmt8888_t
00076      *pDst, int nDstW, int nDstH, int nClipX1, int nClipY1, int nClipX2,
00077      int nClipY2) const;
00078 
00079  private:
00080  
00081     BmfFntImpl_t(); 
00082     BmfFntImpl_t(const BmfFntImpl_t &); 
00083     BmfFntImpl_t & operator = (const BmfFntImpl_t &); 
00084     
00086     struct Hdr_t
00087     {
00088         typedef signed char int8;
00089         typedef unsigned char uint8;
00090         typedef unsigned int uint32;
00091         
00092         bool m_bValid;
00093         uint32 m_uMagic; // E1 E6 D5 1A
00094         uint8 m_uVer; // 11h
00095         uint8 m_uLnH;
00096         int8 m_nOverLn;
00097         int8 m_nUnderLn;
00098         int8 m_nCharSpace;
00099         int8 m_nInnerSize;
00100         uint8 m_uNumClrs; // should be <= 32
00101         uint8 m_uMaxClr;
00102         uint32 m_uRsrvd;
00103         uint8 m_uNumRgb;
00104         const uint8 *m_pPal;
00105         uint8 m_uInfoLen;
00106         const uint8 *m_pInfo;
00107         uint8 m_uNumChars;
00108         const uint8 *m_pChars;
00109 
00110         Hdr_t() : m_bValid(false) {}
00111         explicit Hdr_t(const uint8 *pData);
00112     };
00113     
00115     struct Char_t
00116     {
00117         typedef signed char int8;
00118         typedef unsigned char uint8;
00119     
00120         bool m_bValid;
00121         uint8 m_uID;
00122         uint8 m_uW;
00123         uint8 m_uH;
00124         int8 m_nRelX;
00125         int8 m_nRelY;
00126         uint8 m_uShift;
00127         const uint8 *m_pData;
00128 
00129         Char_t() : m_bValid(false) {}
00130         explicit Char_t(const uint8 *pData);
00131     };
00132     
00133     typedef std::vector<unsigned char> Data_t;
00134     typedef std::vector<Char_t> Chars_t;
00135         
00136     bool LoadData(const char *pszFile, Data_t &Data) const;
00137     void BindChars();
00138      
00139     //---
00140      
00141     Data_t m_Data;
00142     Hdr_t m_Hdr;
00143     Chars_t m_Chars;
00144 };
00145 //---------------------------------------------------------------------------
00146 BmfFntImpl_t::BmfFntImpl_t(const char *pszFile)
00147 {
00148     // --- LOAD BMF DATA (the whole content of the file) ---
00149 
00150     Data_t Data;
00151     
00152     if(!LoadData(pszFile, Data))
00153         return;
00154         
00155     //--- CHECK THE FILE TYPE ---
00156         
00157     {
00158         FS_ASSERT(!Data.empty());
00159         Hdr_t DummyHdr(&Data[0]);
00160     
00161         if(DummyHdr.m_uMagic != 0x1AD5E6E1)
00162             { FS_ASSERT_MSG(0, "Wrong BMF identifier!"); return; }
00163 
00164         if(DummyHdr.m_uVer !=  0x11)
00165             { FS_ASSERT_MSG(0, "Wrong BMF version!"); return; }
00166     }
00167         
00168     //--- TRANSFER THE STATE ---
00169 
00170     // swap the data
00171     m_Data.swap(Data);
00172     // bind the header (there are memory references to the data!)
00173     m_Hdr = Hdr_t(&m_Data[0]);
00174     // bind characters (there are memory references to the data!)
00175     BindChars();
00176 }
00177 //---------------------------------------------------------------------------
00178 bool BmfFntImpl_t::IsValid() const
00179 {
00180     return !m_Data.empty();
00181 }
00182 //---------------------------------------------------------------------------
00183 void BmfFntImpl_t::Print(int nX, int nY, const char *pszText,
00184  BmfFnt_t::PxFmt8888_t *pDst,int nDstW, int /*nDstH*/, int /*nClipX1*/,
00185  int /*nClipY1*/, int /*nClipX2*/, int /*nClipY2*/) const
00186 {
00187     FS_VERIFY_RETURN(pszText && pDst);
00188     
00189     for(int i = 0, nCurX = 0, nCurY = 0, n = static_cast<int>(::strlen
00190      (pszText)); i < n; ++i)
00191     {
00192         const char ch = pszText[i];
00193         const Char_t &Char = m_Chars[ch];
00194         
00195         if(!Char.m_bValid)
00196             continue; // skip undefined characters
00197             
00198         if(ch == '\n')
00199         {
00200             nCurX = 0;
00201             nCurY += m_Hdr.m_uLnH;
00202             continue;       
00203         }
00204             
00205         const unsigned char *pCharData = Char.m_pData;
00206         FS_ASSERT(pCharData);
00207         
00208         const int nSrcRelX = Char.m_nRelX;
00209         const int nSrcRelY = Char.m_nRelY;
00210         const int nSrcW = Char.m_uW;
00211         const int nSrcH = Char.m_uH;
00212         const int nDstBar = nSrcRelX + nX + nCurX;
00213         
00214         for(int y = 0; y < nSrcH; ++y)
00215         {
00216             const int nDstBlock = (y + nSrcRelY + nY + nCurY) * nDstW;
00217             
00218             const unsigned char *pCurSrc = pCharData + y * nSrcW;
00219             BmfFnt_t::PxFmt8888_t *pCurDst = pDst + nDstBlock + nDstBar;
00220                 
00221             for(int x = 0; x < nSrcW; ++x)
00222             {
00223                 int nColor = 3 * (*pCurSrc - 1);
00224                 if(nColor >= 0)
00225                 {
00226                     pCurDst->r = 4 * m_Hdr.m_pPal[nColor];
00227                     pCurDst->g = 4 * m_Hdr.m_pPal[nColor + 1];
00228                     pCurDst->b = 4 * m_Hdr.m_pPal[nColor + 2];
00229                     pCurDst->a = 255;
00230                 }
00231 
00232                 ++pCurSrc;
00233                 ++pCurDst;
00234             }
00235         }
00236         
00237         nCurX += m_Hdr.m_nCharSpace + Char.m_uShift;
00238     }
00239 }
00240 //---------------------------------------------------------------------------
00241 bool BmfFntImpl_t::LoadData(const char *pszFile, Data_t &Data) const
00242 {
00243     FS_VERIFY_RETURN_VAL(pszFile, false);
00244 
00245     // open the BMF file
00246     FILE *pIn = ::fopen(pszFile, "rb");
00247     if(!pIn)
00248         return false; // couldn't open the file
00249         
00250     // get the size of the file
00251     FS_VERIFY(::fseek(pIn, 0, SEEK_END) == 0);
00252     long nFileSize = ::ftell(pIn);
00253     FS_VERIFY(::fseek(pIn, 0, SEEK_SET) == 0);
00254 
00255     // read the whole content    
00256     Data.resize(nFileSize);
00257     FS_VERIFY(::fread(&Data[0], nFileSize, 1, pIn) == 1);
00258     
00259     ::fclose(pIn);
00260     return true;
00261 }
00262 //---------------------------------------------------------------------------
00263 void BmfFntImpl_t::BindChars()
00264 {
00265     m_Chars.resize(256);
00266             
00267     const Hdr_t::uint8 *pCharStart = m_Hdr.m_pChars;
00268     for(int i = 0; i < m_Hdr.m_uNumChars; ++i)
00269     {
00270         Char_t Char(pCharStart);
00271         
00272         FS_ASSERT(Char.m_uID >= 0 && Char.m_uID < 256);
00273         m_Chars[Char.m_uID] = Char;
00274         
00275         pCharStart = Char.m_pData + Char.m_uW * Char.m_uH;
00276     }
00277 }
00278 //---------------------------------------------------------------------------
00279 BmfFntImpl_t::Hdr_t::Hdr_t(const uint8 *pData):
00280 m_bValid(true),
00281 m_uMagic(*reinterpret_cast<const uint32 *>(pData)),
00282 m_uVer(*(pData + 4)),
00283 m_uLnH(*(pData + 5)),
00284 m_nOverLn(*reinterpret_cast<const int8 *>(pData + 6)),
00285 m_nUnderLn(*reinterpret_cast<const int8 *>(pData + 7)),
00286 m_nCharSpace(*reinterpret_cast<const int8 *>(pData + 8)),
00287 m_nInnerSize(*reinterpret_cast<const int8 *>(pData + 9)),
00288 m_uNumClrs(*(pData + 10)),
00289 m_uMaxClr(*(pData + 11)),
00290 m_uRsrvd(*(pData + 12)),
00291 m_uNumRgb(*(pData + 16)),
00292 m_pPal(pData + 17),
00293 m_uInfoLen(*(pData + 17 + 3 * m_uNumRgb)),
00294 m_pInfo(pData + 18 + 3 * m_uNumRgb),
00295 m_uNumChars(*reinterpret_cast<const uint8 *>(pData + 18 +
00296  3 * m_uNumRgb + m_uInfoLen)),
00297 m_pChars(pData + 20 + 3 * m_uNumRgb + m_uInfoLen)
00298 {
00299     FS_STATIC_ASSERT(sizeof(uint32) == 4);
00300 }
00301 //---------------------------------------------------------------------------
00302 BmfFntImpl_t::Char_t::Char_t(const uint8 *pData):
00303 m_bValid(true),
00304 m_uID(*pData),
00305 m_uW(*(pData + 1)),
00306 m_uH(*(pData + 2)),
00307 m_nRelX(*reinterpret_cast<const int8 *>(pData + 3)),
00308 m_nRelY(*reinterpret_cast<const int8 *>(pData + 4)),
00309 m_uShift(*(pData + 5)),
00310 m_pData(pData + 6)
00311 {
00312 }
00313 //---------------------------------------------------------------------------
00314 } // anonymous namespace
00315 //---------------------------------------------------------------------------
00316 //--- CLASS BmfFnt_t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00317 //---------------------------------------------------------------------------
00318 BmfFnt_t::BmfFnt_t(const char *pszFile):
00319 m_pImpl(new BmfFntImpl_t(pszFile))
00320 {
00321     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00322 }
00323 //---------------------------------------------------------------------------
00324 BmfFnt_t::~BmfFnt_t()
00325 {
00326     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00327     delete static_cast<BmfFntImpl_t *>(m_pImpl);
00328 }
00329 //---------------------------------------------------------------------------
00330 bool BmfFnt_t::IsValid() const
00331 {
00332     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00333     return static_cast<BmfFntImpl_t *>(m_pImpl)->IsValid();
00334 }
00335 //---------------------------------------------------------------------------
00336 void BmfFnt_t::Print(int nX, int nY, const char *pszText, PxFmt8888_t
00337  *pDst, int nDstW, int nDstH, int nClipX1, int nClipY1, int nClipX2,
00338  int nClipY2) const
00339 {
00340     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00341     
00342     static_cast<BmfFntImpl_t *>(m_pImpl)->Print(nX, nY, pszText, pDst,
00343      nDstW, nDstH, nClipX1, nClipY1, nClipX2, nClipY2);
00344 }
00345 //---------------------------------------------------------------------------

FipS' Code (Thu Feb 15 22:43:35 2007) - (c) Filip STOKLAS (FipS) - [ www ] [ Guest Book ]