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 "SkStream.h"
     28 #include "SkTypeface.h"
     29 
     30 #include <vector>
     31 #include <minikin/FontCollection.h>
     32 #include <minikin/FontFamily.h>
     33 #include <minikin/Layout.h>
     34 #include "SkPaint.h"
     35 #include "MinikinSkia.h"
     36 
     37 #include "TypefaceImpl.h"
     38 #include "Utils.h"
     39 
     40 namespace android {
     41 
     42 // Resolve the 1..9 weight based on base weight and bold flag
     43 static void resolveStyle(TypefaceImpl* typeface) {
     44     int weight = typeface->fBaseWeight / 100;
     45     if (typeface->fSkiaStyle & SkTypeface::kBold) {
     46         weight += 3;
     47     }
     48     if (weight > 9) {
     49         weight = 9;
     50     }
     51     bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
     52     typeface->fStyle = FontStyle(weight, italic);
     53 }
     54 
     55 TypefaceImpl* gDefaultTypeface = NULL;
     56 pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
     57 
     58 // This installs a default typeface (from a hardcoded path) that allows
     59 // layouts to work (not crash on null pointer) before the default
     60 // typeface is set.
     61 // TODO: investigate why layouts are being created before Typeface.java
     62 // class initialization.
     63 static FontCollection *makeFontCollection() {
     64     std::vector<FontFamily *>typefaces;
     65     const char *fns[] = {
     66         "/system/fonts/Roboto-Regular.ttf",
     67     };
     68 
     69     FontFamily *family = new FontFamily();
     70     for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
     71         const char *fn = fns[i];
     72         ALOGD("makeFontCollection adding %s", fn);
     73         SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
     74         if (skFace != NULL) {
     75             MinikinFont *font = new MinikinFontSkia(skFace);
     76             family->addFont(font);
     77             font->Unref();
     78         } else {
     79             ALOGE("failed to create font %s", fn);
     80         }
     81     }
     82     typefaces.push_back(family);
     83 
     84     FontCollection *result = new FontCollection(typefaces);
     85     family->Unref();
     86     return result;
     87 }
     88 
     89 static void getDefaultTypefaceOnce() {
     90     Layout::init();
     91     if (gDefaultTypeface == NULL) {
     92         // We expect the client to set a default typeface, but provide a
     93         // default so we can make progress before that happens.
     94         gDefaultTypeface = new TypefaceImpl;
     95         gDefaultTypeface->fFontCollection = makeFontCollection();
     96         gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
     97         gDefaultTypeface->fBaseWeight = 400;
     98         resolveStyle(gDefaultTypeface);
     99     }
    100 }
    101 
    102 TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
    103     if (src == NULL) {
    104         pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
    105         return gDefaultTypeface;
    106     } else {
    107         return src;
    108     }
    109 }
    110 
    111 TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
    112     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
    113     TypefaceImpl* result = new TypefaceImpl;
    114     if (result != 0) {
    115         result->fFontCollection = resolvedFace->fFontCollection;
    116         result->fFontCollection->Ref();
    117         result->fSkiaStyle = style;
    118         result->fBaseWeight = resolvedFace->fBaseWeight;
    119         resolveStyle(result);
    120     }
    121     return result;
    122 }
    123 
    124 TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
    125     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
    126     TypefaceImpl* result = new TypefaceImpl;
    127     if (result != 0) {
    128         result->fFontCollection = resolvedFace->fFontCollection;
    129         result->fFontCollection->Ref();
    130         result->fSkiaStyle = resolvedFace->fSkiaStyle;
    131         result->fBaseWeight = weight;
    132         resolveStyle(result);
    133     }
    134     return result;
    135 }
    136 
    137 TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
    138     std::vector<FontFamily *>familyVec;
    139     for (size_t i = 0; i < size; i++) {
    140         FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
    141         familyVec.push_back(family);
    142     }
    143     TypefaceImpl* result = new TypefaceImpl;
    144     result->fFontCollection = new FontCollection(familyVec);
    145     if (size == 0) {
    146         ALOGW("createFromFamilies creating empty collection");
    147         result->fSkiaStyle = SkTypeface::kNormal;
    148     } else {
    149         const FontStyle defaultStyle;
    150         FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
    151         MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
    152         if (mf != NULL) {
    153             SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
    154             // TODO: probably better to query more precise style from family, will be important
    155             // when we open up API to access 100..900 weights
    156             result->fSkiaStyle = skTypeface->style();
    157         } else {
    158             result->fSkiaStyle = SkTypeface::kNormal;
    159         }
    160     }
    161     result->fBaseWeight = 400;
    162     resolveStyle(result);
    163     return result;
    164 }
    165 
    166 void TypefaceImpl_unref(TypefaceImpl* face) {
    167     if (face != NULL) {
    168         face->fFontCollection->Unref();
    169     }
    170     delete face;
    171 }
    172 
    173 int TypefaceImpl_getStyle(TypefaceImpl* face) {
    174     return face->fSkiaStyle;
    175 }
    176 
    177 void TypefaceImpl_setDefault(TypefaceImpl* face) {
    178     gDefaultTypeface = face;
    179 }
    180 
    181 }
    182