SkPDF: move type1 font code into single file

Change-Id: I0e0bf4cdb298b161cabf74eacc4b3950d7240643
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209172
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/gn/pdf.gni b/gn/pdf.gni
index 4b63063..2955515 100644
--- a/gn/pdf.gni
+++ b/gn/pdf.gni
@@ -20,8 +20,6 @@
   "$_src/pdf/SkKeyedImage.h",
   "$_src/pdf/SkPDFBitmap.cpp",
   "$_src/pdf/SkPDFBitmap.h",
-  "$_src/pdf/SkPDFConvertType1FontStream.cpp",
-  "$_src/pdf/SkPDFConvertType1FontStream.h",
   "$_src/pdf/SkPDFDevice.cpp",
   "$_src/pdf/SkPDFDevice.h",
   "$_src/pdf/SkPDFDocument.cpp",
@@ -50,6 +48,8 @@
   "$_src/pdf/SkPDFSubsetFont.h",
   "$_src/pdf/SkPDFTag.cpp",
   "$_src/pdf/SkPDFTag.h",
+  "$_src/pdf/SkPDFType1Font.cpp",
+  "$_src/pdf/SkPDFType1Font.h",
   "$_src/pdf/SkPDFTypes.cpp",
   "$_src/pdf/SkPDFTypes.h",
   "$_src/pdf/SkPDFUtils.cpp",
