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.

537 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_Font.h"
  21. #include "juce_GlyphArrangement.h"
  22. #include "../../components/lookandfeel/juce_LookAndFeel.h"
  23. #include "../../graphics/contexts/juce_LowLevelGraphicsContext.h"
  24. #include "../../../utilities/juce_DeletedAtShutdown.h"
  25. #include "../../../core/juce_Singleton.h"
  26. //==============================================================================
  27. namespace FontValues
  28. {
  29. float limitFontHeight (const float height) throw()
  30. {
  31. return jlimit (0.1f, 10000.0f, height);
  32. }
  33. const float defaultFontHeight = 14.0f;
  34. String fallbackFont;
  35. }
  36. //==============================================================================
  37. class TypefaceCache : public DeletedAtShutdown
  38. {
  39. public:
  40. TypefaceCache()
  41. : counter (0)
  42. {
  43. setSize (10);
  44. }
  45. ~TypefaceCache()
  46. {
  47. clearSingletonInstance();
  48. }
  49. juce_DeclareSingleton_SingleThreaded_Minimal (TypefaceCache)
  50. void setSize (const int numToCache)
  51. {
  52. faces.clear();
  53. faces.insertMultiple (-1, CachedFace(), numToCache);
  54. }
  55. const Typeface::Ptr findTypefaceFor (const Font& font)
  56. {
  57. // (can't initialise defaultFace in the constructor or in getDefaultTypeface() because of recursion).
  58. if (defaultFace == 0)
  59. defaultFace = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (Font());
  60. const int flags = font.getStyleFlags() & (Font::bold | Font::italic);
  61. const String faceName (font.getTypefaceName());
  62. int i;
  63. for (i = faces.size(); --i >= 0;)
  64. {
  65. CachedFace& face = faces.getReference(i);
  66. if (face.flags == flags
  67. && face.typefaceName == faceName
  68. && face.typeface->isSuitableForFont (font))
  69. {
  70. face.lastUsageCount = ++counter;
  71. return face.typeface;
  72. }
  73. }
  74. int replaceIndex = 0;
  75. int bestLastUsageCount = std::numeric_limits<int>::max();
  76. for (i = faces.size(); --i >= 0;)
  77. {
  78. const int lu = faces.getReference(i).lastUsageCount;
  79. if (bestLastUsageCount > lu)
  80. {
  81. bestLastUsageCount = lu;
  82. replaceIndex = i;
  83. }
  84. }
  85. CachedFace& face = faces.getReference (replaceIndex);
  86. face.typefaceName = faceName;
  87. face.flags = flags;
  88. face.lastUsageCount = ++counter;
  89. face.typeface = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (font);
  90. jassert (face.typeface != 0); // the look and feel must return a typeface!
  91. return face.typeface;
  92. }
  93. const Typeface::Ptr getDefaultTypeface() const throw()
  94. {
  95. return defaultFace;
  96. }
  97. private:
  98. struct CachedFace
  99. {
  100. CachedFace() throw()
  101. : lastUsageCount (0), flags (-1)
  102. {
  103. }
  104. // Although it seems a bit wacky to store the name here, it's because it may be a
  105. // placeholder rather than a real one, e.g. "<Sans-Serif>" vs the actual typeface name.
  106. // Since the typeface itself doesn't know that it may have this alias, the name under
  107. // which it was fetched needs to be stored separately.
  108. String typefaceName;
  109. int lastUsageCount, flags;
  110. Typeface::Ptr typeface;
  111. };
  112. Array <CachedFace> faces;
  113. Typeface::Ptr defaultFace;
  114. int counter;
  115. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TypefaceCache);
  116. };
  117. juce_ImplementSingleton_SingleThreaded (TypefaceCache)
  118. void Typeface::setTypefaceCacheSize (int numFontsToCache)
  119. {
  120. TypefaceCache::getInstance()->setSize (numFontsToCache);
  121. }
  122. //==============================================================================
  123. Font::SharedFontInternal::SharedFontInternal (const float height_, const int styleFlags_) throw()
  124. : typefaceName (Font::getDefaultSansSerifFontName()),
  125. height (height_),
  126. horizontalScale (1.0f),
  127. kerning (0),
  128. ascent (0),
  129. styleFlags (styleFlags_),
  130. typeface (TypefaceCache::getInstance()->getDefaultTypeface())
  131. {
  132. }
  133. Font::SharedFontInternal::SharedFontInternal (const String& typefaceName_, const float height_, const int styleFlags_) throw()
  134. : typefaceName (typefaceName_),
  135. height (height_),
  136. horizontalScale (1.0f),
  137. kerning (0),
  138. ascent (0),
  139. styleFlags (styleFlags_),
  140. typeface (0)
  141. {
  142. }
  143. Font::SharedFontInternal::SharedFontInternal (const Typeface::Ptr& typeface_) throw()
  144. : typefaceName (typeface_->getName()),
  145. height (FontValues::defaultFontHeight),
  146. horizontalScale (1.0f),
  147. kerning (0),
  148. ascent (0),
  149. styleFlags (Font::plain),
  150. typeface (typeface_)
  151. {
  152. }
  153. Font::SharedFontInternal::SharedFontInternal (const SharedFontInternal& other) throw()
  154. : typefaceName (other.typefaceName),
  155. height (other.height),
  156. horizontalScale (other.horizontalScale),
  157. kerning (other.kerning),
  158. ascent (other.ascent),
  159. styleFlags (other.styleFlags),
  160. typeface (other.typeface)
  161. {
  162. }
  163. bool Font::SharedFontInternal::operator== (const SharedFontInternal& other) const throw()
  164. {
  165. return height == other.height
  166. && styleFlags == other.styleFlags
  167. && horizontalScale == other.horizontalScale
  168. && kerning == other.kerning
  169. && typefaceName == other.typefaceName;
  170. }
  171. //==============================================================================
  172. Font::Font()
  173. : font (new SharedFontInternal (FontValues::defaultFontHeight, Font::plain))
  174. {
  175. }
  176. Font::Font (const float fontHeight, const int styleFlags_)
  177. : font (new SharedFontInternal (FontValues::limitFontHeight (fontHeight), styleFlags_))
  178. {
  179. }
  180. Font::Font (const String& typefaceName_, const float fontHeight, const int styleFlags_)
  181. : font (new SharedFontInternal (typefaceName_, FontValues::limitFontHeight (fontHeight), styleFlags_))
  182. {
  183. }
  184. Font::Font (const Typeface::Ptr& typeface)
  185. : font (new SharedFontInternal (typeface))
  186. {
  187. }
  188. Font::Font (const Font& other) throw()
  189. : font (other.font)
  190. {
  191. }
  192. Font& Font::operator= (const Font& other) throw()
  193. {
  194. font = other.font;
  195. return *this;
  196. }
  197. Font::~Font() throw()
  198. {
  199. }
  200. bool Font::operator== (const Font& other) const throw()
  201. {
  202. return font == other.font
  203. || *font == *other.font;
  204. }
  205. bool Font::operator!= (const Font& other) const throw()
  206. {
  207. return ! operator== (other);
  208. }
  209. void Font::dupeInternalIfShared()
  210. {
  211. if (font->getReferenceCount() > 1)
  212. font = new SharedFontInternal (*font);
  213. }
  214. //==============================================================================
  215. const String Font::getDefaultSansSerifFontName()
  216. {
  217. static const String name ("<Sans-Serif>");
  218. return name;
  219. }
  220. const String Font::getDefaultSerifFontName()
  221. {
  222. static const String name ("<Serif>");
  223. return name;
  224. }
  225. const String Font::getDefaultMonospacedFontName()
  226. {
  227. static const String name ("<Monospaced>");
  228. return name;
  229. }
  230. void Font::setTypefaceName (const String& faceName)
  231. {
  232. if (faceName != font->typefaceName)
  233. {
  234. dupeInternalIfShared();
  235. font->typefaceName = faceName;
  236. font->typeface = 0;
  237. font->ascent = 0;
  238. }
  239. }
  240. //==============================================================================
  241. const String Font::getFallbackFontName()
  242. {
  243. return FontValues::fallbackFont;
  244. }
  245. void Font::setFallbackFontName (const String& name)
  246. {
  247. FontValues::fallbackFont = name;
  248. }
  249. //==============================================================================
  250. void Font::setHeight (float newHeight)
  251. {
  252. newHeight = FontValues::limitFontHeight (newHeight);
  253. if (font->height != newHeight)
  254. {
  255. dupeInternalIfShared();
  256. font->height = newHeight;
  257. }
  258. }
  259. void Font::setHeightWithoutChangingWidth (float newHeight)
  260. {
  261. newHeight = FontValues::limitFontHeight (newHeight);
  262. if (font->height != newHeight)
  263. {
  264. dupeInternalIfShared();
  265. font->horizontalScale *= (font->height / newHeight);
  266. font->height = newHeight;
  267. }
  268. }
  269. void Font::setStyleFlags (const int newFlags)
  270. {
  271. if (font->styleFlags != newFlags)
  272. {
  273. dupeInternalIfShared();
  274. font->styleFlags = newFlags;
  275. font->typeface = 0;
  276. font->ascent = 0;
  277. }
  278. }
  279. void Font::setSizeAndStyle (float newHeight,
  280. const int newStyleFlags,
  281. const float newHorizontalScale,
  282. const float newKerningAmount)
  283. {
  284. newHeight = FontValues::limitFontHeight (newHeight);
  285. if (font->height != newHeight
  286. || font->horizontalScale != newHorizontalScale
  287. || font->kerning != newKerningAmount)
  288. {
  289. dupeInternalIfShared();
  290. font->height = newHeight;
  291. font->horizontalScale = newHorizontalScale;
  292. font->kerning = newKerningAmount;
  293. }
  294. setStyleFlags (newStyleFlags);
  295. }
  296. void Font::setHorizontalScale (const float scaleFactor)
  297. {
  298. dupeInternalIfShared();
  299. font->horizontalScale = scaleFactor;
  300. }
  301. void Font::setExtraKerningFactor (const float extraKerning)
  302. {
  303. dupeInternalIfShared();
  304. font->kerning = extraKerning;
  305. }
  306. void Font::setBold (const bool shouldBeBold)
  307. {
  308. setStyleFlags (shouldBeBold ? (font->styleFlags | bold)
  309. : (font->styleFlags & ~bold));
  310. }
  311. const Font Font::boldened() const
  312. {
  313. Font f (*this);
  314. f.setBold (true);
  315. return f;
  316. }
  317. bool Font::isBold() const throw()
  318. {
  319. return (font->styleFlags & bold) != 0;
  320. }
  321. void Font::setItalic (const bool shouldBeItalic)
  322. {
  323. setStyleFlags (shouldBeItalic ? (font->styleFlags | italic)
  324. : (font->styleFlags & ~italic));
  325. }
  326. const Font Font::italicised() const
  327. {
  328. Font f (*this);
  329. f.setItalic (true);
  330. return f;
  331. }
  332. bool Font::isItalic() const throw()
  333. {
  334. return (font->styleFlags & italic) != 0;
  335. }
  336. void Font::setUnderline (const bool shouldBeUnderlined)
  337. {
  338. setStyleFlags (shouldBeUnderlined ? (font->styleFlags | underlined)
  339. : (font->styleFlags & ~underlined));
  340. }
  341. bool Font::isUnderlined() const throw()
  342. {
  343. return (font->styleFlags & underlined) != 0;
  344. }
  345. float Font::getAscent() const
  346. {
  347. if (font->ascent == 0)
  348. font->ascent = getTypeface()->getAscent();
  349. return font->height * font->ascent;
  350. }
  351. float Font::getDescent() const
  352. {
  353. return font->height - getAscent();
  354. }
  355. int Font::getStringWidth (const String& text) const
  356. {
  357. return roundToInt (getStringWidthFloat (text));
  358. }
  359. float Font::getStringWidthFloat (const String& text) const
  360. {
  361. float w = getTypeface()->getStringWidth (text);
  362. if (font->kerning != 0)
  363. w += font->kerning * text.length();
  364. return w * font->height * font->horizontalScale;
  365. }
  366. void Font::getGlyphPositions (const String& text, Array <int>& glyphs, Array <float>& xOffsets) const
  367. {
  368. getTypeface()->getGlyphPositions (text, glyphs, xOffsets);
  369. const float scale = font->height * font->horizontalScale;
  370. const int num = xOffsets.size();
  371. if (num > 0)
  372. {
  373. float* const x = &(xOffsets.getReference(0));
  374. if (font->kerning != 0)
  375. {
  376. for (int i = 0; i < num; ++i)
  377. x[i] = (x[i] + i * font->kerning) * scale;
  378. }
  379. else
  380. {
  381. for (int i = 0; i < num; ++i)
  382. x[i] *= scale;
  383. }
  384. }
  385. }
  386. void Font::findFonts (Array<Font>& destArray)
  387. {
  388. const StringArray names (findAllTypefaceNames());
  389. for (int i = 0; i < names.size(); ++i)
  390. destArray.add (Font (names[i], FontValues::defaultFontHeight, Font::plain));
  391. }
  392. //==============================================================================
  393. const String Font::toString() const
  394. {
  395. String s (getTypefaceName());
  396. if (s == getDefaultSansSerifFontName())
  397. s = String::empty;
  398. else
  399. s += "; ";
  400. s += String (getHeight(), 1);
  401. if (isBold())
  402. s += " bold";
  403. if (isItalic())
  404. s += " italic";
  405. return s;
  406. }
  407. const Font Font::fromString (const String& fontDescription)
  408. {
  409. String name;
  410. const int separator = fontDescription.indexOfChar (';');
  411. if (separator > 0)
  412. name = fontDescription.substring (0, separator).trim();
  413. if (name.isEmpty())
  414. name = getDefaultSansSerifFontName();
  415. String sizeAndStyle (fontDescription.substring (separator + 1));
  416. float height = sizeAndStyle.getFloatValue();
  417. if (height <= 0)
  418. height = 10.0f;
  419. int flags = Font::plain;
  420. if (sizeAndStyle.containsIgnoreCase ("bold"))
  421. flags |= Font::bold;
  422. if (sizeAndStyle.containsIgnoreCase ("italic"))
  423. flags |= Font::italic;
  424. return Font (name, height, flags);
  425. }
  426. //==============================================================================
  427. Typeface* Font::getTypeface() const
  428. {
  429. if (font->typeface == 0)
  430. font->typeface = TypefaceCache::getInstance()->findTypefaceFor (*this);
  431. return font->typeface;
  432. }
  433. END_JUCE_NAMESPACE