1/*
2 * Copyright 2012 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
8#include "SkFontDescriptor.h"
9#include "SkStream.h"
10#include <SkData.h>
11
12enum {
13    // these must match the sfnt 'name' enums
14    kFontFamilyName = 0x01,
15    kFullName       = 0x04,
16    kPostscriptName = 0x06,
17
18    // These count backwards from 0xFF, so as not to collide with the SFNT
19    // defines for names in its 'name' table.
20    kFontIndex      = 0xFD,
21    kFontFileName   = 0xFE,
22    kSentinel       = 0xFF,
23};
24
25SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fFontIndex(0), fStyle(style) { }
26
27static void read_string(SkStream* stream, SkString* string) {
28    const uint32_t length = SkToU32(stream->readPackedUInt());
29    if (length > 0) {
30        string->resize(length);
31        stream->read(string->writable_str(), length);
32    }
33}
34
35static void write_string(SkWStream* stream, const SkString& string,
36                         uint32_t id) {
37    if (!string.isEmpty()) {
38        stream->writePackedUInt(id);
39        stream->writePackedUInt(string.size());
40        stream->write(string.c_str(), string.size());
41    }
42}
43
44static size_t read_uint(SkStream* stream) {
45    return stream->readPackedUInt();
46}
47
48static void write_uint(SkWStream* stream, size_t n, uint32_t id) {
49    stream->writePackedUInt(id);
50    stream->writePackedUInt(n);
51}
52
53SkFontDescriptor::SkFontDescriptor(SkStream* stream) : fFontIndex(0) {
54    fStyle = (SkTypeface::Style)stream->readPackedUInt();
55
56    for (size_t id; (id = stream->readPackedUInt()) != kSentinel;) {
57        switch (id) {
58            case kFontFamilyName:
59                read_string(stream, &fFamilyName);
60                break;
61            case kFullName:
62                read_string(stream, &fFullName);
63                break;
64            case kPostscriptName:
65                read_string(stream, &fPostscriptName);
66                break;
67            case kFontIndex:
68                fFontIndex = read_uint(stream);
69                break;
70            case kFontFileName:
71                read_string(stream, &fFontFileName);
72                break;
73            default:
74                SkDEBUGFAIL("Unknown id used by a font descriptor");
75                return;
76        }
77    }
78
79    size_t length = stream->readPackedUInt();
80    if (length > 0) {
81        SkAutoTUnref<SkData> data(SkData::NewUninitialized(length));
82        if (stream->read(data->writable_data(), length) == length) {
83            fFontData.reset(SkNEW_ARGS(SkMemoryStream, (data)));
84        }
85    }
86}
87
88void SkFontDescriptor::serialize(SkWStream* stream) {
89    stream->writePackedUInt(fStyle);
90
91    write_string(stream, fFamilyName, kFontFamilyName);
92    write_string(stream, fFullName, kFullName);
93    write_string(stream, fPostscriptName, kPostscriptName);
94    write_string(stream, fFontFileName, kFontFileName);
95    if (fFontIndex) {
96        write_uint(stream, fFontIndex, kFontIndex);
97    }
98
99    stream->writePackedUInt(kSentinel);
100
101    if (fFontData) {
102        size_t length = fFontData->getLength();
103        stream->writePackedUInt(length);
104        stream->writeStream(fFontData, length);
105    } else {
106        stream->writePackedUInt(0);
107    }
108}
109