diff --git a/src/pdf/SkPDFConvertType1FontStream.cpp b/src/pdf/SkPDFConvertType1FontStream.cpp
deleted file mode 100644
index 2c5d2bf..0000000
--- a/src/pdf/SkPDFConvertType1FontStream.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPDFConvertType1FontStream.h"
-
-#include "SkTemplates.h"
-#include "SkTo.h"
-
-#include <ctype.h>
-
-static bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
-                            size_t* size) {
-    // PFB sections have a two or six bytes header. 0x80 and a one byte
-    // section type followed by a four byte section length.  Type one is
-    // an ASCII section (includes a length), type two is a binary section
-    // (includes a length) and type three is an EOF marker with no length.
-    const uint8_t* buf = *src;
-    if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
-        return false;
-    } else if (buf[1] == 3) {
-        return true;
-    } else if (*len < 6) {
-        return false;
-    }
-
-    *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
-            ((size_t)buf[5] << 24);
-    size_t consumed = *size + 6;
-    if (consumed > *len) {
-        return false;
-    }
-    *src = *src + consumed;
-    *len = *len - consumed;
-    return true;
-}
-
-static bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen,
-                     size_t* dataLen, size_t* trailerLen) {
-    const uint8_t* srcPtr = src;
-    size_t remaining = size;
-
-    return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
-           parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
-           parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
-           parsePFBSection(&srcPtr, &remaining, 3, nullptr);
-}
-
-/* The sections of a PFA file are implicitly defined.  The body starts
- * after the line containing "eexec," and the trailer starts with 512
- * literal 0's followed by "cleartomark" (plus arbitrary white space).
- *
- * This function assumes that src is NUL terminated, but the NUL
- * termination is not included in size.
- *
- */
-static bool parsePFA(const char* src, size_t size, size_t* headerLen,
-                     size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) {
-    const char* end = src + size;
-
-    const char* dataPos = strstr(src, "eexec");
-    if (!dataPos) {
-        return false;
-    }
-    dataPos += strlen("eexec");
-    while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
-            dataPos < end) {
-        dataPos++;
-    }
-    *headerLen = dataPos - src;
-
-    const char* trailerPos = strstr(dataPos, "cleartomark");
-    if (!trailerPos) {
-        return false;
-    }
-    int zeroCount = 0;
-    for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
-        if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
-            continue;
-        } else if (*trailerPos == '0') {
-            zeroCount++;
-        } else {
-            return false;
-        }
-    }
-    if (zeroCount != 512) {
-        return false;
-    }
-
-    *hexDataLen = trailerPos - src - *headerLen;
-    *trailerLen = size - *headerLen - *hexDataLen;
-
-    // Verify that the data section is hex encoded and count the bytes.
-    int nibbles = 0;
-    for (; dataPos < trailerPos; dataPos++) {
-        if (isspace(*dataPos)) {
-            continue;
-        }
-        // isxdigit() is locale-sensitive https://bugs.skia.org/8285
-        if (nullptr == strchr("0123456789abcdefABCDEF", *dataPos)) {
-            return false;
-        }
-        nibbles++;
-    }
-    *dataLen = (nibbles + 1) / 2;
-
-    return true;
-}
-
-static int8_t hexToBin(uint8_t c) {
-    if (!isxdigit(c)) {
-        return -1;
-    } else if (c <= '9') {
-        return c - '0';
-    } else if (c <= 'F') {
-        return c - 'A' + 10;
-    } else if (c <= 'f') {
-        return c - 'a' + 10;
-    }
-    return -1;
-}
-
-sk_sp<SkData> SkPDFConvertType1FontStream(
-        std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen,
-        size_t* dataLen, size_t* trailerLen) {
-    size_t srcLen = srcStream ? srcStream->getLength() : 0;
-    SkASSERT(srcLen);
-    if (!srcLen) {
-        return nullptr;
-    }
-    // Flatten and Nul-terminate the source stream so that we can use
-    // strstr() to search it.
-    SkAutoTMalloc<uint8_t> sourceBuffer(SkToInt(srcLen + 1));
-    (void)srcStream->read(sourceBuffer.get(), srcLen);
-    sourceBuffer[SkToInt(srcLen)] = 0;
-    const uint8_t* src = sourceBuffer.get();
-
-    if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
-        static const int kPFBSectionHeaderLength = 6;
-        const size_t length = *headerLen + *dataLen + *trailerLen;
-        SkASSERT(length > 0);
-        SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
-
-        sk_sp<SkData> data(SkData::MakeUninitialized(length));
-
-        const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
-        // There is a six-byte section header before header and data
-        // (but not trailer) that we're not going to copy.
-        const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength;
-        const uint8_t* const srcTrailer = srcData + *headerLen;
-
-        uint8_t* const resultHeader = (uint8_t*)data->writable_data();
-        uint8_t* const resultData = resultHeader + *headerLen;
-        uint8_t* const resultTrailer = resultData + *dataLen;
-
-        SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
-
-        memcpy(resultHeader,  srcHeader,  *headerLen);
-        memcpy(resultData,    srcData,    *dataLen);
-        memcpy(resultTrailer, srcTrailer, *trailerLen);
-
-        return data;
-    }
-
-    // A PFA has to be converted for PDF.
-    size_t hexDataLen;
-    if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
-                 trailerLen)) {
-        return nullptr;
-    }
-    const size_t length = *headerLen + *dataLen + *trailerLen;
-    SkASSERT(length > 0);
-    auto data = SkData::MakeUninitialized(length);
-    uint8_t* buffer = (uint8_t*)data->writable_data();
-
-    memcpy(buffer, src, *headerLen);
-    uint8_t* const resultData = &(buffer[*headerLen]);
-
-    const uint8_t* hexData = src + *headerLen;
-    const uint8_t* trailer = hexData + hexDataLen;
-    size_t outputOffset = 0;
-    uint8_t dataByte = 0;  // To hush compiler.
-    bool highNibble = true;
-    for (; hexData < trailer; hexData++) {
-        int8_t curNibble = hexToBin(*hexData);
-        if (curNibble < 0) {
-            continue;
-        }
-        if (highNibble) {
-            dataByte = curNibble << 4;
-            highNibble = false;
-        } else {
-            dataByte |= curNibble;
-            highNibble = true;
-            resultData[outputOffset++] = dataByte;
-        }
-    }
-    if (!highNibble) {
-        resultData[outputOffset++] = dataByte;
-    }
-    SkASSERT(outputOffset == *dataLen);
-
-    uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]);
-    memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
-    return data;
-}
diff --git a/src/pdf/SkPDFConvertType1FontStream.h b/src/pdf/SkPDFConvertType1FontStream.h
deleted file mode 100644
index ffd2da3..0000000
--- a/src/pdf/SkPDFConvertType1FontStream.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPDFConvertType1FontStream_DEFINED
-#define SkPDFConvertType1FontStream_DEFINED
-
-#include "SkData.h"
-#include "SkStream.h"
-
-/*
-  "A standard Type 1 font program, as described in the Adobe Type 1
-  Font Format specification, consists of three parts: a clear-text
-  portion (written using PostScript syntax), an encrypted portion, and
-  a fixed-content portion.  The fixed-content portion contains 512
-  ASCII zeros followed by a cleartomark operator, and perhaps followed
-  by additional data. Although the encrypted portion of a standard
-  Type 1 font may be in binary or ASCII hexadecimal format, PDF
-  supports only the binary format."
-*/
-sk_sp<SkData> SkPDFConvertType1FontStream(
-        std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen,
-        size_t* dataLen, size_t* trailerLen);
-
-#endif  // SkPDFConvertType1FontStream_DEFINED
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 2f8369f..3e7d354 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -14,7 +14,6 @@
 #include "SkMakeUnique.h"
 #include "SkPDFBitmap.h"
 #include "SkPDFDocument.h"
