Glyph SimpleFontData::glyphForCharacter(UChar32 codepoint) const { uint16_t glyph; SkTypeface* typeface = platformData().typeface(); RELEASE_ASSERT(typeface); typeface->charsToGlyphs(&codepoint, SkTypeface::kUTF32_Encoding, &glyph, 1); return glyph; }
bool setFont(const char * pFontName = NULL, int nSize = 0) { bool bRet = false; if (m_pPaint) { delete m_pPaint; m_pPaint = NULL; } do { /* init paint */ m_pPaint = new SkPaint(); CC_BREAK_IF(! m_pPaint); m_pPaint->setColor(SK_ColorWHITE); m_pPaint->setTextSize(nSize); /* create font */ SkTypeface *pTypeFace = SkTypeface::CreateFromName(pFontName, SkTypeface::kNormal); if (! pTypeFace) { CC_SAFE_DELETE(m_pPaint); break; } m_pPaint->setTypeface( pTypeFace ); /* can not unref, I don't know why. It may be memory leak, but how to avoid? */ pTypeFace->unref(); bRet = true; } while (0); return bRet; }
GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx, SkGlyphCache* glyphCache) { SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface() : glyphCache->getScalerContext()->getTypeface(); const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getDescriptor(); static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain(); int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt(); GrUniqueKey glyphKey; GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCount); reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0; reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0; if (strokeDataCount > 0) { fStroke.asUniqueKeyFragment(&builder[2]); } builder.finish(); SkAutoTUnref<GrPathRange> glyphs( static_cast<GrPathRange*>( ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey))); if (nullptr == glyphs) { glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStroke)); ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs); } else { SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc)); } return glyphs.detach(); }
static void drawKernText(SkCanvas* canvas, const void* text, size_t len, SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) { SkTypeface* face = font.getTypefaceOrDefault(); if (!face) { canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint); return; } SkAutoSTMalloc<128, uint16_t> glyphStorage(len); uint16_t* glyphs = glyphStorage.get(); int glyphCount = font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len); if (glyphCount < 1) { return; } SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1); int32_t* adjustments = adjustmentStorage.get(); if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) { canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint); return; } SkTextBlobBuilder builder; auto rec = builder.allocRunPos(font, glyphCount); memcpy(rec.glyphs, glyphs, glyphCount * sizeof(SkGlyphID)); getGlyphPositions(font, glyphs, glyphCount, x, y, rec.points()); applyKerning(rec.points(), adjustments, glyphCount, font); canvas->drawTextBlob(builder.make(), 0, 0, paint); }
static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x, SkScalar y, SkPaint& paint, SkFontMgr* fm, const char* fontName, const char* bcp47[], int bcp47Count, const SkFontStyle& fontStyle) { // find typeface containing the requested character and draw it SkString ch; ch.appendUnichar(character); SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, bcp47, bcp47Count, character); SkSafeUnref(paint.setTypeface(typeface)); x = drawString(canvas, ch, x, y, paint) + 20; if (nullptr == typeface) { return x; } // repeat the process, but this time use the family name of the typeface // from the first pass. This emulates the behavior in Blink where it // it expects to get the same glyph when following this pattern. SkString familyName; typeface->getFamilyName(&familyName); SkTypeface* typefaceCopy = fm->legacyCreateTypeface(familyName.c_str(), typeface->fontStyle()); SkSafeUnref(paint.setTypeface(typefaceCopy)); return drawString(canvas, ch, x, y, paint) + 20; }
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { load_system_fonts(); SkAutoMutexAcquire ac(gFamilyMutex); // clip to legal style bits style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); SkTypeface* tf = NULL; if (NULL != familyFace) { tf = find_typeface(familyFace, style); } else if (NULL != familyName) { // SkDebugf("======= familyName <%s>\n", familyName); tf = find_typeface(familyName, style); } if (NULL == tf) { tf = find_best_face(gDefaultFamily, style); } // we ref(), since the symantic is to return a new instance tf->ref(); return tf; }
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const { if (U16_IS_LEAD(buffer[bufferLength-1])) { DLOG(ERROR) << "Last UTF-16 code unit is high-surrogate."; return false; } SkTypeface* typeface = platformData().typeface(); if (!typeface) { DLOG(ERROR) << "fillGlyphPage called on an empty Skia typeface."; return false; } SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length); uint16_t* glyphs = glyphStorage.get(); typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length); bool haveGlyphs = false; for (unsigned i = 0; i < length; i++) { if (glyphs[i]) { pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this); haveGlyphs = true; } } return haveGlyphs; }
// Return the context associated with the next logical typeface, or NULL if // there are no more entries in the fallback chain. SkScalerContext* SkScalerContext::allocNextContext() const { #ifdef SK_BUILD_FOR_ANDROID SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID, fRec.fOrigFontID, fPaintOptionsAndroid); if (0 == newFace) { return NULL; } SkAutoTUnref<SkTypeface> aur(newFace); uint32_t newFontID = newFace->uniqueID(); SkOrderedWriteBuffer androidBuffer(128); fPaintOptionsAndroid.flatten(androidBuffer); SkAutoDescriptor ad(sizeof(fRec) + androidBuffer.size() + SkDescriptor::ComputeOverhead(2)); SkDescriptor* desc = ad.getDesc(); desc->init(); SkScalerContext::Rec* newRec = (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(fRec), &fRec); androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag, androidBuffer.size(), NULL)); newRec->fFontID = newFontID; desc->computeChecksum(); return newFace->createScalerContext(desc); #else return NULL; #endif }
SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) { if (!SkTypeface_ValidScript(script)) { return NULL; } // ensure that our table is populated initFBScriptInfo(); FBScriptInfo& scriptInfo = gFBScriptInfo[script]; // ensure the element with that index actually maps to the correct script SkASSERT(scriptInfo.fScript == script); // if a suitable script could not be found then return NULL if (scriptInfo.fFontID == 0) { return NULL; } SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); // retrieve the typeface the corresponds to this fontID SkTypeface* tf = find_from_uniqueID(scriptInfo.fFontID); // we ref(), since the semantic is to return a new instance tf->ref(); return tf; }
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const { if (U16_IS_LEAD(buffer[bufferLength - 1])) { SkDebugf("%s last char is high-surrogate", __FUNCTION__); return false; } SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length); uint16_t* glyphs = glyphStorage.get(); SkTypeface* typeface = platformData().typeface(); typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length); bool haveGlyphs = false; for (unsigned i = 0; i < length; i++) { if (glyphs[i]) { pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this); haveGlyphs = true; } } return haveGlyphs; }
SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) { SkTDict<SkPdfStandardFontEntry>& standardFontMap = getStandardFonts(); SkTypeface* typeface = NULL; SkPdfStandardFontEntry fontData; if (standardFontMap.find(fontName, &fontData)) { // TODO(edisonn): How does the bold/italic specified in standard definition combines with // the one in /font key? use OR for now. bold = bold || fontData.fIsBold; italic = italic || fontData.fIsItalic; typeface = SkTypeface::CreateFromName( fontData.fName, SkTypeface::Style((bold ? SkTypeface::kBold : 0) | (italic ? SkTypeface::kItalic : 0))); } else { typeface = SkTypeface::CreateFromName( fontName, SkTypeface::kNormal); } if (typeface) { typeface->ref(); } return typeface; }
static void drawKernText(SkCanvas* canvas, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { SkTypeface* face = paint.getTypeface(); if (!face) { canvas->drawText(text, len, x, y, paint); return; } SkAutoSTMalloc<128, uint16_t> glyphStorage(len); uint16_t* glyphs = glyphStorage.get(); int glyphCount = paint.textToGlyphs(text, len, glyphs); if (glyphCount < 1) { return; } SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1); int32_t* adjustments = adjustmentStorage.get(); if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) { canvas->drawText(text, len, x, y, paint); return; } SkPaint glyphPaint(paint); glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount); SkPoint* pos = posStorage.get(); getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos); applyKerning(pos, adjustments, glyphCount, glyphPaint); canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint); }
FONTDef _DC::SelectObject(FONTDef font){ if( !context_ ) return NULL; if (_canvas) { LOGFONT lf; ::GetObject(font, sizeof(LOGFONT), &lf); SkTypeface::Style style = SkTypeface::Style::kNormal; if (lf.lfItalic) { if (lf.lfWidth == FW_BOLD) style = SkTypeface::Style::kBoldItalic; else style = SkTypeface::Style::kItalic; } else { if (lf.lfWidth == FW_BOLD) style = SkTypeface::Style::kBold; else style = SkTypeface::Style::kNormal; } SkTypeface* tf = SkTypeface::CreateFromName(lf.lfFaceName, style); _skPaintText.setTypeface(tf); _skPaintText.setAntiAlias(true); _skPaintText.setTextSize(SkIntToScalar(lf.lfHeight)); _skPaintText.setTextEncoding(SkPaint::TextEncoding::kUTF8_TextEncoding); tf->unref(); } return (FONTDef)::SelectObject(context_, font); }
static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text, size_t len, int glyphCount) { SkTypeface::Encoding encoding = paint2Encoding(paint); SkTypeface* face = paint.getTypeface(); for (int i = 0; i < loops; ++i) { face->charsToGlyphs(text, encoding, NULL, glyphCount); } }
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { const char* name = 0; CString s; if (family.length() == 0) { static const struct { FontDescription::GenericFamilyType mType; const char* mName; } fontDescriptions[] = { { FontDescription::SerifFamily, "serif" }, { FontDescription::SansSerifFamily, "sans-serif" }, { FontDescription::MonospaceFamily, "monospace" }, { FontDescription::CursiveFamily, "cursive" }, { FontDescription::FantasyFamily, "fantasy" } }; FontDescription::GenericFamilyType type = fontDescription.genericFamily(); for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) { if (type == fontDescriptions[i].mType) { name = fontDescriptions[i].mName; break; } } // if we fall out of the loop, it's ok for name to still be 0 } else { // convert the name to utf8 s = family.string().utf8(); name = s.data(); } int style = SkTypeface::kNormal; if (fontDescription.weight() >= FontWeightBold) style |= SkTypeface::kBold; if (fontDescription.italic()) style |= SkTypeface::kItalic; // FIXME: This #ifdef can go away once we're firmly using the new Skia. // During the transition, this makes the code compatible with both versions. #ifdef SK_USE_OLD_255_TO_256 SkTypeface* tf = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style)); #else SkTypeface* tf = SkTypeface::Create(name, static_cast<SkTypeface::Style>(style)); #endif if (!tf) return 0; FontPlatformData* result = new FontPlatformData(tf, fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic()); tf->unref(); return result; }
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { const char* name = 0; CString s; // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into // the fallback name (like "monospace") that fontconfig understands. if (!family.length() || family.startsWith("-webkit-")) { static const struct { FontDescription::GenericFamilyType mType; const char* mName; } fontDescriptions[] = { { FontDescription::SerifFamily, "serif" }, { FontDescription::SansSerifFamily, "sans-serif" }, { FontDescription::MonospaceFamily, "monospace" }, { FontDescription::CursiveFamily, "cursive" }, { FontDescription::FantasyFamily, "fantasy" } }; FontDescription::GenericFamilyType type = fontDescription.genericFamily(); for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) { if (type == fontDescriptions[i].mType) { name = fontDescriptions[i].mName; break; } } if (!name) name = ""; } else { // convert the name to utf8 s = family.string().utf8(); name = s.data(); } int style = SkTypeface::kNormal; if (fontDescription.weight() >= FontWeightBold) style |= SkTypeface::kBold; if (fontDescription.italic()) style |= SkTypeface::kItalic; SkTypeface* tf = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style)); if (!tf) return 0; FontPlatformData* result = new FontPlatformData(tf, name, fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic(), fontDescription.orientation(), fontDescription.textOrientation()); tf->unref(); return result; }
ACanvasSkia::~ACanvasSkia() { for(std::map<AString,SkTypeface*>::iterator it=m_aFontType.begin();it!=m_aFontType.end();it++) { SkTypeface* p = it->second; p->unref(); } m_aFontType.clear(); Free(); }
DEF_TEST(Paint_cmap, reporter) { // need to implement charsToGlyphs on other backends (e.g. linux, win) // before we can run this tests everywhere return; static const int NGLYPHS = 64; SkUnichar src[NGLYPHS]; SkUnichar dst[NGLYPHS]; // used for utf8, utf16, utf32 storage static const struct { size_t (*fSeedTextProc)(const SkUnichar[], void* dst, int count); SkPaint::TextEncoding fEncoding; } gRec[] = { { uni_to_utf8, SkPaint::kUTF8_TextEncoding }, { uni_to_utf16, SkPaint::kUTF16_TextEncoding }, { uni_to_utf32, SkPaint::kUTF32_TextEncoding }, }; SkRandom rand; SkPaint paint; paint.setTypeface(SkTypeface::RefDefault())->unref(); SkTypeface* face = paint.getTypeface(); for (int i = 0; i < 1000; ++i) { // generate some random text for (int j = 0; j < NGLYPHS; ++j) { src[j] = ' ' + j; } // inject some random chars, to sometimes abort early src[rand.nextU() & 63] = rand.nextU() & 0xFFF; for (size_t k = 0; k < SK_ARRAY_COUNT(gRec); ++k) { paint.setTextEncoding(gRec[k].fEncoding); size_t len = gRec[k].fSeedTextProc(src, dst, NGLYPHS); uint16_t glyphs0[NGLYPHS], glyphs1[NGLYPHS]; bool contains = paint.containsText(dst, len); int nglyphs = paint.textToGlyphs(dst, len, glyphs0); int first = face->charsToGlyphs(dst, paint2encoding(paint), glyphs1, NGLYPHS); int index = find_first_zero(glyphs1, NGLYPHS); REPORTER_ASSERT(reporter, NGLYPHS == nglyphs); REPORTER_ASSERT(reporter, index == first); REPORTER_ASSERT(reporter, 0 == memcmp(glyphs0, glyphs1, NGLYPHS * sizeof(uint16_t))); if (contains) { REPORTER_ASSERT(reporter, NGLYPHS == first); } else { REPORTER_ASSERT(reporter, NGLYPHS > first); } } } }
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { char* storage = 0; const char* name = 0; if (family.length() == 0) { static const struct { FontDescription::GenericFamilyType mType; const char* mName; } gNames[] = { { FontDescription::SerifFamily, "serif" }, { FontDescription::SansSerifFamily, "sans-serif" }, { FontDescription::MonospaceFamily, "monospace" }, { FontDescription::CursiveFamily, "cursive" }, { FontDescription::FantasyFamily, "fantasy" } }; FontDescription::GenericFamilyType type = fontDescription.genericFamily(); for (unsigned i = 0; i < SK_ARRAY_COUNT(gNames); i++) { if (type == gNames[i].mType) { name = gNames[i].mName; break; } } // if we fall out of the loop, its ok for name to still be 0 } else { // convert the name to utf8 storage = AtomicStringToUTF8String(family); name = storage; } int style = SkTypeface::kNormal; if (fontDescription.weight() >= FontWeightBold) style |= SkTypeface::kBold; if (fontDescription.italic()) style |= SkTypeface::kItalic; SkTypeface* tf = SkTypeface::CreateFromName(name, (SkTypeface::Style)style); if (!tf) return 0; FontPlatformData* result = new FontPlatformData(tf, name, fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic()); tf->unref(); sk_free(storage); return result; }
static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text, size_t len, int glyphCount) { SkTypeface::Encoding encoding = paint2Encoding(paint); uint16_t glyphs[NGLYPHS]; SkASSERT(glyphCount <= NGLYPHS); SkTypeface* face = paint.getTypeface(); for (int i = 0; i < loops; ++i) { face->charsToGlyphs(text, encoding, glyphs, glyphCount); } }
/** * This guy is public. It first searches the cache, and if a match is not found, * it creates a new face. */ SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { LOGFONT lf = origLF; make_canonical(&lf); SkTypeface* face = SkTypefaceCache::FindByProc(FindByLogFont, &lf); if (face) { face->ref(); } else { face = LogFontTypeface::Create(lf); SkTypefaceCache::Add(face, get_style(lf)); } return face; }
SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, const SkFontStyle& style, bool isFixedWidth) { SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey)); if (typeface) { typeface->ref(); } else { typeface = SkCairoFTTypeface::CreateTypeface(fontFace, style, isFixedWidth); SkTypefaceCache::Add(typeface, style); } return typeface; }
/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt is not modified. */ static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { FamilyRec* curr = gFamilyHead; while (curr != NULL) { for (int i = 0; i < 4; i++) { SkTypeface* face = curr->fFaces[i]; if (face != NULL && face->uniqueID() == uniqueID) { return face; } } curr = curr->fNext; } return NULL; }
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { char* storage = 0; const char* name = 0; FontPlatformData* result = 0; if (family.length()) { storage = AtomicStringToUTF8String(family); name = storage; } else name = getFallbackFontName(fontDescription); int style = SkTypeface::kNormal; #ifndef FONT_SOFTWARE_RENDER if (fontDescription.weight() >= FontWeightBold) style |= SkTypeface::kBold; if (fontDescription.italic()) style |= SkTypeface::kItalic; #endif // CreateFromName always returns a typeface, falling back to a default font // if the one requested is not found. Calling Equal() with a null pointer // serves to compare the returned font against the default, with the caveat // that the default is always of normal style. If we detect the default, we // ignore it and allow WebCore to give us the next font on the CSS fallback // list. The only exception is if the family name is a commonly used generic // family, as when called by getSimilarFontPlatformData() and // getLastResortFallbackFont(). In this case, the default font is an // acceptable result. SkTypeface* tf = SkTypeface::CreateFromName(name, SkTypeface::kNormal); if (!SkTypeface::Equal(tf, 0) || isFallbackFamily(family.string())) { // We had to use normal styling to see if this was a default font. If // we need bold or italic, replace with the corrected typeface. if (style != SkTypeface::kNormal) { tf->unref(); tf = SkTypeface::CreateFromName(name, (SkTypeface::Style)style); } result = new FontPlatformData(tf, fontDescription.computedSize(), (style & SkTypeface::kBold), (style & SkTypeface::kItalic) && !tf->isItalic(), fontDescription.orientation(), fontDescription.textOrientation()); } tf->unref(); sk_free(storage); return result; }
DEF_TEST(FontHostStream, reporter) { { SkPaint paint; paint.setColor(SK_ColorGRAY); paint.setTextSize(SkIntToScalar(30)); SkTypeface* fTypeface = SkTypeface::CreateFromName("Georgia", SkTypeface::kNormal); SkSafeUnref(paint.setTypeface(fTypeface)); SkIRect origRect = SkIRect::MakeWH(64, 64); SkBitmap origBitmap; create(&origBitmap, origRect); SkCanvas origCanvas(origBitmap); SkIRect streamRect = SkIRect::MakeWH(64, 64); SkBitmap streamBitmap; create(&streamBitmap, streamRect); SkCanvas streamCanvas(streamBitmap); SkPoint point = SkPoint::Make(24, 32); // Test: origTypeface and streamTypeface from orig data draw the same drawBG(&origCanvas); origCanvas.drawText("A", 1, point.fX, point.fY, paint); SkTypeface* origTypeface = paint.getTypeface(); SkAutoTUnref<SkTypeface> aur; if (NULL == origTypeface) { origTypeface = aur.reset(SkTypeface::RefDefault()); } int ttcIndex; SkAutoTDelete<SkStreamAsset> fontData(origTypeface->openStream(&ttcIndex)); SkTypeface* streamTypeface = SkTypeface::CreateFromStream(fontData.detach()); SkFontDescriptor desc; bool isLocalStream = false; streamTypeface->getFontDescriptor(&desc, &isLocalStream); REPORTER_ASSERT(reporter, isLocalStream); SkSafeUnref(paint.setTypeface(streamTypeface)); drawBG(&streamCanvas); streamCanvas.drawPosText("A", 1, &point, paint); REPORTER_ASSERT(reporter, compare(origBitmap, origRect, streamBitmap, streamRect)); } //Make sure the typeface is deleted and removed. SkGraphics::PurgeFontCache(); }
GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects, const SkDescriptor& desc) : fScalerContext(typeface.createScalerContext(effects, &desc)) #ifdef SK_DEBUG , fDesc(desc.copy()) #endif {}
std::unique_ptr<SkScalerContext> SkGlyphCache::CreateScalerContext( const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface) { auto scaler = typeface.createScalerContext(effects, &desc, true /* can fail */); // Check if we can create a scaler-context before creating the glyphcache. // If not, we may have exhausted OS/font resources, so try purging the // cache once and try again // pass true the first time, to notice if the scalercontext failed, if (scaler == nullptr) { get_globals().purgeAll(); scaler = typeface.createScalerContext(effects, &desc, false /* must succeed */); } return scaler; }
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { const char* name = 0; // If a fallback font is being created (e.g. "-webkit-monospace"), convert // it in to the fallback name (e.g. "monospace"). if (!family.length() || family.startsWith("-webkit-")) name = getFallbackFontName(fontDescription); else name = family.string().utf8().data(); int style = SkTypeface::kNormal; if (fontDescription.weight() >= FontWeightBold) style |= SkTypeface::kBold; if (fontDescription.italic()) style |= SkTypeface::kItalic; SkTypeface* typeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal); FontPlatformData* result = 0; // CreateFromName always returns a typeface, falling back to a default font // if the one requested could not be found. Calling Equal() with a null // pointer will compare the returned font against the default, with the // caveat that the default is always of normal style. When that happens, // ignore the default font and allow WebCore to provide the next font on the // CSS fallback list. The only exception to this occurs when the family name // is a commonly used generic family, which is the case when called by // getSimilarFontPlatformData() or getLastResortFallbackFont(). In that case // the default font is an acceptable result. if (!SkTypeface::Equal(typeface, 0) || isFallbackFamily(family.string())) { if (style != SkTypeface::kNormal) { typeface->unref(); typeface = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style)); } result = new FontPlatformData(typeface, name, fontDescription.computedSize(), (style & SkTypeface::kBold) && !typeface->isBold(), (style & SkTypeface::kItalic) && !typeface->isItalic(), fontDescription.orientation(), fontDescription.textOrientation()); } typeface->unref(); return result; }
SkTypeface* SkCreateFallbackTypefaceForChar(SkUnichar uni, SkTypeface::Style style) { { SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); load_system_fonts(); } SkTypeface* tf = findFallbackTypefaceForChar(uni); if (!tf) { return NULL; } SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); tf = find_typeface(tf, style); // we ref(), since the semantic is to return a new instance tf->ref(); return tf; }
GlyphGenerator(const SkTypeface& typeface, const SkDescriptor& desc) : fScalerContext(typeface.createScalerContext(&desc)) #ifdef SK_DEBUG , fDesc(desc.copy()) #endif { fFlipMatrix.setScale(1, -1); }