diff options
| -rw-r--r-- | core/jni/android/graphics/Typeface.cpp | 8 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Typeface.java | 72 | ||||
| -rw-r--r-- | libs/hwui/hwui/Typeface.cpp | 66 | ||||
| -rw-r--r-- | libs/hwui/hwui/Typeface.h | 3 | 
4 files changed, 104 insertions, 45 deletions
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp index 95d43c6c8203..86c97a1e558c 100644 --- a/core/jni/android/graphics/Typeface.cpp +++ b/core/jni/android/graphics/Typeface.cpp @@ -87,7 +87,8 @@ static jint Typeface_getBaseWeight(JNIEnv* env, jobject obj, jlong faceHandle) {      return face->fBaseWeight;  } -static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) { +static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray, +        int weight, int italic) {      ScopedLongArrayRO families(env, familyArray);      std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;      familyVec.reserve(families.size()); @@ -95,7 +96,8 @@ static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArr          FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);          familyVec.emplace_back(family->family);      } -    return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec))); +    return reinterpret_cast<jlong>( +            Typeface::createFromFamilies(std::move(familyVec), weight, italic));  }  static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) { @@ -133,7 +135,7 @@ static const JNINativeMethod gTypefaceMethods[] = {      { "nativeUnref",              "(J)V",  (void*)Typeface_unref },      { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },      { "nativeGetBaseWeight",      "(J)I",  (void*)Typeface_getBaseWeight }, -    { "nativeCreateFromArray",    "([J)J", +    { "nativeCreateFromArray",    "([JII)J",                                             (void*)Typeface_createFromArray },      { "nativeSetDefault",         "(J)V",   (void*)Typeface_setDefault },      { "nativeGetSupportedAxes",   "(J)[I",  (void*)Typeface_getSupportedAxes }, diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 2aca7824539e..56f9cc71f782 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -173,7 +173,8 @@ public class Typeface {          if (sFallbackFonts != null) {              synchronized (sDynamicTypefaceCache) {                  final String key = Builder.createAssetUid( -                        mgr, path, 0 /* ttcIndex */, null /* axes */); +                        mgr, path, 0 /* ttcIndex */, null /* axes */, +                        RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);                  Typeface typeface = sDynamicTypefaceCache.get(key);                  if (typeface != null) return typeface; @@ -186,7 +187,8 @@ public class Typeface {                          return null;                      }                      FontFamily[] families = {fontFamily}; -                    typeface = createFromFamiliesWithDefault(families); +                    typeface = createFromFamiliesWithDefault(families, +                            RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);                      sDynamicTypefaceCache.put(key, typeface);                      return typeface;                  } @@ -251,10 +253,12 @@ public class Typeface {              fontFamily.allowUnsupportedFont();              fontFamily.freeze();              FontFamily[] familyChain = { fontFamily }; -            typeface = createFromFamiliesWithDefault(familyChain); +            typeface = createFromFamiliesWithDefault(familyChain, +                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);              synchronized (sDynamicTypefaceCache) {                  final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, -                        null /* axes */); +                        null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */, +                        RESOLVE_BY_FONT_TABLE /* italic */);                  sDynamicTypefaceCache.put(key, typeface);              }              return typeface; @@ -268,7 +272,8 @@ public class Typeface {       */      public static Typeface findFromCache(AssetManager mgr, String path) {          synchronized (sDynamicTypefaceCache) { -            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */); +            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */, +                    RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);              Typeface typeface = sDynamicTypefaceCache.get(key);              if (typeface != null) {                  return typeface; @@ -406,7 +411,9 @@ public class Typeface {                      FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);              return;          } -        Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily }); +        Typeface typeface = Typeface.createFromFamiliesWithDefault( +                new FontFamily[] { fontFamily }, +                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);          synchronized (sDynamicTypefaceCache) {              String key = createProviderUid(request.getProviderAuthority(), request.getQuery());              sDynamicTypefaceCache.put(key, typeface); @@ -715,7 +722,7 @@ public class Typeface {           * @return Unique id for a given AssetManager and asset path.           */          private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex, -                @Nullable FontVariationAxis[] axes) { +                @Nullable FontVariationAxis[] axes, int weight, int italic) {              final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();              final StringBuilder builder = new StringBuilder();              final int size = pkgs.size(); @@ -727,6 +734,10 @@ public class Typeface {              builder.append("-");              builder.append(Integer.toString(ttcIndex));              builder.append("-"); +            builder.append(Integer.toString(weight)); +            builder.append("-"); +            builder.append(Integer.toString(italic)); +            builder.append("-");              if (axes != null) {                  for (FontVariationAxis axis : axes) {                      builder.append(axis.getTag()); @@ -791,7 +802,7 @@ public class Typeface {           * @return Newly created Typeface. May return null if some parameters are invalid.           */          public Typeface build() { -            if (mFd != null) {  // set source by setSourceFromFile(FileDescriptor) +            if (mFd != null) {  // Builder is created with file descriptor.                  try (FileInputStream fis = new FileInputStream(mFd)) {                      FileChannel channel = fis.getChannel();                      long size = channel.size(); @@ -806,12 +817,13 @@ public class Typeface {                          return resolveFallbackTypeface();                      }                      FontFamily[] families = { fontFamily }; -                    return createFromFamiliesWithDefault(families); +                    return createFromFamiliesWithDefault(families, mWeight, mItalic);                  } catch (IOException e) {                      return resolveFallbackTypeface();                  } -            } else if (mAssetManager != null) {  // set source by setSourceFromAsset() -                final String key = createAssetUid(mAssetManager, mPath, mTtcIndex, mAxes); +            } else if (mAssetManager != null) {  // Builder is created with asset manager. +                final String key = createAssetUid( +                        mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic);                  synchronized (sLock) {                      Typeface typeface = sDynamicTypefaceCache.get(key);                      if (typeface != null) return typeface; @@ -825,11 +837,11 @@ public class Typeface {                          return resolveFallbackTypeface();                      }                      FontFamily[] families = { fontFamily }; -                    typeface = createFromFamiliesWithDefault(families); +                    typeface = createFromFamiliesWithDefault(families, mWeight, mItalic);                      sDynamicTypefaceCache.put(key, typeface);                      return typeface;                  } -            } else if (mPath != null) {  // set source by setSourceFromFile(File) +            } else if (mPath != null) {  // Builder is created with file path.                  final FontFamily fontFamily = new FontFamily();                  if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {                      fontFamily.abortCreation(); @@ -839,7 +851,7 @@ public class Typeface {                      return resolveFallbackTypeface();                  }                  FontFamily[] families = { fontFamily }; -                return createFromFamiliesWithDefault(families); +                return createFromFamiliesWithDefault(families, mWeight, mItalic);              } else if (mFonts != null) {                  final FontFamily fontFamily = new FontFamily();                  boolean atLeastOneFont = false; @@ -865,7 +877,7 @@ public class Typeface {                  }                  fontFamily.freeze();                  FontFamily[] families = { fontFamily }; -                return createFromFamiliesWithDefault(families); +                return createFromFamiliesWithDefault(families, mWeight, mItalic);              }              // Must not reach here. @@ -969,7 +981,7 @@ public class Typeface {                  if (typeface != null) return typeface;                  final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, -                        null /* axes */); +                        null /* axes */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);                  typeface = sDynamicTypefaceCache.get(key);                  if (typeface != null) return typeface; @@ -984,7 +996,8 @@ public class Typeface {                      fontFamily.allowUnsupportedFont();                      fontFamily.freeze();                      final FontFamily[] families = { fontFamily }; -                    typeface = createFromFamiliesWithDefault(families); +                    typeface = createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE, +                            RESOLVE_BY_FONT_TABLE);                      sDynamicTypefaceCache.put(key, typeface);                      return typeface;                  } else { @@ -1037,7 +1050,8 @@ public class Typeface {                  fontFamily.allowUnsupportedFont();                  fontFamily.freeze();                  FontFamily[] families = { fontFamily }; -                return createFromFamiliesWithDefault(families); +                return createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE, +                        RESOLVE_BY_FONT_TABLE);              } else {                  fontFamily.abortCreation();              } @@ -1055,16 +1069,25 @@ public class Typeface {          for (int i = 0; i < families.length; i++) {              ptrArray[i] = families[i].mNativePtr;          } -        return new Typeface(nativeCreateFromArray(ptrArray)); +        return new Typeface(nativeCreateFromArray( +                ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));      }      /**       * Create a new typeface from an array of font families, including       * also the font families in the fallback list. -     * +     * @param weight the weight for this family. {@link RESOLVE_BY_FONT_TABLE} can be used. In that +     *               case, the table information in the first family's font is used. If the first +     *               family has multiple fonts, the closest to the regular weight and upright font +     *               is used. +     * @param italic the italic information for this family. {@link RESOLVE_BY_FONT_TABLE} can be +     *               used. In that case, the table information in the first family's font is used. +     *               If the first family has multiple fonts, the closest to the regular weight and +     *               upright font is used.       * @param families array of font families       */ -    private static Typeface createFromFamiliesWithDefault(FontFamily[] families) { +    private static Typeface createFromFamiliesWithDefault(FontFamily[] families, +                int weight, int italic) {          long[] ptrArray = new long[families.length + sFallbackFonts.length];          for (int i = 0; i < families.length; i++) {              ptrArray[i] = families[i].mNativePtr; @@ -1072,7 +1095,7 @@ public class Typeface {          for (int i = 0; i < sFallbackFonts.length; i++) {              ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr;          } -        return new Typeface(nativeCreateFromArray(ptrArray)); +        return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));      }      // don't allow clients to call this directly @@ -1155,7 +1178,8 @@ public class Typeface {                      } else {                          FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);                          FontFamily[] families = { fontFamily }; -                        typeface = Typeface.createFromFamiliesWithDefault(families); +                        typeface = Typeface.createFromFamiliesWithDefault(families, +                                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);                      }                      systemFonts.put(f.getName(), typeface);                  } @@ -1262,7 +1286,7 @@ public class Typeface {      private static native void nativeUnref(long native_instance);      private static native int  nativeGetStyle(long native_instance);      private static native int  nativeGetBaseWeight(long native_instance); -    private static native long nativeCreateFromArray(long[] familyArray); +    private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);      private static native void nativeSetDefault(long native_instance);      private static native int[] nativeGetSupportedAxes(long native_instance);  } diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index 86709ee3a1fa..4fb4b53346e0 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -39,14 +39,22 @@  namespace android { -// Resolve the 1..9 weight based on base weight and bold flag +// This indicates that the passed information should be resolved by OS/2 table. +// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE. +constexpr int RESOLVE_BY_FONT_TABLE = -1; + +// Resolve the 1..10 weight based on base weight and bold flag  static void resolveStyle(Typeface* typeface) { -    int weight = typeface->fBaseWeight / 100; +    // TODO: Better to use raw base weight value for font selection instead of dividing by 100. +    int weight = (typeface->fBaseWeight + 50) / 100;      if (typeface->fSkiaStyle & SkTypeface::kBold) {          weight += 3;      } -    if (weight > 9) { -        weight = 9; +    if (weight > 10) { +        weight = 10; +    } +    if (weight < 1) { +        weight = 1;      }      bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;      typeface->fStyle = minikin::FontStyle(weight, italic); @@ -115,26 +123,50 @@ Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {  }  Typeface* Typeface::createFromFamilies( -        std::vector<std::shared_ptr<minikin::FontFamily>>&& families) { +        std::vector<std::shared_ptr<minikin::FontFamily>>&& families, +        int weight, int italic) {      Typeface* result = new Typeface;      result->fFontCollection.reset(new minikin::FontCollection(families)); -    if (families.empty()) { -        ALOGW("createFromFamilies creating empty collection"); -        result->fSkiaStyle = SkTypeface::kNormal; -    } else { + +    if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) { +        int weightFromFont; +        bool italicFromFont; +          const minikin::FontStyle defaultStyle; -        const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0]; -        const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; +        const minikin::MinikinFont* mf = +                families.empty() ?  nullptr : families[0]->getClosestMatch(defaultStyle).font;          if (mf != nullptr) {              SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface(); -            // TODO: probably better to query more precise style from family, will be important -            // when we open up API to access 100..900 weights -            result->fSkiaStyle = skTypeface->style(); +            const SkFontStyle& style = skTypeface->fontStyle(); +            weightFromFont = style.weight(); +            italicFromFont = style.slant() != SkFontStyle::kUpright_Slant;          } else { -            result->fSkiaStyle = SkTypeface::kNormal; +            // We can't obtain any information from fonts. Just use default values. +            weightFromFont = SkFontStyle::kNormal_Weight; +            italicFromFont = false; +        } + +        if (weight == RESOLVE_BY_FONT_TABLE) { +            weight = weightFromFont; +        } +        if (italic == RESOLVE_BY_FONT_TABLE) { +            italic = italicFromFont? 1 : 0;          }      } -    result->fBaseWeight = 400; + +    // Sanitize the invalid value passed from public API. +    if (weight < 0) { +        weight = SkFontStyle::kNormal_Weight; +    } + +    result->fBaseWeight = weight; +    // This bold detection comes from SkTypefae.h +    const bool isBold = weight >= SkFontStyle::kSemiBold_Weight; +    const bool isItalic = italic == 1; +    // TODO: remove fSkiaStyle +    result->fSkiaStyle = isBold ? +            (isItalic ? SkTypeface::kBoldItalic : SkTypeface::kBold) : +            (isItalic ? SkTypeface::kItalic : SkTypeface::kNormal);      resolveStyle(result);      return result;  } @@ -165,7 +197,7 @@ void Typeface::setRobotoTypefaceForTest() {      Typeface* hwTypeface = new Typeface();      hwTypeface->fFontCollection = collection;      hwTypeface->fSkiaStyle = SkTypeface::kNormal; -    hwTypeface->fBaseWeight = 400; +    hwTypeface->fBaseWeight = SkFontStyle::kSemiBold_Weight;      hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);      Typeface::setDefault(hwTypeface); diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h index 27ee4a2a35aa..e35a7b46c4b2 100644 --- a/libs/hwui/hwui/Typeface.h +++ b/libs/hwui/hwui/Typeface.h @@ -50,7 +50,8 @@ struct ANDROID_API Typeface {      static Typeface* createWeightAlias(Typeface* src, int baseweight);      static Typeface* createFromFamilies( -            std::vector<std::shared_ptr<minikin::FontFamily>>&& families); +            std::vector<std::shared_ptr<minikin::FontFamily>>&& families, +            int weight, int italic);      static void setDefault(Typeface* face);  |