-#include "SkPDFConvertType1FontStream.h"
 #include "SkPDFDevice.h"
 #include "SkPDFDocumentPriv.h"
 #include "SkPDFMakeCIDGlyphWidthsArray.h"
@@ -49,6 +48,10 @@
         font, SkPaint(), props, SkScalerContextFlags::kFakeGammaAndBoostContrast, SkMatrix::I());
 }
 
+void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
+    face.getPostScriptGlyphNames(dst);
+}
+
 namespace {
 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
 // symbols vs. characters.  Rarely is a font the right character set to call it
@@ -57,15 +60,11 @@
 
 
 // scale from em-units to base-1000, returning as a SkScalar
-SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
-    if (emSize == 1000) {
-        return scaled;
-    } else {
-        return scaled * 1000 / emSize;
-    }
+inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
+    return emSize == 1000 ? scaled : scaled * 1000 / emSize;
 }
 
-SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
+inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
     return from_font_units(SkIntToScalar(val), emSize);
 }
 
@@ -239,10 +238,10 @@
     , fIndirectReference(indirectReference)
     , fFontType(fontType) {}
 
-static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
-                                               const SkAdvancedTypefaceMetrics& metrics,
-                                               uint16_t emSize,
-                                               int16_t defaultWidth) {
+void SkPDFFont::PopulateCommonFontDescriptor(SkPDFDict* descriptor,
+                                             const SkAdvancedTypefaceMetrics& metrics,
+                                             uint16_t emSize,
+                                             int16_t defaultWidth) {
     descriptor->insertName("FontName", metrics.fPostScriptName);
     descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
     descriptor->insertScalar("Ascent",
@@ -296,7 +295,7 @@
 
     auto descriptor = SkPDFMakeDict("FontDescriptor");
     uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm());
-    add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);
+    SkPDFFont::PopulateCommonFontDescriptor(descriptor.get(), metrics, emSize , 0);
 
     int ttcIndex;
     std::unique_ptr<SkStreamAsset> fontAsset = face->openStream(&ttcIndex);
@@ -410,117 +409,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Type1Font
-///////////////////////////////////////////////////////////////////////////////
-
-static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc,
-                                                         const SkTypeface* typeface,
-                                                         const SkAdvancedTypefaceMetrics* info) {
-    SkPDFDict descriptor("FontDescriptor");
-    uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
-    if (info) {
-        add_common_font_descriptor_entries(&descriptor, *info, emSize, 0);
-        if (can_embed(*info)) {
-            int ttcIndex;
-            size_t header SK_INIT_TO_AVOID_WARNING;
-            size_t data SK_INIT_TO_AVOID_WARNING;
-            size_t trailer SK_INIT_TO_AVOID_WARNING;
-            std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
-            sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
-                                                                 &header, &data, &trailer);
-            if (fontData) {
-                std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
-                dict->insertInt("Length1", header);
-                dict->insertInt("Length2", data);
-                dict->insertInt("Length3", trailer);
-                auto fontStream = SkMemoryStream::Make(std::move(fontData));
-                descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict),
-                                                                std::move(fontStream), doc, true));
-            }
-        }
-    }
-    return doc->emit(descriptor);
-}
-
-
-static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
-                                                      const SkTypeface* typeface) {
-    SkFontID fontID = typeface->uniqueID();
-    const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
-    if (!glyphNames) {
-        std::vector<SkString> names(typeface->countGlyphs());
-        SkPDFFont::GetType1GlyphNames(*typeface, names.data());
-        glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names));
-    }
-    SkASSERT(glyphNames);
-    return *glyphNames;
-}
-
-static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
-                                                    const SkTypeface* typeface) {
-    SkFontID fontID = typeface->uniqueID();
-    if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
-        return *ptr;
-    }
-    const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
-    auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
-    doc->fFontDescriptors.set(fontID, fontDescriptor);
-    return fontDescriptor;
-}
-
-static void emit_subset_type1(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
-    SkTypeface* typeface = pdfFont.typeface();
-    const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
-    SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
-    SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
-
-    SkPDFDict font("Font");
-    font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
-    font.insertName("Subtype", "Type1");
-    if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
-        font.insertName("BaseFont", info->fPostScriptName);
-    }
-
-    // glyphCount not including glyph 0
-    unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
-    SkASSERT(glyphCount > 0 && glyphCount <= 255);
-    font.insertInt("FirstChar", (size_t)0);
-    font.insertInt("LastChar", (size_t)glyphCount);
-    {
-        int emSize;
-        auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
-        auto widths = SkPDFMakeArray();
-        SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
-        widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
-        for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
-            advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
-            widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
-        }
-        font.insertObject("Widths", std::move(widths));
-    }
-    auto encDiffs = SkPDFMakeArray();
-    encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
-    encDiffs->appendInt(0);
-
-    SkASSERT(glyphNames.size() > lastGlyphID);
-    const SkString unknown("UNKNOWN");
-    encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
-    for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
-        encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
-    }
-
-    auto encoding = SkPDFMakeDict("Encoding");
-    encoding->insertObject("Differences", std::move(encDiffs));
-    font.insertObject("Encoding", std::move(encoding));
-
-    doc->emit(font, pdfFont.indirectReference());
-}
-
-void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
-    face.getPostScriptGlyphNames(dst);
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // PDFType3Font
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -759,15 +647,16 @@
     doc->emit(font, pdfFont.indirectReference());
 }
 
