Add Truetype and Type 1 font embedding support

Sorry this is such a large CL.  It was very exploratory for me to make this
work.

- Add an interface to SkFontHost to retrieve font information and provide NULL implementations on all platforms except Linux.
- Segment large Type 1 fonts into fonts with shared resources with 255 glyphs each.
- Convert the various Type 1 formats to the form PDF wants.
- Update font as we draw text instead of as part of the graphical state.
- Remove built-in font support, we can't really use it.

Other changes I can pull out to a separate CL if you like.

- Add SkTScopedPtr class.
- Fix double free of resources.
- Fix bug in resource unique-ifying code.
- Don't print anything for any empty clip path.
- Fix copy paste error - MiterLimit.
- Fix sign extension bug in SkPDFString
- Fix FlateTest rename that was missed on a previous commit.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@728 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index ca538d1..4363ecd 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -176,6 +176,11 @@
 
     ///////////////////////////////////////////////////////////////////////////
 
+    /** Retrieve information about the typeface needed for inclusion in a
+        PDF output device. Returns NULL if it is unable to find the font.
+     */
+    static SkPDFTypefaceInfo* GetPDFTypefaceInfo(SkFontID);
+
     /** Return the number of tables in the font
      */
     static int CountTables(SkFontID);
diff --git a/include/core/SkTScopedPtr.h b/include/core/SkTScopedPtr.h
new file mode 100644
index 0000000..1e5d4c4
--- /dev/null
+++ b/include/core/SkTScopedPtr.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkTScopedPtr_DEFINED
+#define SkTScopedPtr_DEFINED
+
+#include "SkTypes.h"
+
+/** \class SkTScopedPtr
+  A SkTScopedPtr<T> is like a T*, except that the destructor of SkTScopedPtr<T>
+  automatically deletes the pointer it holds (if any).  That is, SkTScopedPtr<T>
+  owns the T object that it points to.  Like a T*, a SkTScopedPtr<T> may hold
+  either NULL or a pointer to a T object.  Also like T*, SkTScopedPtr<T> is
+  thread-compatible, and once you dereference it, you get the threadsafety
+  guarantees of T.
+
+  The size of a SkTScopedPtr is small: sizeof(SkTScopedPtr<T>) == sizeof(T*)
+*/
+template <typename T> class SkTScopedPtr : SkNoncopyable {
+public:
+    explicit SkTScopedPtr(T* o = NULL) : fObj(o) {}
+    ~SkTScopedPtr() {
+        enum { kTypeMustBeComplete = sizeof(T) };
+        delete fObj;
+    }
+
+    /** Delete the current object, if any.  Then take ownership of the
+        passed object.
+     */
+    void reset(T* o = NULL) {
+        if (o != fObj) {
+            enum { kTypeMustBeComplete = sizeof(T) };
+            delete fObj;
+            fObj = o;
+        }
+    }
+
+    /** Without deleting the current object, return it and forget about it.
+        Similar to calling get() and reset(), but the object is not deleted.
+     */
+    T* release() {
+        T* retVal = fObj;
+        fObj = NULL;
+        return retVal;
+    }
+
+    T& operator*() const {
+        SkASSERT(fObj != NULL);
+        return *fObj;
+    }
+    T* operator->() const  {
+        SkASSERT(fObj != NULL);
+        return fObj;
+    }
+    T* get() const { return fObj; }
+
+    bool operator==(T* o) const { return fObj == o; }
+    bool operator!=(T* o) const { return fObj != o; }
+
+private:
+    T* fObj;
+
+    // Forbid comparison of SkTScopedPtr types.  If T2 != T, it doesn't make
+    // sense, and if T2 == T, it still doesn't make sense because the same
+    // object can't be owned by two different scoped_ptrs.
+    template <class T2> bool operator==(SkTScopedPtr<T2> const& o2) const;
+    template <class T2> bool operator!=(SkTScopedPtr<T2> const& o2) const;
+};
+
+#endif
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 27ebd41..eaa812f 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -59,6 +59,7 @@
     T* fObj;
 };
 
