Typeface.cpp revision a3b9f2e3c66ec485f3b712560d52e31632a9cbe8
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#include "Typeface.h" 24 25#include <pthread.h> 26#include <fcntl.h> // For tests. 27#include <sys/stat.h> // For tests. 28#include <sys/mman.h> // For tests. 29 30#include "MinikinSkia.h" 31#include "SkTypeface.h" 32#include "SkPaint.h" 33#include "SkStream.h" // Fot tests. 34 35#include <minikin/FontCollection.h> 36#include <minikin/FontFamily.h> 37#include <minikin/Layout.h> 38#include <utils/Log.h> 39 40namespace android { 41 42// Resolve the 1..9 weight based on base weight and bold flag 43static void resolveStyle(Typeface* 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 = minikin::FontStyle(weight, italic); 53} 54 55Typeface* gDefaultTypeface = NULL; 56 57Typeface* Typeface::resolveDefault(Typeface* src) { 58 LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr); 59 return src == nullptr ? gDefaultTypeface : src; 60} 61 62Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) { 63 Typeface* resolvedFace = Typeface::resolveDefault(src); 64 Typeface* result = new Typeface; 65 if (result != 0) { 66 result->fFontCollection = resolvedFace->fFontCollection; 67 result->fFontCollection->Ref(); 68 result->fSkiaStyle = style; 69 result->fBaseWeight = resolvedFace->fBaseWeight; 70 resolveStyle(result); 71 } 72 return result; 73} 74 75Typeface* Typeface::createWeightAlias(Typeface* src, int weight) { 76 Typeface* resolvedFace = Typeface::resolveDefault(src); 77 Typeface* result = new Typeface; 78 if (result != 0) { 79 result->fFontCollection = resolvedFace->fFontCollection; 80 result->fFontCollection->Ref(); 81 result->fSkiaStyle = resolvedFace->fSkiaStyle; 82 result->fBaseWeight = weight; 83 resolveStyle(result); 84 } 85 return result; 86} 87 88Typeface* Typeface::createFromFamilies(const std::vector<minikin::FontFamily*>& families) { 89 Typeface* result = new Typeface; 90 result->fFontCollection = new minikin::FontCollection(families); 91 if (families.empty()) { 92 ALOGW("createFromFamilies creating empty collection"); 93 result->fSkiaStyle = SkTypeface::kNormal; 94 } else { 95 const minikin::FontStyle defaultStyle; 96 minikin::FontFamily* firstFamily = reinterpret_cast<minikin::FontFamily*>(families[0]); 97 minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; 98 if (mf != NULL) { 99 SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); 100 // TODO: probably better to query more precise style from family, will be important 101 // when we open up API to access 100..900 weights 102 result->fSkiaStyle = skTypeface->style(); 103 } else { 104 result->fSkiaStyle = SkTypeface::kNormal; 105 } 106 } 107 result->fBaseWeight = 400; 108 resolveStyle(result); 109 return result; 110} 111 112void Typeface::unref() { 113 fFontCollection->Unref(); 114 delete this; 115} 116 117void Typeface::setDefault(Typeface* face) { 118 gDefaultTypeface = face; 119} 120 121void Typeface::setRobotoTypefaceForTest() { 122 const char* kRobotoFont = "/system/fonts/Roboto-Regular.ttf"; 123 124 int fd = open(kRobotoFont, O_RDONLY); 125 LOG_ALWAYS_FATAL_IF(fd == -1, "Failed to open file %s", kRobotoFont); 126 struct stat st = {}; 127 LOG_ALWAYS_FATAL_IF(fstat(fd, &st) == -1, "Failed to stat file %s", kRobotoFont); 128 void* data = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0); 129 std::unique_ptr<SkMemoryStream> fontData(new SkMemoryStream(data, st.st_size)); 130 sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release()); 131 LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont); 132 133 minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0); 134 minikin::FontFamily* family = new minikin::FontFamily( 135 std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) })); 136 font->Unref(); 137 138 std::vector<minikin::FontFamily*> typefaces = { family }; 139 minikin::FontCollection *collection = new minikin::FontCollection(typefaces); 140 family->Unref(); 141 142 Typeface* hwTypeface = new Typeface(); 143 hwTypeface->fFontCollection = collection; 144 hwTypeface->fSkiaStyle = SkTypeface::kNormal; 145 hwTypeface->fBaseWeight = 400; 146 hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */); 147 148 Typeface::setDefault(hwTypeface); 149} 150 151} 152