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