llfontfreetype.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:14k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfontfreetype.cpp
  3.  * @brief Freetype font library wrapper
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llfontfreetype.h"
  34. #include "llfontgl.h"
  35. // Freetype stuff
  36. #include <ft2build.h>
  37. // For some reason, this won't work if it's not wrapped in the ifdef
  38. #ifdef FT_FREETYPE_H
  39. #include FT_FREETYPE_H
  40. #endif
  41. #include "llerror.h"
  42. #include "llimage.h"
  43. //#include "llimagej2c.h"
  44. #include "llmath.h" // Linden math
  45. #include "llstring.h"
  46. //#include "imdebug.h"
  47. #include "llfontbitmapcache.h"
  48. #include "llgl.h"
  49. FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
  50. LLFontManager *gFontManagerp = NULL;
  51. FT_Library gFTLibrary = NULL;
  52. //static
  53. void LLFontManager::initClass()
  54. {
  55. gFontManagerp = new LLFontManager;
  56. }
  57. //static
  58. void LLFontManager::cleanupClass()
  59. {
  60. delete gFontManagerp;
  61. gFontManagerp = NULL;
  62. }
  63. LLFontManager::LLFontManager()
  64. {
  65. int error;
  66. error = FT_Init_FreeType(&gFTLibrary);
  67. if (error)
  68. {
  69. // Clean up freetype libs.
  70. llerrs << "Freetype initialization failure!" << llendl;
  71. FT_Done_FreeType(gFTLibrary);
  72. }
  73. }
  74. LLFontManager::~LLFontManager()
  75. {
  76. FT_Done_FreeType(gFTLibrary);
  77. }
  78. LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
  79. : mGlyphIndex(index),
  80. mWidth(0), // In pixels
  81. mHeight(0), // In pixels
  82. mXAdvance(0.f), // In pixels
  83. mYAdvance(0.f), // In pixels
  84. mXBitmapOffset(0),  // Offset to the origin in the bitmap
  85. mYBitmapOffset(0),  // Offset to the origin in the bitmap
  86. mXBearing(0), // Distance from baseline to left in pixels
  87. mYBearing(0), // Distance from baseline to top in pixels
  88. mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph
  89. {
  90. }
  91. LLFontFreetype::LLFontFreetype()
  92. : mFontBitmapCachep(new LLFontBitmapCache),
  93. mValid(FALSE),
  94. mAscender(0.f),
  95. mDescender(0.f),
  96. mLineHeight(0.f),
  97. mIsFallback(FALSE),
  98. mFTFace(NULL),
  99. mRenderGlyphCount(0),
  100. mAddGlyphCount(0),
  101. mStyle(0),
  102. mPointSize(0)
  103. {
  104. }
  105. LLFontFreetype::~LLFontFreetype()
  106. {
  107. // Clean up freetype libs.
  108. if (mFTFace)
  109. FT_Done_Face(mFTFace);
  110. mFTFace = NULL;
  111. // Delete glyph info
  112. std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
  113. // mFontBitmapCachep will be cleaned up by LLPointer destructor.
  114. // mFallbackFonts cleaned up by LLPointer destructor
  115. }
  116. BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
  117. {
  118. // Don't leak face objects.  This is also needed to deal with
  119. // changed font file names.
  120. if (mFTFace)
  121. {
  122. FT_Done_Face(mFTFace);
  123. mFTFace = NULL;
  124. }
  125. int error;
  126. error = FT_New_Face( gFTLibrary,
  127.  filename.c_str(),
  128.  0,
  129.  &mFTFace );
  130.     if (error)
  131. {
  132. return FALSE;
  133. }
  134. mIsFallback = is_fallback;
  135. F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
  136. error = FT_Set_Char_Size(mFTFace,    /* handle to face object           */
  137. 0,       /* char_width in 1/64th of points  */
  138. (S32)(point_size*64),   /* char_height in 1/64th of points */
  139. (U32)horz_dpi,     /* horizontal device resolution    */
  140. (U32)vert_dpi);   /* vertical device resolution      */
  141. if (error)
  142. {
  143. // Clean up freetype libs.
  144. FT_Done_Face(mFTFace);
  145. mFTFace = NULL;
  146. return FALSE;
  147. }
  148. F32 y_max, y_min, x_max, x_min;
  149. F32 ems_per_unit = 1.f/ mFTFace->units_per_EM;
  150. F32 pixels_per_unit = pixels_per_em * ems_per_unit;
  151. // Get size of bbox in pixels
  152. y_max = mFTFace->bbox.yMax * pixels_per_unit;
  153. y_min = mFTFace->bbox.yMin * pixels_per_unit;
  154. x_max = mFTFace->bbox.xMax * pixels_per_unit;
  155. x_min = mFTFace->bbox.xMin * pixels_per_unit;
  156. mAscender = mFTFace->ascender * pixels_per_unit;
  157. mDescender = -mFTFace->descender * pixels_per_unit;
  158. mLineHeight = mFTFace->height * pixels_per_unit;
  159. S32 max_char_width = llround(0.5f + (x_max - x_min));
  160. S32 max_char_height = llround(0.5f + (y_max - y_min));
  161. mFontBitmapCachep->init(components, max_char_width, max_char_height);
  162. if (!mFTFace->charmap)
  163. {
  164. //llinfos << " no unicode encoding, set whatever encoding there is..." << llendl;
  165. FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]);
  166. }
  167. if (!mIsFallback)
  168. {
  169. // Add the default glyph
  170. addGlyphFromFont(this, 0, 0);
  171. }
  172. mName = filename;
  173. mPointSize = point_size;
  174. mStyle = LLFontGL::NORMAL;
  175. if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
  176. {
  177. mStyle |= LLFontGL::BOLD;
  178. mStyle &= ~LLFontGL::NORMAL;
  179. }
  180. if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
  181. {
  182. mStyle |= LLFontGL::ITALIC;
  183. mStyle &= ~LLFontGL::NORMAL;
  184. }
  185. return TRUE;
  186. }
  187. void LLFontFreetype::setFallbackFonts(const font_vector_t &font)
  188. {
  189. mFallbackFonts = font;
  190. }
  191. const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const
  192. {
  193. return mFallbackFonts;
  194. }
  195. F32 LLFontFreetype::getLineHeight() const
  196. {
  197. return mLineHeight;
  198. }
  199. F32 LLFontFreetype::getAscenderHeight() const
  200. {
  201. return mAscender;
  202. }
  203. F32 LLFontFreetype::getDescenderHeight() const
  204. {
  205. return mDescender;
  206. }
  207. F32 LLFontFreetype::getXAdvance(llwchar wch) const
  208. {
  209. if (mFTFace == NULL)
  210. return 0.0;
  211. // Return existing info only if it is current
  212. LLFontGlyphInfo* gi = getGlyphInfo(wch);
  213. if (gi)
  214. {
  215. return gi->mXAdvance;
  216. }
  217. else
  218. {
  219. gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL);
  220. if (gi)
  221. {
  222. return gi->mXAdvance;
  223. }
  224. }
  225. // Last ditch fallback - no glyphs defined at all.
  226. return (F32)mFontBitmapCachep->getMaxCharWidth();
  227. }
  228. F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
  229. {
  230. if (mFTFace == NULL)
  231. return 0.0;
  232. return glyph->mXAdvance;
  233. }
  234. F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
  235. {
  236. if (mFTFace == NULL)
  237. return 0.0;
  238. //llassert(!mIsFallback);
  239. LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
  240. U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
  241. // Kern this puppy.
  242. LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
  243. U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
  244. FT_Vector  delta;
  245. llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
  246. return delta.x*(1.f/64.f);
  247. }
  248. F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
  249. {
  250. if (mFTFace == NULL)
  251. return 0.0;
  252. U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
  253. U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
  254. FT_Vector  delta;
  255. llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
  256. return delta.x*(1.f/64.f);
  257. }
  258. BOOL LLFontFreetype::hasGlyph(llwchar wch) const
  259. {
  260. llassert(!mIsFallback);
  261. return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
  262. }
  263. LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
  264. {
  265. if (mFTFace == NULL)
  266. return FALSE;
  267. llassert(!mIsFallback);
  268. //lldebugs << "Adding new glyph for " << wch << " to font" << llendl;
  269. FT_UInt glyph_index;
  270. // Initialize char to glyph map
  271. glyph_index = FT_Get_Char_Index(mFTFace, wch);
  272. if (glyph_index == 0)
  273. {
  274. //llinfos << "Trying to add glyph from fallback font!" << llendl;
  275. font_vector_t::const_iterator iter;
  276. for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++)
  277. {
  278. glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
  279. if (glyph_index)
  280. {
  281. return addGlyphFromFont(*iter, wch, glyph_index);
  282. }
  283. }
  284. }
  285. char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
  286. if (iter == mCharGlyphInfoMap.end())
  287. {
  288. return addGlyphFromFont(this, wch, glyph_index);
  289. }
  290. return NULL;
  291. }
  292. LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
  293. {
  294. if (mFTFace == NULL)
  295. return NULL;
  296. llassert(!mIsFallback);
  297. fontp->renderGlyph(glyph_index);
  298. S32 width = fontp->mFTFace->glyph->bitmap.width;
  299. S32 height = fontp->mFTFace->glyph->bitmap.rows;
  300. S32 pos_x, pos_y;
  301. S32 bitmap_num;
  302. mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num);
  303. mAddGlyphCount++;
  304. LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index);
  305. gi->mXBitmapOffset = pos_x;
  306. gi->mYBitmapOffset = pos_y;
  307. gi->mBitmapNum = bitmap_num;
  308. gi->mWidth = width;
  309. gi->mHeight = height;
  310. gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
  311. gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
  312. // Convert these from 26.6 units to float pixels.
  313. gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
  314. gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
  315. insertGlyphInfo(wch, gi);
  316. llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
  317.     || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
  318. if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
  319.     || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
  320. {
  321. U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;
  322. S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch;
  323. U8 *tmp_graydata = NULL;
  324. if (fontp->mFTFace->glyph->bitmap.pixel_mode
  325.     == FT_PIXEL_MODE_MONO)
  326. {
  327. // need to expand 1-bit bitmap to 8-bit graymap.
  328. tmp_graydata = new U8[width * height];
  329. S32 xpos, ypos;
  330. for (ypos = 0; ypos < height; ++ypos)
  331. {
  332. S32 bm_row_offset = buffer_row_stride * ypos;
  333. for (xpos = 0; xpos < width; ++xpos)
  334. {
  335. U32 bm_col_offsetbyte = xpos / 8;
  336. U32 bm_col_offsetbit = 7 - (xpos % 8);
  337. U32 bit =
  338. !!(buffer_data[bm_row_offset
  339.        + bm_col_offsetbyte
  340.    ] & (1 << bm_col_offsetbit) );
  341. tmp_graydata[width*ypos + xpos] =
  342. 255 * bit;
  343. }
  344. }
  345. // use newly-built graymap.
  346. buffer_data = tmp_graydata;
  347. buffer_row_stride = width;
  348. }
  349. switch (mFontBitmapCachep->getNumComponents())
  350. {
  351. case 1:
  352. mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x,
  353. pos_y,
  354. width,
  355. height,
  356. buffer_data,
  357. buffer_row_stride,
  358. TRUE);
  359. break;
  360. case 2:
  361. setSubImageLuminanceAlpha(pos_x,
  362.   pos_y,
  363.   bitmap_num,
  364.   width,
  365.   height,
  366.   buffer_data,
  367.   buffer_row_stride);
  368. break;
  369. default:
  370. break;
  371. }
  372. if (tmp_graydata)
  373. delete[] tmp_graydata;
  374. } else {
  375. // we don't know how to handle this pixel format from FreeType;
  376. // omit it from the font-image.
  377. }
  378. LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
  379. LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
  380. image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
  381. return gi;
  382. }
  383. LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
  384. {
  385. char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
  386. if (iter != mCharGlyphInfoMap.end())
  387. {
  388. return iter->second;
  389. }
  390. else
  391. {
  392. // this glyph doesn't yet exist, so render it and return the result
  393. return addGlyph(wch);
  394. }
  395. }
  396. void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
  397. {
  398. char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
  399. if (iter != mCharGlyphInfoMap.end())
  400. {
  401. delete iter->second;
  402. iter->second = gi;
  403. }
  404. else
  405. {
  406. mCharGlyphInfoMap[wch] = gi;
  407. }
  408. }
  409. void LLFontFreetype::renderGlyph(U32 glyph_index) const
  410. {
  411. if (mFTFace == NULL)
  412. return;
  413. int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT );
  414. llassert(!error);
  415. error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode);
  416. mRenderGlyphCount++;
  417. llassert(!error);
  418. }
  419. void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
  420. {
  421. resetBitmapCache(); 
  422. loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
  423. if (!mIsFallback)
  424. {
  425. // This is the head of the list - need to rebuild ourself and all fallbacks.
  426. if (mFallbackFonts.empty())
  427. {
  428. llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
  429. }
  430. else
  431. {
  432. for(font_vector_t::iterator it = mFallbackFonts.begin();
  433. it != mFallbackFonts.end();
  434. ++it)
  435. {
  436. (*it)->reset(vert_dpi, horz_dpi);
  437. }
  438. }
  439. }
  440. }
  441. void LLFontFreetype::resetBitmapCache()
  442. {
  443. for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
  444. mCharGlyphInfoMap.clear();
  445. mFontBitmapCachep->reset();
  446. // Adding default glyph is skipped for fallback fonts here as well as in loadFace(). 
  447. // This if was added as fix for EXT-4971.
  448. if(!mIsFallback)
  449. {
  450. // Add the empty glyph
  451. addGlyphFromFont(this, 0, 0);
  452. }
  453. }
  454. void LLFontFreetype::destroyGL()
  455. {
  456. mFontBitmapCachep->destroyGL();
  457. }
  458. const std::string &LLFontFreetype::getName() const
  459. {
  460. return mName;
  461. }
  462. const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const
  463. {
  464. return mFontBitmapCachep;
  465. }
  466. void LLFontFreetype::setStyle(U8 style)
  467. {
  468. mStyle = style;
  469. }
  470. U8 LLFontFreetype::getStyle() const
  471. {
  472. return mStyle;
  473. }
  474. void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
  475. {
  476. LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
  477. llassert(!mIsFallback);
  478. llassert(image_raw && (image_raw->getComponents() == 2));
  479. U8 *target = image_raw->getData();
  480. if (!data)
  481. {
  482. return;
  483. }
  484. if (0 == stride)
  485. stride = width;
  486. U32 i, j;
  487. U32 to_offset;
  488. U32 from_offset;
  489. U32 target_width = image_raw->getWidth();
  490. for (i = 0; i < height; i++)
  491. {
  492. to_offset = (y + i)*target_width + x;
  493. from_offset = (height - 1 - i)*stride;
  494. for (j = 0; j < width; j++)
  495. {
  496. *(target + to_offset*2 + 1) = *(data + from_offset);
  497. to_offset++;
  498. from_offset++;
  499. }
  500. }
  501. }