00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <fs/ras/fsBmfFnt.h>
00015
00016
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
00048
00049 #include <vector>
00050
00051
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
00063
00064 namespace {
00065
00066
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;
00094 uint8 m_uVer;
00095 uint8 m_uLnH;
00096 int8 m_nOverLn;
00097 int8 m_nUnderLn;
00098 int8 m_nCharSpace;
00099 int8 m_nInnerSize;
00100 uint8 m_uNumClrs;
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
00149
00150 Data_t Data;
00151
00152 if(!LoadData(pszFile, Data))
00153 return;
00154
00155
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
00169
00170
00171 m_Data.swap(Data);
00172
00173 m_Hdr = Hdr_t(&m_Data[0]);
00174
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 , int ,
00185 int , int , int ) 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;
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
00246 FILE *pIn = ::fopen(pszFile, "rb");
00247 if(!pIn)
00248 return false;
00249
00250
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
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 }
00315
00316
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