• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkData.h"
9  #include "include/core/SkStream.h"
10  #include "src/core/SkFontDescriptor.h"
11  
12  enum {
13      kInvalid        = 0x00,
14  
15      // these must match the sfnt 'name' enums
16      kFontFamilyName = 0x01,
17      kFullName       = 0x04,
18      kPostscriptName = 0x06,
19  
20      // These count backwards from 0xFF, so as not to collide with the SFNT
21      // defines for names in its 'name' table.
22      kFontAxes       = 0xFB,
23      kFontAxes_bad   = 0xFC, // Broken negative axes, remove when MIN_PICTURE_VERSION > 62.
24      kFontIndex      = 0xFD,
25      kSentinel       = 0xFF,
26  };
27  
SkFontDescriptor()28  SkFontDescriptor::SkFontDescriptor() { }
29  
read_string(SkStream * stream,SkString * string)30  static bool SK_WARN_UNUSED_RESULT read_string(SkStream* stream, SkString* string) {
31      size_t length;
32      if (!stream->readPackedUInt(&length)) { return false; }
33      if (length > 0) {
34          string->resize(length);
35          if (stream->read(string->writable_str(), length) != length) { return false; }
36      }
37      return true;
38  }
39  
write_string(SkWStream * stream,const SkString & string,uint32_t id)40  static bool write_string(SkWStream* stream, const SkString& string, uint32_t id) {
41      if (string.isEmpty()) { return true; }
42      return stream->writePackedUInt(id) &&
43             stream->writePackedUInt(string.size()) &&
44             stream->write(string.c_str(), string.size());
45  }
46  
write_uint(SkWStream * stream,size_t n,uint32_t id)47  static bool write_uint(SkWStream* stream, size_t n, uint32_t id) {
48      return stream->writePackedUInt(id) &&
49             stream->writePackedUInt(n);
50  }
51  
read_id(SkStream * stream)52  static size_t SK_WARN_UNUSED_RESULT read_id(SkStream* stream) {
53      size_t i;
54      if (!stream->readPackedUInt(&i)) { return kInvalid; }
55      return i;
56  }
57  
Deserialize(SkStream * stream,SkFontDescriptor * result)58  bool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) {
59      size_t styleBits;
60      if (!stream->readPackedUInt(&styleBits)) { return false; }
61      result->fStyle = SkFontStyle((styleBits >> 16) & 0xFFFF,
62                                   (styleBits >> 8 ) & 0xFF,
63                                   static_cast<SkFontStyle::Slant>(styleBits & 0xFF));
64  
65      SkAutoSTMalloc<4, SkFixed> axis;
66      size_t axisCount = 0;
67      size_t index = 0;
68      for (size_t id; (id = read_id(stream)) != kSentinel;) {
69          switch (id) {
70              case kFontFamilyName:
71                  if (!read_string(stream, &result->fFamilyName)) { return false; }
72                  break;
73              case kFullName:
74                  if (!read_string(stream, &result->fFullName)) { return false; }
75                  break;
76              case kPostscriptName:
77                  if (!read_string(stream, &result->fPostscriptName)) { return false; }
78                  break;
79              case kFontAxes:
80                  if (!stream->readPackedUInt(&axisCount)) { return false; }
81                  axis.reset(axisCount);
82                  for (size_t i = 0; i < axisCount; ++i) {
83                      if (!stream->readS32(&axis[i])) { return false; }
84                  }
85                  break;
86              case kFontAxes_bad:
87                  if (!stream->readPackedUInt(&axisCount)) { return false; }
88                  axis.reset(axisCount);
89                  for (size_t i = 0; i < axisCount; ++i) {
90                      size_t packedAxis;
91                      if (!stream->readPackedUInt(&packedAxis)) { return false; }
92                      axis[i] = packedAxis;
93                  }
94                  break;
95              case kFontIndex:
96                  if (!stream->readPackedUInt(&index)) { return false; }
97                  break;
98              default:
99                  SkDEBUGFAIL("Unknown id used by a font descriptor");
100                  return false;
101          }
102      }
103  
104      size_t length;
105      if (!stream->readPackedUInt(&length)) { return false; }
106      if (length > 0) {
107          sk_sp<SkData> data(SkData::MakeUninitialized(length));
108          if (stream->read(data->writable_data(), length) != length) {
109              SkDEBUGFAIL("Could not read font data");
110              return false;
111          }
112          result->fFontData = std::make_unique<SkFontData>(
113              SkMemoryStream::Make(std::move(data)), index, axis, axisCount);
114      }
115      return true;
116  }
117  
serialize(SkWStream * stream) const118  void SkFontDescriptor::serialize(SkWStream* stream) const {
119      uint32_t styleBits = (fStyle.weight() << 16) | (fStyle.width() << 8) | (fStyle.slant());
120      stream->writePackedUInt(styleBits);
121  
122      write_string(stream, fFamilyName, kFontFamilyName);
123      write_string(stream, fFullName, kFullName);
124      write_string(stream, fPostscriptName, kPostscriptName);
125      if (fFontData.get()) {
126          if (fFontData->getIndex()) {
127              write_uint(stream, fFontData->getIndex(), kFontIndex);
128          }
129          if (fFontData->getAxisCount()) {
130              write_uint(stream, fFontData->getAxisCount(), kFontAxes);
131              for (int i = 0; i < fFontData->getAxisCount(); ++i) {
132                  stream->write32(fFontData->getAxis()[i]);
133              }
134          }
135      }
136  
137      stream->writePackedUInt(kSentinel);
138  
139      if (fFontData.get() && fFontData->hasStream()) {
140          std::unique_ptr<SkStreamAsset> fontStream = fFontData->detachStream();
141          size_t length = fontStream->getLength();
142          stream->writePackedUInt(length);
143          stream->writeStream(fontStream.get(), length);
144      } else {
145          stream->writePackedUInt(0);
146      }
147  }
148