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.

320 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. struct DefaultFontNames
  19. {
  20. DefaultFontNames()
  21. : defaultSans ("sans"),
  22. defaultSerif ("serif"),
  23. defaultFixed ("monospace"),
  24. defaultFallback ("sans")
  25. {
  26. }
  27. String getRealFontName (const String& faceName) const
  28. {
  29. if (faceName == Font::getDefaultSansSerifFontName()) return defaultSans;
  30. if (faceName == Font::getDefaultSerifFontName()) return defaultSerif;
  31. if (faceName == Font::getDefaultMonospacedFontName()) return defaultFixed;
  32. return faceName;
  33. }
  34. String defaultSans, defaultSerif, defaultFixed, defaultFallback;
  35. };
  36. Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
  37. {
  38. static DefaultFontNames defaultNames;
  39. Font f (font);
  40. f.setTypefaceName (defaultNames.getRealFontName (font.getTypefaceName()));
  41. return Typeface::createSystemTypefaceFor (f);
  42. }
  43. //==============================================================================
  44. #if JUCE_USE_FREETYPE
  45. void FontFileIterator::findFontDirectories()
  46. {
  47. fontDirs.add ("/system/fonts");
  48. }
  49. Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
  50. {
  51. return new FreeTypeTypeface (font);
  52. }
  53. StringArray Font::findAllTypefaceNames()
  54. {
  55. return FTTypefaceList::getInstance()->findAllFamilyNames();
  56. }
  57. StringArray Font::findAllTypefaceStyles (const String& family)
  58. {
  59. return FTTypefaceList::getInstance()->findAllTypefaceStyles (family);
  60. }
  61. bool TextLayout::createNativeLayout (const AttributedString&)
  62. {
  63. return false;
  64. }
  65. #else
  66. //==============================================================================
  67. #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
  68. STATICMETHOD (create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \
  69. STATICMETHOD (createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
  70. DECLARE_JNI_CLASS (TypefaceClass, "android/graphics/Typeface");
  71. #undef JNI_CLASS_MEMBERS
  72. //==============================================================================
  73. StringArray Font::findAllTypefaceNames()
  74. {
  75. StringArray results;
  76. Array<File> fonts;
  77. File ("/system/fonts").findChildFiles (fonts, File::findFiles, false, "*.ttf");
  78. for (int i = 0; i < fonts.size(); ++i)
  79. results.addIfNotAlreadyThere (fonts.getReference(i).getFileNameWithoutExtension()
  80. .upToLastOccurrenceOf ("-", false, false));
  81. return results;
  82. }
  83. StringArray Font::findAllTypefaceStyles (const String& family)
  84. {
  85. StringArray results ("Regular");
  86. Array<File> fonts;
  87. File ("/system/fonts").findChildFiles (fonts, File::findFiles, false, family + "-*.ttf");
  88. for (int i = 0; i < fonts.size(); ++i)
  89. results.addIfNotAlreadyThere (fonts.getReference(i).getFileNameWithoutExtension()
  90. .fromLastOccurrenceOf ("-", false, false));
  91. return results;
  92. }
  93. const float referenceFontSize = 256.0f;
  94. const float referenceFontToUnits = 1.0f / referenceFontSize;
  95. //==============================================================================
  96. class AndroidTypeface : public Typeface
  97. {
  98. public:
  99. AndroidTypeface (const Font& font)
  100. : Typeface (font.getTypefaceName(), font.getTypefaceStyle()),
  101. ascent (0), descent (0), heightToPointsFactor (1.0f)
  102. {
  103. JNIEnv* const env = getEnv();
  104. const bool isBold = style.contains ("Bold");
  105. const bool isItalic = style.contains ("Italic");
  106. File fontFile (getFontFile (name, style));
  107. if (! fontFile.exists())
  108. fontFile = findFontFile (name, isBold, isItalic);
  109. if (fontFile.exists())
  110. typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile,
  111. javaString (fontFile.getFullPathName()).get()));
  112. else
  113. typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create,
  114. javaString (getName()).get(),
  115. (isBold ? 1 : 0) + (isItalic ? 2 : 0)));
  116. rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
  117. paint = GlobalRef (GraphicsHelpers::createPaint (Graphics::highResamplingQuality));
  118. const LocalRef<jobject> ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get()));
  119. paint.callVoidMethod (Paint.setTextSize, referenceFontSize);
  120. const float fullAscent = std::abs (paint.callFloatMethod (Paint.ascent));
  121. const float fullDescent = paint.callFloatMethod (Paint.descent);
  122. const float totalHeight = fullAscent + fullDescent;
  123. ascent = fullAscent / totalHeight;
  124. descent = fullDescent / totalHeight;
  125. heightToPointsFactor = referenceFontSize / totalHeight;
  126. }
  127. float getAscent() const { return ascent; }
  128. float getDescent() const { return descent; }
  129. float getHeightToPointsFactor() const { return heightToPointsFactor; }
  130. float getStringWidth (const String& text)
  131. {
  132. JNIEnv* env = getEnv();
  133. const int numChars = text.length();
  134. jfloatArray widths = env->NewFloatArray (numChars);
  135. const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
  136. HeapBlock<jfloat> localWidths (numDone);
  137. env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
  138. env->DeleteLocalRef (widths);
  139. float x = 0;
  140. for (int i = 0; i < numDone; ++i)
  141. x += localWidths[i];
  142. return x * referenceFontToUnits;
  143. }
  144. void getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets)
  145. {
  146. JNIEnv* env = getEnv();
  147. const int numChars = text.length();
  148. jfloatArray widths = env->NewFloatArray (numChars);
  149. const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
  150. HeapBlock<jfloat> localWidths (numDone);
  151. env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
  152. env->DeleteLocalRef (widths);
  153. String::CharPointerType s (text.getCharPointer());
  154. xOffsets.add (0);
  155. float x = 0;
  156. for (int i = 0; i < numDone; ++i)
  157. {
  158. glyphs.add ((int) s.getAndAdvance());
  159. x += localWidths[i];
  160. xOffsets.add (x * referenceFontToUnits);
  161. }
  162. }
  163. bool getOutlineForGlyph (int /*glyphNumber*/, Path& /*destPath*/)
  164. {
  165. return false;
  166. }
  167. EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& t)
  168. {
  169. JNIEnv* env = getEnv();
  170. jobject matrix = GraphicsHelpers::createMatrix (env, AffineTransform::scale (referenceFontToUnits).followedBy (t));
  171. jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
  172. env->DeleteLocalRef (matrix);
  173. const int left = env->GetIntField (rect.get(), RectClass.left);
  174. const int top = env->GetIntField (rect.get(), RectClass.top);
  175. const int right = env->GetIntField (rect.get(), RectClass.right);
  176. const int bottom = env->GetIntField (rect.get(), RectClass.bottom);
  177. const Rectangle<int> bounds (left, top, right - left, bottom - top);
  178. EdgeTable* et = nullptr;
  179. if (! bounds.isEmpty())
  180. {
  181. et = new EdgeTable (bounds);
  182. jint* const maskDataElements = env->GetIntArrayElements (maskData, 0);
  183. const jint* mask = maskDataElements;
  184. for (int y = top; y < bottom; ++y)
  185. {
  186. #if JUCE_LITTLE_ENDIAN
  187. const uint8* const lineBytes = ((const uint8*) mask) + 3;
  188. #else
  189. const uint8* const lineBytes = (const uint8*) mask;
  190. #endif
  191. et->clipLineToMask (left, y, lineBytes, 4, bounds.getWidth());
  192. mask += bounds.getWidth();
  193. }
  194. env->ReleaseIntArrayElements (maskData, maskDataElements, 0);
  195. }
  196. env->DeleteLocalRef (maskData);
  197. return et;
  198. }
  199. GlobalRef typeface, paint, rect;
  200. float ascent, descent, heightToPointsFactor;
  201. private:
  202. static File findFontFile (const String& family,
  203. const bool bold, const bool italic)
  204. {
  205. File file;
  206. if (bold || italic)
  207. {
  208. String suffix;
  209. if (bold) suffix = "Bold";
  210. if (italic) suffix << "Italic";
  211. file = getFontFile (family, suffix);
  212. if (file.exists())
  213. return file;
  214. }
  215. file = getFontFile (family, "Regular");
  216. if (! file.exists())
  217. file = getFontFile (family, String::empty);
  218. return file;
  219. }
  220. static File getFontFile (const String& family, const String& style)
  221. {
  222. String path ("/system/fonts/" + family);
  223. if (style.isNotEmpty())
  224. path << '-' << style;
  225. return File (path + ".ttf");
  226. }
  227. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidTypeface)
  228. };
  229. //==============================================================================
  230. Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
  231. {
  232. return new AndroidTypeface (font);
  233. }
  234. bool TextLayout::createNativeLayout (const AttributedString&)
  235. {
  236. return false;
  237. }
  238. #endif