1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkData.h"
9cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
10cb93a386Sopenharmony_ci#include "src/core/SkFontDescriptor.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_cienum {
13cb93a386Sopenharmony_ci    kInvalid        = 0x00,
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci    // these must match the sfnt 'name' enums
16cb93a386Sopenharmony_ci    kFontFamilyName = 0x01,
17cb93a386Sopenharmony_ci    kFullName       = 0x04,
18cb93a386Sopenharmony_ci    kPostscriptName = 0x06,
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci    // These count backwards from 0xFF, so as not to collide with the SFNT
21cb93a386Sopenharmony_ci    // defines for names in its 'name' table.
22cb93a386Sopenharmony_ci    kFontVariation  = 0xFA,
23cb93a386Sopenharmony_ci    kFontIndex      = 0xFD,
24cb93a386Sopenharmony_ci    kSentinel       = 0xFF,
25cb93a386Sopenharmony_ci};
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ciSkFontDescriptor::SkFontDescriptor() { }
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_cistatic bool SK_WARN_UNUSED_RESULT read_string(SkStream* stream, SkString* string) {
30cb93a386Sopenharmony_ci    size_t length;
31cb93a386Sopenharmony_ci    if (!stream->readPackedUInt(&length)) { return false; }
32cb93a386Sopenharmony_ci    if (length > 0) {
33cb93a386Sopenharmony_ci        string->resize(length);
34cb93a386Sopenharmony_ci        if (stream->read(string->writable_str(), length) != length) { return false; }
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci    return true;
37cb93a386Sopenharmony_ci}
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_cistatic bool write_string(SkWStream* stream, const SkString& string, uint32_t id) {
40cb93a386Sopenharmony_ci    if (string.isEmpty()) { return true; }
41cb93a386Sopenharmony_ci    return stream->writePackedUInt(id) &&
42cb93a386Sopenharmony_ci           stream->writePackedUInt(string.size()) &&
43cb93a386Sopenharmony_ci           stream->write(string.c_str(), string.size());
44cb93a386Sopenharmony_ci}
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_cistatic bool write_uint(SkWStream* stream, size_t n, uint32_t id) {
47cb93a386Sopenharmony_ci    return stream->writePackedUInt(id) &&
48cb93a386Sopenharmony_ci           stream->writePackedUInt(n);
49cb93a386Sopenharmony_ci}
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_cistatic size_t SK_WARN_UNUSED_RESULT read_id(SkStream* stream) {
52cb93a386Sopenharmony_ci    size_t i;
53cb93a386Sopenharmony_ci    if (!stream->readPackedUInt(&i)) { return kInvalid; }
54cb93a386Sopenharmony_ci    return i;
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_cibool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) {
58cb93a386Sopenharmony_ci    size_t styleBits;
59cb93a386Sopenharmony_ci    if (!stream->readPackedUInt(&styleBits)) { return false; }
60cb93a386Sopenharmony_ci    result->fStyle = SkFontStyle((styleBits >> 16) & 0xFFFF,
61cb93a386Sopenharmony_ci                                 (styleBits >> 8 ) & 0xFF,
62cb93a386Sopenharmony_ci                                 static_cast<SkFontStyle::Slant>(styleBits & 0xFF));
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    size_t coordinateCount;
65cb93a386Sopenharmony_ci    using CoordinateCountType = decltype(result->fCoordinateCount);
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci    size_t index;
68cb93a386Sopenharmony_ci    using CollectionIndexType = decltype(result->fCollectionIndex);
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    for (size_t id; (id = read_id(stream)) != kSentinel;) {
71cb93a386Sopenharmony_ci        switch (id) {
72cb93a386Sopenharmony_ci            case kFontFamilyName:
73cb93a386Sopenharmony_ci                if (!read_string(stream, &result->fFamilyName)) { return false; }
74cb93a386Sopenharmony_ci                break;
75cb93a386Sopenharmony_ci            case kFullName:
76cb93a386Sopenharmony_ci                if (!read_string(stream, &result->fFullName)) { return false; }
77cb93a386Sopenharmony_ci                break;
78cb93a386Sopenharmony_ci            case kPostscriptName:
79cb93a386Sopenharmony_ci                if (!read_string(stream, &result->fPostscriptName)) { return false; }
80cb93a386Sopenharmony_ci                break;
81cb93a386Sopenharmony_ci            case kFontVariation:
82cb93a386Sopenharmony_ci                if (!stream->readPackedUInt(&coordinateCount)) { return false; }
83cb93a386Sopenharmony_ci                if (!SkTFitsIn<CoordinateCountType>(coordinateCount)) { return false; }
84cb93a386Sopenharmony_ci                result->fCoordinateCount = SkTo<CoordinateCountType>(coordinateCount);
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci                result->fVariation.reset(coordinateCount);
87cb93a386Sopenharmony_ci                for (size_t i = 0; i < coordinateCount; ++i) {
88cb93a386Sopenharmony_ci                    if (!stream->readU32(&result->fVariation[i].axis)) { return false; }
89cb93a386Sopenharmony_ci                    if (!stream->readScalar(&result->fVariation[i].value)) { return false; }
90cb93a386Sopenharmony_ci                }
91cb93a386Sopenharmony_ci                break;
92cb93a386Sopenharmony_ci            case kFontIndex:
93cb93a386Sopenharmony_ci                if (!stream->readPackedUInt(&index)) { return false; }
94cb93a386Sopenharmony_ci                if (!SkTFitsIn<CollectionIndexType>(index)) { return false; }
95cb93a386Sopenharmony_ci                result->fCollectionIndex = SkTo<CollectionIndexType>(index);
96cb93a386Sopenharmony_ci                break;
97cb93a386Sopenharmony_ci            default:
98cb93a386Sopenharmony_ci                SkDEBUGFAIL("Unknown id used by a font descriptor");
99cb93a386Sopenharmony_ci                return false;
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    size_t length;
104cb93a386Sopenharmony_ci    if (!stream->readPackedUInt(&length)) { return false; }
105cb93a386Sopenharmony_ci    if (length > 0) {
106cb93a386Sopenharmony_ci        sk_sp<SkData> data(SkData::MakeUninitialized(length));
107cb93a386Sopenharmony_ci        if (stream->read(data->writable_data(), length) != length) {
108cb93a386Sopenharmony_ci            SkDEBUGFAIL("Could not read font data");
109cb93a386Sopenharmony_ci            return false;
110cb93a386Sopenharmony_ci        }
111cb93a386Sopenharmony_ci        result->fStream = SkMemoryStream::Make(std::move(data));
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci    return true;
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_civoid SkFontDescriptor::serialize(SkWStream* stream) const {
117cb93a386Sopenharmony_ci    uint32_t styleBits = (fStyle.weight() << 16) | (fStyle.width() << 8) | (fStyle.slant());
118cb93a386Sopenharmony_ci    stream->writePackedUInt(styleBits);
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci    write_string(stream, fFamilyName, kFontFamilyName);
121cb93a386Sopenharmony_ci    write_string(stream, fFullName, kFullName);
122cb93a386Sopenharmony_ci    write_string(stream, fPostscriptName, kPostscriptName);
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    if (fCollectionIndex) {
125cb93a386Sopenharmony_ci        write_uint(stream, fCollectionIndex, kFontIndex);
126cb93a386Sopenharmony_ci    }
127cb93a386Sopenharmony_ci    if (fCoordinateCount) {
128cb93a386Sopenharmony_ci        write_uint(stream, fCoordinateCount, kFontVariation);
129cb93a386Sopenharmony_ci        for (int i = 0; i < fCoordinateCount; ++i) {
130cb93a386Sopenharmony_ci            stream->write32(fVariation[i].axis);
131cb93a386Sopenharmony_ci            stream->writeScalar(fVariation[i].value);
132cb93a386Sopenharmony_ci        }
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    stream->writePackedUInt(kSentinel);
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    if (fStream) {
138cb93a386Sopenharmony_ci        std::unique_ptr<SkStreamAsset> fontStream = fStream->duplicate();
139cb93a386Sopenharmony_ci        size_t length = fontStream->getLength();
140cb93a386Sopenharmony_ci        stream->writePackedUInt(length);
141cb93a386Sopenharmony_ci        stream->writeStream(fontStream.get(), length);
142cb93a386Sopenharmony_ci    } else {
143cb93a386Sopenharmony_ci        stream->writePackedUInt(0);
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci}
146