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 
12 enum {
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 
SkFontDescriptor(SkTypeface::Style style)25 SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fFontIndex(0), fStyle(style) { }
26 
read_string(SkStream * stream,SkString * string)27 static 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
skip_string(SkStream * stream)36 static void skip_string(SkStream* stream) {
37     const uint32_t length = SkToU32(stream->readPackedUInt());
38     if (length > 0) {
39         stream->skip(length);
40     }
41 }
42 
write_string(SkWStream * stream,const SkString & string,uint32_t id)43 static 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 
read_uint(SkStream * stream)52 static size_t read_uint(SkStream* stream) {
53     return stream->readPackedUInt();
54 }
55 
write_uint(SkWStream * stream,size_t n,uint32_t id)56 static void write_uint(SkWStream* stream, size_t n, uint32_t id) {
57     stream->writePackedUInt(id);
58     stream->writePackedUInt(n);
59 }
60 
SkFontDescriptor(SkStream * stream)61 SkFontDescriptor::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 
serialize(SkWStream * stream)96 void 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