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,  // Remove when MIN_PICTURE_VERSION > 41
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
35// Remove when MIN_PICTURE_VERSION > 41
36static void skip_string(SkStream* stream) {
37    const uint32_t length = SkToU32(stream->readPackedUInt());
38    if (length > 0) {
39        stream->skip(length);
40    }
41}
42
43static void write_string(SkWStream* stream, const SkString& string,
44                         uint32_t id) {
45    if (!string.isEmpty()) {
46        stream->writePackedUInt(id);
47        stream->writePackedUInt(string.size());
48        stream->write(string.c_str(), string.size());
49    }
50}
51
52static size_t read_uint(SkStream* stream) {
53    return stream->readPackedUInt();
54}
55
56static void write_uint(SkWStream* stream, size_t n, uint32_t id) {
57    stream->writePackedUInt(id);
58    stream->writePackedUInt(n);
59}
60
61SkFontDescriptor::SkFontDescriptor(SkStream* stream) : fFontIndex(0) {
62    fStyle = (SkTypeface::Style)stream->readPackedUInt();
63
64    for (size_t id; (id = stream->readPackedUInt()) != kSentinel;) {
65        switch (id) {
66            case kFontFamilyName:
67                read_string(stream, &fFamilyName);
68                break;
69            case kFullName:
70                read_string(stream, &fFullName);
71                break;
72            case kPostscriptName:
73                read_string(stream, &fPostscriptName);
74                break;
75            case kFontIndex:
76                fFontIndex = read_uint(stream);
77                break;
78            case kFontFileName:  // Remove when MIN_PICTURE_VERSION > 41
79                skip_string(stream);
80                break;
81            default:
82                SkDEBUGFAIL("Unknown id used by a font descriptor");
83                return;
84        }
85    }
86
87    size_t length = stream->readPackedUInt();
88    if (length > 0) {
89        SkAutoTUnref<SkData> data(SkData::NewUninitialized(length));
90        if (stream->read(data->writable_data(), length) == length) {
91            fFontData.reset(SkNEW_ARGS(SkMemoryStream, (data)));
92        }
93    }
94}
95
96void SkFontDescriptor::serialize(SkWStream* stream) {
97    stream->writePackedUInt(fStyle);
98
99    write_string(stream, fFamilyName, kFontFamilyName);
100    write_string(stream, fFullName, kFullName);
101    write_string(stream, fPostscriptName, kPostscriptName);
102    if (fFontIndex) {
103        write_uint(stream, fFontIndex, kFontIndex);
104    }
105
106    stream->writePackedUInt(kSentinel);
107
108    if (fFontData) {
109        size_t length = fFontData->getLength();
110        stream->writePackedUInt(length);
111        stream->writeStream(fFontData, length);
112    } else {
113        stream->writePackedUInt(0);
114    }
115}
116