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 #include "Typeface.h" 18 19 #include <fcntl.h> // For tests. 20 #include <pthread.h> 21 #include <sys/mman.h> // For tests. 22 #include <sys/stat.h> // For tests. 23 24 #include "MinikinSkia.h" 25 #include "SkPaint.h" 26 #include "SkStream.h" // Fot tests. 27 #include "SkTypeface.h" 28 29 #include <minikin/FontCollection.h> 30 #include <minikin/FontFamily.h> 31 #include <minikin/Layout.h> 32 #include <utils/Log.h> 33 #include <utils/MathUtils.h> 34 35 namespace android { 36 37 static Typeface::Style computeAPIStyle(int weight, bool italic) { 38 // This bold detection comes from SkTypeface.h 39 if (weight >= SkFontStyle::kSemiBold_Weight) { 40 return italic ? Typeface::kBoldItalic : Typeface::kBold; 41 } else { 42 return italic ? Typeface::kItalic : Typeface::kNormal; 43 } 44 } 45 46 static minikin::FontStyle computeMinikinStyle(int weight, bool italic) { 47 return minikin::FontStyle(uirenderer::MathUtils::clamp(weight, 1, 1000), 48 static_cast<minikin::FontStyle::Slant>(italic)); 49 } 50 51 // Resolve the relative weight from the baseWeight and target style. 52 static minikin::FontStyle computeRelativeStyle(int baseWeight, Typeface::Style relativeStyle) { 53 int weight = baseWeight; 54 if ((relativeStyle & Typeface::kBold) != 0) { 55 weight += 300; 56 } 57 bool italic = (relativeStyle & Typeface::kItalic) != 0; 58 return computeMinikinStyle(weight, italic); 59 } 60 61 const Typeface* gDefaultTypeface = NULL; 62 63 const Typeface* Typeface::resolveDefault(const Typeface* src) { 64 LOG_ALWAYS_FATAL_IF(src == nullptr && gDefaultTypeface == nullptr); 65 return src == nullptr ? gDefaultTypeface : src; 66 } 67 68 Typeface* Typeface::createRelative(Typeface* src, Typeface::Style style) { 69 const Typeface* resolvedFace = Typeface::resolveDefault(src); 70 Typeface* result = new Typeface; 71 if (result != nullptr) { 72 result->fFontCollection = resolvedFace->fFontCollection; 73 result->fBaseWeight = resolvedFace->fBaseWeight; 74 result->fAPIStyle = style; 75 result->fStyle = computeRelativeStyle(result->fBaseWeight, style); 76 } 77 return result; 78 } 79 80 Typeface* Typeface::createAbsolute(Typeface* base, int weight, bool italic) { 81 const Typeface* resolvedFace = Typeface::resolveDefault(base); 82 Typeface* result = new Typeface(); 83 if (result != nullptr) { 84 result->fFontCollection = resolvedFace->fFontCollection; 85 result->fBaseWeight = resolvedFace->fBaseWeight; 86 result->fAPIStyle = computeAPIStyle(weight, italic); 87 result->fStyle = computeMinikinStyle(weight, italic); 88 } 89 return result; 90 } 91 92 Typeface* Typeface::createFromTypefaceWithVariation( 93 Typeface* src, const std::vector<minikin::FontVariation>& variations) { 94 const Typeface* resolvedFace = Typeface::resolveDefault(src); 95 Typeface* result = new Typeface(); 96 if (result != nullptr) { 97 result->fFontCollection = 98 resolvedFace->fFontCollection->createCollectionWithVariation(variations); 99 if (result->fFontCollection == nullptr) { 100 // None of passed axes are supported by this collection. 101 // So we will reuse the same collection with incrementing reference count. 102 result->fFontCollection = resolvedFace->fFontCollection; 103 } 104 // Do not update styles. 105 // TODO: We may want to update base weight if the 'wght' is specified. 106 result->fBaseWeight = resolvedFace->fBaseWeight; 107 result->fAPIStyle = resolvedFace->fAPIStyle; 108 result->fStyle = resolvedFace->fStyle; 109 } 110 return result; 111 } 112 113 Typeface* Typeface::createWithDifferentBaseWeight(Typeface* src, int weight) { 114 const Typeface* resolvedFace = Typeface::resolveDefault(src); 115 Typeface* result = new Typeface; 116 if (result != nullptr) { 117 result->fFontCollection = resolvedFace->fFontCollection; 118 result->fBaseWeight = weight; 119 result->fAPIStyle = resolvedFace->fAPIStyle; 120 result->fStyle = computeRelativeStyle(weight, result->fAPIStyle); 121 } 122 return result; 123 } 124 125 Typeface* Typeface::createFromFamilies(std::vector<std::shared_ptr<minikin::FontFamily>>&& families, 126 int weight, int italic) { 127 Typeface* result = new Typeface; 128 result->fFontCollection.reset(new minikin::FontCollection(families)); 129 130 if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) { 131 int weightFromFont; 132 bool italicFromFont; 133 134 const minikin::FontStyle defaultStyle; 135 const minikin::MinikinFont* mf = families.empty() ? nullptr 136 : families[0]->getClosestMatch(defaultStyle).font->typeface().get(); 137 if (mf != nullptr) { 138 SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface(); 139 const SkFontStyle& style = skTypeface->fontStyle(); 140 weightFromFont = style.weight(); 141 italicFromFont = style.slant() != SkFontStyle::kUpright_Slant; 142 } else { 143 // We can't obtain any information from fonts. Just use default values. 144 weightFromFont = SkFontStyle::kNormal_Weight; 145 italicFromFont = false; 146 } 147 148 if (weight == RESOLVE_BY_FONT_TABLE) { 149 weight = weightFromFont; 150 } 151 if (italic == RESOLVE_BY_FONT_TABLE) { 152 italic = italicFromFont ? 1 : 0; 153 } 154 } 155 156 // Sanitize the invalid value passed from public API. 157 if (weight < 0) { 158 weight = SkFontStyle::kNormal_Weight; 159 } 160 161 result->fBaseWeight = weight; 162 result->fAPIStyle = computeAPIStyle(weight, italic); 163 result->fStyle = computeMinikinStyle(weight, italic); 164 return result; 165 } 166 167 void Typeface::setDefault(const Typeface* face) { 168 gDefaultTypeface = face; 169 } 170 171 void Typeface::setRobotoTypefaceForTest() { 172 const char* kRobotoFont = "/system/fonts/Roboto-Regular.ttf"; 173 174 int fd = open(kRobotoFont, O_RDONLY); 175 LOG_ALWAYS_FATAL_IF(fd == -1, "Failed to open file %s", kRobotoFont); 176 struct stat st = {}; 177 LOG_ALWAYS_FATAL_IF(fstat(fd, &st) == -1, "Failed to stat file %s", kRobotoFont); 178 void* data = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0); 179 std::unique_ptr<SkMemoryStream> fontData(new SkMemoryStream(data, st.st_size)); 180 sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release()); 181 LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont); 182 183 std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>( 184 std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>()); 185 std::vector<minikin::Font> fonts; 186 fonts.push_back(minikin::Font::Builder(font).build()); 187 188 std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>( 189 std::make_shared<minikin::FontFamily>(std::move(fonts))); 190 191 Typeface* hwTypeface = new Typeface(); 192 hwTypeface->fFontCollection = collection; 193 hwTypeface->fAPIStyle = Typeface::kNormal; 194 hwTypeface->fBaseWeight = SkFontStyle::kNormal_Weight; 195 hwTypeface->fStyle = minikin::FontStyle(); 196 197 Typeface::setDefault(hwTypeface); 198 } 199 } // namespace android 200