SkPDFFont.cpp revision ee5ee582430196ee3a9b9473bf865e060515996c
1/*
2 * Copyright (C) 2011 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <ctype.h>
18
19#include "SkFontHost.h"
20#include "SkGlyphCache.h"
21#include "SkPaint.h"
22#include "SkPDFDevice.h"
23#include "SkPDFFont.h"
24#include "SkPDFStream.h"
25#include "SkPDFTypes.h"
26#include "SkPDFUtils.h"
27#include "SkRefCnt.h"
28#include "SkScalar.h"
29#include "SkStream.h"
30#include "SkTypeface.h"
31#include "SkTypes.h"
32#include "SkUtils.h"
33
34namespace {
35
36bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
37                     size_t* size) {
38    // PFB sections have a two or six bytes header. 0x80 and a one byte
39    // section type followed by a four byte section length.  Type one is
40    // an ASCII section (includes a length), type two is a binary section
41    // (includes a length) and type three is an EOF marker with no length.
42    const uint8_t* buf = *src;
43    if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType)
44        return false;
45    if (buf[1] == 3)
46        return true;
47    if (*len < 6)
48        return false;
49
50    *size = buf[2] | (buf[3] << 8) | (buf[4] << 16) | (buf[5] << 24);
51    size_t consumed = *size + 6;
52    if (consumed > *len)
53        return false;
54    *src = *src + consumed;
55    *len = *len - consumed;
56    return true;
57}
58
59bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen,
60              size_t* dataLen, size_t* trailerLen) {
61    const uint8_t* srcPtr = src;
62    size_t remaining = size;
63
64    return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
65           parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
66           parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
67           parsePFBSection(&srcPtr, &remaining, 3, NULL);
68}
69
70/* The sections of a PFA file are implicitly defined.  The body starts
71 * after the line containing "eexec," and the trailer starts with 512
72 * literal 0's followed by "cleartomark" (plus arbitrary white space).
73 *
74 * This function assumes that src is NUL terminated, but the NUL
75 * termination is not included in size.
76 *
77 */
78bool parsePFA(const char* src, size_t size, size_t* headerLen,
79              size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) {
80    const char* end = src + size;
81
82    const char* dataPos = strstr(src, "eexec");
83    if (!dataPos)
84        return false;
85    dataPos += strlen("eexec");
86    while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
87            dataPos < end)
88        dataPos++;
89    *headerLen = dataPos - src;
90
91    const char* trailerPos = strstr(dataPos, "cleartomark");
92    if (!trailerPos)
93        return false;
94    int zeroCount = 0;
95    for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
96        if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
97            continue;
98        } else if (*trailerPos == '0') {
99            zeroCount++;
100        } else {
101            return false;
102        }
103    }
104    if (zeroCount != 512)
105        return false;
106
107    *hexDataLen = trailerPos - src - *headerLen;
108    *trailerLen = size - *headerLen - *hexDataLen;
109
110    // Verify that the data section is hex encoded and count the bytes.
111    int nibbles = 0;
112    for (; dataPos < trailerPos; dataPos++) {
113        if (isspace(*dataPos))
114            continue;
115        if (!isxdigit(*dataPos))
116            return false;
117        nibbles++;
118    }
119    *dataLen = (nibbles + 1) / 2;
120
121    return true;
122}
123
124int8_t hexToBin(uint8_t c) {
125    if (!isxdigit(c))
126        return -1;
127    if (c <= '9') return c - '0';
128    if (c <= 'F') return c - 'A' + 10;
129    if (c <= 'f') return c - 'a' + 10;
130    return -1;
131}
132
133SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen,
134                            size_t* dataLen, size_t* trailerLen) {
135    // srcStream may be backed by a file or a unseekable fd, so we may not be
136    // able to use skip(), rewind(), or getMemoryBase().  read()ing through
137    // the input only once is doable, but very ugly. Furthermore, it'd be nice
138    // if the data was NUL terminated so that we can use strstr() to search it.
139    // Make as few copies as possible given these constraints.
140    SkDynamicMemoryWStream dynamicStream;
141    SkRefPtr<SkMemoryStream> staticStream;
142    const uint8_t* src;
143    size_t srcLen;
144    if ((srcLen = srcStream->getLength()) > 0) {
145        staticStream = new SkMemoryStream(srcLen + 1);
146        staticStream->unref();  // new and SkRefPtr both took a ref.
147        src = (const uint8_t*)staticStream->getMemoryBase();
148        if (srcStream->getMemoryBase() != NULL) {
149            memcpy((void *)src, srcStream->getMemoryBase(), srcLen);
150        } else {
151            size_t read = 0;
152            while (read < srcLen) {
153                size_t got = srcStream->read((void *)staticStream->getAtPos(),
154                                             srcLen - read);
155                if (got == 0)
156                    return NULL;
157                read += got;
158                staticStream->seek(read);
159            }
160        }
161        ((uint8_t *)src)[srcLen] = 0;
162    } else {
163        static const size_t bufSize = 4096;
164        uint8_t buf[bufSize];
165        size_t amount;
166        while ((amount = srcStream->read(buf, bufSize)) > 0)
167            dynamicStream.write(buf, amount);
168        amount = 0;
169        dynamicStream.write(&amount, 1);  // NULL terminator.
170        // getStream makes another copy, but we couldn't do any better.
171        src = (const uint8_t*)dynamicStream.getStream();
172        srcLen = dynamicStream.getOffset() - 1;
173    }
174
175    if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
176        SkMemoryStream* result =
177            new SkMemoryStream(*headerLen + *dataLen + *trailerLen);
178        memcpy((char*)result->getAtPos(), src + 6, *headerLen);
179        result->seek(*headerLen);
180        memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6, *dataLen);
181        result->seek(*headerLen + *dataLen);
182        memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6 + *dataLen,
183               *trailerLen);
184        result->rewind();
185        return result;
186    }
187
188    // A PFA has to be converted for PDF.
189    size_t hexDataLen;
190    if (parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
191                 trailerLen)) {
192        SkMemoryStream* result =
193            new SkMemoryStream(*headerLen + *dataLen + *trailerLen);
194        memcpy((char*)result->getAtPos(), src, *headerLen);
195        result->seek(*headerLen);
196
197        const uint8_t* hexData = src + *headerLen;
198        const uint8_t* trailer = hexData + hexDataLen;
199        size_t outputOffset = 0;
200        uint8_t dataByte = 0;  // To hush compiler.
201        bool highNibble = true;
202        for (; hexData < trailer; hexData++) {
203            char curNibble = hexToBin(*hexData);
204            if (curNibble < 0)
205                continue;
206            if (highNibble) {
207                dataByte = curNibble << 4;
208                highNibble = false;
209            } else {
210                dataByte |= curNibble;
211                highNibble = true;
212                ((char *)result->getAtPos())[outputOffset++] = dataByte;
213            }
214        }
215        if (!highNibble)
216            ((char *)result->getAtPos())[outputOffset++] = dataByte;
217        SkASSERT(outputOffset == *dataLen);
218        result->seek(*headerLen + outputOffset);
219
220        memcpy((char *)result->getAtPos(), src + *headerLen + hexDataLen,
221               *trailerLen);
222        result->rewind();
223        return result;
224    }
225
226    return NULL;
227}
228
229// scale from em-units to base-1000, returning as a SkScalar
230SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
231    SkScalar scaled = SkIntToScalar(val);
232    if (emSize == 1000) {
233        return scaled;
234    } else {
235        return SkScalarMulDiv(scaled, 1000, emSize);
236    }
237}
238
239void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
240                                 SkWStream* content) {
241    // Specify width and bounding box for the glyph.
242    SkPDFScalar::Append(width, content);
243    content->writeText(" 0 ");
244    content->writeDecAsText(box.fLeft);
245    content->writeText(" ");
246    content->writeDecAsText(box.fTop);
247    content->writeText(" ");
248    content->writeDecAsText(box.fRight);
249    content->writeText(" ");
250    content->writeDecAsText(box.fBottom);
251    content->writeText(" d1\n");
252}
253
254SkPDFArray* makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
255    SkPDFArray* bbox = new SkPDFArray;
256    bbox->reserve(4);
257    bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fLeft,
258                                                    emSize)))->unref();
259    bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fBottom,
260                                                    emSize)))->unref();
261    bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fRight,
262                                                    emSize)))->unref();
263    bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fTop,
264                                                    emSize)))->unref();
265    return bbox;
266}
267
268SkPDFArray* appendWidth(const int16_t& width, uint16_t emSize,
269                        SkPDFArray* array) {
270    array->append(new SkPDFScalar(scaleFromFontUnits(width, emSize)))->unref();
271    return array;
272}
273
274SkPDFArray* appendVerticalAdvance(
275        const SkAdvancedTypefaceMetrics::VerticalMetric& advance,
276        uint16_t emSize, SkPDFArray* array) {
277    appendWidth(advance.fVerticalAdvance, emSize, array);
278    appendWidth(advance.fOriginXDisp, emSize, array);
279    appendWidth(advance.fOriginYDisp, emSize, array);
280    return array;
281}
282
283template <typename Data>
284SkPDFArray* composeAdvanceData(
285        SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* advanceInfo,
286        uint16_t emSize,
287        SkPDFArray* (*appendAdvance)(const Data& advance, uint16_t emSize,
288                                     SkPDFArray* array),
289        Data* defaultAdvance) {
290    SkPDFArray* result = new SkPDFArray();
291    for (; advanceInfo != NULL; advanceInfo = advanceInfo->fNext.get()) {
292        switch (advanceInfo->fType) {
293            case SkAdvancedTypefaceMetrics::WidthRange::kDefault: {
294                SkASSERT(advanceInfo->fAdvance.count() == 1);
295                *defaultAdvance = advanceInfo->fAdvance[0];
296                break;
297            }
298            case SkAdvancedTypefaceMetrics::WidthRange::kRange: {
299                SkRefPtr<SkPDFArray> advanceArray = new SkPDFArray();
300                advanceArray->unref();  // SkRefPtr and new both took a ref.
301                for (int j = 0; j < advanceInfo->fAdvance.count(); j++)
302                    appendAdvance(advanceInfo->fAdvance[j], emSize,
303                                  advanceArray.get());
304                result->append(new SkPDFInt(advanceInfo->fStartId))->unref();
305                result->append(advanceArray.get());
306                break;
307            }
308            case SkAdvancedTypefaceMetrics::WidthRange::kRun: {
309                SkASSERT(advanceInfo->fAdvance.count() == 1);
310                result->append(new SkPDFInt(advanceInfo->fStartId))->unref();
311                result->append(new SkPDFInt(advanceInfo->fEndId))->unref();
312                appendAdvance(advanceInfo->fAdvance[0], emSize, result);
313                break;
314            }
315        }
316    }
317    return result;
318}
319
320}  // namespace
321
322/* Font subset design: It would be nice to be able to subset fonts
323 * (particularly type 3 fonts), but it's a lot of work and not a priority.
324 *
325 * Resources are canonicalized and uniqueified by pointer so there has to be
326 * some additional state indicating which subset of the font is used.  It
327 * must be maintained at the page granularity and then combined at the document
328 * granularity. a) change SkPDFFont to fill in its state on demand, kind of
329 * like SkPDFGraphicState.  b) maintain a per font glyph usage class in each
330 * page/pdf device. c) in the document, retrieve the per font glyph usage
331 * from each page and combine it and ask for a resource with that subset.
332 */
333
334SkPDFFont::~SkPDFFont() {
335    SkAutoMutexAcquire lock(canonicalFontsMutex());
336    int index;
337    if (find(SkTypeface::UniqueID(fTypeface.get()), fFirstGlyphID, &index)) {
338        canonicalFonts().removeShuffle(index);
339#ifdef SK_DEBUG
340        SkASSERT(!fDescendant);
341    } else {
342        SkASSERT(fDescendant);
343#endif
344    }
345    fResources.unrefAll();
346}
347
348void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) {
349    resourceList->setReserve(resourceList->count() + fResources.count());
350    for (int i = 0; i < fResources.count(); i++) {
351        resourceList->push(fResources[i]);
352        fResources[i]->ref();
353        fResources[i]->getResources(resourceList);
354    }
355}
356
357SkTypeface* SkPDFFont::typeface() {
358    return fTypeface.get();
359}
360
361bool SkPDFFont::hasGlyph(uint16_t id) {
362    return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0;
363}
364
365bool SkPDFFont::multiByteGlyphs() {
366    return fMultiByteGlyphs;
367}
368
369size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs,
370                                          size_t numGlyphs) {
371    // A font with multibyte glyphs will support all glyph IDs in a single font.
372    if (fMultiByteGlyphs) {
373        return numGlyphs;
374    }
375
376    for (size_t i = 0; i < numGlyphs; i++) {
377        if (glyphIDs[i] == 0) {
378            continue;
379        }
380        if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) {
381            return i;
382        }
383        glyphIDs[i] -= (fFirstGlyphID - 1);
384    }
385
386    return numGlyphs;
387}
388
389// static
390SkPDFFont* SkPDFFont::getFontResource(SkTypeface* typeface, uint16_t glyphID) {
391    SkAutoMutexAcquire lock(canonicalFontsMutex());
392    const uint32_t fontID = SkTypeface::UniqueID(typeface);
393    int index;
394    if (find(fontID, glyphID, &index)) {
395        canonicalFonts()[index].fFont->ref();
396        return canonicalFonts()[index].fFont;
397    }
398
399    SkRefPtr<SkAdvancedTypefaceMetrics> fontInfo;
400    SkPDFDict* fontDescriptor = NULL;
401    if (index >= 0) {
402        SkPDFFont* relatedFont = canonicalFonts()[index].fFont;
403        SkASSERT(relatedFont->fFontInfo.get());
404        fontInfo = relatedFont->fFontInfo;
405        fontDescriptor = relatedFont->fDescriptor.get();
406    } else {
407        fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, SkTBitOr(
408                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo,
409                SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo));
410        SkSafeUnref(fontInfo.get());  // SkRefPtr and Get both took a reference.
411    }
412
413    SkPDFFont* font = new SkPDFFont(fontInfo.get(), typeface, glyphID, false,
414                                    fontDescriptor);
415    FontRec newEntry(font, fontID, font->fFirstGlyphID);
416    index = canonicalFonts().count();
417    canonicalFonts().push(newEntry);
418    return font;  // Return the reference new SkPDFFont() created.
419}
420
421// static
422SkTDArray<SkPDFFont::FontRec>& SkPDFFont::canonicalFonts() {
423    // This initialization is only thread safe with gcc.
424    static SkTDArray<FontRec> gCanonicalFonts;
425    return gCanonicalFonts;
426}
427
428// static
429SkMutex& SkPDFFont::canonicalFontsMutex() {
430    // This initialization is only thread safe with gcc.
431    static SkMutex gCanonicalFontsMutex;
432    return gCanonicalFontsMutex;
433}
434
435// static
436bool SkPDFFont::find(uint32_t fontID, uint16_t glyphID, int* index) {
437    // TODO(vandebo) optimize this, do only one search?
438    FontRec search(NULL, fontID, glyphID);
439    *index = canonicalFonts().find(search);
440    if (*index >= 0)
441        return true;
442    search.fGlyphID = 0;
443    *index = canonicalFonts().find(search);
444    return false;
445}
446
447SkPDFFont::SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo,
448                     SkTypeface* typeface,
449                     uint16_t glyphID,
450                     bool descendantFont,
451                     SkPDFDict* fontDescriptor)
452        : SkPDFDict("Font"),
453          fTypeface(typeface),
454#ifdef SK_DEBUG
455          fDescendant(descendantFont),
456#endif
457          fMultiByteGlyphs(false),
458          fFirstGlyphID(1),
459          fLastGlyphID(fontInfo ? fontInfo->fLastGlyphID : 0),
460          fFontInfo(fontInfo),
461          fDescriptor(fontDescriptor) {
462
463    SkAdvancedTypefaceMetrics::FontType type;
464    if (fontInfo) {
465        type = fontInfo->fType;
466    } else {
467        type = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
468    }
469
470    if (fontInfo && fontInfo->fMultiMaster) {
471        SkASSERT(false);  // Not supported yet.
472        fontInfo->fType = SkAdvancedTypefaceMetrics::kOther_Font;
473    }
474    if (type == SkAdvancedTypefaceMetrics::kType1CID_Font ||
475        type == SkAdvancedTypefaceMetrics::kTrueType_Font) {
476        if (descendantFont) {
477            populateCIDFont();
478        } else {
479            populateType0Font();
480        }
481        // No need to hold onto the font info for fonts types that
482        // support multibyte glyphs.
483        fFontInfo = NULL;
484        return;
485    }
486
487    if (type == SkAdvancedTypefaceMetrics::kType1_Font &&
488        populateType1Font(glyphID)) {
489        return;
490    }
491
492    SkASSERT(type == SkAdvancedTypefaceMetrics::kType1_Font ||
493             type == SkAdvancedTypefaceMetrics::kCFF_Font ||
494             type == SkAdvancedTypefaceMetrics::kOther_Font ||
495             type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font);
496    populateType3Font(glyphID);
497}
498
499void SkPDFFont::populateType0Font() {
500    // TODO(vandebo) add a ToUnicode mapping.
501    fMultiByteGlyphs = true;
502
503    insert("Subtype", new SkPDFName("Type0"))->unref();
504    insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref();
505    insert("Encoding",  new SkPDFName("Identity-H"))->unref();
506
507    SkRefPtr<SkPDFArray> descendantFonts = new SkPDFArray();
508    descendantFonts->unref();  // SkRefPtr and new took a reference.
509
510    // Pass ref new created to fResources.
511    fResources.push(
512        new SkPDFFont(fFontInfo.get(), fTypeface.get(), 1, true, NULL));
513    descendantFonts->append(new SkPDFObjRef(fResources.top()))->unref();
514    insert("DescendantFonts", descendantFonts.get());
515}
516
517void SkPDFFont::populateCIDFont() {
518    fMultiByteGlyphs = true;
519    insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref();
520
521    if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kType1CID_Font) {
522        insert("Subtype", new SkPDFName("CIDFontType0"))->unref();
523    } else if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
524        insert("Subtype", new SkPDFName("CIDFontType2"))->unref();
525    } else {
526        SkASSERT(false);
527    }
528
529    SkRefPtr<SkPDFDict> sysInfo = new SkPDFDict;
530    sysInfo->unref();  // SkRefPtr and new both took a reference.
531    sysInfo->insert("Registry", new SkPDFString("Adobe"))->unref();
532    sysInfo->insert("Ordering", new SkPDFString("Identity"))->unref();
533    sysInfo->insert("Supplement", new SkPDFInt(0))->unref();
534    insert("CIDSystemInfo", sysInfo.get());
535
536    addFontDescriptor(0);
537
538    if (fFontInfo->fGlyphWidths.get()) {
539        int16_t defaultWidth = 0;
540        SkRefPtr<SkPDFArray> widths =
541            composeAdvanceData(fFontInfo->fGlyphWidths.get(),
542                               fFontInfo->fEmSize, &appendWidth, &defaultWidth);
543        widths->unref();  // SkRefPtr and compose both took a reference.
544        if (widths->size())
545            insert("W", widths.get());
546        if (defaultWidth != 0) {
547            insert("DW", new SkPDFScalar(scaleFromFontUnits(
548                    defaultWidth, fFontInfo->fEmSize)))->unref();
549        }
550    }
551    if (fFontInfo->fVerticalMetrics.get()) {
552        struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance;
553        defaultAdvance.fVerticalAdvance = 0;
554        defaultAdvance.fOriginXDisp = 0;
555        defaultAdvance.fOriginYDisp = 0;
556        SkRefPtr<SkPDFArray> advances =
557            composeAdvanceData(fFontInfo->fVerticalMetrics.get(),
558                               fFontInfo->fEmSize, &appendVerticalAdvance,
559                               &defaultAdvance);
560        advances->unref();  // SkRefPtr and compose both took a ref.
561        if (advances->size())
562            insert("W2", advances.get());
563        if (defaultAdvance.fVerticalAdvance ||
564                defaultAdvance.fOriginXDisp ||
565                defaultAdvance.fOriginYDisp) {
566            insert("DW2", appendVerticalAdvance(defaultAdvance,
567                                                fFontInfo->fEmSize,
568                                                new SkPDFArray))->unref();
569        }
570    }
571}
572
573bool SkPDFFont::populateType1Font(int16_t glyphID) {
574    SkASSERT(!fFontInfo->fVerticalMetrics.get());
575    SkASSERT(fFontInfo->fGlyphWidths.get());
576
577    adjustGlyphRangeForSingleByteEncoding(glyphID);
578
579    int16_t defaultWidth = 0;
580    const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL;
581    const SkAdvancedTypefaceMetrics::WidthRange* widthEntry;
582    for (widthEntry = fFontInfo.get()->fGlyphWidths.get();
583            widthEntry != NULL;
584            widthEntry = widthEntry->fNext.get()) {
585        switch (widthEntry->fType) {
586            case SkAdvancedTypefaceMetrics::WidthRange::kDefault:
587                defaultWidth = widthEntry->fAdvance[0];
588                break;
589            case SkAdvancedTypefaceMetrics::WidthRange::kRun:
590                SkASSERT(false);
591                break;
592            case SkAdvancedTypefaceMetrics::WidthRange::kRange:
593                SkASSERT(widthRangeEntry == NULL);
594                widthRangeEntry = widthEntry;
595                break;
596        }
597    }
598
599    if (!addFontDescriptor(defaultWidth))
600        return false;
601
602    insert("Subtype", new SkPDFName("Type1"))->unref();
603    insert("BaseFont", new SkPDFName(fFontInfo->fFontName))->unref();
604
605    addWidthInfoFromRange(defaultWidth, widthRangeEntry);
606
607    SkRefPtr<SkPDFDict> encoding = new SkPDFDict("Encoding");
608    encoding->unref();  // SkRefPtr and new both took a reference.
609    insert("Encoding", encoding.get());
610
611    SkRefPtr<SkPDFArray> encDiffs = new SkPDFArray;
612    encDiffs->unref();  // SkRefPtr and new both took a reference.
613    encoding->insert("Differences", encDiffs.get());
614
615    encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2);
616    encDiffs->append(new SkPDFInt(1))->unref();
617    for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) {
618        encDiffs->append(
619            new SkPDFName(fFontInfo->fGlyphNames->get()[gID]))->unref();
620    }
621
622    if (fFontInfo->fLastGlyphID <= 255)
623        fFontInfo = NULL;
624    return true;
625}
626
627void SkPDFFont::populateType3Font(int16_t glyphID) {
628    SkPaint paint;
629    paint.setTypeface(fTypeface.get());
630    paint.setTextSize(1000);
631    SkAutoGlyphCache autoCache(paint, NULL);
632    SkGlyphCache* cache = autoCache.getCache();
633    // If fLastGlyphID isn't set (because there is not fFontInfo), look it up.
634    if (fLastGlyphID == 0) {
635        fLastGlyphID = cache->getGlyphCount() - 1;
636    }
637
638    adjustGlyphRangeForSingleByteEncoding(glyphID);
639
640    insert("Subtype", new SkPDFName("Type3"))->unref();
641    // Flip about the x-axis and scale by 1/1000.
642    SkMatrix fontMatrix;
643    fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000));
644    insert("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix))->unref();
645
646    SkRefPtr<SkPDFDict> charProcs = new SkPDFDict;
647    charProcs->unref();  // SkRefPtr and new both took a reference.
648    insert("CharProcs", charProcs.get());
649
650    SkRefPtr<SkPDFDict> encoding = new SkPDFDict("Encoding");
651    encoding->unref();  // SkRefPtr and new both took a reference.
652    insert("Encoding", encoding.get());
653
654    SkRefPtr<SkPDFArray> encDiffs = new SkPDFArray;
655    encDiffs->unref();  // SkRefPtr and new both took a reference.
656    encoding->insert("Differences", encDiffs.get());
657    encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2);
658    encDiffs->append(new SkPDFInt(1))->unref();
659
660    SkRefPtr<SkPDFArray> widthArray = new SkPDFArray();
661    widthArray->unref();  // SkRefPtr and new both took a ref.
662
663    SkIRect bbox = SkIRect::MakeEmpty();
664    for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) {
665        SkString characterName;
666        characterName.printf("gid%d", gID);
667        encDiffs->append(new SkPDFName(characterName))->unref();
668
669        const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
670        widthArray->append(new SkPDFScalar(SkFixedToScalar(glyph.fAdvanceX)))->unref();
671        SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
672                                              glyph.fWidth, glyph.fHeight);
673        bbox.join(glyphBBox);
674
675        SkDynamicMemoryWStream content;
676        setGlyphWidthAndBoundingBox(SkFixedToScalar(glyph.fAdvanceX), glyphBBox,
677                                    &content);
678        const SkPath* path = cache->findPath(glyph);
679        if (path) {
680            SkPDFUtils::EmitPath(*path, &content);
681            SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(),
682                                  &content);
683        }
684        SkRefPtr<SkMemoryStream> glyphStream = new SkMemoryStream();
685        glyphStream->unref();  // SkRefPtr and new both took a ref.
686        glyphStream->setMemoryOwned(content.detach(), content.getOffset());
687
688        SkRefPtr<SkPDFStream> glyphDescription =
689            new SkPDFStream(glyphStream.get());
690        // SkRefPtr and new both ref()'d charProcs, pass one.
691        fResources.push(glyphDescription.get());
692        charProcs->insert(characterName.c_str(),
693                          new SkPDFObjRef(glyphDescription.get()))->unref();
694    }
695
696    insert("FontBBox", makeFontBBox(bbox, 1000))->unref();
697    insert("FirstChar", new SkPDFInt(fFirstGlyphID))->unref();
698    insert("LastChar", new SkPDFInt(fLastGlyphID))->unref();
699    insert("Widths", widthArray.get());
700
701    if (fFontInfo && fFontInfo->fLastGlyphID <= 255)
702        fFontInfo = NULL;
703}
704
705bool SkPDFFont::addFontDescriptor(int16_t defaultWidth) {
706    if (fDescriptor.get() != NULL) {
707        fResources.push(fDescriptor.get());
708        fDescriptor->ref();
709        insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref();
710        return true;
711    }
712
713    fDescriptor = new SkPDFDict("FontDescriptor");
714    fDescriptor->unref();  // SkRefPtr and new both took a ref.
715
716    switch (fFontInfo->fType) {
717        case SkAdvancedTypefaceMetrics::kType1_Font: {
718            size_t header SK_INIT_TO_AVOID_WARNING;
719            size_t data SK_INIT_TO_AVOID_WARNING;
720            size_t trailer SK_INIT_TO_AVOID_WARNING;
721            SkRefPtr<SkStream> rawFontData =
722                SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get()));
723            rawFontData->unref();  // SkRefPtr and OpenStream both took a ref.
724            SkStream* fontData = handleType1Stream(rawFontData.get(), &header,
725                                                   &data, &trailer);
726            if (fontData == NULL)
727                return false;
728            SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData);
729            // SkRefPtr and new both ref()'d fontStream, pass one.
730            fResources.push(fontStream.get());
731            fontStream->insert("Length1", new SkPDFInt(header))->unref();
732            fontStream->insert("Length2", new SkPDFInt(data))->unref();
733            fontStream->insert("Length3", new SkPDFInt(trailer))->unref();
734            fDescriptor->insert("FontFile",
735                                new SkPDFObjRef(fontStream.get()))->unref();
736            break;
737        }
738        case SkAdvancedTypefaceMetrics::kTrueType_Font: {
739            SkRefPtr<SkStream> fontData =
740                SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get()));
741            fontData->unref();  // SkRefPtr and OpenStream both took a ref.
742            SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get());
743            // SkRefPtr and new both ref()'d fontStream, pass one.
744            fResources.push(fontStream.get());
745
746            fontStream->insert("Length1",
747                               new SkPDFInt(fontData->getLength()))->unref();
748            fDescriptor->insert("FontFile2",
749                                new SkPDFObjRef(fontStream.get()))->unref();
750            break;
751        }
752        case SkAdvancedTypefaceMetrics::kCFF_Font:
753        case SkAdvancedTypefaceMetrics::kType1CID_Font: {
754            SkRefPtr<SkStream> fontData =
755                SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get()));
756            fontData->unref();  // SkRefPtr and OpenStream both took a ref.
757            SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get());
758            // SkRefPtr and new both ref()'d fontStream, pass one.
759            fResources.push(fontStream.get());
760
761            if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kCFF_Font) {
762                fontStream->insert("Subtype", new SkPDFName("Type1C"))->unref();
763            } else {
764                fontStream->insert("Subtype",
765                        new SkPDFName("CIDFontType0c"))->unref();
766            }
767            fDescriptor->insert("FontFile3",
768                                new SkPDFObjRef(fontStream.get()))->unref();
769            break;
770        }
771        default:
772            SkASSERT(false);
773    }
774
775    const uint16_t emSize = fFontInfo->fEmSize;
776    fResources.push(fDescriptor.get());
777    fDescriptor->ref();
778    insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref();
779
780    fDescriptor->insert("FontName", new SkPDFName(
781            fFontInfo->fFontName))->unref();
782    fDescriptor->insert("Flags", new SkPDFInt(fFontInfo->fStyle))->unref();
783    fDescriptor->insert("Ascent", new SkPDFScalar(
784            scaleFromFontUnits(fFontInfo->fAscent, emSize)))->unref();
785    fDescriptor->insert("Descent", new SkPDFScalar(
786            scaleFromFontUnits(fFontInfo->fDescent, emSize)))->unref();
787    fDescriptor->insert("StemV", new SkPDFScalar(
788            scaleFromFontUnits(fFontInfo->fStemV, emSize)))->unref();
789    fDescriptor->insert("CapHeight", new SkPDFScalar(
790            scaleFromFontUnits(fFontInfo->fCapHeight, emSize)))->unref();
791    fDescriptor->insert("ItalicAngle", new SkPDFInt(
792            fFontInfo->fItalicAngle))->unref();
793    fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox,
794                                                 fFontInfo->fEmSize))->unref();
795
796    if (defaultWidth > 0) {
797        fDescriptor->insert("MissingWidth", new SkPDFScalar(
798                scaleFromFontUnits(defaultWidth, emSize)))->unref();
799    }
800    return true;
801}
802void SkPDFFont::addWidthInfoFromRange(
803        int16_t defaultWidth,
804        const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) {
805    SkRefPtr<SkPDFArray> widthArray = new SkPDFArray();
806    widthArray->unref();  // SkRefPtr and new both took a ref.
807    int firstChar = 0;
808    if (widthRangeEntry) {
809        const uint16_t emSize = fFontInfo->fEmSize;
810        int startIndex = fFirstGlyphID - widthRangeEntry->fStartId;
811        int endIndex = startIndex + fLastGlyphID - fFirstGlyphID + 1;
812        if (startIndex < 0)
813            startIndex = 0;
814        if (endIndex > widthRangeEntry->fAdvance.count())
815            endIndex = widthRangeEntry->fAdvance.count();
816        if (widthRangeEntry->fStartId == 0) {
817            appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get());
818        } else {
819            firstChar = startIndex + widthRangeEntry->fStartId;
820        }
821        for (int i = startIndex; i < endIndex; i++)
822            appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get());
823    } else {
824        appendWidth(defaultWidth, 1000, widthArray.get());
825    }
826    insert("FirstChar", new SkPDFInt(firstChar))->unref();
827    insert("LastChar",
828           new SkPDFInt(firstChar + widthArray->size() - 1))->unref();
829    insert("Widths", widthArray.get());
830}
831
832void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) {
833    // Single byte glyph encoding supports a max of 255 glyphs.
834    fFirstGlyphID = glyphID - (glyphID - 1) % 255;
835    if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
836        fLastGlyphID = fFirstGlyphID + 255 - 1;
837    }
838}
839
840
841bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const {
842    if (fFontID != b.fFontID)
843        return false;
844    if (fFont != NULL && b.fFont != NULL) {
845        return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID &&
846            fFont->fLastGlyphID == b.fFont->fLastGlyphID;
847    }
848    if (fGlyphID == 0 || b.fGlyphID == 0)
849        return true;
850
851    if (fFont != NULL) {
852        return fFont->fFirstGlyphID <= b.fGlyphID &&
853            b.fGlyphID <= fFont->fLastGlyphID;
854    } else if (b.fFont != NULL) {
855        return b.fFont->fFirstGlyphID <= fGlyphID &&
856            fGlyphID <= b.fFont->fLastGlyphID;
857    }
858    return fGlyphID == b.fGlyphID;
859}
860
861SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID)
862    : fFont(font),
863      fFontID(fontID),
864      fGlyphID(glyphID) {
865}
866