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