-
 void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
     SkASSERT(fFontType != SkPDFFont().fFontType); // not default value
     switch (fFontType) {
         case SkAdvancedTypefaceMetrics::kType1CID_Font:
         case SkAdvancedTypefaceMetrics::kTrueType_Font:
             return emit_subset_type0(*this, doc);
+#ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
         case SkAdvancedTypefaceMetrics::kType1_Font:
-            return emit_subset_type1(*this, doc);
+            return SkPDFEmitType1Font(*this, doc);
+#endif
         default:
             return emit_subset_type3(*this, doc);
     }
diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h
index 316e1b2..ec44732 100644
--- a/src/pdf/SkPDFFont.h
+++ b/src/pdf/SkPDFFont.h
@@ -10,6 +10,7 @@
 #include "SkAdvancedTypefaceMetrics.h"
 #include "SkPDFDocument.h"
 #include "SkPDFGlyphUse.h"
+#include "SkPDFType1Font.h"
 #include "SkPDFTypes.h"
 #include "SkStrikeCache.h"
 #include "SkTypeface.h"
@@ -98,6 +99,11 @@
     static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface,
                                                        SkPDFDocument* canon);
 
+    static void PopulateCommonFontDescriptor(SkPDFDict* descriptor,
+                                             const SkAdvancedTypefaceMetrics&,
+                                             uint16_t emSize,
+                                             int16_t defaultWidth);
+
     void emitSubset(SkPDFDocument*) const;
 
     /**
diff --git a/src/pdf/SkPDFType1Font.cpp b/src/pdf/SkPDFType1Font.cpp
new file mode 100644
index 0000000..5f4c997
--- /dev/null
+++ b/src/pdf/SkPDFType1Font.cpp
@@ -0,0 +1,328 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "SkPDFType1Font.h"
+
+#include "SkTemplates.h"
+#include "SkTo.h"
+
+#include <ctype.h>
+
+/*
+  "A standard Type 1 font program, as described in the Adobe Type 1
+  Font Format specification, consists of three parts: a clear-text
+  portion (written using PostScript syntax), an encrypted portion, and
+  a fixed-content portion.  The fixed-content portion contains 512
+  ASCII zeros followed by a cleartomark operator, and perhaps followed
+  by additional data. Although the encrypted portion of a standard
+  Type 1 font may be in binary or ASCII hexadecimal format, PDF
+  supports only the binary format."
+*/
+static bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
+                            size_t* size) {
+    // PFB sections have a two or six bytes header. 0x80 and a one byte
+    // section type followed by a four byte section length.  Type one is
+    // an ASCII section (includes a length), type two is a binary section
+    // (includes a length) and type three is an EOF marker with no length.
+    const uint8_t* buf = *src;
+    if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
+        return false;
+    } else if (buf[1] == 3) {
+        return true;
+    } else if (*len < 6) {
+        return false;
+    }
+
+    *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
+            ((size_t)buf[5] << 24);
+    size_t consumed = *size + 6;
+    if (consumed > *len) {
+        return false;
+    }
+    *src = *src + consumed;
+    *len = *len - consumed;
+    return true;
+}
+
+static bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen,
+                     size_t* dataLen, size_t* trailerLen) {
+    const uint8_t* srcPtr = src;
+    size_t remaining = size;
+
+    return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
+           parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
+           parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
+           parsePFBSection(&srcPtr, &remaining, 3, nullptr);
+}
+
+/* The sections of a PFA file are implicitly defined.  The body starts
+ * after the line containing "eexec," and the trailer starts with 512
+ * literal 0's followed by "cleartomark" (plus arbitrary white space).
+ *
+ * This function assumes that src is NUL terminated, but the NUL
+ * termination is not included in size.
+ *
+ */
+static bool parsePFA(const char* src, size_t size, size_t* headerLen,
+                     size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) {
+    const char* end = src + size;
+
+    const char* dataPos = strstr(src, "eexec");
+    if (!dataPos) {
+        return false;
+    }
+    dataPos += strlen("eexec");
+    while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
+            dataPos < end) {
+        dataPos++;
+    }
+    *headerLen = dataPos - src;
+
+    const char* trailerPos = strstr(dataPos, "cleartomark");
+    if (!trailerPos) {
+        return false;
+    }
+    int zeroCount = 0;
+    for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
+        if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
+            continue;
+        } else if (*trailerPos == '0') {
+            zeroCount++;
+        } else {
+            return false;
+        }
+    }
+    if (zeroCount != 512) {
+        return false;
+    }
+
+    *hexDataLen = trailerPos - src - *headerLen;
+    *trailerLen = size - *headerLen - *hexDataLen;
+
+    // Verify that the data section is hex encoded and count the bytes.
+    int nibbles = 0;
+    for (; dataPos < trailerPos; dataPos++) {
+        if (isspace(*dataPos)) {
+            continue;
+        }
+        // isxdigit() is locale-sensitive https://bugs.skia.org/8285
+        if (nullptr == strchr("0123456789abcdefABCDEF", *dataPos)) {
+            return false;
+        }
+        nibbles++;
+    }
+    *dataLen = (nibbles + 1) / 2;
+
+    return true;
+}
+
+static int8_t hexToBin(uint8_t c) {
+    if (!isxdigit(c)) {
+        return -1;
+    } else if (c <= '9') {
+        return c - '0';
+    } else if (c <= 'F') {
+        return c - 'A' + 10;
+    } else if (c <= 'f') {
+        return c - 'a' + 10;
+    }
+    return -1;
+}
+
+static sk_sp<SkData> convert_type1_font_stream(std::unique_ptr<SkStreamAsset> srcStream,
+                                               size_t* headerLen,
+                                               size_t* dataLen,
+                                               size_t* trailerLen) {
+    size_t srcLen = srcStream ? srcStream->getLength() : 0;
+    SkASSERT(srcLen);
+    if (!srcLen) {
+        return nullptr;
+    }
+    // Flatten and Nul-terminate the source stream so that we can use
+    // strstr() to search it.
+    SkAutoTMalloc<uint8_t> sourceBuffer(SkToInt(srcLen + 1));
+    (void)srcStream->read(sourceBuffer.get(), srcLen);
+    sourceBuffer[SkToInt(srcLen)] = 0;
+    const uint8_t* src = sourceBuffer.get();
+
+    if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
+        static const int kPFBSectionHeaderLength = 6;
+        const size_t length = *headerLen + *dataLen + *trailerLen;
+        SkASSERT(length > 0);
+        SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
+
+        sk_sp<SkData> data(SkData::MakeUninitialized(length));
+
+        const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
+        // There is a six-byte section header before header and data
+        // (but not trailer) that we're not going to copy.
+        const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength;
+        const uint8_t* const srcTrailer = srcData + *headerLen;
+
+        uint8_t* const resultHeader = (uint8_t*)data->writable_data();
+        uint8_t* const resultData = resultHeader + *headerLen;
+        uint8_t* const resultTrailer = resultData + *dataLen;
+
+        SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
+
+        memcpy(resultHeader,  srcHeader,  *headerLen);
+        memcpy(resultData,    srcData,    *dataLen);
+        memcpy(resultTrailer, srcTrailer, *trailerLen);
+
+        return data;
+    }
+
+    // A PFA has to be converted for PDF.
+    size_t hexDataLen;
+    if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
+                 trailerLen)) {
+        return nullptr;
+    }
+    const size_t length = *headerLen + *dataLen + *trailerLen;
+    SkASSERT(length > 0);
+    auto data = SkData::MakeUninitialized(length);
+    uint8_t* buffer = (uint8_t*)data->writable_data();
+
+    memcpy(buffer, src, *headerLen);
+    uint8_t* const resultData = &(buffer[*headerLen]);
+
+    const uint8_t* hexData = src + *headerLen;
+    const uint8_t* trailer = hexData + hexDataLen;
+    size_t outputOffset = 0;
+    uint8_t dataByte = 0;  // To hush compiler.
+    bool highNibble = true;
+    for (; hexData < trailer; hexData++) {
+        int8_t curNibble = hexToBin(*hexData);
+        if (curNibble < 0) {
+            continue;
+        }
+        if (highNibble) {
+            dataByte = curNibble << 4;
+            highNibble = false;
+        } else {
+            dataByte |= curNibble;
+            highNibble = true;
+            resultData[outputOffset++] = dataByte;
+        }
+    }
+    if (!highNibble) {
+        resultData[outputOffset++] = dataByte;
+    }
+    SkASSERT(outputOffset == *dataLen);
+
+    uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]);
+    memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
+    return data;
+}
+
+inline static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
+    return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
+}
+
+inline static SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
+    return emSize == 1000 ? scaled : scaled * 1000 / emSize;
+}
+
+static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc,
+                                                         const SkTypeface* typeface,
+                                                         const SkAdvancedTypefaceMetrics* info) {
+    SkPDFDict descriptor("FontDescriptor");
+    uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
+    if (info) {
+        SkPDFFont::PopulateCommonFontDescriptor(&descriptor, *info, emSize, 0);
+        if (can_embed(*info)) {
+            int ttcIndex;
+            size_t header SK_INIT_TO_AVOID_WARNING;
+            size_t data SK_INIT_TO_AVOID_WARNING;
+            size_t trailer SK_INIT_TO_AVOID_WARNING;
+            std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
+            sk_sp<SkData> fontData = convert_type1_font_stream(std::move(rawFontData),
+                                                               &header, &data, &trailer);
+            if (fontData) {
+                std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
+                dict->insertInt("Length1", header);
+                dict->insertInt("Length2", data);
+                dict->insertInt("Length3", trailer);
+                auto fontStream = SkMemoryStream::Make(std::move(fontData));
+                descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict),
+                                                                std::move(fontStream), doc, true));
+            }
+        }
+    }
+    return doc->emit(descriptor);
+}
+
+
+static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
+                                                      const SkTypeface* typeface) {
+    SkFontID fontID = typeface->uniqueID();
+    const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
+    if (!glyphNames) {
+        std::vector<SkString> names(typeface->countGlyphs());
+        SkPDFFont::GetType1GlyphNames(*typeface, names.data());
+        glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names));
+    }
+    SkASSERT(glyphNames);
+    return *glyphNames;
+}
+
+static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
+                                                    const SkTypeface* typeface) {
+    SkFontID fontID = typeface->uniqueID();
+    if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
+        return *ptr;
+    }
+    const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
+    auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
+    doc->fFontDescriptors.set(fontID, fontDescriptor);
+    return fontDescriptor;
+}
+
+
+void SkPDFEmitType1Font(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
+    SkTypeface* typeface = pdfFont.typeface();
+    const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
+    SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
+    SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
+
+    SkPDFDict font("Font");
+    font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
+    font.insertName("Subtype", "Type1");
+    if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
+        font.insertName("BaseFont", info->fPostScriptName);
+    }
+
+    // glyphCount not including glyph 0
+    unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
+    SkASSERT(glyphCount > 0 && glyphCount <= 255);
+    font.insertInt("FirstChar", (size_t)0);
+    font.insertInt("LastChar", (size_t)glyphCount);
+    {
+        int emSize;
+        auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
+        auto widths = SkPDFMakeArray();
+        SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
+        widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
+        for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
+            advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
+            widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
+        }
+        font.insertObject("Widths", std::move(widths));
+    }
+    auto encDiffs = SkPDFMakeArray();
+    encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
+    encDiffs->appendInt(0);
+
+    SkASSERT(glyphNames.size() > lastGlyphID);
+    const SkString unknown("UNKNOWN");
+    encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
+    for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
+        encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
+    }
+
+    auto encoding = SkPDFMakeDict("Encoding");
+    encoding->insertObject("Differences", std::move(encDiffs));
+    font.insertObject("Encoding", std::move(encoding));
+
+    doc->emit(font, pdfFont.indirectReference());
+}
diff --git a/src/pdf/SkPDFType1Font.h b/src/pdf/SkPDFType1Font.h
new file mode 100644
index 0000000..8f8778a
--- /dev/null
+++ b/src/pdf/SkPDFType1Font.h
@@ -0,0 +1,11 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef SkPDFType1Font_DEFINED
+#define SkPDFType1Font_DEFINED
+
+#include "SkPDFDocumentPriv.h"
+#include "SkPDFFont.h"
+
+void SkPDFEmitType1Font(const SkPDFFont&, SkPDFDocument*);
+
+#endif  // SkPDFType1Font_DEFINED