The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

781 lines
24KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "win32_headers.h"
  24. #include "../../../src/juce_core/basics/juce_StandardHeader.h"
  25. BEGIN_JUCE_NAMESPACE
  26. #include "../../../src/juce_appframework/gui/graphics/fonts/juce_Font.h"
  27. #include "../../../src/juce_appframework/application/juce_DeletedAtShutdown.h"
  28. #include "../../../src/juce_core/basics/juce_SystemStats.h"
  29. #include "../../../src/juce_core/basics/juce_Singleton.h"
  30. #include "../../../src/juce_appframework/gui/graphics/imaging/juce_Image.h"
  31. //==============================================================================
  32. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  33. UNICODE_FUNCTION (GetGlyphOutlineW, DWORD, (HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, CONST MAT2*))
  34. UNICODE_FUNCTION (GetTextMetricsW, BOOL, (HDC, LPTEXTMETRICW))
  35. UNICODE_FUNCTION (GetKerningPairsW, DWORD, (HDC, DWORD, LPKERNINGPAIR))
  36. UNICODE_FUNCTION (EnumFontFamiliesExW, int, (HDC, LPLOGFONTW, FONTENUMPROCW, LPARAM, DWORD))
  37. UNICODE_FUNCTION (CreateFontIndirectW, HFONT, (CONST LOGFONTW *));
  38. UNICODE_FUNCTION (GetGlyphIndicesW, DWORD, (HDC, LPCWSTR, int, LPWORD, DWORD));
  39. static void juce_initialiseUnicodeFileFontFunctions()
  40. {
  41. static bool initialised = false;
  42. if (! initialised)
  43. {
  44. initialised = true;
  45. if ((SystemStats::getOperatingSystemType() & SystemStats::WindowsNT) != 0)
  46. {
  47. HMODULE h = LoadLibraryA ("gdi32.dll");
  48. UNICODE_FUNCTION_LOAD (GetGlyphOutlineW)
  49. UNICODE_FUNCTION_LOAD (GetTextMetricsW)
  50. UNICODE_FUNCTION_LOAD (GetKerningPairsW)
  51. UNICODE_FUNCTION_LOAD (EnumFontFamiliesExW)
  52. UNICODE_FUNCTION_LOAD (CreateFontIndirectW)
  53. UNICODE_FUNCTION_LOAD (GetGlyphIndicesW)
  54. }
  55. }
  56. }
  57. #endif
  58. //==============================================================================
  59. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  60. static int CALLBACK fontEnum2 (ENUMLOGFONTEX* lpelfe,
  61. NEWTEXTMETRICEX*,
  62. int type,
  63. LPARAM lParam)
  64. {
  65. if (lpelfe != 0 && type == TRUETYPE_FONTTYPE)
  66. {
  67. const String fontName (lpelfe->elfLogFont.lfFaceName);
  68. ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@")));
  69. }
  70. return 1;
  71. }
  72. #endif
  73. static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe,
  74. NEWTEXTMETRICEXW*,
  75. int type,
  76. LPARAM lParam)
  77. {
  78. if (lpelfe != 0 && type == TRUETYPE_FONTTYPE)
  79. {
  80. const String fontName (lpelfe->elfLogFont.lfFaceName);
  81. ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@")));
  82. }
  83. return 1;
  84. }
  85. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  86. static int CALLBACK fontEnum1 (ENUMLOGFONTEX* lpelfe,
  87. NEWTEXTMETRICEX*,
  88. int type,
  89. LPARAM lParam)
  90. {
  91. if (lpelfe != 0
  92. && ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0))
  93. {
  94. LOGFONT lf;
  95. zerostruct (lf);
  96. lf.lfWeight = FW_DONTCARE;
  97. lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  98. lf.lfQuality = DEFAULT_QUALITY;
  99. lf.lfCharSet = DEFAULT_CHARSET;
  100. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  101. lf.lfPitchAndFamily = FF_DONTCARE;
  102. const String fontName (lpelfe->elfLogFont.lfFaceName);
  103. fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);
  104. HDC dc = CreateCompatibleDC (0);
  105. EnumFontFamiliesEx (dc, &lf,
  106. (FONTENUMPROC) &fontEnum2,
  107. lParam, 0);
  108. DeleteDC (dc);
  109. }
  110. return 1;
  111. }
  112. #endif
  113. static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe,
  114. NEWTEXTMETRICEXW*,
  115. int type,
  116. LPARAM lParam)
  117. {
  118. if (lpelfe != 0
  119. && ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0))
  120. {
  121. LOGFONTW lf;
  122. zerostruct (lf);
  123. lf.lfWeight = FW_DONTCARE;
  124. lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  125. lf.lfQuality = DEFAULT_QUALITY;
  126. lf.lfCharSet = DEFAULT_CHARSET;
  127. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  128. lf.lfPitchAndFamily = FF_DONTCARE;
  129. const String fontName (lpelfe->elfLogFont.lfFaceName);
  130. fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);
  131. HDC dc = CreateCompatibleDC (0);
  132. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  133. wEnumFontFamiliesExW (dc, &lf,
  134. (FONTENUMPROCW) &wfontEnum2,
  135. lParam, 0);
  136. #else
  137. EnumFontFamiliesExW (dc, &lf,
  138. (FONTENUMPROCW) &wfontEnum2,
  139. lParam, 0);
  140. #endif
  141. DeleteDC (dc);
  142. }
  143. return 1;
  144. }
  145. const StringArray Font::findAllTypefaceNames() throw()
  146. {
  147. StringArray results;
  148. HDC dc = CreateCompatibleDC (0);
  149. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  150. if (wEnumFontFamiliesExW != 0)
  151. {
  152. LOGFONTW lf;
  153. zerostruct (lf);
  154. lf.lfWeight = FW_DONTCARE;
  155. lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  156. lf.lfQuality = DEFAULT_QUALITY;
  157. lf.lfCharSet = DEFAULT_CHARSET;
  158. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  159. lf.lfPitchAndFamily = FF_DONTCARE;
  160. lf.lfFaceName[0] = 0;
  161. wEnumFontFamiliesExW (dc, &lf,
  162. (FONTENUMPROCW) &wfontEnum1,
  163. (LPARAM) &results, 0);
  164. }
  165. else
  166. {
  167. LOGFONT lf;
  168. zerostruct (lf);
  169. lf.lfWeight = FW_DONTCARE;
  170. lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  171. lf.lfQuality = DEFAULT_QUALITY;
  172. lf.lfCharSet = DEFAULT_CHARSET;
  173. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  174. lf.lfPitchAndFamily = FF_DONTCARE;
  175. lf.lfFaceName[0] = 0;
  176. EnumFontFamiliesEx (dc, &lf,
  177. (FONTENUMPROC) &fontEnum1,
  178. (LPARAM) &results, 0);
  179. }
  180. #else
  181. {
  182. LOGFONTW lf;
  183. zerostruct (lf);
  184. lf.lfWeight = FW_DONTCARE;
  185. lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  186. lf.lfQuality = DEFAULT_QUALITY;
  187. lf.lfCharSet = DEFAULT_CHARSET;
  188. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  189. lf.lfPitchAndFamily = FF_DONTCARE;
  190. lf.lfFaceName[0] = 0;
  191. EnumFontFamiliesExW (dc, &lf,
  192. (FONTENUMPROCW) &wfontEnum1,
  193. (LPARAM) &results, 0);
  194. }
  195. #endif
  196. DeleteDC (dc);
  197. results.sort (true);
  198. return results;
  199. }
  200. extern bool juce_IsRunningInWine() throw();
  201. void Font::getDefaultFontNames (String& defaultSans,
  202. String& defaultSerif,
  203. String& defaultFixed) throw()
  204. {
  205. if (juce_IsRunningInWine())
  206. {
  207. // If we're running in Wine, then use fonts that might be available on Linux..
  208. defaultSans = "Bitstream Vera Sans";
  209. defaultSerif = "Bitstream Vera Serif";
  210. defaultFixed = "Bitstream Vera Sans Mono";
  211. }
  212. else
  213. {
  214. defaultSans = "Verdana";
  215. defaultSerif = "Times";
  216. defaultFixed = "Lucida Console";
  217. }
  218. }
  219. //==============================================================================
  220. class FontDCHolder : private DeletedAtShutdown
  221. {
  222. HDC dc;
  223. String fontName;
  224. KERNINGPAIR* kps;
  225. int numKPs;
  226. bool bold, italic;
  227. int size;
  228. FontDCHolder (const FontDCHolder&);
  229. const FontDCHolder& operator= (const FontDCHolder&);
  230. public:
  231. HFONT fontH;
  232. //==============================================================================
  233. FontDCHolder() throw()
  234. : dc (0),
  235. kps (0),
  236. numKPs (0),
  237. bold (false),
  238. italic (false),
  239. size (0)
  240. {
  241. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  242. juce_initialiseUnicodeFileFontFunctions();
  243. #endif
  244. }
  245. ~FontDCHolder() throw()
  246. {
  247. if (dc != 0)
  248. {
  249. DeleteDC (dc);
  250. DeleteObject (fontH);
  251. juce_free (kps);
  252. }
  253. clearSingletonInstance();
  254. }
  255. juce_DeclareSingleton_SingleThreaded_Minimal (FontDCHolder);
  256. //==============================================================================
  257. HDC loadFont (const String& fontName_,
  258. const bool bold_,
  259. const bool italic_,
  260. const int size_) throw()
  261. {
  262. if (fontName != fontName_ || bold != bold_ || italic != italic_ || size != size_)
  263. {
  264. fontName = fontName_;
  265. bold = bold_;
  266. italic = italic_;
  267. size = size_;
  268. if (dc != 0)
  269. {
  270. DeleteDC (dc);
  271. DeleteObject (fontH);
  272. juce_free (kps);
  273. kps = 0;
  274. }
  275. fontH = 0;
  276. dc = CreateCompatibleDC (0);
  277. SetMapperFlags (dc, 0);
  278. SetMapMode (dc, MM_TEXT);
  279. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  280. LOGFONT lf;
  281. LOGFONTW lfw;
  282. HFONT standardSizedFont = 0;
  283. if (wCreateFontIndirectW != 0)
  284. {
  285. zerostruct (lfw);
  286. lfw.lfCharSet = DEFAULT_CHARSET;
  287. lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  288. lfw.lfOutPrecision = OUT_OUTLINE_PRECIS;
  289. lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  290. lfw.lfQuality = PROOF_QUALITY;
  291. lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE);
  292. lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL;
  293. fontName.copyToBuffer (lfw.lfFaceName, LF_FACESIZE - 1);
  294. lfw.lfHeight = size > 0 ? size : -256;
  295. standardSizedFont = wCreateFontIndirectW (&lfw);
  296. }
  297. else
  298. {
  299. zerostruct (lf);
  300. lf.lfCharSet = DEFAULT_CHARSET;
  301. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  302. lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
  303. lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  304. lf.lfQuality = PROOF_QUALITY;
  305. lf.lfItalic = (BYTE) (italic ? TRUE : FALSE);
  306. lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
  307. fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);
  308. lf.lfHeight = size > 0 ? size : -256;
  309. standardSizedFont = CreateFontIndirect (&lf);
  310. }
  311. #else
  312. LOGFONTW lfw;
  313. zerostruct (lfw);
  314. lfw.lfCharSet = DEFAULT_CHARSET;
  315. lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  316. lfw.lfOutPrecision = OUT_OUTLINE_PRECIS;
  317. lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  318. lfw.lfQuality = PROOF_QUALITY;
  319. lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE);
  320. lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL;
  321. fontName.copyToBuffer (lfw.lfFaceName, LF_FACESIZE - 1);
  322. lfw.lfHeight = size > 0 ? size : -256;
  323. HFONT standardSizedFont = CreateFontIndirectW (&lfw);
  324. #endif
  325. if (standardSizedFont != 0)
  326. {
  327. if (SelectObject (dc, standardSizedFont) != 0)
  328. {
  329. fontH = standardSizedFont;
  330. if (size == 0)
  331. {
  332. OUTLINETEXTMETRIC otm;
  333. if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
  334. {
  335. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  336. if (wCreateFontIndirectW != 0)
  337. {
  338. lfw.lfHeight = -(int) otm.otmEMSquare;
  339. fontH = wCreateFontIndirectW (&lfw);
  340. }
  341. else
  342. {
  343. lf.lfHeight = -(int) otm.otmEMSquare;
  344. fontH = CreateFontIndirect (&lf);
  345. }
  346. #else
  347. lfw.lfHeight = -(int) otm.otmEMSquare;
  348. fontH = CreateFontIndirectW (&lfw);
  349. #endif
  350. SelectObject (dc, fontH);
  351. DeleteObject (standardSizedFont);
  352. }
  353. }
  354. }
  355. else
  356. {
  357. jassertfalse
  358. }
  359. }
  360. else
  361. {
  362. jassertfalse
  363. }
  364. }
  365. return dc;
  366. }
  367. //==============================================================================
  368. KERNINGPAIR* getKerningPairs (int& numKPs_) throw()
  369. {
  370. if (kps == 0)
  371. {
  372. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  373. if (wGetKerningPairsW != 0)
  374. {
  375. numKPs = wGetKerningPairsW (dc, 0, 0);
  376. kps = (KERNINGPAIR*) juce_calloc (sizeof (KERNINGPAIR) * numKPs);
  377. wGetKerningPairsW (dc, numKPs, kps);
  378. }
  379. else
  380. {
  381. numKPs = GetKerningPairs (dc, 0, 0);
  382. kps = (KERNINGPAIR*) juce_calloc (sizeof (KERNINGPAIR) * numKPs);
  383. GetKerningPairs (dc, numKPs, kps);
  384. }
  385. #else
  386. numKPs = GetKerningPairsW (dc, 0, 0);
  387. kps = (KERNINGPAIR*) juce_calloc (sizeof (KERNINGPAIR) * numKPs);
  388. GetKerningPairsW (dc, numKPs, kps);
  389. #endif
  390. }
  391. numKPs_ = numKPs;
  392. return kps;
  393. }
  394. };
  395. juce_ImplementSingleton_SingleThreaded (FontDCHolder);
  396. //==============================================================================
  397. static bool addGlyphToTypeface (HDC dc,
  398. juce_wchar character,
  399. Typeface& dest,
  400. bool addKerning)
  401. {
  402. Path destShape;
  403. GLYPHMETRICS gm;
  404. float height;
  405. BOOL ok = false;
  406. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  407. if (wGetGlyphIndicesW != 0)
  408. {
  409. const WCHAR charToTest[] = { (WCHAR)character, 0 };
  410. WORD index = 0;
  411. if (wGetGlyphIndicesW (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR
  412. && index == 0xffff)
  413. {
  414. return false;
  415. }
  416. }
  417. if (wGetTextMetricsW != 0)
  418. {
  419. TEXTMETRICW tm;
  420. ok = wGetTextMetricsW (dc, &tm);
  421. height = (float) tm.tmHeight;
  422. }
  423. else
  424. {
  425. TEXTMETRIC tm;
  426. ok = GetTextMetrics (dc, &tm);
  427. height = (float) tm.tmHeight;
  428. }
  429. #else
  430. {
  431. const WCHAR charToTest[] = { (WCHAR)character, 0 };
  432. WORD index = 0;
  433. if (GetGlyphIndicesW (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR
  434. && index == 0xffff)
  435. {
  436. return false;
  437. }
  438. }
  439. TEXTMETRICW tm;
  440. ok = GetTextMetricsW (dc, &tm);
  441. height = (float) tm.tmHeight;
  442. #endif
  443. if (! ok)
  444. {
  445. dest.addGlyph (character, destShape, 0);
  446. return true;
  447. }
  448. const float scaleX = 1.0f / height;
  449. const float scaleY = -1.0f / height;
  450. static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
  451. int bufSize;
  452. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  453. if (wGetGlyphOutlineW != 0)
  454. bufSize = wGetGlyphOutlineW (dc, character, GGO_NATIVE,
  455. &gm, 0, 0, &identityMatrix);
  456. else
  457. bufSize = GetGlyphOutline (dc, character, GGO_NATIVE,
  458. &gm, 0, 0, &identityMatrix);
  459. #else
  460. bufSize = GetGlyphOutlineW (dc, character, GGO_NATIVE,
  461. &gm, 0, 0, &identityMatrix);
  462. #endif
  463. if (bufSize > 0)
  464. {
  465. char* const data = (char*) juce_malloc (bufSize);
  466. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  467. if (wGetGlyphOutlineW != 0)
  468. wGetGlyphOutlineW (dc, character, GGO_NATIVE, &gm,
  469. bufSize, data, &identityMatrix);
  470. else
  471. GetGlyphOutline (dc, character, GGO_NATIVE, &gm,
  472. bufSize, data, &identityMatrix);
  473. #else
  474. GetGlyphOutlineW (dc, character, GGO_NATIVE, &gm,
  475. bufSize, data, &identityMatrix);
  476. #endif
  477. const TTPOLYGONHEADER* pheader = (TTPOLYGONHEADER*) data;
  478. while ((char*) pheader < data + bufSize)
  479. {
  480. #define remapX(v) (scaleX * (v).x.value)
  481. #define remapY(v) (scaleY * (v).y.value)
  482. float x = remapX (pheader->pfxStart);
  483. float y = remapY (pheader->pfxStart);
  484. destShape.startNewSubPath (x, y);
  485. const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER));
  486. const char* const curveEnd = ((const char*) pheader) + pheader->cb;
  487. while ((const char*) curve < curveEnd)
  488. {
  489. if (curve->wType == TT_PRIM_LINE)
  490. {
  491. for (int i = 0; i < curve->cpfx; ++i)
  492. {
  493. x = remapX (curve->apfx [i]);
  494. y = remapY (curve->apfx [i]);
  495. destShape.lineTo (x, y);
  496. }
  497. }
  498. else if (curve->wType == TT_PRIM_QSPLINE)
  499. {
  500. for (int i = 0; i < curve->cpfx - 1; ++i)
  501. {
  502. const float x2 = remapX (curve->apfx [i]);
  503. const float y2 = remapY (curve->apfx [i]);
  504. float x3, y3;
  505. if (i < curve->cpfx - 2)
  506. {
  507. x3 = 0.5f * (x2 + remapX (curve->apfx [i + 1]));
  508. y3 = 0.5f * (y2 + remapY (curve->apfx [i + 1]));
  509. }
  510. else
  511. {
  512. x3 = remapX (curve->apfx [i + 1]);
  513. y3 = remapY (curve->apfx [i + 1]);
  514. }
  515. destShape.quadraticTo (x2, y2, x3, y3);
  516. x = x3;
  517. y = y3;
  518. }
  519. }
  520. curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]);
  521. }
  522. pheader = (const TTPOLYGONHEADER*) curve;
  523. destShape.closeSubPath();
  524. }
  525. juce_free (data);
  526. }
  527. dest.addGlyph (character, destShape, gm.gmCellIncX / height);
  528. if (addKerning)
  529. {
  530. int numKPs;
  531. const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs);
  532. for (int i = 0; i < numKPs; ++i)
  533. {
  534. if (kps[i].wFirst == character)
  535. {
  536. dest.addKerningPair (kps[i].wFirst,
  537. kps[i].wSecond,
  538. kps[i].iKernAmount / height);
  539. }
  540. }
  541. }
  542. return true;
  543. }
  544. //==============================================================================
  545. bool Typeface::findAndAddSystemGlyph (juce_wchar character) throw()
  546. {
  547. HDC dc = FontDCHolder::getInstance()->loadFont (getName(), isBold(), isItalic(), 0);
  548. return addGlyphToTypeface (dc, character, *this, true);
  549. }
  550. /*Image* Typeface::renderGlyphToImage (juce_wchar character, float& topLeftX, float& topLeftY)
  551. {
  552. HDC dc = FontDCHolder::getInstance()->loadFont (getName(), isBold(), isItalic(), hintingSize);
  553. int bufSize;
  554. GLYPHMETRICS gm;
  555. const UINT format = GGO_GRAY2_BITMAP;
  556. const int shift = 6;
  557. if (wGetGlyphOutlineW != 0)
  558. bufSize = wGetGlyphOutlineW (dc, character, format, &gm, 0, 0, &identityMatrix);
  559. else
  560. bufSize = GetGlyphOutline (dc, character, format, &gm, 0, 0, &identityMatrix);
  561. Image* im = new Image (Image::SingleChannel, jmax (1, gm.gmBlackBoxX), jmax (1, gm.gmBlackBoxY), true);
  562. if (bufSize > 0)
  563. {
  564. topLeftX = (float) gm.gmptGlyphOrigin.x;
  565. topLeftY = (float) -gm.gmptGlyphOrigin.y;
  566. uint8* const data = (uint8*) juce_calloc (bufSize);
  567. if (wGetGlyphOutlineW != 0)
  568. wGetGlyphOutlineW (dc, character, format, &gm, bufSize, data, &identityMatrix);
  569. else
  570. GetGlyphOutline (dc, character, format, &gm, bufSize, data, &identityMatrix);
  571. const int stride = ((gm.gmBlackBoxX + 3) & ~3);
  572. for (int y = gm.gmBlackBoxY; --y >= 0;)
  573. {
  574. for (int x = gm.gmBlackBoxX; --x >= 0;)
  575. {
  576. const int level = data [x + y * stride] << shift;
  577. if (level > 0)
  578. im->setPixelAt (x, y, Colour ((uint8) 0xff, (uint8) 0xff, (uint8) 0xff, (uint8) jmin (0xff, level)));
  579. }
  580. }
  581. juce_free (data);
  582. }
  583. return im;
  584. }*/
  585. //==============================================================================
  586. void Typeface::initialiseTypefaceCharacteristics (const String& fontName,
  587. bool bold,
  588. bool italic,
  589. bool addAllGlyphsToFont) throw()
  590. {
  591. clear();
  592. HDC dc = FontDCHolder::getInstance()->loadFont (fontName, bold, italic, 0);
  593. float height;
  594. int firstChar, lastChar;
  595. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  596. if (wGetTextMetricsW != 0)
  597. {
  598. TEXTMETRICW tm;
  599. wGetTextMetricsW (dc, &tm);
  600. height = (float) tm.tmHeight;
  601. firstChar = tm.tmFirstChar;
  602. lastChar = tm.tmLastChar;
  603. setAscent (tm.tmAscent / height);
  604. setDefaultCharacter (tm.tmDefaultChar);
  605. }
  606. else
  607. {
  608. TEXTMETRIC tm;
  609. GetTextMetrics (dc, &tm);
  610. height = (float) tm.tmHeight;
  611. firstChar = tm.tmFirstChar;
  612. lastChar = tm.tmLastChar;
  613. setAscent (tm.tmAscent / height);
  614. setDefaultCharacter (tm.tmDefaultChar);
  615. }
  616. #else
  617. {
  618. TEXTMETRICW tm;
  619. GetTextMetricsW (dc, &tm);
  620. height = (float) tm.tmHeight;
  621. firstChar = tm.tmFirstChar;
  622. lastChar = tm.tmLastChar;
  623. setAscent (tm.tmAscent / height);
  624. setDefaultCharacter (tm.tmDefaultChar);
  625. }
  626. #endif
  627. setName (fontName);
  628. setBold (bold);
  629. setItalic (italic);
  630. if (addAllGlyphsToFont)
  631. {
  632. for (int character = firstChar; character <= lastChar; ++character)
  633. addGlyphToTypeface (dc, (juce_wchar) character, *this, false);
  634. int numKPs;
  635. const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs);
  636. for (int i = 0; i < numKPs; ++i)
  637. {
  638. addKerningPair (kps[i].wFirst,
  639. kps[i].wSecond,
  640. kps[i].iKernAmount / height);
  641. }
  642. }
  643. }
  644. END_JUCE_NAMESPACE