TypefaceImpl.cpp revision 15cf4757dc0099301662f8a26da561434cc07cfa
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#ifdef USE_MINIKIN 31#include <vector> 32#include <minikin/FontCollection.h> 33#include <minikin/FontFamily.h> 34#include <minikin/Layout.h> 35#include "MinikinSkia.h" 36#endif 37 38#include "TypefaceImpl.h" 39#include "Utils.h" 40 41namespace android { 42 43#ifdef USE_MINIKIN 44 45// Any weight greater than or equal to this is considered "bold" for 46// legacy API. 47static const int kBoldThreshold = 6; 48 49static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 50 int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 51 bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 52 return FontStyle(weight, italic); 53} 54 55TypefaceImpl* gDefaultTypeface = NULL; 56pthread_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. 63static 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 89static 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->fStyle = FontStyle(); 97 } 98} 99 100TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 101 if (src == NULL) { 102 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 103 return gDefaultTypeface; 104 } else { 105 return src; 106 } 107} 108 109TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 110 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 111 TypefaceImpl* result = new TypefaceImpl; 112 if (result != 0) { 113 result->fFontCollection = resolvedFace->fFontCollection; 114 result->fFontCollection->Ref(); 115 result->fStyle = styleFromSkiaStyle(style); 116 } 117 return result; 118} 119 120static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 121 if (typeface == NULL) { 122 return NULL; 123 } 124 MinikinFont* minikinFont = new MinikinFontSkia(typeface); 125 std::vector<FontFamily *> typefaces; 126 FontFamily* family = new FontFamily(); 127 family->addFont(minikinFont); 128 minikinFont->Unref(); 129 typefaces.push_back(family); 130 TypefaceImpl* result = new TypefaceImpl; 131 result->fFontCollection = new FontCollection(typefaces); 132 family->Unref(); 133 result->fStyle = FontStyle(); // TODO: improve 134 return result; 135} 136 137TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 138 // TODO: should create a font collection with all styles corresponding to 139 // the name 140 SkTypeface* face = SkTypeface::CreateFromName(name, style); 141 return createFromSkTypeface(face); 142} 143 144TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 145 SkTypeface* face = SkTypeface::CreateFromFile(filename); 146 return createFromSkTypeface(face); 147} 148 149TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 150 SkStream* stream = new AssetStreamAdaptor(asset, 151 AssetStreamAdaptor::kYes_OwnAsset, 152 AssetStreamAdaptor::kYes_HasMemoryBase); 153 SkTypeface* face = SkTypeface::CreateFromStream(stream); 154 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 155 // need to unref it here or it won't be freed later on 156 stream->unref(); 157 return createFromSkTypeface(face); 158} 159 160TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 161 ALOGD("createFromFamilies size=%d", size); 162 std::vector<FontFamily *>familyVec; 163 for (size_t i = 0; i < size; i++) { 164 FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 165 familyVec.push_back(family); 166 } 167 TypefaceImpl* result = new TypefaceImpl; 168 result->fFontCollection = new FontCollection(familyVec); 169 result->fStyle = FontStyle(); // TODO: improve 170 return result; 171} 172 173void TypefaceImpl_unref(TypefaceImpl* face) { 174 face->fFontCollection->Unref(); 175 delete face; 176} 177 178int TypefaceImpl_getStyle(TypefaceImpl* face) { 179 FontStyle style = face->fStyle; 180 int result = style.getItalic() ? SkTypeface::kItalic : 0; 181 if (style.getWeight() >= kBoldThreshold) { 182 result |= SkTypeface::kBold; 183 } 184 return result; 185} 186 187void TypefaceImpl_setDefault(TypefaceImpl* face) { 188 gDefaultTypeface = face; 189} 190 191#else // USE_MINIKIN 192 193/* Just use SkTypeface instead. */ 194 195typedef SkTypeface TypefaceImpl; 196 197TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 198 return SkTypeface::CreateFromTypeface(src, style); 199} 200 201TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 202 return SkTypeface::CreateFromName(name, style); 203} 204 205TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 206 return SkTypeface::CreateFromFile(filename); 207} 208 209TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 210 SkStream* stream = new AssetStreamAdaptor(asset, 211 AssetStreamAdaptor::kYes_OwnAsset, 212 AssetStreamAdaptor::kYes_HasMemoryBase); 213 SkTypeface* face = SkTypeface::CreateFromStream(stream); 214 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 215 // need to unref it here or it won't be freed later on 216 stream->unref(); 217 218 return face; 219} 220 221TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 222 // Should never be called in non-Minikin builds 223 return 0; 224} 225 226void TypefaceImpl_unref(TypefaceImpl* face) { 227 SkSafeUnref(face); 228} 229 230int TypefaceImpl_getStyle(TypefaceImpl* face) { 231 return face->style(); 232} 233 234void TypefaceImpl_setDefault(TypefaceImpl* face) { 235} 236 237#endif // USE_MINIKIN 238 239} 240