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