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.

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