1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef SkPDFFont_DEFINED
8 #define SkPDFFont_DEFINED
9 
10 #include "SkAdvancedTypefaceMetrics.h"
11 #include "SkPDFDocument.h"
12 #include "SkPDFGlyphUse.h"
13 #include "SkPDFTypes.h"
14 #include "SkStrikeCache.h"
15 #include "SkTypeface.h"
16 
17 /** \class SkPDFFont
18     A PDF Object class representing a font.  The font may have resources
19     attached to it in order to embed the font.  SkPDFFonts are canonicalized
20     so that resource deduplication will only include one copy of a font.
21     This class uses the same pattern as SkPDFGraphicState, a static weak
22     reference to each instantiated class.
23 */
24 class SkPDFFont {
25 public:
26     SkPDFFont() {}
27     ~SkPDFFont();
28     SkPDFFont(SkPDFFont&&);
29     SkPDFFont& operator=(SkPDFFont&&);
30 
31     /** Returns the typeface represented by this class. Returns nullptr for the
32      *  default typeface.
33      */
34     SkTypeface* typeface() const { return fTypeface.get(); }
35 
36     /** Returns the font type represented in this font.  For Type0 fonts,
37      *  returns the type of the descendant font.
38      */
39     SkAdvancedTypefaceMetrics::FontType getType() const { return fFontType; }
40 
41     static SkAdvancedTypefaceMetrics::FontType FontType(const SkAdvancedTypefaceMetrics&);
42     static void GetType1GlyphNames(const SkTypeface&, SkString*);
43 
44     static bool IsMultiByte(SkAdvancedTypefaceMetrics::FontType type) {
45         return type == SkAdvancedTypefaceMetrics::kType1CID_Font ||
46                type == SkAdvancedTypefaceMetrics::kTrueType_Font;
47     }
48 
49     static SkExclusiveStrikePtr MakeVectorCache(SkTypeface*, int* sizeOut);
50 
51     /** Returns true if this font encoding supports glyph IDs above 255.
52      */
53     bool multiByteGlyphs() const { return SkPDFFont::IsMultiByte(this->getType()); }
54 
55     /** Return true if this font has an encoding for the passed glyph id.
56      */
57     bool hasGlyph(SkGlyphID gid) {
58         return (gid >= this->firstGlyphID() && gid <= this->lastGlyphID()) || gid == 0;
59     }
60 
61     /** Convert the input glyph ID into the font encoding.  */
62     SkGlyphID glyphToPDFFontEncoding(SkGlyphID gid) const {
63         if (this->multiByteGlyphs() || gid == 0) {
64             return gid;
65         }
66         SkASSERT(gid >= this->firstGlyphID() && gid <= this->lastGlyphID());
67         SkASSERT(this->firstGlyphID() > 0);
68         return gid - this->firstGlyphID() + 1;
69     }
70 
71     void noteGlyphUsage(SkGlyphID glyph) {
72         SkASSERT(this->hasGlyph(glyph));
73         fGlyphUsage.set(glyph);
74     }
75 
76     SkPDFIndirectReference indirectReference() const { return fIndirectReference; }
77 
78     /** Get the font resource for the passed typeface and glyphID. The
79      *  reference count of the object is incremented and it is the caller's
80      *  responsibility to unreference it when done.  This is needed to
81      *  accommodate the weak reference pattern used when the returned object
82      *  is new and has no other references.
83      *  @param typeface  The typeface to find, not nullptr.
84      *  @param glyphID   Specify which section of a large font is of interest.
85      */
86     static SkPDFFont* GetFontResource(SkPDFDocument* doc,
87                                       SkStrike* cache,
88                                       SkTypeface* typeface,
89                                       SkGlyphID glyphID);
90 
91     /** Gets SkAdvancedTypefaceMetrics, and caches the result.
92      *  @param typeface can not be nullptr.
93      *  @return nullptr only when typeface is bad.
94      */
95     static const SkAdvancedTypefaceMetrics* GetMetrics(const SkTypeface* typeface,
96                                                        SkPDFDocument* canon);
97 
98     static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface,
99                                                        SkPDFDocument* canon);
100 
101     void emitSubset(SkPDFDocument*) const;
102 
103     /**
104      *  Return false iff the typeface has its NotEmbeddable flag set.
105      *  typeface is not nullptr
106      */
107     static bool CanEmbedTypeface(SkTypeface*, SkPDFDocument*);
108 
109     SkGlyphID firstGlyphID() const { return fGlyphUsage.firstNonZero(); }
110     SkGlyphID lastGlyphID() const { return fGlyphUsage.lastGlyph(); }
111     const SkPDFGlyphUse& glyphUsage() const { return fGlyphUsage; }
112     sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
113 
114 private:
115     sk_sp<SkTypeface> fTypeface;
116     SkPDFGlyphUse fGlyphUsage;
117     SkPDFIndirectReference fIndirectReference;
118     SkAdvancedTypefaceMetrics::FontType fFontType = (SkAdvancedTypefaceMetrics::FontType)(-1);
119 
120     SkPDFFont(sk_sp<SkTypeface>,
121               SkGlyphID firstGlyphID,
122               SkGlyphID lastGlyphID,
123               SkAdvancedTypefaceMetrics::FontType fontType,
124               SkPDFIndirectReference indirectReference);
125     // The glyph IDs accessible with this font.  For Type1 (non CID) fonts,
126     // this will be a subset if the font has more than 255 glyphs.
127 
128     SkPDFFont(const SkPDFFont&) = delete;
129     SkPDFFont& operator=(const SkPDFFont&) = delete;
130 };
131 
132 #endif
133