PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/JuceLibraryCode/modules/juce_graphics/native/juce_android_Fonts.cpp

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