// 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 }
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(); }
// We're only interested in some fields of the SkPaint, so we have a custom // operator== function. bool SkPDFGraphicState::GSCanonicalEntry::operator==( const SkPDFGraphicState::GSCanonicalEntry& gs) const { const SkPaint* a = fPaint; const SkPaint* b = gs.fPaint; SkASSERT(a != NULL); SkASSERT(b != NULL); SkTypeface* aFace = a->getTypeface(); SkTypeface* bFace = b->getTypeface(); return SkColorGetA(a->getColor()) == SkColorGetA(b->getColor()) && a->getStrokeCap() == b->getStrokeCap() && a->getStrokeJoin() == b->getStrokeJoin() && a->getTextSize() == b->getTextSize() && a->getStrokeWidth() == b->getStrokeWidth() && a->getStrokeMiter() == b->getStrokeMiter() && (aFace == NULL) == (bFace == NULL) && (aFace == NULL || aFace->uniqueID() == bFace->uniqueID()); }
/* 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; }
HB_Error harfbuzzSkiaGetTable(void* font, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) { SkTypeface* typeface = static_cast<SkTypeface*>(font); if (!typeface) { ALOGD("Typeface cannot be null"); return HB_Err_Invalid_Argument; } const size_t tableSize = SkFontHost::GetTableSize(typeface->uniqueID(), tag); if (!tableSize) return HB_Err_Invalid_Argument; // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. if (!buffer) { *len = tableSize; return HB_Err_Ok; } if (*len < tableSize) return HB_Err_Invalid_Argument; SkFontHost::GetTableData(typeface->uniqueID(), tag, 0, tableSize, buffer); return HB_Err_Ok; }
void ScriptRunLayoutShaper::getConversionFactor(unsigned int &x_ppem, unsigned int &y_ppem, int &x_scale, int &y_scale, const SkPaint *paint) { SkTypeface *typeface = paint->getTypeface(); int textSize = paint->getTextSize(); float scaleX = paint->getTextScaleX(); x_ppem = floor(scaleX * textSize + 0.5); y_ppem = textSize; uint32_t unitsPerEm = SkFontHost::GetUnitsPerEm(typeface->uniqueID()); // x_ and y_scale are the conversion factors from font design space // (unitsPerEm) to 1/64th of device pixels in 16.16 format. const int kDevicePixelFraction = 64; const int kMultiplyFor16Dot16 = 1 << 16; float emScale = kDevicePixelFraction * kMultiplyFor16Dot16 / (float)unitsPerEm; x_scale = emScale * scaleX * textSize; y_scale = emScale * textSize; }
PassRefPtr<FontDataForRangeSet> FontFallbackIterator::uniqueOrNext( PassRefPtr<FontDataForRangeSet> candidate, const Vector<UChar32>& hintList) { SkTypeface* candidateTypeface = candidate->fontData()->platformData().typeface(); if (!candidateTypeface) return next(hintList); uint32_t candidateId = candidateTypeface->uniqueID(); if (m_uniqueFontDataForRangeSetsReturned.contains(candidateId)) { return next(hintList); } // We don't want to skip subsetted ranges because HarfBuzzShaper's behavior // depends on the subsetting. if (candidate->isEntireRange()) m_uniqueFontDataForRangeSetsReturned.add(candidateId); return candidate; }
uint32_t SkTypeface::UniqueID(const SkTypeface* face) { if (face) { return face->uniqueID(); } // We cache the default fontID, assuming it will not change during a boot // The initial value of 0 is fine, since a typeface's uniqueID should not // be zero. static uint32_t gDefaultFontID; if (0 == gDefaultFontID) { SkTypeface* defaultFace = SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal); SkASSERT(defaultFace); gDefaultFontID = defaultFace->uniqueID(); defaultFace->unref(); } return gDefaultFontID; }
/* Called once (ensured by the sentinel check at the beginning of our body). Initializes all the globals, and register the system fonts. */ static void load_system_fonts() { // check if we've already be called if (NULL != gDefaultNormal) { return; } const FontInitRec* rec = gSystemFonts; SkTypeface* firstInFamily = NULL; int fallbackCount = 0; for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { // if we're the first in a new family, clear firstInFamily if (rec[i].fNames != NULL) { firstInFamily = NULL; } SkString name; SkTypeface::Style style; // we expect all the fonts, except the "fallback" fonts bool isExpected = (rec[i].fNames != gFBNames); if (!get_name_and_style(rec[i].fFileName, &name, &style, isExpected)) { continue; } SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style, true, // system-font (cannot delete) firstInFamily, // what family to join rec[i].fFileName) // filename ); if (rec[i].fNames != NULL) { // see if this is one of our fallback fonts if (rec[i].fNames == gFBNames) { // SkDebugf("---- adding %s as fallback[%d] fontID %d\n", // rec[i].fFileName, fallbackCount, tf->uniqueID()); gFallbackFonts[fallbackCount++] = tf->uniqueID(); } firstInFamily = tf; FamilyRec* family = find_family(tf); const char* const* names = rec[i].fNames; // record the default family if this is it if (names == DEFAULT_NAMES) { gDefaultFamily = family; } // add the names to map to this family while (*names) { add_name(*names, family); names += 1; } } } // do this after all fonts are loaded. This is our default font, and it // acts as a sentinel so we only execute load_system_fonts() once gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); // now terminate our fallback list with the sentinel value gFallbackFonts[fallbackCount] = 0; }
/* * Called once (ensured by the sentinel check at the beginning of our body). * Initializes all the globals, and register the system fonts. * * gFamilyHeadAndNameListMutex must already be acquired. */ static void init_system_fonts() { // check if we've already been called if (gDefaultNormal) { return; } SkASSERT(gUniqueFontID == 0); load_font_info(); FontInitRec* rec = gSystemFonts; SkTypeface* firstInFamily = NULL; int fallbackCount = 0; for (size_t i = 0; i < gNumSystemFonts; i++) { // if we're the first in a new family, clear firstInFamily if (rec[i].fNames != NULL) { firstInFamily = NULL; } bool isFixedWidth; SkString name; SkTypeface::Style style; // we expect all the fonts, except the "fallback" fonts bool isExpected = (rec[i].fNames != gFBNames); if (!get_name_and_style(rec[i].fFileName, &name, &style, &isFixedWidth, isExpected)) { // We need to increase gUniqueFontID here so that the unique id of // each font matches its index in gSystemFonts array, as expected // by find_uniqueID. sk_atomic_inc(&gUniqueFontID); continue; } SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style, true, // system-font (cannot delete) firstInFamily, // what family to join rec[i].fFileName, isFixedWidth) // filename ); #if SK_DEBUG_FONTS SkDebugf("---- SkTypeface[%d] %s fontID %d", i, rec[i].fFileName, tf->uniqueID()); #endif if (rec[i].fNames != NULL) { // see if this is one of our fallback fonts if (rec[i].fNames == gFBNames) { #if SK_DEBUG_FONTS SkDebugf("---- adding %s as fallback[%d] fontID %d", rec[i].fFileName, fallbackCount, tf->uniqueID()); #endif gFallbackFonts[fallbackCount++] = tf->uniqueID(); // Use the font file name as the name of the typeface. const char **nameList = (const char**)malloc(2 * sizeof(char*)); if (nameList == NULL) { // shouldn't get here SkDEBUGFAIL("Failed to allocate nameList"); break; } nameList[0] = rec[i].fFileName; nameList[1] = NULL; rec[i].fNames = nameList; } firstInFamily = tf; FamilyRec* family = find_family(tf); const char* const* names = rec[i].fNames; // record the default family if this is it if (names == gDefaultNames) { gDefaultFamily = family; } // add the names to map to this family while (*names) { add_name(*names, family); names += 1; } } } // do this after all fonts are loaded. This is our default font, and it // acts as a sentinel so we only execute load_system_fonts() once gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); // now terminate our fallback list with the sentinel value gFallbackFonts[fallbackCount] = 0; // SkDEBUGCODE(dump_globals()); }
void SkFontEmbeddedList::initFontsLocked() { if( gDefaultNormal ) return; SkASSERT( gUniqueFontID == 0 ); loadFontInfoLocked(); SkTypeface * firstInFamily = NULL; for( int i = 0 ; i < gSystemFonts.count() ; i++ ) { const char * const * names = gSystemFonts[i].fNames; if( names != NULL ) firstInFamily = NULL; bool isFixedWidth; SkString name; SkTypeface::Style style; bool isExpected = ( names != gFBNames ); if( !getNameAndStyle( gSystemFonts[i].fFileName, &name, &style, &isFixedWidth, isExpected ) ) { sk_atomic_inc( &gUniqueFontID ); continue; } SkString fullpath; SkTypeface * tf = NULL; getFullPathForSysFonts( &fullpath, gSystemFonts[i].fFileName ); tf = SkNEW_ARGS( FileTypeface, ( style, true, fullpath.c_str(), isFixedWidth ) ); addTypefaceLocked( tf, firstInFamily ); if( names != NULL ) { if( names == gFBNames ) { FallbackFontRec fallbackRec; fallbackRec.fFontID = tf->uniqueID(); fallbackRec.fVariant = gSystemFonts[i].fVariant; addFallbackFontLocked( fallbackRec, gSystemFonts[i].fLanguage ); } firstInFamily = tf; FamilyRec * family = findFamilyLocked( tf ); if( isDefaultSansFont( names ) == true ) { FileTypeface * ftf = ( FileTypeface * )tf; SkFontData * font = SkNEW( SkFontData ); if( font ) { font->setFamilyAndTypeface( family, ftf ); font->setFontFullPath( ftf->getFilePath() ); font->setWebFaceName( names[0] ); addFonts( font ); } else { HyLogef( "SkNEW( SkFontData ) (%s)", ftf->getFilePath() ); continue; } } while( *names ) { addNameLocked( *names, family ); names += 1; } } } finaliseFallbackFontListsLocked(); }