[PDF] Add font subsetting using the sfntly library.

Patch from Arthur Hsu, original CL: http://codereview.chromium.org/7513003/

Review URL: http://codereview.appspot.com/4828041

git-svn-id: http://skia.googlecode.com/svn/trunk@1957 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
vandebo@chromium.org 2011-07-26 02:11:41 +00:00
parent 9859428e71
commit 1f16589855
2 changed files with 75 additions and 6 deletions

View File

@ -135,6 +135,10 @@
*/ */
//#define SK_ALLOW_LARGE_PDF_SCALARS //#define SK_ALLOW_LARGE_PDF_SCALARS
/* Define this to provide font subsetter in PDF generation.
*/
//#define SK_SFNTLY_SUBSETTER "sfntly/subsetter/font_subsetter.h"
/* Define this to remove dimension checks on bitmaps. Not all blits will be /* Define this to remove dimension checks on bitmaps. Not all blits will be
correct yet, so this is mostly for debugging the implementation. correct yet, so this is mostly for debugging the implementation.
*/ */

View File

@ -34,6 +34,10 @@
#include "SkTypes.h" #include "SkTypes.h"
#include "SkUtils.h" #include "SkUtils.h"
#if defined (SK_SFNTLY_SUBSETTER)
#include SK_SFNTLY_SUBSETTER
#endif
namespace { namespace {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -427,6 +431,63 @@ static SkPDFStream* generate_tounicode_cmap(
return new SkPDFStream(cmapStream.get()); return new SkPDFStream(cmapStream.get());
} }
static void sk_delete_array(const void* ptr, size_t, void*) {
// Use C-style cast to cast away const and cast type simultaneously.
delete[] (unsigned char*)ptr;
}
static int get_subset_font_stream(const char* fontName,
const SkTypeface* typeface,
const SkPDFGlyphSet* subset,
SkPDFStream** fontStream) {
SkRefPtr<SkStream> fontData =
SkFontHost::OpenStream(SkTypeface::UniqueID(typeface));
fontData->unref(); // SkRefPtr and OpenStream both took a ref.
int fontSize = fontData->getLength();
#if defined (SK_SFNTLY_SUBSETTER)
// Generate glyph id array.
SkTDArray<unsigned int> glyphIDs;
glyphIDs.push(0); // Always include glyph 0.
for (int i = 0; i <= SK_MaxU16; ++i) {
if (subset->has(i)) {
glyphIDs.push(i);
}
}
// Read font into buffer.
SkPDFStream* subsetFontStream = NULL;
SkTDArray<unsigned char> originalFont;
originalFont.setCount(fontSize);
if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) {
unsigned char* subsetFont = NULL;
int subsetFontSize = SfntlyWrapper::SubsetFont(fontName,
originalFont.begin(),
fontSize,
glyphIDs.begin(),
glyphIDs.count(),
&subsetFont);
if (subsetFontSize > 0 && subsetFont != NULL) {
SkData* data = SkData::NewWithProc(subsetFont,
subsetFontSize,
sk_delete_array,
NULL);
subsetFontStream = new SkPDFStream(data);
fontSize = subsetFontSize;
}
}
if (subsetFontStream) {
*fontStream = subsetFontStream;
return fontSize;
}
#endif
// Fail over: just embed the whole font.
*fontStream = new SkPDFStream(fontData.get());
return fontSize;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// class SkPDFGlyphSet // class SkPDFGlyphSet
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -858,15 +919,19 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
switch (getType()) { switch (getType()) {
case SkAdvancedTypefaceMetrics::kTrueType_Font: { case SkAdvancedTypefaceMetrics::kTrueType_Font: {
// TODO(arthurhsu): sfntly font subsetting // Font subsetting
SkRefPtr<SkStream> fontData = SkPDFStream* rawStream = NULL;
SkFontHost::OpenStream(SkTypeface::UniqueID(typeface())); int fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(),
fontData->unref(); // SkRefPtr and OpenStream both took a ref. typeface(),
SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get()); subset,
&rawStream);
SkASSERT(fontSize);
SkASSERT(rawStream);
SkRefPtr<SkPDFStream> fontStream = rawStream;
// SkRefPtr and new both ref()'d fontStream, pass one. // SkRefPtr and new both ref()'d fontStream, pass one.
addResource(fontStream.get()); addResource(fontStream.get());
fontStream->insertInt("Length1", fontData->getLength()); fontStream->insertInt("Length1", fontSize);
descriptor->insert("FontFile2", descriptor->insert("FontFile2",
new SkPDFObjRef(fontStream.get()))->unref(); new SkPDFObjRef(fontStream.get()))->unref();
break; break;