TypefaceImpl.cpp revision e95b5850ac2e56330abf68362451e7614b3dfe16
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 "SkPaint.h" 36#include "MinikinSkia.h" 37#endif 38 39#include "TypefaceImpl.h" 40#include "Utils.h" 41 42namespace android { 43 44#ifdef USE_MINIKIN 45 46// Any weight greater than or equal to this is considered "bold" for 47// legacy API. 48static const int kBoldThreshold = 6; 49 50static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 51 int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 52 bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 53 return FontStyle(weight, italic); 54} 55 56TypefaceImpl* gDefaultTypeface = NULL; 57pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 58 59// This installs a default typeface (from a hardcoded path) that allows 60// layouts to work (not crash on null pointer) before the default 61// typeface is set. 62// TODO: investigate why layouts are being created before Typeface.java 63// class initialization. 64static FontCollection *makeFontCollection() { 65 std::vector<FontFamily *>typefaces; 66 const char *fns[] = { 67 "/system/fonts/Roboto-Regular.ttf", 68 }; 69 70 FontFamily *family = new FontFamily(); 71 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 72 const char *fn = fns[i]; 73 ALOGD("makeFontCollection adding %s", fn); 74 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 75 if (skFace != NULL) { 76 MinikinFont *font = new MinikinFontSkia(skFace); 77 family->addFont(font); 78 font->Unref(); 79 } else { 80 ALOGE("failed to create font %s", fn); 81 } 82 } 83 typefaces.push_back(family); 84 85 FontCollection *result = new FontCollection(typefaces); 86 family->Unref(); 87 return result; 88} 89 90static void getDefaultTypefaceOnce() { 91 Layout::init(); 92 if (gDefaultTypeface == NULL) { 93 // We expect the client to set a default typeface, but provide a 94 // default so we can make progress before that happens. 95 gDefaultTypeface = new TypefaceImpl; 96 gDefaultTypeface->fFontCollection = makeFontCollection(); 97 gDefaultTypeface->fStyle = FontStyle(); 98 } 99} 100 101TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 102 if (src == NULL) { 103 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 104 return gDefaultTypeface; 105 } else { 106 return src; 107 } 108} 109 110TypefaceImpl* 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->fStyle = styleFromSkiaStyle(style); 117 } 118 return result; 119} 120 121static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 122 if (typeface == NULL) { 123 return NULL; 124 } 125 MinikinFont* minikinFont = new MinikinFontSkia(typeface); 126 std::vector<FontFamily *> typefaces; 127 FontFamily* family = new FontFamily(); 128 family->addFont(minikinFont); 129 minikinFont->Unref(); 130 typefaces.push_back(family); 131 TypefaceImpl* result = new TypefaceImpl; 132 result->fFontCollection = new FontCollection(typefaces); 133 family->Unref(); 134 result->fStyle = FontStyle(); // TODO: improve 135 return result; 136} 137 138TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 139 // TODO: should create a font collection with all styles corresponding to 140 // the name 141 SkTypeface* face = SkTypeface::CreateFromName(name, style); 142 return createFromSkTypeface(face); 143} 144 145TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 146 SkTypeface* face = SkTypeface::CreateFromFile(filename); 147 return createFromSkTypeface(face); 148} 149 150TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 151 SkStream* stream = new AssetStreamAdaptor(asset, 152 AssetStreamAdaptor::kYes_OwnAsset, 153 AssetStreamAdaptor::kYes_HasMemoryBase); 154 SkTypeface* face = SkTypeface::CreateFromStream(stream); 155 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 156 // need to unref it here or it won't be freed later on 157 stream->unref(); 158 return createFromSkTypeface(face); 159} 160 161TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 162 ALOGD("createFromFamilies size=%d", size); 163 std::vector<FontFamily *>familyVec; 164 for (size_t i = 0; i < size; i++) { 165 FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 166 familyVec.push_back(family); 167 } 168 TypefaceImpl* result = new TypefaceImpl; 169 result->fFontCollection = new FontCollection(familyVec); 170 result->fStyle = FontStyle(); // TODO: improve 171 return result; 172} 173 174void TypefaceImpl_unref(TypefaceImpl* face) { 175 if (face != NULL) { 176 face->fFontCollection->Unref(); 177 } 178 delete face; 179} 180 181int TypefaceImpl_getStyle(TypefaceImpl* face) { 182 FontStyle style = face->fStyle; 183 int result = style.getItalic() ? SkTypeface::kItalic : 0; 184 if (style.getWeight() >= kBoldThreshold) { 185 result |= SkTypeface::kBold; 186 } 187 return result; 188} 189 190void TypefaceImpl_setDefault(TypefaceImpl* face) { 191 gDefaultTypeface = face; 192} 193 194#else // USE_MINIKIN 195 196/* Just use SkTypeface instead. */ 197 198typedef SkTypeface TypefaceImpl; 199 200TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 201 return SkTypeface::CreateFromTypeface(src, style); 202} 203 204TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 205 return SkTypeface::CreateFromName(name, style); 206} 207 208TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 209 return SkTypeface::CreateFromFile(filename); 210} 211 212TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 213 SkStream* stream = new AssetStreamAdaptor(asset, 214 AssetStreamAdaptor::kYes_OwnAsset, 215 AssetStreamAdaptor::kYes_HasMemoryBase); 216 SkTypeface* face = SkTypeface::CreateFromStream(stream); 217 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 218 // need to unref it here or it won't be freed later on 219 stream->unref(); 220 221 return face; 222} 223 224TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 225 // Should never be called in non-Minikin builds 226 return 0; 227} 228 229void TypefaceImpl_unref(TypefaceImpl* face) { 230 SkSafeUnref(face); 231} 232 233int TypefaceImpl_getStyle(TypefaceImpl* face) { 234 return face->style(); 235} 236 237void TypefaceImpl_setDefault(TypefaceImpl* face) { 238} 239 240#endif // USE_MINIKIN 241 242} 243