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(); }
void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) { const SkAdvancedTypefaceMetrics* metricsPtr = SkPDFFont::GetMetrics(this->typeface(), canon); SkASSERT(metricsPtr); if (!metricsPtr) { return; } const SkAdvancedTypefaceMetrics& metrics = *metricsPtr; SkASSERT(can_embed(metrics)); SkAdvancedTypefaceMetrics::FontType type = this->getType(); SkTypeface* face = this->typeface(); SkASSERT(face); auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); uint16_t emSize = SkToU16(this->typeface()->getUnitsPerEm()); add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0); int ttcIndex; std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); size_t fontSize = fontAsset ? fontAsset->getLength() : 0; if (0 == fontSize) { SkDebugf("Error: (SkTypeface)(%p)::openStream() returned " "empty stream (%p) when identified as kType1CID_Font " "or kTrueType_Font.\n", face, fontAsset.get()); } else { switch (type) { case SkAdvancedTypefaceMetrics::kTrueType_Font: { #ifdef SK_PDF_USE_SFNTLY if (!SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) { sk_sp<SkPDFStream> subsetStream = get_subset_font_stream( std::move(fontAsset), this->glyphUsage(), metrics.fFontName.c_str(), ttcIndex); if (subsetStream) { descriptor->insertObjRef("FontFile2", std::move(subsetStream)); break; } // If subsetting fails, fall back to original font data. fontAsset.reset(face->openStream(&ttcIndex)); SkASSERT(fontAsset); SkASSERT(fontAsset->getLength() == fontSize); if (!fontAsset || fontAsset->getLength() == 0) { break; } } #endif // SK_PDF_USE_SFNTLY auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); fontStream->dict()->insertInt("Length1", fontSize); descriptor->insertObjRef("FontFile2", std::move(fontStream)); break; } case SkAdvancedTypefaceMetrics::kType1CID_Font: { auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); fontStream->dict()->insertName("Subtype", "CIDFontType0C"); descriptor->insertObjRef("FontFile3", std::move(fontStream)); break; } default: SkASSERT(false); } } auto newCIDFont = sk_make_sp<SkPDFDict>("Font"); newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor)); newCIDFont->insertName("BaseFont", metrics.fPostScriptName); switch (type) { case SkAdvancedTypefaceMetrics::kType1CID_Font: newCIDFont->insertName("Subtype", "CIDFontType0"); break; case SkAdvancedTypefaceMetrics::kTrueType_Font: newCIDFont->insertName("Subtype", "CIDFontType2"); newCIDFont->insertName("CIDToGIDMap", "Identity"); break; default: SkASSERT(false); } auto sysInfo = sk_make_sp<SkPDFDict>(); sysInfo->insertString("Registry", "Adobe"); sysInfo->insertString("Ordering", "Identity"); sysInfo->insertInt("Supplement", 0); newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); int16_t defaultWidth = 0; { int emSize; auto glyphCache = SkPDFFont::MakeVectorCache(face, &emSize); sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( glyphCache.get(), &this->glyphUsage(), SkToS16(emSize), &defaultWidth); if (widths && widths->size() > 0) { newCIDFont->insertObject("W", std::move(widths)); } newCIDFont->insertScalar( "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize))); } //////////////////////////////////////////////////////////////////////////// this->insertName("Subtype", "Type0"); this->insertName("BaseFont", metrics.fPostScriptName); this->insertName("Encoding", "Identity-H"); auto descendantFonts = sk_make_sp<SkPDFArray>(); descendantFonts->appendObjRef(std::move(newCIDFont)); this->insertObject("DescendantFonts", std::move(descendantFonts)); if (metrics.fGlyphToUnicode.count() > 0) { this->insertObjRef("ToUnicode", SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, &this->glyphUsage(), multiByteGlyphs(), firstGlyphID(), lastGlyphID())); } SkDEBUGCODE(fPopulated = true); return; }