PageRenderTime 118ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/System/Text/OSGTextWIN32Backend.cpp

https://github.com/danguilliams/OpenSGDevMaster_Toolbox
C++ | 1329 lines | 770 code | 198 blank | 361 comment | 133 complexity | 8309e3ca5878ae94d476de38df0b861d MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause
  1. /*---------------------------------------------------------------------------*\
  2. * OpenSG *
  3. * *
  4. * *
  5. * Copyright (C) 2000-2002 by the OpenSG Forum *
  6. * *
  7. * www.opensg.org *
  8. * *
  9. * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
  10. * *
  11. \*---------------------------------------------------------------------------*/
  12. /*---------------------------------------------------------------------------*\
  13. * License *
  14. * *
  15. * This library is free software; you can redistribute it and/or modify it *
  16. * under the terms of the GNU Library General Public License as published *
  17. * by the Free Software Foundation, version 2. *
  18. * *
  19. * This library is distributed in the hope that it will be useful, but *
  20. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  22. * Library General Public License for more details. *
  23. * *
  24. * You should have received a copy of the GNU Library General Public *
  25. * License along with this library; if not, write to the Free Software *
  26. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
  27. * *
  28. \*---------------------------------------------------------------------------*/
  29. /*---------------------------------------------------------------------------*\
  30. * Changes *
  31. * *
  32. * *
  33. * *
  34. * *
  35. * *
  36. * *
  37. \*---------------------------------------------------------------------------*/
  38. #include "OSGTextWIN32Backend.h"
  39. #include "OSGBaseTypes.h"
  40. #ifdef _WIN32
  41. #ifdef _MSC_VER
  42. # pragma warning (disable: 4786)
  43. #endif
  44. #include "OSGTextPixmapFace.h"
  45. #include "OSGTextPixmapGlyph.h"
  46. #include "OSGTextVectorFace.h"
  47. #include "OSGTextVectorGlyph.h"
  48. #include "OSGTextTXFFace.h"
  49. #include "OSGTextTXFGlyph.h"
  50. #include "OSGTextLayoutParam.h"
  51. #include "OSGTextLayoutResult.h"
  52. #include <iostream>
  53. #include <algorithm>
  54. #include <set>
  55. using namespace std;
  56. OSG_BEGIN_NAMESPACE
  57. //----------------------------------------------------------------------
  58. // WIN32 specific implementation of the TextVectorFace class
  59. // Author: pdaehne
  60. //----------------------------------------------------------------------
  61. class TextWIN32VectorFace: public TextVectorFace
  62. {
  63. public:
  64. // Constructor
  65. TextWIN32VectorFace(TextWIN32Backend *backend, HFONT hHoriFont, HFONT hVertFont);
  66. // Destructor
  67. virtual ~TextWIN32VectorFace();
  68. // Lays out one line of text
  69. virtual void layout(const wstring &text, const TextLayoutParam &param,
  70. TextLayoutResult &layoutResult);
  71. protected:
  72. // Creates a new Glyph object
  73. virtual auto_ptr<TextVectorGlyph> createGlyph(TextGlyph::Index glyphIndex);
  74. private:
  75. // The backend that created the face
  76. TextWIN32Backend *_backend;
  77. // Font handle for horizontal layout
  78. HFONT _hHoriFont;
  79. // Font handle for vertical layout
  80. HFONT _hVertFont;
  81. };
  82. //----------------------------------------------------------------------
  83. // WIN32 specific implementation of the TextVectorGlyph class
  84. // Author: pdaehne
  85. //----------------------------------------------------------------------
  86. class TextWIN32VectorGlyph: public TextVectorGlyph
  87. {
  88. public:
  89. // Constructor
  90. TextWIN32VectorGlyph(Index glyphIndex, Real32 scale,
  91. const GLYPHMETRICS &hpgm, const GLYPHMETRICS &vhpgm,
  92. LPTTPOLYGONHEADER lpHeader, DWORD size);
  93. // Destructor
  94. virtual ~TextWIN32VectorGlyph();
  95. };
  96. //----------------------------------------------------------------------
  97. // WIN32 specific implementation of the TextPixmapFace class
  98. // Author: pdaehne
  99. //----------------------------------------------------------------------
  100. class TextWIN32PixmapFace: public TextPixmapFace
  101. {
  102. public:
  103. // Constructor
  104. TextWIN32PixmapFace(TextWIN32Backend *backend, HFONT hHoriFont, HFONT hVertFont, UInt32 size);
  105. // Destructor
  106. virtual ~TextWIN32PixmapFace();
  107. // Lays out one line of text
  108. virtual void layout(const wstring &text, const TextLayoutParam &param,
  109. TextLayoutResult &layoutResult);
  110. protected:
  111. // Creates a new Glyph object
  112. virtual auto_ptr<TextPixmapGlyph> createGlyph(TextGlyph::Index glyphIndex);
  113. private:
  114. // The backend that created the face
  115. TextWIN32Backend *_backend;
  116. // Font handle for horizontal layout
  117. HFONT _hHoriFont;
  118. // Font handle for vertical layout
  119. HFONT _hVertFont;
  120. };
  121. //----------------------------------------------------------------------
  122. // WIN32 specific implementation of the TextPixmapGlyph class
  123. // Author: pdaehne
  124. //----------------------------------------------------------------------
  125. class TextWIN32PixmapGlyph: public TextPixmapGlyph
  126. {
  127. public:
  128. // Constructor
  129. TextWIN32PixmapGlyph(Index glyphIndex, const GLYPHMETRICS &hpgm,
  130. const GLYPHMETRICS &vpgm, UInt8 *pixmap);
  131. // Destructor
  132. virtual ~TextWIN32PixmapGlyph();
  133. };
  134. //----------------------------------------------------------------------
  135. // WIN32 specific implementation of the TextTXFFace class
  136. // Author: pdaehne
  137. //----------------------------------------------------------------------
  138. class TextWIN32TXFFace: public TextTXFFace
  139. {
  140. public:
  141. // Constructor
  142. TextWIN32TXFFace(const TextWIN32Backend *backend, HFONT hHoriFont, HFONT hVertFont,
  143. const TextTXFParam &param);
  144. // Destructor
  145. virtual ~TextWIN32TXFFace();
  146. };
  147. //----------------------------------------------------------------------
  148. // WIN32 specific implementation of the TextTXFGlyph class
  149. // Author: pdaehne
  150. //----------------------------------------------------------------------
  151. class TextWIN32TXFGlyph: public TextTXFGlyph
  152. {
  153. public:
  154. // Constructor
  155. TextWIN32TXFGlyph(Index glyphIndex, TextWIN32TXFFace *face, Real32 scale,
  156. const GLYPHMETRICS &hpgm, const GLYPHMETRICS &vpgm);
  157. // Destructor
  158. virtual ~TextWIN32TXFGlyph();
  159. };
  160. //----------------------------------------------------------------------
  161. // Constructor
  162. // Author: pdaehne
  163. //----------------------------------------------------------------------
  164. TextWIN32Backend::TextWIN32Backend()
  165. : TextBackend(), _hDC(0)
  166. {
  167. // Create device context
  168. _hDC = CreateDC("DISPLAY", 0, 0, 0);
  169. if (_hDC == 0)
  170. // There is not much we can do here...
  171. return;
  172. SetGraphicsMode(_hDC, GM_ADVANCED);
  173. }
  174. //----------------------------------------------------------------------
  175. // Destructor
  176. // Author: pdaehne
  177. //----------------------------------------------------------------------
  178. TextWIN32Backend::~TextWIN32Backend()
  179. {
  180. // Destroy device context
  181. DeleteDC(_hDC);
  182. }
  183. //----------------------------------------------------------------------
  184. // Helper struct used by enumFamCallBack
  185. // Author: pdaehne
  186. //----------------------------------------------------------------------
  187. class EnumData
  188. {
  189. public:
  190. string fullname;
  191. UINT emSize;
  192. };
  193. //----------------------------------------------------------------------
  194. // Callback that gets called by Windows to enumerate fonts
  195. // Author: pdaehne
  196. //----------------------------------------------------------------------
  197. static int CALLBACK enumFamCallBack(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *lpntm,
  198. DWORD fontType, LPARAM lParam)
  199. {
  200. // We are not interested in raster fonts
  201. if ((fontType & RASTER_FONTTYPE) != 0)
  202. return 1;
  203. // Fill enumData structure
  204. EnumData *enumData = reinterpret_cast<EnumData*>(lParam);
  205. enumData->fullname = (const char *)lpelf->elfFullName;
  206. enumData->emSize = lpntm->ntmSizeEM;
  207. // Quit enumeration
  208. return 0;
  209. }
  210. //----------------------------------------------------------------------
  211. // Creates horizontal and vertical fonts from given fontname,
  212. // size and style
  213. // Author: pdaehne
  214. //----------------------------------------------------------------------
  215. void TextWIN32Backend::createFonts(const string &family, UInt32 size, TextFace::Style style,
  216. HFONT &hHoriFont, HFONT &hVertFont)
  217. {
  218. // Initialization
  219. hHoriFont = hVertFont = 0;
  220. // Handle generic family names
  221. string f;
  222. if (family == "SERIF")
  223. f = "Times New Roman";
  224. else if (family == "SANS")
  225. f = "Arial";
  226. else if (family == "TYPEWRITER")
  227. f = "Courier New";
  228. else
  229. f = family;
  230. if (size == 0)
  231. {
  232. // Grrr - this is only necessary to get the EM size -pdaehne
  233. EnumData enumData;
  234. EnumFontFamilies(_hDC, (LPCTSTR)(f.c_str()), (FONTENUMPROC)enumFamCallBack,
  235. (LPARAM)&enumData);
  236. if (enumData.fullname.empty() == true)
  237. return;
  238. size = -enumData.emSize;
  239. }
  240. // Handle style
  241. BYTE italic;
  242. LONG weight;
  243. switch (style)
  244. {
  245. default:
  246. FWARNING(("Invalid font style parameter.\n"));
  247. // intentionally fall through
  248. case TextFace::STYLE_PLAIN:
  249. italic = FALSE;
  250. weight = FW_NORMAL;
  251. break;
  252. case TextFace::STYLE_BOLD:
  253. italic = FALSE;
  254. weight = FW_BOLD;
  255. break;
  256. case TextFace::STYLE_ITALIC:
  257. italic = TRUE;
  258. weight = FW_NORMAL;
  259. break;
  260. case TextFace::STYLE_BOLDITALIC:
  261. italic = TRUE;
  262. weight = FW_BOLD;
  263. break;
  264. }
  265. // Create the the horizontal font
  266. hHoriFont = CreateFont(size, 0, 0, 0, weight, italic, FALSE, FALSE,
  267. DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS,
  268. ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
  269. f.c_str());
  270. // Create the the vertical font
  271. hVertFont = CreateFont(size, 0, -900, 0, weight, italic, FALSE, FALSE,
  272. DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS,
  273. ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
  274. f.c_str());
  275. }
  276. //----------------------------------------------------------------------
  277. // Creates a new vector face
  278. // Author: pdaehne
  279. //----------------------------------------------------------------------
  280. TextVectorFaceTransitPtr TextWIN32Backend::createVectorFace(
  281. const string &family, TextFace::Style style)
  282. {
  283. TextVectorFaceTransitPtr retVal;
  284. // Try to create the font handles
  285. HFONT hHoriFont, hVertFont;
  286. createFonts(family, 0, style, hHoriFont, hVertFont);
  287. if (hHoriFont != 0)
  288. {
  289. // Create the new face object
  290. retVal = new TextWIN32VectorFace(this, hHoriFont, hVertFont);
  291. }
  292. return retVal;
  293. }
  294. //----------------------------------------------------------------------
  295. // Creates a new pixmap face
  296. // Author: pdaehne
  297. //----------------------------------------------------------------------
  298. TextPixmapFaceTransitPtr TextWIN32Backend::createPixmapFace(
  299. const string &family, TextFace::Style style, UInt32 size)
  300. {
  301. TextPixmapFaceTransitPtr retVal;
  302. // Try to create the font handles
  303. HFONT hHoriFont, hVertFont;
  304. createFonts(family, size, style, hHoriFont, hVertFont);
  305. if (hHoriFont != 0)
  306. {
  307. // Create the new face object
  308. retVal = new TextWIN32PixmapFace(this, hHoriFont, hVertFont, size);
  309. }
  310. return retVal;
  311. }
  312. //----------------------------------------------------------------------
  313. // Creates a new TXF face
  314. // Author: pdaehne
  315. //----------------------------------------------------------------------
  316. TextTXFFaceTransitPtr TextWIN32Backend::createTXFFace(
  317. const string &family, TextFace::Style style, const TextTXFParam &param)
  318. {
  319. TextTXFFaceTransitPtr retVal;
  320. // Try to create the font handles
  321. HFONT hHoriFont, hVertFont;
  322. createFonts(family, param.size, style, hHoriFont, hVertFont);
  323. if (hHoriFont != 0)
  324. {
  325. // Create the new face object
  326. retVal = new TextWIN32TXFFace(this, hHoriFont, hVertFont, param);
  327. }
  328. return retVal;
  329. }
  330. //----------------------------------------------------------------------
  331. // Callback that gets called by Windows to enumerate fonts
  332. // Author: pdaehne
  333. //----------------------------------------------------------------------
  334. static int CALLBACK enumFamCallBack2(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *lpntm,
  335. DWORD fontType, LPARAM lParam)
  336. {
  337. // We are not interested in raster fonts
  338. if ((fontType & RASTER_FONTTYPE) != 0)
  339. return 1;
  340. // Fill enumData structure
  341. set<string> *familySet = reinterpret_cast<set<string>*>(lParam);
  342. familySet->insert(lpelf->elfLogFont.lfFaceName);
  343. // Continue enumeration
  344. return 1;
  345. }
  346. //----------------------------------------------------------------------
  347. // Returns the names of all font families available
  348. // Author: pdaehne
  349. //----------------------------------------------------------------------
  350. void TextWIN32Backend::getFontFamilies(vector<string> &families)
  351. {
  352. families.clear();
  353. set<string> familySet;
  354. EnumFontFamilies(_hDC, 0, (FONTENUMPROC)enumFamCallBack2, (LPARAM)&familySet);
  355. // GRRRR, this does not work on WIN32...
  356. //families.assign(familySet.begin(), familySet.end());
  357. families.resize(familySet.size());
  358. copy(familySet.begin(), familySet.end(), families.begin());
  359. }
  360. //----------------------------------------------------------------------
  361. // Returns information about a given font
  362. // Author: pdaehne
  363. //----------------------------------------------------------------------
  364. static void getFontInfo(HDC hDC, HFONT hFont, string &family,
  365. TextFace::Style &style, Real32 &ascent, Real32 &descent)
  366. {
  367. // Select the font into the device context
  368. HGDIOBJ oldFont = SelectObject(hDC, hFont);
  369. // Get the name of the font
  370. int nameLength = GetTextFace(hDC, 0, 0);
  371. family.resize(nameLength);
  372. GetTextFace(hDC, nameLength, &(family[0]));
  373. // GetTextFace also puts a trailing '\0' into the string, so we have to remove it
  374. family.resize(nameLength - 1);
  375. // Get metrics of the font
  376. TEXTMETRIC tm;
  377. BOOL result = GetTextMetrics(hDC, &tm);
  378. SelectObject(hDC, oldFont);
  379. if (result == FALSE)
  380. return;
  381. // Determine the style
  382. if (tm.tmWeight > (FW_NORMAL + FW_BOLD) / 2)
  383. style = tm.tmItalic != 0 ? TextFace::STYLE_BOLDITALIC : TextFace::STYLE_BOLD;
  384. else
  385. style = tm.tmItalic != 0 ? TextFace::STYLE_ITALIC : TextFace::STYLE_PLAIN;
  386. // Determine ascent
  387. ascent = static_cast<Real32>(tm.tmAscent);
  388. // Determine descent
  389. descent = static_cast<Real32>(-tm.tmDescent);
  390. }
  391. //----------------------------------------------------------------------
  392. // Constructor
  393. // Author: pdaehne
  394. //----------------------------------------------------------------------
  395. TextWIN32VectorFace::TextWIN32VectorFace(TextWIN32Backend *backend,
  396. HFONT hHoriFont, HFONT hVertFont)
  397. : TextVectorFace(), _backend(backend), _hHoriFont(hHoriFont), _hVertFont(hVertFont)
  398. {
  399. // Get information about the font
  400. getFontInfo(_backend->_hDC, _hHoriFont, _family, _style,
  401. _horiAscent, _horiDescent);
  402. // Determine the scale factor and adjust ascent and descent
  403. _scale = 1.f / (_horiAscent - _horiDescent);
  404. _horiAscent *= _scale;
  405. _horiDescent *= _scale;
  406. // Determine vertical ascent and descent
  407. _vertAscent = -0.5f;
  408. _vertDescent = 0.5f;
  409. }
  410. //----------------------------------------------------------------------
  411. // Destructor
  412. // Author: pdaehne
  413. //----------------------------------------------------------------------
  414. TextWIN32VectorFace::~TextWIN32VectorFace()
  415. {
  416. // Destroy the font objects
  417. DeleteObject(_hHoriFont);
  418. DeleteObject(_hVertFont);
  419. }
  420. //----------------------------------------------------------------------
  421. // Converts a unicode string to utf16
  422. // RFC2781: UTF-16, an encoding of ISO 10646
  423. // Author: pdaehne
  424. //----------------------------------------------------------------------
  425. static void convertUnicodeToUTF16(const wstring &text, vector<WCHAR> &utf16Text)
  426. {
  427. wstring::size_type i, textTotalLength = text.length();
  428. utf16Text.clear();
  429. utf16Text.reserve(textTotalLength);
  430. for (i = 0; i < textTotalLength; ++i)
  431. {
  432. wchar_t unicode = text[i];
  433. if (unicode < 0x10000)
  434. utf16Text.push_back(unicode);
  435. else if (unicode < 0x110000)
  436. {
  437. unsigned long u = unicode - 0x10000;
  438. utf16Text.push_back(0xd800 | (u >> 10));
  439. utf16Text.push_back(0xdc00 | (u & 0x3ff));
  440. }
  441. }
  442. }
  443. //----------------------------------------------------------------------
  444. // Lays out one line of text
  445. // Author: pdaehne
  446. //----------------------------------------------------------------------
  447. void TextWIN32VectorFace::layout(const wstring &text, const TextLayoutParam &param,
  448. TextLayoutResult &layoutResult)
  449. {
  450. // Initialize return values
  451. layoutResult.clear();
  452. if (param.horizontal == true)
  453. layoutResult.textBounds[1] = _horiAscent - _horiDescent;
  454. else
  455. layoutResult.textBounds[0] = _vertDescent - _vertAscent;
  456. layoutResult.lineBounds.push_back(layoutResult.textBounds);
  457. // Convert the unicode string to utf16
  458. vector<WCHAR> utf16Text;
  459. convertUnicodeToUTF16(text, utf16Text);
  460. vector<WCHAR>::size_type len = utf16Text.size();
  461. if (len == 0)
  462. return;
  463. // Select the font into the device context
  464. HGDIOBJ oldFont;
  465. if (param.horizontal == true)
  466. oldFont = SelectObject(_backend->_hDC, _hHoriFont);
  467. else
  468. oldFont = SelectObject(_backend->_hDC, _hVertFont);
  469. GCP_RESULTSW results;
  470. ZeroMemory(&results, sizeof(results));
  471. results.lStructSize = sizeof(results);
  472. results.lpDx = new int[len];
  473. results.lpGlyphs = new WCHAR[len];
  474. results.lpGlyphs[0] = 0; // needed by GCP_LIGATE
  475. results.nGlyphs = len;
  476. DWORD dwFlags = GCP_GLYPHSHAPE | GCP_LIGATE | GCP_REORDER | GCP_USEKERNING;
  477. int nMaxExtent = 0;
  478. Real32 length = param.getLength(0);
  479. if (length > 0)
  480. {
  481. dwFlags |= GCP_JUSTIFY | GCP_KASHIDA | GCP_MAXEXTENT;
  482. nMaxExtent = length / _scale;
  483. }
  484. DWORD result = GetCharacterPlacementW(_backend->_hDC, &(utf16Text[0]), len, nMaxExtent, &results, dwFlags);
  485. if (result != 0)
  486. {
  487. layoutResult.indices.reserve(results.nGlyphs);
  488. layoutResult.positions.reserve(results.nGlyphs);
  489. UINT j;
  490. Vec2f currPos;
  491. for (j = 0; j < results.nGlyphs; ++j)
  492. {
  493. // Get glyph
  494. const TextGlyph &glyph = getGlyph(results.lpGlyphs[j]);
  495. // Calculate position
  496. Vec2f pos;
  497. if (param.horizontal == true)
  498. {
  499. pos = currPos;
  500. pos[0] += glyph.getHoriBearingX();
  501. pos[1] += glyph.getHoriBearingY();
  502. currPos[0] += results.lpDx[j] * _scale;
  503. }
  504. else
  505. {
  506. pos = currPos;
  507. pos[0] += glyph.getVertBearingX();
  508. pos[1] += glyph.getVertBearingY();
  509. currPos[1] -= results.lpDx[j] * _scale;
  510. }
  511. layoutResult.indices.push_back(results.lpGlyphs[j]);
  512. layoutResult.positions.push_back(pos);
  513. }
  514. // Adjust the origin depending on the major and the minor alignment
  515. adjustLineOrigin(param, currPos, layoutResult);
  516. // Determine text bounds / line bounds
  517. if (param.horizontal == true)
  518. layoutResult.textBounds[0] = osgAbs(currPos.x());
  519. else
  520. layoutResult.textBounds[1] = osgAbs(currPos.y());
  521. assert(layoutResult.lineBounds.empty() == false);
  522. layoutResult.lineBounds.front() = layoutResult.textBounds;
  523. }
  524. delete [] results.lpDx;
  525. delete [] results.lpGlyphs;
  526. // Unselect the font
  527. SelectObject(_backend->_hDC, oldFont);
  528. }
  529. //----------------------------------------------------------------------
  530. // Creates a new Glyph object
  531. // Author: pdaehne
  532. //----------------------------------------------------------------------
  533. auto_ptr<TextVectorGlyph> TextWIN32VectorFace::createGlyph(TextGlyph::Index glyphIndex)
  534. {
  535. // We cannot create glyphs for invalid glyph indices
  536. if (glyphIndex == TextGlyph::INVALID_INDEX)
  537. return auto_ptr<TextVectorGlyph>();
  538. // Select the vertical font into the device context
  539. HGDIOBJ oldFont = SelectObject(_backend->_hDC, _hVertFont);
  540. // Get the vertical metrics
  541. GLYPHMETRICS vpgm;
  542. MAT2 mat2 = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
  543. DWORD size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_METRICS | GGO_GLYPH_INDEX,
  544. &vpgm, 0, 0, &mat2);
  545. if (size == GDI_ERROR)
  546. {
  547. SelectObject(_backend->_hDC, oldFont);
  548. return auto_ptr<TextVectorGlyph>();
  549. }
  550. // Select the horizontal font into the device context
  551. SelectObject(_backend->_hDC, _hHoriFont);
  552. // Get glyph outline
  553. GLYPHMETRICS hpgm;
  554. size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_NATIVE | GGO_GLYPH_INDEX, &hpgm, 0, 0, &mat2);
  555. if (size == GDI_ERROR)
  556. {
  557. SelectObject(_backend->_hDC, oldFont);
  558. return auto_ptr<TextVectorGlyph>();
  559. }
  560. LPTTPOLYGONHEADER lpHeader = (LPTTPOLYGONHEADER) new char[size];
  561. size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_NATIVE | GGO_GLYPH_INDEX, &hpgm, size, lpHeader, &mat2);
  562. // Unselect the font
  563. SelectObject(_backend->_hDC, oldFont);
  564. if (size == GDI_ERROR)
  565. {
  566. delete [] lpHeader;
  567. return auto_ptr<TextVectorGlyph>();
  568. }
  569. // Create and return the new glyph object
  570. auto_ptr<TextVectorGlyph> glyph(new TextWIN32VectorGlyph(glyphIndex, _scale,
  571. hpgm, vpgm, lpHeader, size));
  572. delete [] lpHeader;
  573. return glyph;
  574. }
  575. //----------------------------------------------------------------------
  576. // Constructor
  577. // Author: pdaehne
  578. //----------------------------------------------------------------------
  579. TextWIN32VectorGlyph::TextWIN32VectorGlyph(Index glyphIndex, Real32 scale,
  580. const GLYPHMETRICS &hpgm,
  581. const GLYPHMETRICS &vpgm,
  582. LPTTPOLYGONHEADER lpHeader,
  583. DWORD size)
  584. : TextVectorGlyph()
  585. {
  586. _glyphIndex = glyphIndex;
  587. _width = static_cast<Real32>(hpgm.gmBlackBoxX) * scale;
  588. _height = static_cast<Real32>(hpgm.gmBlackBoxY) * scale;
  589. // Determine horizontal glyph metrics
  590. _horiAdvance = static_cast<Real32>(hpgm.gmCellIncX) * scale;
  591. _horiBearingX = static_cast<Real32>(hpgm.gmptGlyphOrigin.x) * scale;
  592. _horiBearingY = static_cast<Real32>(hpgm.gmptGlyphOrigin.y) * scale;
  593. // Determine vertical glyph metrics
  594. // Hmmm, there is no useful information here for vertical layout -
  595. // the values provided are just the same as for horizontal layout.
  596. // So we have to guess resonable values -pdaehne
  597. //_vertAdvance = static_cast<Real32>(vpgm.gmCellIncY) * scale;
  598. //_vertBearingX = static_cast<Real32>(vpgm.gmptGlyphOrigin.x) * scale;
  599. //_vertBearingY = static_cast<Real32>(vpgm.gmptGlyphOrigin.y) * scale;
  600. _vertAdvance = -_height;
  601. _vertBearingX = -_width / 2.f;
  602. _vertBearingY = 0.f;
  603. Vec2f offset(_horiBearingX, _horiBearingY), p;
  604. // The following algorithm has been taken from MSDN article Q243285
  605. // "HOWTO: Draw TrueType Glyph Outlines" - pdaehne
  606. WORD i;
  607. LPTTPOLYGONHEADER lpStart; // the start of the buffer
  608. LPTTPOLYCURVE lpCurve; // the current curve of a contour
  609. POINTFX *endPoint = 0;
  610. lpStart = lpHeader;
  611. // Loop until we have processed the entire buffer of contours.
  612. // The buffer may contain one or more contours that begin with
  613. // a TTPOLYGONHEADER. We have them all when we the end of the buffer.
  614. while ((DWORD)lpHeader < (DWORD)(((LPSTR)lpStart) + size))
  615. {
  616. if (lpHeader->dwType == TT_POLYGON_TYPE)
  617. // Draw each coutour, currently this is the only valid
  618. // type of contour.
  619. {
  620. _outline.push_back(TextVectorGlyph::Contour());
  621. // Convert the starting point. It is an on curve point.
  622. // All other points are continuous from the "last"
  623. // point of the contour. Thus the start point the next
  624. // bezier is always pt[cTotal-1] - the last point of the
  625. // previous bezier. See PolyBezier.
  626. POINTFX &startPoint = lpHeader->pfxStart;
  627. p.setValues(startPoint.x.value, startPoint.y.value);
  628. p *= scale;
  629. p -= offset;
  630. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  631. // Get to first curve of contour -
  632. // it starts at the next byte beyond header
  633. lpCurve = (LPTTPOLYCURVE) (lpHeader + 1);
  634. // Walk this contour and process each curve (or line) segment
  635. // and add it to the Beziers
  636. while ((DWORD)lpCurve < (DWORD)(((LPSTR)lpHeader) + lpHeader->cb))
  637. {
  638. //**********************************************
  639. // Format assumption:
  640. // The bytes immediately preceding a POLYCURVE
  641. // structure contain a valid POINTFX.
  642. //
  643. // If this is first curve, this points to the
  644. // pfxStart of the POLYGONHEADER.
  645. // Otherwise, this points to the last point of
  646. // the previous POLYCURVE.
  647. //
  648. // In either case, this is representative of the
  649. // previous curve's last point.
  650. //**********************************************
  651. if (lpCurve->wType == TT_PRIM_LINE)
  652. {
  653. // All point are on the curve
  654. for (i = 0; i < lpCurve->cpfx; ++i)
  655. {
  656. p.setValues(lpCurve->apfx[i].x.value, lpCurve->apfx[i].y.value);
  657. p *= scale;
  658. p -= offset;
  659. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  660. }
  661. }
  662. else if (lpCurve->wType == TT_PRIM_QSPLINE)
  663. {
  664. // All points apart from the last point of off the curve quadratric
  665. // Bezier spline control points. The last point is on the curve.
  666. // Between two consecutive control points, we have to insert a point
  667. // that is on the curve. This point lies directly between the two control
  668. // points.
  669. short x1, x2, y1, y2;
  670. for (i = 0; i < lpCurve->cpfx; ++i)
  671. {
  672. x2 = lpCurve->apfx[i].x.value;
  673. y2 = lpCurve->apfx[i].y.value;
  674. if (i >= lpCurve->cpfx - 1)
  675. {
  676. p.setValues(x2, y2);
  677. p *= scale;
  678. p -= offset;
  679. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  680. break;
  681. }
  682. if (i > 0)
  683. {
  684. x1 = (x1 + x2) >> 1;
  685. y1 = (y1 + y2) >> 1;
  686. p.setValues(x1, y1);
  687. p *= scale;
  688. p -= offset;
  689. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  690. }
  691. p.setValues(x2, y2);
  692. p *= scale;
  693. p -= offset;
  694. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_QUAD));
  695. x1 = x2;
  696. y1 = y2;
  697. }
  698. }
  699. else if (lpCurve->wType == TT_PRIM_CSPLINE)
  700. {
  701. // TODO: Did not find any font until now that contains cubic
  702. // splines, so this code is untested -pdaehne
  703. for (i = 0; i < lpCurve->cpfx; ++i)
  704. {
  705. p.setValues(lpCurve->apfx[i].x.value, lpCurve->apfx[i].y.value);
  706. p *= scale;
  707. p -= offset;
  708. if (i >= lpCurve->cpfx - 1)
  709. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  710. else
  711. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_CUBIC));
  712. }
  713. }
  714. else
  715. // Oops! A POLYCURVE format we don't understand.
  716. ; // error, error, error
  717. // Keep the end point
  718. endPoint = &(lpCurve->apfx[lpCurve->cpfx - 1]);
  719. // Move on to next curve in the contour.
  720. lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[lpCurve->cpfx]);
  721. }
  722. // Check if the contour is valid, i.e. if it has more than two points.
  723. // When not, we simply delete the contour.
  724. if (_outline.back().size() < 3)
  725. _outline.erase(_outline.end() - 1);
  726. else
  727. // Add points to close the contour.
  728. // All contours are implied closed by TrueType definition.
  729. // Depending on the specific font and glyph being used, these
  730. // may not always be needed.
  731. if ((startPoint.x.value != endPoint->x.value) || (startPoint.y.value != endPoint->y.value))
  732. {
  733. p.setValues(startPoint.x.value, startPoint.y.value);
  734. p *= scale;
  735. p -= offset;
  736. _outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
  737. }
  738. }
  739. else
  740. // Bad, bail, must have a bogus buffer.
  741. break; // error, error, error
  742. // Move on to next Contour.
  743. // Its header starts immediate after this contour
  744. lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb);
  745. }
  746. }
  747. //----------------------------------------------------------------------
  748. // Destructor
  749. // Author: pdaehne
  750. //----------------------------------------------------------------------
  751. TextWIN32VectorGlyph::~TextWIN32VectorGlyph() {}
  752. //----------------------------------------------------------------------
  753. // Constructor
  754. // Author: pdaehne
  755. //----------------------------------------------------------------------
  756. TextWIN32PixmapFace::TextWIN32PixmapFace(TextWIN32Backend *backend, HFONT hHoriFont, HFONT hVertFont, UInt32 size)
  757. : TextPixmapFace(), _backend(backend), _hHoriFont(hHoriFont), _hVertFont(hVertFont)
  758. {
  759. // Get information about the font
  760. getFontInfo(_backend->_hDC, _hHoriFont, _family, _style,
  761. _horiAscent, _horiDescent);
  762. // Set the size
  763. _size = size;
  764. // Determine vertical ascent and descent
  765. _vertAscent = -static_cast<Real32>(_size) / 2.f;
  766. _vertDescent = static_cast<Real32>(_size) / 2.f;
  767. }
  768. //----------------------------------------------------------------------
  769. // Destructor
  770. // Author: pdaehne
  771. //----------------------------------------------------------------------
  772. TextWIN32PixmapFace::~TextWIN32PixmapFace()
  773. {
  774. // Destroy the font objects
  775. DeleteObject(_hHoriFont);
  776. DeleteObject(_hVertFont);
  777. }
  778. //----------------------------------------------------------------------
  779. // Lays out one line of text
  780. // Author: pdaehne
  781. //----------------------------------------------------------------------
  782. void TextWIN32PixmapFace::layout(const wstring &text, const TextLayoutParam &param,
  783. TextLayoutResult &layoutResult)
  784. {
  785. // Initialize return values
  786. layoutResult.clear();
  787. if (param.horizontal == true)
  788. layoutResult.textBounds[1] = _horiAscent - _horiDescent;
  789. else
  790. layoutResult.textBounds[0] = _vertDescent - _vertAscent;
  791. layoutResult.lineBounds.push_back(layoutResult.textBounds);
  792. // Convert the unicode string to utf16
  793. vector<WCHAR> utf16Text;
  794. convertUnicodeToUTF16(text, utf16Text);
  795. vector<WCHAR>::size_type len = utf16Text.size();
  796. if (len == 0)
  797. return;
  798. // Select the font into the device context
  799. HGDIOBJ oldFont;
  800. if (param.horizontal == true)
  801. oldFont = SelectObject(_backend->_hDC, _hHoriFont);
  802. else
  803. oldFont = SelectObject(_backend->_hDC, _hVertFont);
  804. GCP_RESULTSW results;
  805. ZeroMemory(&results, sizeof(results));
  806. results.lStructSize = sizeof(results);
  807. results.lpDx = new int[len];
  808. results.lpGlyphs = new WCHAR[len];
  809. results.lpGlyphs[0] = 0; // needed by GCP_LIGATE
  810. results.nGlyphs = len;
  811. DWORD dwFlags = GCP_GLYPHSHAPE | GCP_LIGATE | GCP_REORDER | GCP_USEKERNING;
  812. int nMaxExtent = 0;
  813. Real32 length = param.getLength(0);
  814. if (length > 0)
  815. {
  816. dwFlags |= GCP_JUSTIFY | GCP_KASHIDA | GCP_MAXEXTENT;
  817. nMaxExtent = length;
  818. }
  819. DWORD result = GetCharacterPlacementW(_backend->_hDC, &(utf16Text[0]), len, nMaxExtent, &results, dwFlags);
  820. if (result != 0)
  821. {
  822. layoutResult.indices.reserve(results.nGlyphs);
  823. layoutResult.positions.reserve(results.nGlyphs);
  824. UINT j;
  825. Vec2f currPos;
  826. for (j = 0; j < results.nGlyphs; ++j)
  827. {
  828. // Get glyph
  829. const TextGlyph &glyph = getGlyph(results.lpGlyphs[j]);
  830. // Calculate position
  831. Vec2f pos;
  832. if (param.horizontal == true)
  833. {
  834. pos[0] = currPos.x() + glyph.getHoriBearingX();
  835. pos[1] = currPos.y() + glyph.getHoriBearingY();
  836. currPos[0] += results.lpDx[j];
  837. }
  838. else
  839. {
  840. pos[0] = currPos.x() + glyph.getVertBearingX();
  841. pos[1] = currPos.y() + glyph.getVertBearingY();
  842. currPos[1] -= results.lpDx[j];
  843. }
  844. layoutResult.indices.push_back(results.lpGlyphs[j]);
  845. layoutResult.positions.push_back(pos);
  846. }
  847. // Adjust the origin depending on the major and the minor alignment
  848. adjustLineOrigin(param, currPos, layoutResult);
  849. // Determine text bounds / line bounds
  850. if (param.horizontal == true)
  851. layoutResult.textBounds[0] = osgAbs(currPos.x());
  852. else
  853. layoutResult.textBounds[1] = osgAbs(currPos.y());
  854. assert(layoutResult.lineBounds.empty() == false);
  855. layoutResult.lineBounds.front() = layoutResult.textBounds;
  856. }
  857. delete [] results.lpDx;
  858. delete [] results.lpGlyphs;
  859. // Unselect the font
  860. SelectObject(_backend->_hDC, oldFont);
  861. }
  862. //----------------------------------------------------------------------
  863. // Creates a new Glyph object
  864. // Author: pdaehne
  865. //----------------------------------------------------------------------
  866. auto_ptr<TextPixmapGlyph> TextWIN32PixmapFace::createGlyph(TextGlyph::Index glyphIndex)
  867. {
  868. // We cannot create glyphs for invalid glyph indices
  869. if (glyphIndex == TextGlyph::INVALID_INDEX)
  870. return auto_ptr<TextPixmapGlyph>();
  871. // Select the vertical font into the device context
  872. HGDIOBJ oldFont = SelectObject(_backend->_hDC, _hVertFont);
  873. // Get the vertical metrics
  874. GLYPHMETRICS vpgm;
  875. MAT2 mat2 = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
  876. DWORD size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_METRICS | GGO_GLYPH_INDEX,
  877. &vpgm, 0, 0, &mat2);
  878. if (size == GDI_ERROR)
  879. {
  880. SelectObject(_backend->_hDC, oldFont);
  881. return auto_ptr<TextPixmapGlyph>();
  882. }
  883. // Select the horizontal font into the device context
  884. SelectObject(_backend->_hDC, _hHoriFont);
  885. GLYPHMETRICS hpgm;
  886. size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
  887. &hpgm, 0, 0, &mat2);
  888. if (size == GDI_ERROR)
  889. {
  890. SelectObject(_backend->_hDC, oldFont);
  891. return auto_ptr<TextPixmapGlyph>();
  892. }
  893. UInt8 *buffer;
  894. if (size == 0)
  895. buffer = 0;
  896. else
  897. {
  898. // Get the pixmap
  899. buffer = new UInt8[size];
  900. size = GetGlyphOutlineW(_backend->_hDC, glyphIndex, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
  901. &hpgm, size, buffer, &mat2);
  902. if (size == GDI_ERROR)
  903. {
  904. delete [] buffer;
  905. SelectObject(_backend->_hDC, oldFont);
  906. return auto_ptr<TextPixmapGlyph>();
  907. }
  908. // The gray values in the buffer are between 0 and 64, inclusively.
  909. // So we have to scale them
  910. DWORD i;
  911. UInt8 *ptr = buffer;
  912. for (i = size; i > 0; --i)
  913. {
  914. *ptr = *ptr >= 64 ? 255 : *ptr << 2;
  915. ++ptr;
  916. }
  917. }
  918. SelectObject(_backend->_hDC, oldFont);
  919. // Create and return the new glyph object
  920. return auto_ptr<TextPixmapGlyph>(new TextWIN32PixmapGlyph(glyphIndex, hpgm, vpgm, buffer));
  921. }
  922. //----------------------------------------------------------------------
  923. // Constructor
  924. // Author: pdaehne
  925. //----------------------------------------------------------------------
  926. TextWIN32PixmapGlyph::TextWIN32PixmapGlyph(Index glyphIndex, const GLYPHMETRICS &hpgm,
  927. const GLYPHMETRICS &vpgm, UInt8 *pixmap)
  928. : TextPixmapGlyph()
  929. {
  930. _glyphIndex = glyphIndex;
  931. _width = hpgm.gmBlackBoxX;
  932. _pitch = (hpgm.gmBlackBoxX + 3) & ~3;
  933. _height = hpgm.gmBlackBoxY;
  934. _pixmap = pixmap;
  935. flipPixmap();
  936. // Determine horizontal glyph metrics
  937. _horiAdvance = hpgm.gmCellIncX;
  938. _horiBearingX = hpgm.gmptGlyphOrigin.x;
  939. _horiBearingY = hpgm.gmptGlyphOrigin.y;
  940. // Determine vertical glyph metrics
  941. // Hmmm, there is no useful information here for vertical layout -
  942. // the values provided are just the same as for horizontal layout.
  943. // So we have to guess resonable values -pdaehne
  944. //_vertAdvance = vpgm.gmCellIncY;
  945. //_vertBearingX = vpgm.gmptGlyphOrigin.x;
  946. //_vertBearingY = vpgm.gmptGlyphOrigin.y;
  947. _vertAdvance = -static_cast<Int32>(_height);
  948. _vertBearingX = -static_cast<Int32>(_width >> 1);
  949. _vertBearingY = 0;
  950. }
  951. //----------------------------------------------------------------------
  952. // Destructor
  953. // Author: pdaehne
  954. //----------------------------------------------------------------------
  955. TextWIN32PixmapGlyph::~TextWIN32PixmapGlyph() {}
  956. //----------------------------------------------------------------------
  957. // Constructor
  958. // Author: pdaehne
  959. //----------------------------------------------------------------------
  960. TextWIN32TXFFace::TextWIN32TXFFace(const TextWIN32Backend *backend, HFONT hHoriFont, HFONT hVertFont, const TextTXFParam &param)
  961. : TextTXFFace()
  962. {
  963. // Get information about the font
  964. getFontInfo(backend->_hDC, hHoriFont, _family, _style,
  965. _horiAscent, _horiDescent);
  966. // Set the parameters
  967. _param = param;
  968. // Determine the scale factor & adjust ascent and descent
  969. _scale = 1.f / (_horiAscent - _horiDescent);
  970. _horiAscent *= _scale;
  971. _horiDescent *= _scale;
  972. // Determine vertical ascent and descent
  973. _vertAscent = -0.5f;
  974. _vertDescent = 0.5f;
  975. // Convert the unicode string to utf16
  976. vector<WCHAR> utf16Text;
  977. convertUnicodeToUTF16(param.getCharacters(), utf16Text);
  978. vector<WCHAR>::size_type len = utf16Text.size();
  979. if (len == 0)
  980. {
  981. DeleteObject(hHoriFont);
  982. DeleteObject(hVertFont);
  983. return;
  984. }
  985. // Select the font into the device context
  986. HGDIOBJ oldFont = SelectObject(backend->_hDC, hHoriFont);
  987. GCP_RESULTSW results;
  988. ZeroMemory(&results, sizeof(results));
  989. results.lStructSize = sizeof(results);
  990. results.lpGlyphs = new WCHAR[len];
  991. results.nGlyphs = len;
  992. DWORD result = GetCharacterPlacementW(backend->_hDC, &(utf16Text[0]), len, 0, &results, 0);
  993. if (result == 0)
  994. {
  995. delete [] results.lpGlyphs;
  996. SelectObject(backend->_hDC, oldFont);
  997. DeleteObject(hHoriFont);
  998. DeleteObject(hVertFont);
  999. return;
  1000. }
  1001. // Create all glyphs
  1002. assert(results.nGlyphs == param.getCharacters().length());
  1003. UINT j;
  1004. for (j = 0; j < results.nGlyphs; ++j)
  1005. {
  1006. // Select the vertical font into the device context
  1007. SelectObject(backend->_hDC, hVertFont);
  1008. // Get the vertical metrics
  1009. GLYPHMETRICS vpgm;
  1010. MAT2 mat2 = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
  1011. DWORD size = GetGlyphOutlineW(backend->_hDC, results.lpGlyphs[j], GGO_METRICS | GGO_GLYPH_INDEX,
  1012. &vpgm, 0, 0, &mat2);
  1013. if (size == GDI_ERROR)
  1014. continue;
  1015. // Select the horizontal font into the device context
  1016. SelectObject(backend->_hDC, hHoriFont);
  1017. // Get the horizontal metrics
  1018. GLYPHMETRICS hpgm;
  1019. // Using GGO_METRICS gives a to small value for the width of the glyph...
  1020. size = GetGlyphOutlineW(backend->_hDC, results.lpGlyphs[j], /*GGO_METRICS*/GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
  1021. &hpgm, 0, 0, &mat2);
  1022. if (size == GDI_ERROR)
  1023. continue;
  1024. _glyphMap.insert(GlyphMap::value_type(param.getCharacters()[j], new TextWIN32TXFGlyph(param.getCharacters()[j], this, _scale, hpgm, vpgm)));
  1025. }
  1026. // Calculate the positions of the glyphs on the texture
  1027. prepareTexture(param);
  1028. assert(_texture != NULL);
  1029. assert(_texture->getSize() == static_cast<UInt32>(_texture->getWidth() * _texture->getHeight()));
  1030. // Create the texture
  1031. SelectObject(backend->_hDC, hHoriFont);
  1032. vector<unsigned char> buffer;
  1033. for (j = 0; j < results.nGlyphs; ++j)
  1034. {
  1035. // Get the pixmap
  1036. GLYPHMETRICS hpgm;
  1037. MAT2 mat2 = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
  1038. DWORD size = GetGlyphOutlineW(backend->_hDC, results.lpGlyphs[j], GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
  1039. &hpgm, 0, 0, &mat2);
  1040. if ((size == GDI_ERROR) || (size == 0))
  1041. continue;
  1042. buffer.resize(size);
  1043. size = GetGlyphOutlineW(backend->_hDC, results.lpGlyphs[j], GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
  1044. &hpgm, size, &(buffer[0]), &mat2);
  1045. if (size == GDI_ERROR)
  1046. continue;
  1047. // Try to find the glyph in the glyphmap
  1048. GlyphMap::iterator gIt = _glyphMap.find(param.getCharacters()[j]);
  1049. if (gIt == _glyphMap.end())
  1050. continue;
  1051. assert(gIt->second != 0);
  1052. TextTXFGlyph *glyph = gIt->second;
  1053. // Put the glyph pixmap into the texture
  1054. unsigned char *src = &(buffer[0]);
  1055. int bpl = (hpgm.gmBlackBoxX + 3) & ~3;
  1056. src += bpl * (hpgm.gmBlackBoxY - 1);
  1057. unsigned char *src2;
  1058. UInt8 *dst = _texture->editData() + glyph->getX() + glyph->getY() * _texture->getWidth();
  1059. UInt32 dstPitch = _texture->getWidth() - glyph->getPixmapWidth();
  1060. UInt32 x, y;
  1061. for (y = 0; y < glyph->getPixmapHeight(); ++y)
  1062. {
  1063. src2 = src;
  1064. for (x = 0; x < glyph->getPixmapWidth(); ++x)
  1065. {
  1066. // The gray values in the buffer are between 0 and 64, inclusively.
  1067. // So we have to scale them
  1068. *dst++ = *src2 >= 64 ? 255 : *src2 << 2;
  1069. ++src2;
  1070. }
  1071. src -= bpl;
  1072. dst += dstPitch;
  1073. }
  1074. }
  1075. delete [] results.lpGlyphs;
  1076. // Unselect the font
  1077. SelectObject(backend->_hDC, oldFont);
  1078. // Cleanup
  1079. DeleteObject(hHoriFont);
  1080. DeleteObject(hVertFont);
  1081. }
  1082. //----------------------------------------------------------------------
  1083. // Destructor
  1084. // Author: pdaehne
  1085. //----------------------------------------------------------------------
  1086. TextWIN32TXFFace::~TextWIN32TXFFace() {}
  1087. //----------------------------------------------------------------------
  1088. // Constructor
  1089. // Author: pdaehne
  1090. //----------------------------------------------------------------------
  1091. TextWIN32TXFGlyph::TextWIN32TXFGlyph(Index glyphIndex, TextWIN32TXFFace *face, Real32 scale,
  1092. const GLYPHMETRICS &hpgm, const GLYPHMETRICS &vpgm)
  1093. : TextTXFGlyph()
  1094. {
  1095. _glyphIndex = glyphIndex;
  1096. _scale = scale;
  1097. _width = hpgm.gmBlackBoxX;
  1098. _height = hpgm.gmBlackBoxY;
  1099. // Determine horizontal glyph metrics
  1100. _horiAdvance = static_cast<Real32>(hpgm.gmCellIncX) * _scale;
  1101. _horiBearingX = hpgm.gmptGlyphOrigin.x;
  1102. _horiBearingY = hpgm.gmptGlyphOrigin.y;
  1103. // Determine vertical glyph metrics
  1104. // Hmmm, there is no useful information here for vertical layout -
  1105. // the values provided are just the same as for horizontal layout.
  1106. // So we have to guess resonable values -pdaehne
  1107. //_vertAdvance = static_cast<Real32>(vpgm.gmCellIncY) * _scale;
  1108. //_vertBearingX = vpgm.gmptGlyphOrigin.x;
  1109. //_vertBearingY = vpgm.gmptGlyphOrigin.y;
  1110. _vertBearingX = -static_cast<Int32>(_width >> 1);
  1111. if (glyphIndex == 32)
  1112. {
  1113. _vertBearingY = -_horiBearingX;
  1114. _vertAdvance = -_horiAdvance;
  1115. }
  1116. else
  1117. {
  1118. _vertBearingY = static_cast<Int32>(-(face->getHoriAscent() - face->getHoriDescent()) / _scale / 20.f);
  1119. if (_vertBearingY > -1)
  1120. _vertBearingY = -1;
  1121. Real32 vertAdvanceOffset = static_cast<Real32>(_vertBearingY) * 2.f * _scale;
  1122. _vertAdvance = -static_cast<Real32>(_height) * _scale + vertAdvanceOffset;
  1123. }
  1124. }
  1125. //----------------------------------------------------------------------
  1126. // Destructor
  1127. // Author: pdaehne
  1128. //----------------------------------------------------------------------
  1129. TextWIN32TXFGlyph::~TextWIN32TXFGlyph() {}
  1130. OSG_END_NAMESPACE
  1131. #endif // _WIN32