PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Core/Dependencies/OgreSource/OgreMain/src/OgreFont.cpp

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
C++ | 544 lines | 400 code | 53 blank | 91 comment | 40 complexity | cd1b7f8836ee71c9466146f693561196 MD5 | raw file
  1. /*-------------------------------------------------------------------------
  2. This source file is a part of OGRE
  3. (Object-oriented Graphics Rendering Engine)
  4. For the latest info, see http://www.ogre3d.org/
  5. Copyright (c) 2000-2012 Torus Knot Software Ltd
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE
  21. -------------------------------------------------------------------------*/
  22. #include "OgreStableHeaders.h"
  23. #include "OgreFont.h"
  24. #include "OgreMaterialManager.h"
  25. #include "OgreTextureManager.h"
  26. #include "OgreTexture.h"
  27. #include "OgreResourceGroupManager.h"
  28. #include "OgreLogManager.h"
  29. #include "OgreStringConverter.h"
  30. #include "OgreRenderWindow.h"
  31. #include "OgreException.h"
  32. #include "OgreBlendMode.h"
  33. #include "OgreTextureUnitState.h"
  34. #include "OgreTechnique.h"
  35. #include "OgrePass.h"
  36. #include "OgreMaterial.h"
  37. #include "OgreBitwise.h"
  38. #include <ft2build.h>
  39. #include FT_FREETYPE_H
  40. #include FT_GLYPH_H
  41. namespace Ogre
  42. {
  43. //---------------------------------------------------------------------
  44. Font::CmdType Font::msTypeCmd;
  45. Font::CmdSource Font::msSourceCmd;
  46. Font::CmdCharSpacer Font::msCharacterSpacerCmd;
  47. Font::CmdSize Font::msSizeCmd;
  48. Font::CmdResolution Font::msResolutionCmd;
  49. Font::CmdCodePoints Font::msCodePointsCmd;
  50. //---------------------------------------------------------------------
  51. Font::Font(ResourceManager* creator, const String& name, ResourceHandle handle,
  52. const String& group, bool isManual, ManualResourceLoader* loader)
  53. :Resource (creator, name, handle, group, isManual, loader),
  54. mType(FT_TRUETYPE), mCharacterSpacer(5), mTtfSize(0), mTtfResolution(0), mTtfMaxBearingY(0), mAntialiasColour(false)
  55. {
  56. if (createParamDictionary("Font"))
  57. {
  58. ParamDictionary* dict = getParamDictionary();
  59. dict->addParameter(
  60. ParameterDef("type", "'truetype' or 'image' based font", PT_STRING),
  61. &msTypeCmd);
  62. dict->addParameter(
  63. ParameterDef("source", "Filename of the source of the font.", PT_STRING),
  64. &msSourceCmd);
  65. dict->addParameter(
  66. ParameterDef("character_spacer", "Spacing between characters to prevent overlap artifacts.", PT_STRING),
  67. &msCharacterSpacerCmd);
  68. dict->addParameter(
  69. ParameterDef("size", "True type size", PT_REAL),
  70. &msSizeCmd);
  71. dict->addParameter(
  72. ParameterDef("resolution", "True type resolution", PT_UNSIGNED_INT),
  73. &msResolutionCmd);
  74. dict->addParameter(
  75. ParameterDef("code_points", "Add a range of code points", PT_STRING),
  76. &msCodePointsCmd);
  77. }
  78. }
  79. //---------------------------------------------------------------------
  80. Font::~Font()
  81. {
  82. // have to call this here reather than in Resource destructor
  83. // since calling virtual methods in base destructors causes crash
  84. unload();
  85. }
  86. //---------------------------------------------------------------------
  87. void Font::setType(FontType ftype)
  88. {
  89. mType = ftype;
  90. }
  91. //---------------------------------------------------------------------
  92. FontType Font::getType(void) const
  93. {
  94. return mType;
  95. }
  96. //---------------------------------------------------------------------
  97. void Font::setSource(const String& source)
  98. {
  99. mSource = source;
  100. }
  101. //---------------------------------------------------------------------
  102. void Font::setTrueTypeSize(Real ttfSize)
  103. {
  104. mTtfSize = ttfSize;
  105. }
  106. //---------------------------------------------------------------------
  107. void Font::setCharacterSpacer(uint charSpacer)
  108. {
  109. mCharacterSpacer = charSpacer;
  110. }
  111. //---------------------------------------------------------------------
  112. void Font::setTrueTypeResolution(uint ttfResolution)
  113. {
  114. mTtfResolution = ttfResolution;
  115. }
  116. //---------------------------------------------------------------------
  117. const String& Font::getSource(void) const
  118. {
  119. return mSource;
  120. }
  121. //---------------------------------------------------------------------
  122. uint Font::getCharacterSpacer(void) const
  123. {
  124. return mCharacterSpacer;
  125. }
  126. //---------------------------------------------------------------------
  127. Real Font::getTrueTypeSize(void) const
  128. {
  129. return mTtfSize;
  130. }
  131. //---------------------------------------------------------------------
  132. uint Font::getTrueTypeResolution(void) const
  133. {
  134. return mTtfResolution;
  135. }
  136. //---------------------------------------------------------------------
  137. int Font::getTrueTypeMaxBearingY() const
  138. {
  139. return mTtfMaxBearingY;
  140. }
  141. //---------------------------------------------------------------------
  142. const Font::GlyphInfo& Font::getGlyphInfo(CodePoint id) const
  143. {
  144. CodePointMap::const_iterator i = mCodePointMap.find(id);
  145. if (i == mCodePointMap.end())
  146. {
  147. OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
  148. "Code point " + StringConverter::toString(id) + " not found in font "
  149. + mName, "Font::getGlyphInfo");
  150. }
  151. return i->second;
  152. }
  153. //---------------------------------------------------------------------
  154. void Font::loadImpl()
  155. {
  156. // Create a new material
  157. mMaterial = MaterialManager::getSingleton().create(
  158. "Fonts/" + mName, mGroup);
  159. if (mMaterial.isNull())
  160. {
  161. OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
  162. "Error creating new material!", "Font::load" );
  163. }
  164. TextureUnitState *texLayer;
  165. bool blendByAlpha = true;
  166. if (mType == FT_TRUETYPE)
  167. {
  168. createTextureFromFont();
  169. texLayer = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0);
  170. // Always blend by alpha
  171. blendByAlpha = true;
  172. }
  173. else
  174. {
  175. // Manually load since we need to load to get alpha
  176. mTexture = TextureManager::getSingleton().load(mSource, mGroup, TEX_TYPE_2D, 0);
  177. blendByAlpha = mTexture->hasAlpha();
  178. texLayer = mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(mSource);
  179. }
  180. // Make sure material is aware of colour per vertex.
  181. mMaterial->getTechnique(0)->getPass(0)->setVertexColourTracking(TVC_DIFFUSE);
  182. // Clamp to avoid fuzzy edges
  183. texLayer->setTextureAddressingMode( TextureUnitState::TAM_CLAMP );
  184. // Allow min/mag filter, but no mip
  185. texLayer->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
  186. // Set up blending
  187. if (blendByAlpha)
  188. {
  189. mMaterial->setSceneBlending( SBT_TRANSPARENT_ALPHA );
  190. }
  191. else
  192. {
  193. // Use add if no alpha (assume black background)
  194. mMaterial->setSceneBlending(SBT_ADD);
  195. }
  196. }
  197. //---------------------------------------------------------------------
  198. void Font::unloadImpl()
  199. {
  200. if (!mMaterial.isNull())
  201. {
  202. MaterialManager::getSingleton().remove(mMaterial->getHandle());
  203. mMaterial.setNull();
  204. }
  205. if (!mTexture.isNull())
  206. {
  207. TextureManager::getSingleton().remove(mTexture->getHandle());
  208. mTexture.setNull();
  209. }
  210. }
  211. //---------------------------------------------------------------------
  212. void Font::createTextureFromFont(void)
  213. {
  214. // Just create the texture here, and point it at ourselves for when
  215. // it wants to (re)load for real
  216. String texName = mName + "Texture";
  217. // Create, setting isManual to true and passing self as loader
  218. mTexture = TextureManager::getSingleton().create(
  219. texName, mGroup, true, this);
  220. mTexture->setTextureType(TEX_TYPE_2D);
  221. mTexture->setNumMipmaps(0);
  222. mTexture->load();
  223. TextureUnitState* t = mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );
  224. // Allow min/mag filter, but no mip
  225. t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
  226. }
  227. //---------------------------------------------------------------------
  228. void Font::loadResource(Resource* res)
  229. {
  230. // ManualResourceLoader implementation - load the texture
  231. FT_Library ftLibrary;
  232. // Init freetype
  233. if( FT_Init_FreeType( &ftLibrary ) )
  234. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
  235. "Font::Font");
  236. FT_Face face;
  237. // Locate ttf file, load it pre-buffered into memory by wrapping the
  238. // original DataStream in a MemoryDataStream
  239. DataStreamPtr dataStreamPtr =
  240. ResourceGroupManager::getSingleton().openResource(
  241. mSource, mGroup, true, this);
  242. MemoryDataStream ttfchunk(dataStreamPtr);
  243. // Load font
  244. if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.size() , 0, &face ) )
  245. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
  246. "Could not open font face!", "Font::createTextureFromFont" );
  247. // Convert our point size to freetype 26.6 fixed point format
  248. FT_F26Dot6 ftSize = (FT_F26Dot6)(mTtfSize * (1 << 6));
  249. if( FT_Set_Char_Size( face, ftSize, 0, mTtfResolution, mTtfResolution ) )
  250. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
  251. "Could not set char size!", "Font::createTextureFromFont" );
  252. //FILE *fo_def = stdout;
  253. int max_height = 0, max_width = 0;
  254. // Backwards compatibility - if codepoints not supplied, assume 33-166
  255. if (mCodePointRangeList.empty())
  256. {
  257. mCodePointRangeList.push_back(CodePointRange(33, 166));
  258. }
  259. // Calculate maximum width, height and bearing
  260. size_t glyphCount = 0;
  261. for (CodePointRangeList::const_iterator r = mCodePointRangeList.begin();
  262. r != mCodePointRangeList.end(); ++r)
  263. {
  264. const CodePointRange& range = *r;
  265. for(CodePoint cp = range.first; cp <= range.second; ++cp, ++glyphCount)
  266. {
  267. FT_Load_Char( face, cp, FT_LOAD_RENDER );
  268. if( ( 2 * ( face->glyph->bitmap.rows << 6 ) - face->glyph->metrics.horiBearingY ) > max_height )
  269. max_height = ( 2 * ( face->glyph->bitmap.rows << 6 ) - face->glyph->metrics.horiBearingY );
  270. if( face->glyph->metrics.horiBearingY > mTtfMaxBearingY )
  271. mTtfMaxBearingY = face->glyph->metrics.horiBearingY;
  272. if( (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 ) > max_width)
  273. max_width = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );
  274. }
  275. }
  276. // Now work out how big our texture needs to be
  277. size_t rawSize = (max_width + mCharacterSpacer) *
  278. ((max_height >> 6) + mCharacterSpacer) * glyphCount;
  279. uint32 tex_side = static_cast<uint32>(Math::Sqrt((Real)rawSize));
  280. // just in case the size might chop a glyph in half, add another glyph width/height
  281. tex_side += std::max(max_width, (max_height>>6));
  282. // Now round up to nearest power of two
  283. uint32 roundUpSize = Bitwise::firstPO2From(tex_side);
  284. // Would we benefit from using a non-square texture (2X width(
  285. size_t finalWidth, finalHeight;
  286. if (roundUpSize*roundUpSize*0.5 >= rawSize)
  287. {
  288. finalHeight = static_cast<size_t>(roundUpSize * 0.5);
  289. }
  290. else
  291. {
  292. finalHeight = roundUpSize;
  293. }
  294. finalWidth = roundUpSize;
  295. Real textureAspect = (Real)finalWidth / (Real)finalHeight;
  296. const size_t pixel_bytes = 2;
  297. size_t data_width = finalWidth * pixel_bytes;
  298. size_t data_size = finalWidth * finalHeight * pixel_bytes;
  299. LogManager::getSingleton().logMessage("Font " + mName + " using texture size " +
  300. StringConverter::toString(finalWidth) + "x" + StringConverter::toString(finalHeight));
  301. uchar* imageData = OGRE_ALLOC_T(uchar, data_size, MEMCATEGORY_GENERAL);
  302. // Reset content (White, transparent)
  303. for (size_t i = 0; i < data_size; i += pixel_bytes)
  304. {
  305. imageData[i + 0] = 0xFF; // luminance
  306. imageData[i + 1] = 0x00; // alpha
  307. }
  308. size_t l = 0, m = 0;
  309. for (CodePointRangeList::const_iterator r = mCodePointRangeList.begin();
  310. r != mCodePointRangeList.end(); ++r)
  311. {
  312. const CodePointRange& range = *r;
  313. for(CodePoint cp = range.first; cp <= range.second; ++cp )
  314. {
  315. FT_Error ftResult;
  316. // Load & render glyph
  317. ftResult = FT_Load_Char( face, cp, FT_LOAD_RENDER );
  318. if (ftResult)
  319. {
  320. // problem loading this glyph, continue
  321. LogManager::getSingleton().logMessage("Info: cannot load character " +
  322. StringConverter::toString(cp) + " in font " + mName);
  323. continue;
  324. }
  325. FT_Int advance = face->glyph->advance.x >> 6;
  326. unsigned char* buffer = face->glyph->bitmap.buffer;
  327. if (!buffer)
  328. {
  329. // Yuck, FT didn't detect this but generated a null pointer!
  330. LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
  331. StringConverter::toString(cp) + " in font " + mName);
  332. continue;
  333. }
  334. int y_bearing = ( mTtfMaxBearingY >> 6 ) - ( face->glyph->metrics.horiBearingY >> 6 );
  335. int x_bearing = face->glyph->metrics.horiBearingX >> 6;
  336. for(int j = 0; j < face->glyph->bitmap.rows; j++ )
  337. {
  338. size_t row = j + m + y_bearing;
  339. uchar* pDest = &imageData[(row * data_width) + (l + x_bearing) * pixel_bytes];
  340. for(int k = 0; k < face->glyph->bitmap.width; k++ )
  341. {
  342. if (mAntialiasColour)
  343. {
  344. // Use the same greyscale pixel for all components RGBA
  345. *pDest++= *buffer;
  346. }
  347. else
  348. {
  349. // Always white whether 'on' or 'off' pixel, since alpha
  350. // will turn off
  351. *pDest++= 0xFF;
  352. }
  353. // Always use the greyscale value for alpha
  354. *pDest++= *buffer++;
  355. }
  356. }
  357. this->setGlyphTexCoords(cp,
  358. (Real)l / (Real)finalWidth, // u1
  359. (Real)m / (Real)finalHeight, // v1
  360. (Real)( l + ( face->glyph->advance.x >> 6 ) ) / (Real)finalWidth, // u2
  361. ( m + ( max_height >> 6 ) ) / (Real)finalHeight, // v2
  362. textureAspect
  363. );
  364. // Advance a column
  365. l += (advance + mCharacterSpacer);
  366. // If at end of row
  367. if( finalWidth - 1 < l + ( advance ) )
  368. {
  369. m += ( max_height >> 6 ) + mCharacterSpacer;
  370. l = 0;
  371. }
  372. }
  373. }
  374. DataStreamPtr memStream(
  375. OGRE_NEW MemoryDataStream(imageData, data_size, true));
  376. Image img;
  377. img.loadRawData( memStream, finalWidth, finalHeight, PF_BYTE_LA );
  378. Texture* tex = static_cast<Texture*>(res);
  379. // Call internal _loadImages, not loadImage since that's external and
  380. // will determine load status etc again, and this is a manual loader inside load()
  381. ConstImagePtrList imagePtrs;
  382. imagePtrs.push_back(&img);
  383. tex->_loadImages( imagePtrs );
  384. FT_Done_FreeType(ftLibrary);
  385. }
  386. //-----------------------------------------------------------------------
  387. //-----------------------------------------------------------------------
  388. String Font::CmdType::doGet(const void* target) const
  389. {
  390. const Font* f = static_cast<const Font*>(target);
  391. if (f->getType() == FT_TRUETYPE)
  392. {
  393. return "truetype";
  394. }
  395. else
  396. {
  397. return "image";
  398. }
  399. }
  400. void Font::CmdType::doSet(void* target, const String& val)
  401. {
  402. Font* f = static_cast<Font*>(target);
  403. if (val == "truetype")
  404. {
  405. f->setType(FT_TRUETYPE);
  406. }
  407. else
  408. {
  409. f->setType(FT_IMAGE);
  410. }
  411. }
  412. //-----------------------------------------------------------------------
  413. String Font::CmdSource::doGet(const void* target) const
  414. {
  415. const Font* f = static_cast<const Font*>(target);
  416. return f->getSource();
  417. }
  418. void Font::CmdSource::doSet(void* target, const String& val)
  419. {
  420. Font* f = static_cast<Font*>(target);
  421. f->setSource(val);
  422. }
  423. //-----------------------------------------------------------------------
  424. String Font::CmdCharSpacer::doGet(const void* target) const
  425. {
  426. const Font* f = static_cast<const Font*>(target);
  427. char buf[sizeof(uint)];
  428. sprintf(buf, "%d", f->getCharacterSpacer());
  429. return String(buf);
  430. }
  431. void Font::CmdCharSpacer::doSet(void* target, const String& val)
  432. {
  433. Font* f = static_cast<Font*>(target);
  434. f->setCharacterSpacer(atoi(val.c_str()));
  435. }
  436. //-----------------------------------------------------------------------
  437. String Font::CmdSize::doGet(const void* target) const
  438. {
  439. const Font* f = static_cast<const Font*>(target);
  440. return StringConverter::toString(f->getTrueTypeSize());
  441. }
  442. void Font::CmdSize::doSet(void* target, const String& val)
  443. {
  444. Font* f = static_cast<Font*>(target);
  445. f->setTrueTypeSize(StringConverter::parseReal(val));
  446. }
  447. //-----------------------------------------------------------------------
  448. String Font::CmdResolution::doGet(const void* target) const
  449. {
  450. const Font* f = static_cast<const Font*>(target);
  451. return StringConverter::toString(f->getTrueTypeResolution());
  452. }
  453. void Font::CmdResolution::doSet(void* target, const String& val)
  454. {
  455. Font* f = static_cast<Font*>(target);
  456. f->setTrueTypeResolution(StringConverter::parseUnsignedInt(val));
  457. }
  458. //-----------------------------------------------------------------------
  459. String Font::CmdCodePoints::doGet(const void* target) const
  460. {
  461. const Font* f = static_cast<const Font*>(target);
  462. const CodePointRangeList& rangeList = f->getCodePointRangeList();
  463. StringUtil::StrStreamType str;
  464. for (CodePointRangeList::const_iterator i = rangeList.begin(); i != rangeList.end(); ++i)
  465. {
  466. str << i->first << "-" << i->second << " ";
  467. }
  468. return str.str();
  469. }
  470. void Font::CmdCodePoints::doSet(void* target, const String& val)
  471. {
  472. // Format is "code_points start1-end1 start2-end2"
  473. Font* f = static_cast<Font*>(target);
  474. StringVector vec = StringUtil::split(val, " \t");
  475. for (StringVector::iterator i = vec.begin(); i != vec.end(); ++i)
  476. {
  477. String& item = *i;
  478. StringVector itemVec = StringUtil::split(item, "-");
  479. if (itemVec.size() == 2)
  480. {
  481. f->addCodePointRange(CodePointRange(
  482. StringConverter::parseLong(itemVec[0]),
  483. StringConverter::parseLong(itemVec[1])));
  484. }
  485. }
  486. }
  487. }