+// See also SkTScopedPtr.
 template <typename T> class SkAutoTDelete : SkNoncopyable {
 public:
     SkAutoTDelete(T* obj) : fObj(obj) {}
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index d4af700..b7ccf51 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -20,6 +20,7 @@
 #include "SkRefCnt.h"
 
 class SkStream;
+class SkPDFTypefaceInfo;
 class SkWStream;
 
 /** \class SkTypeface
@@ -130,6 +131,11 @@
      */
     static SkTypeface* Deserialize(SkStream*);
 
+    /** Retrieve information about the typeface needed for inclusion in a
+        PDF output device.
+     */
+    SkPDFTypefaceInfo* getPDFTypefaceInfo() const;
+
 protected:
     /** uniqueID must be unique (please!) and non-zero
     */
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 3ef234a..64e0407 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -143,13 +143,14 @@
     // one entry: a transform
     // one entry: a clip
     // two entries: a clip and then a transform
+    // Pointers are owned by the respective Resources list.
     struct GraphicStackEntry {
         SkColor fColor;
         SkScalar fTextSize;
         SkScalar fTextScaleX;
         SkPaint::Style fTextFill;
-        SkRefPtr<SkPDFFont> fFont;
-        SkRefPtr<SkPDFGraphicState> fGraphicState;
+        SkPDFFont* fFont;
+        SkPDFGraphicState* fGraphicState;
         SkRegion fClip;
         SkMatrix fTransform;
     };
@@ -159,7 +160,8 @@
     SkString fContent;
 
     void updateGSFromPaint(const SkPaint& newPaint, bool forText);
-    int getFontResourceIndex(uint32_t fontID);
+    void updateFont(const SkPaint& paint, uint16_t glyphID);
+    int getFontResourceIndex(uint32_t fontID, uint16_t glyphID);
 
     void moveTo(SkScalar x, SkScalar y);
     void appendLine(SkScalar x, SkScalar y);
diff --git a/include/pdf/SkPDFFont.h b/include/pdf/SkPDFFont.h
index 82357ef..d020163 100644
--- a/include/pdf/SkPDFFont.h
+++ b/include/pdf/SkPDFFont.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 #include "SkThread.h"
 
 class SkPaint;
+class SkPDFTypefaceInfo;
 
 /** \class SkPDFFont
     A PDF Object class representing a font.  The font may have resources
@@ -40,53 +41,95 @@
      */
     uint32_t fontID();
 
-    /** Returns true if this font supports glyph IDs above 255.
+    /** Return true if this font has an encoding for the passed glyph id.
+     */
+    bool hasGlyph(uint16_t glyphID);
+
+    /** Returns true if this font encoding supports glyph IDs above 255.
      */
     bool multiByteGlyphs();
 
-    /** Covert the specified text to glyph IDs, taking into consideration
-     *  PDF encodings and return the number of glyphs IDs written.
+    /** Convert the input glyph IDs into the font encoding.  If the font has
+     *  more glyphs than can be encoded (like a type 1 font with more than
+     *  255 glyphs) this method only converts up to the first out of range
+     *  glyph ID.
+     *  @param glyphIDs       The input text as glyph IDs.
+     *  @param numGlyphs      The number of input glyphs.
+     *  @param encodedValues  The method writes its result to this parameter.
+     *                        multiByteGlyphs() reveals the output format.
+     *  @param encodedLength  The size of encodedValues (in bytes), which is
+     *                        overwritten with how much of encodedValues is
+     *                        used.
+     *  @return               Returns the number of glyphs consumed.
      */
-    int textToPDFGlyphs(const void* text, size_t byteLength,
-                        const SkPaint& paint, uint16_t* glyphs,
-                        size_t glyphsLength) const;
+    size_t glyphsToPDFFontEncoding(const uint16_t* glyphIDs, size_t numGlyphs,
+                                   void* encodedValues, size_t* encodedLength);
 
-    /** Get the font resource for the passed font ID. The reference count of
-     *  the object is incremented and it is the caller's responsibility to
-     *  unreference it when done.  This is needed to accommodate the weak
-     *  reference pattern used when the returned object is new and has no
-     *  other references.
-     *  @param paint  The SkPaint to emulate.
+    /** Get the font resource for the passed font ID and glyphID. The
+     *  reference count of the object is incremented and it is the caller's
+     *  responsibility to unreference it when done.  This is needed to
+     *  accommodate the weak reference pattern used when the returned object
+     *  is new and has no other references.
+     *  @param fontID  The fontId to find.
+     *  @param glyphID Specify which section of a large font is of interest.
      */
-    static SkPDFFont* getFontResouceByID(uint32_t fontID);
+    static SkPDFFont* getFontResource(uint32_t fontID, uint16_t glyphID);
 
 private:
     uint32_t fFontID;
+#ifdef SK_DEBUG
+    bool fDescendant;
+#endif
     bool fMultiByteGlyphs;
 
+    // The glyph IDs accessible with this font.  For Type1 (non CID) fonts,
+    // this will be a subset if the font has more than 255 glyphs.
+    uint16_t fFirstGlyphID;
+    uint16_t fLastGlyphID;
+    // The font info is only kept around after construction for large
+    // Type1 (non CID) fonts that need multiple "fonts" to access all glyphs.
+    SkRefPtr<SkPDFTypefaceInfo> fFontInfo;
     SkTDArray<SkPDFObject*> fResources;
+    SkRefPtr<SkPDFDict> fDescriptor;
 
     class FontRec {
     public:
         SkPDFFont* fFont;
         uint32_t fFontID;
+        uint16_t fGlyphID;
 
+        // A fGlyphID of 0 with no fFont always matches.
         bool operator==(const FontRec& b) const;
-        FontRec(SkPDFFont* font, uint32_t fontID);
+        FontRec(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
     };
 
     // This should be made a hash table if performance is a problem.
     static SkTDArray<FontRec>& canonicalFonts();
     static SkMutex& canonicalFontsMutex();
 
-    SkPDFFont(uint32_t fontID, bool multiByteGlyphs);
+    /** Construct a new font dictionary and support objects.
+     *  @param fontInfo       Information about the to create.
+     *  @param fontID         The font ID of the font.
+     *  @param glyphID        The glyph ID the caller is interested in. This
+     *                        is important only for Type1 fonts, which have
+     *                        more than 255 glyphs.
+     *  @param descendantFont If this is the descendant (true) or root
+     *                        (Type 0 font - false) font dictionary.  Only True
+     *                        Type and CID encoded fonts will use a true value.
+     *  @param fontDescriptor If the font descriptor has already have generated
+     *                        for this font, pass it in here, otherwise pass
+     *                        NULL.
+     */
+    SkPDFFont(class SkPDFTypefaceInfo* fontInfo, uint32_t fontID,
+              uint16_t glyphID, bool descendantFont, SkPDFDict* fontDescriptor);
 
-    void populateBuiltinFont(const char fontName[]);
-    void populateFont(const char subType[], const char fontName[],
-                      int firstChar, int lastChar, int widths[],
-                      SkPDFObject* fontDescriptor);
+    void populateType0Font();
+    void populateCIDFont();
+    bool populateType1Font(uint16_t firstGlyphID, uint16_t lastGlyphID);
+    void populateType3Font();
+    bool addFontDescriptor(int defaultWidth);
 
-    static int find(uint32_t fontID);
+    static bool find(uint32_t fontID, uint16_t glyphID, int* index);
 };
 
 #endif
diff --git a/include/pdf/SkPDFTypefaceInfo.h b/include/pdf/SkPDFTypefaceInfo.h
new file mode 100644
index 0000000..2655d14
--- /dev/null
+++ b/include/pdf/SkPDFTypefaceInfo.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkPDFTypefaceInfo_DEFINED
+#define SkPDFTypefaceInfo_DEFINED
+
+#include "SkRect.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+#include "SkTemplates.h"
+#include "SkTScopedPtr.h"
+
+/** \class SkPDFTypefaceInfo
+
+    The SkPDFTypefaceInfo is used by the PDF backend to correctly embed
+    typefaces.  This class is filled in with information about a given typeface
+    by the SkFontHost class.
+*/
+
+class SkPDFTypefaceInfo : public SkRefCnt {
+public:
+    enum FontType {
+        kType1_Font,
+        kType1CID_Font,
+        kCFF_Font,
+        kTrueType_Font,
+        kOther_Font,
+        kNotEmbeddable_Font,
+    };
+    // The type of the underlying font program.  This field determines which
+    // of the following fields are valid.  If it is kOther_Font or
+    // kNotEmbeddable_Font, fFontName may be valid, but no other fields are
+    // valid.
+    FontType fType;
+
+    // fMultiMaster may be true for Type1_Font or CFF_Font.
+    bool fMultiMaster;
+    SkString fFontName;
+    SkIRect fBBox;  // The bounding box of all glyphs (in font units).
+
+    uint16_t fLastGlyphID;
+
+    template <typename Data>
+    struct AdvanceMetric {
+        enum MetricType {
+            kDefault,  // Default advance: fAdvance.count = 1
+            kRange,    // Advances for a range: fAdvance.count = fEndID-fStartID
+            kRun,      // fStartID-fEndID have same advance: fAdvance.count = 1
+        };
+        MetricType fType;
+        int fStartId;
+        int fEndId;
+        SkTDArray<Data> fAdvance;
+        SkTScopedPtr<AdvanceMetric<Data> > fNext;
+    };
+
+    struct VerticalMetric {
+        int fVerticalAdvance;
+        int fOriginXDisp;  // Horizontal displacement of the secondary origin.
+        int fOriginYDisp;  // Vertical displacement of the secondary origin.
+    };
+    typedef struct VerticalMetric VerticalMetric;
+    typedef AdvanceMetric<int> WidthRange;
+    typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
+
+    // This is indexed by glyph id.
+    SkTScopedPtr<WidthRange> fGlyphWidths;
+    // Only used for Vertical CID fonts.
+    SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
+
+    // The names of each glyph, only populated for postscript fonts.
+    SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
+
+    // Metrics: probably used by the pdf renderer for substitution, which
+    // shouldn't be needed with embedding fonts.  Optional fields with a value
+    // of 0 will be ignored.
+
+    // The enum values match the values used in the PDF file format.
+    enum StyleFlags {
+        kFixedPitch_Style  = 0x00001,
+        kSerif_Style       = 0x00002,
+        kSymbolic_Style    = 0x00004,
+        kScript_Style      = 0x00008,
+        kNonsymbolic_Style = 0x00020,
+        kItalic_Style      = 0x00040,
+        kAllCaps_Style     = 0x10000,
+        kSmallCaps_Style   = 0x20000,
+        kForceBold_Style   = 0x40000,
+    };
+    uint16_t fStyle;        // Font style characteristics.
+    long fItalicAngle;      // Counterclockwise degrees from vertical of the
+                            // dominant vertical stroke for an Italic face.
+    SkScalar fAscent;       // Max height above baseline, not including accents.
+    SkScalar fDescent;      // Max depth below baseline (negative).
+    SkScalar fStemV;        // Thickness of dominant vertical stem.
+    SkScalar fCapHeight;    // Height (from baseline) of top of flat capitals.
+
+    /* Omit the optional entries. Better to let the viewer compute them, since
+     * it has to be able to anyway.
+    SkScalar fLeading;      // Space between lines. Optional.
+    SkScalar fXHeight;      // Height of top of 'x'. Optional.
+    SkScalar fStemH;        // Thickness of dominant horizontal stem. Optional.
+    SkScalar fAvgWidth;     // Average width of glyphs. Optional.
+    SkScalar fMaxWidth;     // Max width of a glyph. Optional.
+    */
+};
+
+#endif