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.

221 lines
8.1KB

  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.add (fonts.getReference(i).getFileNameWithoutExtension());
  32. return results;
  33. }
  34. struct DefaultFontNames
  35. {
  36. DefaultFontNames()
  37. : defaultSans ("sans"),
  38. defaultSerif ("serif"),
  39. defaultFixed ("monospace"),
  40. defaultFallback ("sans")
  41. {
  42. }
  43. String defaultSans, defaultSerif, defaultFixed, defaultFallback;
  44. };
  45. Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
  46. {
  47. static DefaultFontNames defaultNames;
  48. String faceName (font.getTypefaceName());
  49. if (faceName == Font::getDefaultSansSerifFontName()) faceName = defaultNames.defaultSans;
  50. else if (faceName == Font::getDefaultSerifFontName()) faceName = defaultNames.defaultSerif;
  51. else if (faceName == Font::getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
  52. Font f (font);
  53. f.setTypefaceName (faceName);
  54. return Typeface::createSystemTypefaceFor (f);
  55. }
  56. //==============================================================================
  57. class AndroidTypeface : public Typeface
  58. {
  59. public:
  60. AndroidTypeface (const Font& font)
  61. : Typeface (font.getTypefaceName()),
  62. ascent (0),
  63. descent (0)
  64. {
  65. jint flags = 0;
  66. if (font.isBold()) flags = 1;
  67. if (font.isItalic()) flags += 2;
  68. JNIEnv* env = getEnv();
  69. File fontFile (File ("/system/fonts").getChildFile (name).withFileExtension (".ttf"));
  70. if (fontFile.exists())
  71. typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile,
  72. javaString (fontFile.getFullPathName()).get()));
  73. else
  74. typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create,
  75. javaString (getName()).get(), flags));
  76. rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
  77. paint = GlobalRef (GraphicsHelpers::createPaint (Graphics::highResamplingQuality));
  78. const LocalRef<jobject> ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get()));
  79. const float standardSize = 256.0f;
  80. paint.callVoidMethod (Paint.setTextSize, standardSize);
  81. ascent = std::abs (paint.callFloatMethod (Paint.ascent)) / standardSize;
  82. descent = paint.callFloatMethod (Paint.descent) / standardSize;
  83. const float height = ascent + descent;
  84. unitsToHeightScaleFactor = 1.0f / 256.0f;//(height * standardSize);
  85. }
  86. float getAscent() const { return ascent; }
  87. float getDescent() const { return descent; }
  88. float getStringWidth (const String& text)
  89. {
  90. JNIEnv* env = getEnv();
  91. const int numChars = text.length();
  92. jfloatArray widths = env->NewFloatArray (numChars);
  93. const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
  94. HeapBlock<jfloat> localWidths (numDone);
  95. env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
  96. env->DeleteLocalRef (widths);
  97. float x = 0;
  98. for (int i = 0; i < numDone; ++i)
  99. x += localWidths[i];
  100. return x * unitsToHeightScaleFactor;
  101. }
  102. void getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets)
  103. {
  104. JNIEnv* env = getEnv();
  105. const int numChars = text.length();
  106. jfloatArray widths = env->NewFloatArray (numChars);
  107. const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
  108. HeapBlock<jfloat> localWidths (numDone);
  109. env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
  110. env->DeleteLocalRef (widths);
  111. String::CharPointerType s (text.getCharPointer());
  112. xOffsets.add (0);
  113. float x = 0;
  114. for (int i = 0; i < numDone; ++i)
  115. {
  116. glyphs.add ((int) s.getAndAdvance());
  117. x += localWidths[i];
  118. xOffsets.add (x * unitsToHeightScaleFactor);
  119. }
  120. }
  121. bool getOutlineForGlyph (int /*glyphNumber*/, Path& /*destPath*/)
  122. {
  123. return false;
  124. }
  125. EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& t)
  126. {
  127. JNIEnv* env = getEnv();
  128. jobject matrix = GraphicsHelpers::createMatrix (env, AffineTransform::scale (unitsToHeightScaleFactor, unitsToHeightScaleFactor).followedBy (t));
  129. jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
  130. env->DeleteLocalRef (matrix);
  131. const int left = env->GetIntField (rect.get(), RectClass.left);
  132. const int top = env->GetIntField (rect.get(), RectClass.top);
  133. const int right = env->GetIntField (rect.get(), RectClass.right);
  134. const int bottom = env->GetIntField (rect.get(), RectClass.bottom);
  135. const Rectangle<int> bounds (left, top, right - left, bottom - top);
  136. if (bounds.isEmpty())
  137. return nullptr;
  138. jint* const maskDataElements = env->GetIntArrayElements (maskData, 0);
  139. EdgeTable* et = new EdgeTable (bounds);
  140. const jint* mask = maskDataElements;
  141. for (int y = top; y < bottom; ++y)
  142. {
  143. #if JUCE_LITTLE_ENDIAN
  144. const uint8* const lineBytes = ((const uint8*) mask) + 3;
  145. #else
  146. const uint8* const lineBytes = (const uint8*) mask;
  147. #endif
  148. et->clipLineToMask (left, y, lineBytes, 4, bounds.getWidth());
  149. mask += bounds.getWidth();
  150. }
  151. env->ReleaseIntArrayElements (maskData, maskDataElements, 0);
  152. env->DeleteLocalRef (maskData);
  153. return et;
  154. }
  155. GlobalRef typeface, paint, rect;
  156. float ascent, descent, unitsToHeightScaleFactor;
  157. private:
  158. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidTypeface);
  159. };
  160. //==============================================================================
  161. Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
  162. {
  163. return new AndroidTypeface (font);
  164. }