• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
resolveStyle(TypefaceImpl * typeface)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.
makeFontCollection()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 
getDefaultTypefaceOnce()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 
TypefaceImpl_resolveDefault(TypefaceImpl * src)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 
TypefaceImpl_createFromTypeface(TypefaceImpl * src,SkTypeface::Style style)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 
TypefaceImpl_createWeightAlias(TypefaceImpl * src,int weight)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 
TypefaceImpl_createFromFamilies(const jlong * families,size_t size)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 
TypefaceImpl_unref(TypefaceImpl * face)166 void TypefaceImpl_unref(TypefaceImpl* face) {
167     if (face != NULL) {
168         face->fFontCollection->Unref();
169     }
170     delete face;
171 }
172 
TypefaceImpl_getStyle(TypefaceImpl * face)173 int TypefaceImpl_getStyle(TypefaceImpl* face) {
174     return face->fSkiaStyle;
175 }
176 
TypefaceImpl_setDefault(TypefaceImpl * face)177 void TypefaceImpl_setDefault(TypefaceImpl* face) {
178     gDefaultTypeface = face;
179 }
180 
181 }
182