sk_sp<SkTypeface> emoji_typeface() { if (!strcmp(sk_tool_utils::platform_os_emoji(), "CBDT")) { return MakeResourceAsTypeface("/fonts/Funkster.ttf"); } if (!strcmp(sk_tool_utils::platform_os_emoji(), "SBIX")) { return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle()); } if (!strcmp(sk_tool_utils::platform_os_emoji(), "COLR")) { sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); const char *colorEmojiFontName = "Segoe UI Emoji"; sk_sp<SkTypeface> typeface(fm->matchFamilyStyle(colorEmojiFontName, SkFontStyle())); if (typeface) { return typeface; } sk_sp<SkTypeface> fallback(fm->matchFamilyStyleCharacter( colorEmojiFontName, SkFontStyle(), nullptr /* bcp47 */, 0 /* bcp47Count */, 0x1f4b0 /* character: 💰 */)); if (fallback) { return fallback; } // If we don't have Segoe UI Emoji and can't find a fallback, try Segoe UI Symbol. // Windows 7 does not have Segoe UI Emoji; Segoe UI Symbol has the (non - color) emoji. return SkTypeface::MakeFromName("Segoe UI Symbol", SkFontStyle()); } return nullptr; }
static sk_sp<SkTypeface> chinese_typeface() { #ifdef SK_BUILD_FOR_ANDROID return MakeResourceAsTypeface("fonts/NotoSansCJK-Regular.ttc"); #elif defined(SK_BUILD_FOR_WIN) return SkTypeface::MakeFromName("SimSun", SkFontStyle()); #elif defined(SK_BUILD_FOR_MAC) return SkTypeface::MakeFromName("Hiragino Sans GB W3", SkFontStyle()); #elif defined(SK_BUILD_FOR_IOS) return SkTypeface::MakeFromName("Hiragino Sans GB W3", SkFontStyle()); #elif defined(SK_BUILD_FOR_UNIX) return SkTypeface::MakeFromName("Noto Sans CJK SC", SkFontStyle()); #else return nullptr; #endif }
explicit SkFontStyleSet_Android(const FontFamily& family, const SkTypeface_FreeType::Scanner& scanner) { const SkString* cannonicalFamilyName = NULL; if (family.fNames.count() > 0) { cannonicalFamilyName = &family.fNames[0]; } // TODO? make this lazy for (int i = 0; i < family.fFonts.count(); ++i) { const FontFileInfo& fontFile = family.fFonts[i]; SkString pathName(family.fBasePath); pathName.append(fontFile.fFileName); SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str())); if (!stream.get()) { SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n", pathName.c_str())); continue; } const int ttcIndex = fontFile.fIndex; SkString familyName; SkFontStyle style; bool isFixedWidth; if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) { SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n", pathName.c_str())); continue; } int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight(); SkFontStyle::Slant slant = style.slant(); switch (fontFile.fStyle) { case FontFileInfo::Style::kAuto: slant = style.slant(); break; case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break; case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break; default: SkASSERT(false); break; } style = SkFontStyle(weight, style.width(), slant); const SkLanguage& lang = family.fLanguage; uint32_t variant = family.fVariant; if (kDefault_FontVariant == variant) { variant = kCompact_FontVariant | kElegant_FontVariant; } // The first specified family name overrides the family name found in the font. // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return // all of the specified family names in addition to the names found in the font. if (cannonicalFamilyName != NULL) { familyName = *cannonicalFamilyName; } fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, (pathName, ttcIndex, style, isFixedWidth, familyName, lang, variant))); } }
explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(NULL) { loader.loadSystemFonts(fScanner, &fFamilies); // Try to pick a default font. static const char* defaultNames[] = { "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL }; for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { SkFontStyleSet_Custom* set = this->onMatchFamily(defaultNames[i]); if (NULL == set) { continue; } SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant)); if (NULL == tf) { continue; } fDefaultFamily = set; break; } if (NULL == fDefaultFamily) { fDefaultFamily = fFamilies[0]; } }
BevelView() : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize)) , fControlPanel(kCtrlRange) { this->setBGColor(0xFF666868); // Slightly colorized gray for contrast // Controls fBevelWidth = 25.0f; fBevelHeight = 25.0f; fBevelType = 0; int currLight = 0; fLightDefs[currLight++] = {SkVector::Make(0.0f, 1.0f), 1.0f, SkColor3f::Make(0.6f, 0.45f, 0.3f)}; fLightDefs[currLight++] = {SkVector::Make(0.0f, -1.0f), 1.0f, SkColor3f::Make(0.3f, 0.45f, 0.6f)}; fLightDefs[currLight++] = {SkVector::Make(1.0f, 0.0f), 1.0f, SkColor3f::Make(0.0f, 0.0f, 0.0f)}; // Making sure we initialized all lights SkASSERT(currLight == kNumLights); fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelWidth"), &fBevelWidth, 1.0f, kShapeBoundsSize)); fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelHeight"), &fBevelHeight, -50.0f, 50.0f)); fControlPanel.add(DiscreteSliderControl::Make(SkString("BevelType"), &fBevelType, 0, 2)); sk_sp<ParentControl> lightCtrlSelector = ControlSwitcher::Make(SkString("SelectedLight")); for (int i = 0; i < kNumLights; i++) { SkString name("Light"); name.appendS32(i); sk_sp<ParentControl> currLightPanel = ControlPanel::Make(); SkString dirName(name); dirName.append("Dir"); currLightPanel->add(RadialDirectionControl::Make(dirName, &(fLightDefs[i].fDirXY))); SkString heightName(name); heightName.append("Height"); currLightPanel->add(ContinuousSliderControl::Make(heightName, &(fLightDefs[i].fDirZ), 0.0f, 2.0f)); SkString redName(name); redName.append("Red"); currLightPanel->add(ContinuousSliderControl::Make(redName, &(fLightDefs[i].fColor.fX), 0.0f, 1.0f)); SkString greenName(name); greenName.append("Green"); currLightPanel->add(ContinuousSliderControl::Make(greenName, &(fLightDefs[i].fColor.fY), 0.0f, 1.0f)); SkString blueName(name); blueName.append("Blue"); currLightPanel->add(ContinuousSliderControl::Make(blueName, &(fLightDefs[i].fColor.fZ), 0.0f, 1.0f)); currLightPanel->add(ColorDisplay::Make(&(fLightDefs[i].fColor))); lightCtrlSelector->add(currLightPanel); } fControlPanel.add(lightCtrlSelector); fControlPanelSelected = false; fDirtyNormalSource = true; fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle()); }
static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, const uint8_t* data, size_t size, int index, SkFontMgr_Custom::Families* families) { SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false)); int numFaces; if (!scanner.recognizedFont(stream, &numFaces)) { SkDebugf("---- failed to open <%d> as a font\n", index); return; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) { SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); return; } SkTypeface_Custom* tf = new SkTypeface_Stream(style, isFixedPitch, true, // system-font (cannot delete) realname, stream.release(), faceIndex); SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (nullptr == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } addTo->appendTypeface(tf); } }
void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) { SkTScopedComPtr<IDWriteFont> font; HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); if (fs) { SkFontStyle::Slant slant; switch (font->GetStyle()) { case DWRITE_FONT_STYLE_NORMAL: slant = SkFontStyle::kUpright_Slant; break; case DWRITE_FONT_STYLE_OBLIQUE: case DWRITE_FONT_STYLE_ITALIC: slant = SkFontStyle::kItalic_Slant; break; default: SkASSERT(false); } int weight = font->GetWeight(); int width = font->GetStretch(); *fs = SkFontStyle(weight, width, slant); } if (styleName) { SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; if (SUCCEEDED(font->GetFaceNames(&faceNames))) { sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName); } } }
SkFontStyle FontDescription::skiaFontStyle() const { int width = static_cast<int>(stretch()); SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant; switch (style()) { case FontStyleNormal: slant = SkFontStyle::kUpright_Slant; break; case FontStyleItalic: slant = SkFontStyle::kItalic_Slant; break; case FontStyleOblique: slant = SkFontStyle::kOblique_Slant; break; default: NOTREACHED(); break; } return SkFontStyle(numericFontWeight(weight()), width, slant); static_assert( static_cast<int>(FontStretchUltraCondensed) == static_cast<int>(SkFontStyle::kUltraCondensed_Width), "FontStretchUltraCondensed should map to kUltraCondensed_Width"); static_assert(static_cast<int>(FontStretchNormal) == static_cast<int>(SkFontStyle::kNormal_Width), "FontStretchNormal should map to kNormal_Width"); static_assert(static_cast<int>(FontStretchUltraExpanded) == static_cast<int>(SkFontStyle::kUltraExpanded_Width), "FontStretchUltraExpanded should map to kUltraExpanded_Width"); }
DEF_TEST(Typeface, reporter) { sk_sp<SkTypeface> t1(SkTypeface::MakeFromName(nullptr, SkFontStyle())); sk_sp<SkTypeface> t2(SkTypeface::MakeDefault(SkTypeface::kNormal)); REPORTER_ASSERT(reporter, SkTypeface::Equal(t1.get(), t2.get())); REPORTER_ASSERT(reporter, SkTypeface::Equal(0, t1.get())); REPORTER_ASSERT(reporter, SkTypeface::Equal(0, t2.get())); REPORTER_ASSERT(reporter, SkTypeface::Equal(t1.get(), 0)); REPORTER_ASSERT(reporter, SkTypeface::Equal(t2.get(), 0)); #ifdef SK_BUILD_FOR_ANDROID sk_sp<SkTypeface> t3(SkTypeface::MakeFromName("non-existent-font", SkFontStyle())); REPORTER_ASSERT(reporter, nullptr == t3); #endif }
static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, const uint8_t* data, size_t size, int index, SkFontMgr_Custom::Families* families) { auto stream = skstd::make_unique<SkMemoryStream>(data, size, false); int numFaces; if (!scanner.recognizedFont(stream.get(), &numFaces)) { SkDebugf("---- failed to open <%d> as a font\n", index); return; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream.get(), faceIndex, &realname, &style, &isFixedPitch, nullptr)) { SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); return; } SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (nullptr == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0); addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data), style, isFixedPitch, true, realname)); } }
void onDelayedSetup() override { int maxGlyphs = 0; for (int i = 0; i < fLineCount; i++) { fLines.emplace_back(this->convertLine(i)); maxGlyphs = std::max(maxGlyphs, fLines.back()->glyphCount); } fGlyphIds.insert(fGlyphIds.begin(), maxGlyphs, 0); fTypeface = SkTypeface::MakeFromName("monospace", SkFontStyle()); }
static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, const SkString& directory, const char* suffix, SkFontMgr_Custom::Families* families) { SkOSFile::Iter iter(directory.c_str(), suffix); SkString name; while (iter.next(&name, false)) { SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str())); if (!stream.get()) { SkDebugf("---- failed to open <%s>\n", filename.c_str()); continue; } int numFaces; if (!scanner.recognizedFont(stream, &numFaces)) { SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); continue; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, NULL)) { SkDebugf("---- failed to open <%s> <%d> as a font\n", filename.c_str(), faceIndex); continue; } SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( style, isFixedPitch, true, // system-font (cannot delete) realname, filename.c_str(), faceIndex)); SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (NULL == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } addTo->appendTypeface(tf); } } SkOSFile::Iter dirIter(directory.c_str()); while (dirIter.next(&name, true)) { if (name.startsWith(".")) { continue; } SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); load_directory_fonts(scanner, dirname, suffix, families); } }
void onOnceBeforeDraw() override { fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle()); SkFont font(fTypeface); size_t txtLen = strlen(fText); int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8); fGlyphs.append(glyphCount); font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount); }
void getStyle(int index, SkFontStyle* style, SkString* name) override { SkASSERT(index < fStyles.count()); bool bold = fStyles[index]->isBold(); bool italic = fStyles[index]->isItalic(); *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); name->reset(); }
void onOnceBeforeDraw() override { fTypeface = sk_tool_utils::create_portable_typeface("serif", SkFontStyle()); SkPaint p; p.setTypeface(fTypeface); size_t txtLen = strlen(fText); int glyphCount = p.textToGlyphs(fText, txtLen, nullptr); fGlyphs.append(glyphCount); p.textToGlyphs(fText, txtLen, fGlyphs.begin()); }
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override { SkFontStyle style = SkFontStyle(styleBits); if (familyName) { // On Android, we must return NULL when we can't find the requested // named typeface so that the system/app can provide their own recovery // mechanism. On other platforms we'd provide a typeface from the // default family instead. return this->onMatchFamilyStyle(familyName, style); } return fDefaultFamily->matchStyle(style); }
sk_sp<SkTypeface> emoji_typeface() { const char* filename; #if defined(SK_BUILD_FOR_WIN) filename = "fonts/colr.ttf"; #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) filename = "fonts/sbix.ttf"; #else filename = "fonts/cbdt.ttf"; #endif sk_sp<SkTypeface> typeface = MakeResourceAsTypeface(filename); if (typeface) { return typeface; } return SkTypeface::MakeFromName("Emoji", SkFontStyle()); }
size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr, size_t size) { SkRBuffer buffer(addr, size); fID = buffer.readU32(); fTTCIndex = buffer.readU32(); size_t strLen = buffer.readU32(); int weight = buffer.readU32(); int width = buffer.readU32(); SkFontStyle::Slant slant = (SkFontStyle::Slant)buffer.readU8(); fStyle = SkFontStyle(weight, width, slant); fString.resize(strLen); buffer.read(fString.writable_str(), strLen); buffer.skipToAlign4(); return buffer.pos(); // the actual number of bytes read }
// Draws a label for the component, using its name and a passed value. Does NOT modulate by // relative height, expects CTM to have been adjusted in advance. void drawLabel(SkCanvas *canvas, const SkString& valueStr) const { // TODO Cache this sk_sp<SkTypeface> fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle()); SkString label; label.append(fName); label.append(": "); label.append(valueStr); SkPaint labelPaint; labelPaint.setTypeface(fLabelTypeface); labelPaint.setAntiAlias(true); labelPaint.setColor(0xFFFFFFFF); labelPaint.setTextSize(12.0f); canvas->drawText(label.c_str(), label.size(), 0, kLabelHeight - 6.0f, labelPaint); }
sk_sp<SkTypeface> planet_typeface() { static const sk_sp<SkTypeface> planetTypeface = []() { const char* filename; #if defined(SK_BUILD_FOR_WIN) filename = "fonts/planetcolr.ttf"; #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) filename = "fonts/planetsbix.ttf"; #else filename = "fonts/planetcbdt.ttf"; #endif sk_sp<SkTypeface> typeface = MakeResourceAsTypeface(filename); if (typeface) { return typeface; } return SkTypeface::MakeFromName("Planet", SkFontStyle()); }(); return planetTypeface; }
void draw(SkCanvas* canvas) { const char* colors[] = { "Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x", "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16Norm", "RGBA_F16" }; SkPaint paint; SkFont font(SkTypeface::MakeFromName("monospace", SkFontStyle()), 10); int y = 15; canvas->drawString(" colorType bytes", 10, y, font, paint); for (SkColorType colorType : { kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType, kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType, kGray_8_SkColorType, kRGBA_F16_SkColorType } ) { int result = SkColorTypeBytesPerPixel(colorType); SkString string; string.printf("%13s %4d", colors[(int) colorType], result); canvas->drawString(string, 10, y += 14, font, paint); } }
size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr, size_t size) { SkRBuffer buffer(addr, size); (void)buffer.readU32(&fID); (void)buffer.readS32(&fTTCIndex); uint32_t strLen, weight, width; (void)buffer.readU32(&strLen); (void)buffer.readU32(&weight); (void)buffer.readU32(&width); uint8_t u8; (void)buffer.readU8(&u8); SkFontStyle::Slant slant = (SkFontStyle::Slant)u8; fStyle = SkFontStyle(weight, width, slant); fString.resize(strLen); (void)buffer.read(fString.writable_str(), strLen); buffer.skipToAlign4(); return buffer.pos(); // the actual number of bytes read }
SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) { if (!family) { return SkTypeface::RefDefault(s); } if (family->style() == s) { family->ref(); return const_cast<SkTypeface*>(family); } SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); bool bold = s & SkTypeface::kBold; bool italic = s & SkTypeface::kItalic; SkFontStyle newStyle = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); return fm->matchFaceStyle(family, newStyle); }
SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override { SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, oldStyle & SkTypeface::kItalic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); SkTypeface* tf = NULL; if (familyName) { tf = this->onMatchFamilyStyle(familyName, style); } if (NULL == tf) { tf = fDefaultFamily->matchStyle(style); } return SkSafeRef(tf); }
SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char familyName[], SkTypeface::Style style) { SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); if (nullptr == fci.get()) { return nullptr; } // Check if requested NameStyle is in the NameStyle cache. SkFontStyle requestedStyle(style); NameStyle nameStyle(familyName, requestedStyle); SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &nameStyle); if (face) { //SkDebugf("found cached face <%s> <%s> %p [%d]\n", // familyName, ((FontConfigTypeface*)face)->getFamilyName(), // face, face->getRefCnt()); return face; } SkFontConfigInterface::FontIdentity indentity; SkString outFamilyName; SkTypeface::Style outStyle; if (!fci->matchFamilyName(familyName, style, &indentity, &outFamilyName, &outStyle)) { return nullptr; } // Check if a typeface with this FontIdentity is already in the FontIdentity cache. face = SkTypefaceCache::FindByProcAndRef(find_by_FontIdentity, &indentity); if (!face) { face = FontConfigTypeface::Create(SkFontStyle(outStyle), indentity, outFamilyName); // Add this FontIdentity to the FontIdentity cache. SkTypefaceCache::Add(face, requestedStyle); } // TODO: Ensure requested NameStyle and resolved NameStyle are both in the NameStyle cache. //SkDebugf("add face <%s> <%s> %p [%d]\n", // familyName, outFamilyName.c_str(), // face, face->getRefCnt()); return face; }
SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const { bool bold = SkToBool(styleBits & SkTypeface::kBold); bool italic = SkToBool(styleBits & SkTypeface::kItalic); SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style)); if (nullptr == face.get()) { face.reset(this->matchFamilyStyle(nullptr, style)); } if (nullptr == face.get()) { SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style); face.reset(this->createTypefaceFromFontId(fontId)); } return face.release(); }
void findDefaultFont() { SkASSERT(!fFontStyleSets.empty()); static const char* gDefaultNames[] = { "sans-serif" }; for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); if (NULL == set) { continue; } SkTypeface* tf = set->matchStyle(SkFontStyle()); if (NULL == tf) { continue; } fDefaultFamily = set; fDefaultTypeface = tf; break; } if (NULL == fDefaultTypeface) { fDefaultFamily = fFontStyleSets[0]; fDefaultTypeface = fDefaultFamily->createTypeface(0); } SkASSERT(fDefaultFamily); SkASSERT(fDefaultTypeface); }
SkTypeface* matchStyle(const SkFontStyle& pattern) override { if (0 == fStyles.count()) { return NULL; } SkTypeface_Custom* closest = fStyles[0]; int minScore = std::numeric_limits<int>::max(); for (int i = 0; i < fStyles.count(); ++i) { bool bold = fStyles[i]->isBold(); bool italic = fStyles[i]->isItalic(); SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); int score = match_score(pattern, style); if (score < minScore) { closest = fStyles[i]; minScore = score; } } return SkRef(closest); }
static void make_iden(SkFontConfigInterface::FontIdentity* iden) { iden->fID = 10; iden->fTTCIndex = 2; iden->fString.set("Hello world"); iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant); }
virtual void onDraw(SkCanvas* inputCanvas) override { SkScalar textSizes[] = { 9.0f, 9.0f*2.0f, 9.0f*5.0f, 9.0f*2.0f*5.0f }; SkScalar scales[] = { 2.0f*5.0f, 5.0f, 2.0f, 1.0f }; // set up offscreen rendering with distance field text GrContext* ctx = inputCanvas->getGrContext(); SkISize size = onISize(); SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType, inputCanvas->imageInfo().refColorSpace()); SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, SkSurfaceProps::kLegacyFontHost_InitType); auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props)); SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas; // init our new canvas with the old canvas's matrix canvas->setMatrix(inputCanvas->getTotalMatrix()); // apply global scale to test glyph positioning canvas->scale(1.05f, 1.05f); canvas->clear(0xffffffff); SkPaint paint; paint.setAntiAlias(true); SkFont font(ToolUtils::create_portable_typeface("serif", SkFontStyle())); font.setSubpixel(true); const char* text = "Hamburgefons"; const size_t textLen = strlen(text); // check scaling up SkScalar x = SkIntToScalar(0); SkScalar y = SkIntToScalar(78); for (size_t i = 0; i < SK_ARRAY_COUNT(textSizes); ++i) { SkAutoCanvasRestore acr(canvas, true); canvas->translate(x, y); canvas->scale(scales[i], scales[i]); font.setSize(textSizes[i]); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint); y += font.getMetrics(nullptr)*scales[i]; } // check rotation for (size_t i = 0; i < 5; ++i) { SkScalar rotX = SkIntToScalar(10); SkScalar rotY = y; SkAutoCanvasRestore acr(canvas, true); canvas->translate(SkIntToScalar(10 + i * 200), -80); canvas->rotate(SkIntToScalar(i * 5), rotX, rotY); for (int ps = 6; ps <= 32; ps += 3) { font.setSize(SkIntToScalar(ps)); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, rotX, rotY, font, paint); rotY += font.getMetrics(nullptr); } } // check scaling down font.setEdging(SkFont::Edging::kSubpixelAntiAlias); x = SkIntToScalar(680); y = SkIntToScalar(20); size_t arraySize = SK_ARRAY_COUNT(textSizes); for (size_t i = 0; i < arraySize; ++i) { SkAutoCanvasRestore acr(canvas, true); canvas->translate(x, y); SkScalar scaleFactor = SkScalarInvert(scales[arraySize - i - 1]); canvas->scale(scaleFactor, scaleFactor); font.setSize(textSizes[i]); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint); y += font.getMetrics(nullptr)*scaleFactor; } // check pos text { SkAutoCanvasRestore acr(canvas, true); canvas->scale(2.0f, 2.0f); SkAutoTArray<SkGlyphID> glyphs(SkToInt(textLen)); int count = font.textToGlyphs(text, textLen, SkTextEncoding::kUTF8, glyphs.get(), textLen); SkAutoTArray<SkPoint> pos(count); font.setSize(textSizes[0]); font.getPos(glyphs.get(), count, pos.get(), {340, 75}); auto blob = SkTextBlob::MakeFromPosText(glyphs.get(), count * sizeof(SkGlyphID), pos.get(), font, SkTextEncoding::kGlyphID); canvas->drawTextBlob(blob, 0, 0, paint); } // check gamma-corrected blending const SkColor fg[] = { 0xFFFFFFFF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFF000000, }; paint.setColor(0xFFF7F3F7); SkRect r = SkRect::MakeLTRB(670, 215, 820, 397); canvas->drawRect(r, paint); x = SkIntToScalar(680); y = SkIntToScalar(235); font.setSize(SkIntToScalar(19)); for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { paint.setColor(fg[i]); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); y += font.getMetrics(nullptr); } paint.setColor(0xFF181C18); r = SkRect::MakeLTRB(820, 215, 970, 397); canvas->drawRect(r, paint); x = SkIntToScalar(830); y = SkIntToScalar(235); font.setSize(SkIntToScalar(19)); for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { paint.setColor(fg[i]); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); y += font.getMetrics(nullptr); } // check skew { font.setEdging(SkFont::Edging::kAntiAlias); SkAutoCanvasRestore acr(canvas, true); canvas->skew(0.0f, 0.151515f); font.setSize(SkIntToScalar(32)); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 745, 70, font, paint); } { font.setEdging(SkFont::Edging::kSubpixelAntiAlias); SkAutoCanvasRestore acr(canvas, true); canvas->skew(0.5f, 0.0f); font.setSize(SkIntToScalar(32)); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 580, 125, font, paint); } // check perspective { font.setEdging(SkFont::Edging::kAntiAlias); SkAutoCanvasRestore acr(canvas, true); SkMatrix persp; persp.setAll(0.9839f, 0, 0, 0.2246f, 0.6829f, 0, 0.0002352f, -0.0003844f, 1); canvas->concat(persp); canvas->translate(1100, -295); font.setSize(37.5f); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint); } { font.setSubpixel(false); font.setEdging(SkFont::Edging::kAlias); SkAutoCanvasRestore acr(canvas, true); SkMatrix persp; persp.setAll(0.9839f, 0, 0, 0.2246f, 0.6829f, 0, 0.0002352f, -0.0003844f, 1); canvas->concat(persp); canvas->translate(1075, -245); canvas->scale(375, 375); font.setSize(0.1f); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint); } // check color emoji if (fEmojiTypeface) { SkFont emoiFont; emoiFont.setSubpixel(true); emoiFont.setTypeface(fEmojiTypeface); emoiFont.setSize(SkIntToScalar(19)); canvas->drawSimpleText(fEmojiText, strlen(fEmojiText), SkTextEncoding::kUTF8, 670, 90, emoiFont, paint); } // render offscreen buffer if (surface) { SkAutoCanvasRestore acr(inputCanvas, true); // since we prepended this matrix already, we blit using identity inputCanvas->resetMatrix(); inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); } }