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 "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     kFontAxes       = 0xFC,
     21     kFontIndex      = 0xFD,
     22     kFontFileName   = 0xFE,  // Remove when MIN_PICTURE_VERSION > 41
     23     kSentinel       = 0xFF,
     24 };
     25 
     26 SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fStyle(style) { }
     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 // Remove when MIN_PICTURE_VERSION > 41
     37 static void skip_string(SkStream* stream) {
     38     const uint32_t length = SkToU32(stream->readPackedUInt());
     39     if (length > 0) {
     40         stream->skip(length);
     41     }
     42 }
     43 
     44 static void write_string(SkWStream* stream, const SkString& string, 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 
     52 static size_t read_uint(SkStream* stream) {
     53     return stream->readPackedUInt();
     54 }
     55 
     56 static void write_uint(SkWStream* stream, size_t n, uint32_t id) {
     57     stream->writePackedUInt(id);
     58     stream->writePackedUInt(n);
     59 }
     60 
     61 bool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) {
     62     result->fStyle = (SkTypeface::Style)stream->readPackedUInt();
     63 
     64     SkAutoSTMalloc<4, SkFixed> axis;
     65     size_t axisCount = 0;
     66     size_t index = 0;
     67     for (size_t id; (id = stream->readPackedUInt()) != kSentinel;) {
     68         switch (id) {
     69             case kFontFamilyName:
     70                 read_string(stream, &result->fFamilyName);
     71                 break;
     72             case kFullName:
     73                 read_string(stream, &result->fFullName);
     74                 break;
     75             case kPostscriptName:
     76                 read_string(stream, &result->fPostscriptName);
     77                 break;
     78             case kFontAxes:
     79                 axisCount = read_uint(stream);
     80                 axis.reset(axisCount);
     81                 for (size_t i = 0; i < axisCount; ++i) {
     82                     axis[i] = read_uint(stream);
     83                 }
     84                 break;
     85             case kFontIndex:
     86                 index = read_uint(stream);
     87                 break;
     88             case kFontFileName:  // Remove when MIN_PICTURE_VERSION > 41
     89                 skip_string(stream);
     90                 break;
     91             default:
     92                 SkDEBUGFAIL("Unknown id used by a font descriptor");
     93                 return false;
     94         }
     95     }
     96 
     97     size_t length = stream->readPackedUInt();
     98     if (length > 0) {
     99         SkAutoTUnref<SkData> data(SkData::NewUninitialized(length));
    100         if (stream->read(data->writable_data(), length) == length) {
    101             result->fFontData.reset(new SkFontData(new SkMemoryStream(data),
    102                                                    index, axis, axisCount));
    103         } else {
    104             SkDEBUGFAIL("Could not read font data");
    105             return false;
    106         }
    107     }
    108     return true;
    109 }
    110 
    111 void SkFontDescriptor::serialize(SkWStream* stream) {
    112     stream->writePackedUInt(fStyle);
    113 
    114     write_string(stream, fFamilyName, kFontFamilyName);
    115     write_string(stream, fFullName, kFullName);
    116     write_string(stream, fPostscriptName, kPostscriptName);
    117     if (fFontData.get()) {
    118         if (fFontData->getIndex()) {
    119             write_uint(stream, fFontData->getIndex(), kFontIndex);
    120         }
    121         if (fFontData->getAxisCount()) {
    122             write_uint(stream, fFontData->getAxisCount(), kFontAxes);
    123             for (int i = 0; i < fFontData->getAxisCount(); ++i) {
    124                 stream->writePackedUInt(fFontData->getAxis()[i]);
    125             }
    126         }
    127     }
    128 
    129     stream->writePackedUInt(kSentinel);
    130 
    131     if (fFontData.get() && fFontData->hasStream()) {
    132         SkAutoTDelete<SkStreamAsset> fontData(fFontData->detachStream());
    133         size_t length = fontData->getLength();
    134         stream->writePackedUInt(length);
    135         stream->writeStream(fontData, length);
    136     } else {
    137         stream->writePackedUInt(0);
    138     }
    139 }
    140