TypefaceImpl.cpp revision a0cba0fde3e39723052a50e1f09e3b254da6c175
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 if (face != NULL) { 175 face->fFontCollection->Unref(); 176 } 177 delete face; 178} 179 180int TypefaceImpl_getStyle(TypefaceImpl* face) { 181 FontStyle style = face->fStyle; 182 int result = style.getItalic() ? SkTypeface::kItalic : 0; 183 if (style.getWeight() >= kBoldThreshold) { 184 result |= SkTypeface::kBold; 185 } 186 return result; 187} 188 189void TypefaceImpl_setDefault(TypefaceImpl* face) { 190 gDefaultTypeface = face; 191} 192 193#else // USE_MINIKIN 194 195/* Just use SkTypeface instead. */ 196 197typedef SkTypeface TypefaceImpl; 198 199TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 200 return SkTypeface::CreateFromTypeface(src, style); 201} 202 203TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 204 return SkTypeface::CreateFromName(name, style); 205} 206 207TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 208 return SkTypeface::CreateFromFile(filename); 209} 210 211TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 212 SkStream* stream = new AssetStreamAdaptor(asset, 213 AssetStreamAdaptor::kYes_OwnAsset, 214 AssetStreamAdaptor::kYes_HasMemoryBase); 215 SkTypeface* face = SkTypeface::CreateFromStream(stream); 216 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 217 // need to unref it here or it won't be freed later on 218 stream->unref(); 219 220 return face; 221} 222 223TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 224 // Should never be called in non-Minikin builds 225 return 0; 226} 227 228void TypefaceImpl_unref(TypefaceImpl* face) { 229 SkSafeUnref(face); 230} 231 232int TypefaceImpl_getStyle(TypefaceImpl* face) { 233 return face->style(); 234} 235 236void TypefaceImpl_setDefault(TypefaceImpl* face) { 237} 238 239#endif // USE_MINIKIN 240 241} 242