Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * This is the implementation of the Typeface object. Historically, it has
     19  * just been SkTypeface, but we are migrating to Minikin. For the time
     20  * being, that choice is hidden under the USE_MINIKIN compile-time flag.
     21  */
     22 
     23 #define LOG_TAG "TypefaceImpl"
     24 
     25 #include "jni.h"  // for jlong, remove when being passed proper type
     26 
     27 #include "SkTypeface.h"
     28 
     29 #include <vector>
     30 #include <minikin/FontCollection.h>
     31 #include <minikin/FontFamily.h>
     32 #include <minikin/Layout.h>
     33 #include "SkPaint.h"
     34 #include "MinikinSkia.h"
     35 
     36 #include "TypefaceImpl.h"
     37 #include "Utils.h"
     38 
     39 namespace android {
     40 
     41 // Resolve the 1..9 weight based on base weight and bold flag
     42 static void resolveStyle(TypefaceImpl* typeface) {
     43     int weight = typeface->fBaseWeight / 100;
     44     if (typeface->fSkiaStyle & SkTypeface::kBold) {
     45         weight += 3;
     46     }
     47     if (weight > 9) {
     48         weight = 9;
     49     }
     50     bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
     51     typeface->fStyle = FontStyle(weight, italic);
     52 }
     53 
     54 TypefaceImpl* gDefaultTypeface = NULL;
     55 pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
     56 
     57 // This installs a default typeface (from a hardcoded path) that allows
     58 // layouts to work (not crash on null pointer) before the default
     59 // typeface is set.
     60 // TODO: investigate why layouts are being created before Typeface.java
     61 // class initialization.
     62 static FontCollection *makeFontCollection() {
     63     std::vector<FontFamily *>typefaces;
     64     const char *fns[] = {
     65         "/system/fonts/Roboto-Regular.ttf",
     66     };
     67 
     68     FontFamily *family = new FontFamily();
     69     for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
     70         const char *fn = fns[i];
     71         ALOGD("makeFontCollection adding %s", fn);
     72         SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
     73         if (skFace != NULL) {
     74             MinikinFont *font = new MinikinFontSkia(skFace);
     75             family->addFont(font);
     76             font->Unref();
     77         } else {
     78             ALOGE("failed to create font %s", fn);
     79         }
     80     }
     81     typefaces.push_back(family);
     82 
     83     FontCollection *result = new FontCollection(typefaces);
     84     family->Unref();
     85     return result;
     86 }
     87 
     88 static void getDefaultTypefaceOnce() {
     89     Layout::init();
     90     if (gDefaultTypeface == NULL) {
     91         // We expect the client to set a default typeface, but provide a
     92         // default so we can make progress before that happens.
     93         gDefaultTypeface = new TypefaceImpl;
     94         gDefaultTypeface->fFontCollection = makeFontCollection();
     95         gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
     96         gDefaultTypeface->fBaseWeight = 400;
     97         resolveStyle(gDefaultTypeface);
     98     }
     99 }
    100 
    101 TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
    102     if (src == NULL) {
    103         pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
    104         return gDefaultTypeface;
    105     } else {
    106         return src;
    107     }
    108 }
    109 
    110 TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
    111     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
    112     TypefaceImpl* result = new TypefaceImpl;
    113     if (result != 0) {
    114         result->fFontCollection = resolvedFace->fFontCollection;
    115         result->fFontCollection->Ref();
    116         result->fSkiaStyle = style;
    117         result->fBaseWeight = resolvedFace->fBaseWeight;
    118         resolveStyle(result);
    119     }
    120     return result;
    121 }
    122 
    123 TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
    124     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
    125     TypefaceImpl* result = new TypefaceImpl;
    126     if (result != 0) {
    127         result->fFontCollection = resolvedFace->fFontCollection;
    128         result->fFontCollection->Ref();
    129         result->fSkiaStyle = resolvedFace->fSkiaStyle;
    130         result->fBaseWeight = weight;
    131         resolveStyle(result);
    132     }
    133     return result;
    134 }
    135 
    136 TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
    137     std::vector<FontFamily *>familyVec;
    138     for (size_t i = 0; i < size; i++) {
    139         FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
    140         familyVec.push_back(family);
    141     }
    142     TypefaceImpl* result = new TypefaceImpl;
    143     result->fFontCollection = new FontCollection(familyVec);
    144     if (size == 0) {
    145         ALOGW("createFromFamilies creating empty collection");
    146         result->fSkiaStyle = SkTypeface::kNormal;
    147     } else {
    148         const FontStyle defaultStyle;
    149         FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
    150         MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
    151         if (mf != NULL) {
    152             SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
    153             // TODO: probably better to query more precise style from family, will be important
    154             // when we open up API to access 100..900 weights
    155             result->fSkiaStyle = skTypeface->style();
    156         } else {
    157             result->fSkiaStyle = SkTypeface::kNormal;
    158         }
    159     }
    160     result->fBaseWeight = 400;
    161     resolveStyle(result);
    162     return result;
    163 }
    164 
    165 void TypefaceImpl_unref(TypefaceImpl* face) {
    166     if (face != NULL) {
    167         face->fFontCollection->Unref();
    168     }
    169     delete face;
    170 }
    171 
    172 int TypefaceImpl_getStyle(TypefaceImpl* face) {
    173     return face->fSkiaStyle;
    174 }
    175 
    176 void TypefaceImpl_setDefault(TypefaceImpl* face) {
    177     gDefaultTypeface = face;
    178 }
    179 
    180 }
    181