SkPath_serial.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*
  2. * Copyright 2018 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. #include "include/core/SkData.h"
  8. #include "include/core/SkMath.h"
  9. #include "include/private/SkPathRef.h"
  10. #include "include/private/SkTo.h"
  11. #include "src/core/SkBuffer.h"
  12. #include "src/core/SkPathPriv.h"
  13. #include "src/core/SkRRectPriv.h"
  14. #include "src/core/SkSafeMath.h"
  15. #include <cmath>
  16. enum SerializationOffsets {
  17. kType_SerializationShift = 28, // requires 4 bits
  18. kDirection_SerializationShift = 26, // requires 2 bits
  19. kFillType_SerializationShift = 8, // requires 8 bits
  20. // low-8-bits are version
  21. kVersion_SerializationMask = 0xFF,
  22. };
  23. enum SerializationVersions {
  24. // kPathPrivFirstDirection_Version = 1,
  25. kPathPrivLastMoveToIndex_Version = 2,
  26. kPathPrivTypeEnumVersion = 3,
  27. kJustPublicData_Version = 4, // introduced Feb/2018
  28. kCurrent_Version = kJustPublicData_Version
  29. };
  30. enum SerializationType {
  31. kGeneral = 0,
  32. kRRect = 1
  33. };
  34. static unsigned extract_version(uint32_t packed) {
  35. return packed & kVersion_SerializationMask;
  36. }
  37. static SkPath::FillType extract_filltype(uint32_t packed) {
  38. return static_cast<SkPath::FillType>((packed >> kFillType_SerializationShift) & 0x3);
  39. }
  40. static SerializationType extract_serializationtype(uint32_t packed) {
  41. return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
  42. }
  43. ///////////////////////////////////////////////////////////////////////////////////////////////////
  44. size_t SkPath::writeToMemoryAsRRect(void* storage) const {
  45. SkRect oval;
  46. SkRRect rrect;
  47. bool isCCW;
  48. unsigned start;
  49. if (fPathRef->isOval(&oval, &isCCW, &start)) {
  50. rrect.setOval(oval);
  51. // Convert to rrect start indices.
  52. start *= 2;
  53. } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) {
  54. return 0;
  55. }
  56. // packed header, rrect, start index.
  57. const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
  58. if (!storage) {
  59. return sizeNeeded;
  60. }
  61. int firstDir = isCCW ? SkPathPriv::kCCW_FirstDirection : SkPathPriv::kCW_FirstDirection;
  62. int32_t packed = (fFillType << kFillType_SerializationShift) |
  63. (firstDir << kDirection_SerializationShift) |
  64. (SerializationType::kRRect << kType_SerializationShift) |
  65. kCurrent_Version;
  66. SkWBuffer buffer(storage);
  67. buffer.write32(packed);
  68. SkRRectPriv::WriteToBuffer(rrect, &buffer);
  69. buffer.write32(SkToS32(start));
  70. buffer.padToAlign4();
  71. SkASSERT(sizeNeeded == buffer.pos());
  72. return buffer.pos();
  73. }
  74. size_t SkPath::writeToMemory(void* storage) const {
  75. SkDEBUGCODE(this->validate();)
  76. if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
  77. return bytes;
  78. }
  79. int32_t packed = (fFillType << kFillType_SerializationShift) |
  80. (SerializationType::kGeneral << kType_SerializationShift) |
  81. kCurrent_Version;
  82. int32_t pts = fPathRef->countPoints();
  83. int32_t cnx = fPathRef->countWeights();
  84. int32_t vbs = fPathRef->countVerbs();
  85. SkSafeMath safe;
  86. size_t size = 4 * sizeof(int32_t);
  87. size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
  88. size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
  89. size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
  90. size = safe.alignUp(size, 4);
  91. if (!safe) {
  92. return 0;
  93. }
  94. if (!storage) {
  95. return size;
  96. }
  97. SkWBuffer buffer(storage);
  98. buffer.write32(packed);
  99. buffer.write32(pts);
  100. buffer.write32(cnx);
  101. buffer.write32(vbs);
  102. buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
  103. buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
  104. buffer.write(fPathRef->verbsMemBegin(), vbs * sizeof(uint8_t));
  105. buffer.padToAlign4();
  106. SkASSERT(buffer.pos() == size);
  107. return size;
  108. }
  109. sk_sp<SkData> SkPath::serialize() const {
  110. size_t size = this->writeToMemory(nullptr);
  111. sk_sp<SkData> data = SkData::MakeUninitialized(size);
  112. this->writeToMemory(data->writable_data());
  113. return data;
  114. }
  115. //////////////////////////////////////////////////////////////////////////////////////////////////
  116. // reading
  117. size_t SkPath::readFromMemory(const void* storage, size_t length) {
  118. SkRBuffer buffer(storage, length);
  119. uint32_t packed;
  120. if (!buffer.readU32(&packed)) {
  121. return 0;
  122. }
  123. unsigned version = extract_version(packed);
  124. if (version <= kPathPrivTypeEnumVersion) {
  125. return this->readFromMemory_LE3(storage, length);
  126. }
  127. if (version == kJustPublicData_Version) {
  128. return this->readFromMemory_EQ4(storage, length);
  129. }
  130. return 0;
  131. }
  132. size_t SkPath::readAsRRect(const void* storage, size_t length) {
  133. SkRBuffer buffer(storage, length);
  134. uint32_t packed;
  135. if (!buffer.readU32(&packed)) {
  136. return 0;
  137. }
  138. SkASSERT(extract_serializationtype(packed) == SerializationType::kRRect);
  139. uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
  140. FillType fillType = extract_filltype(packed);
  141. Direction rrectDir;
  142. SkRRect rrect;
  143. int32_t start;
  144. switch (dir) {
  145. case SkPathPriv::kCW_FirstDirection:
  146. rrectDir = kCW_Direction;
  147. break;
  148. case SkPathPriv::kCCW_FirstDirection:
  149. rrectDir = kCCW_Direction;
  150. break;
  151. default:
  152. return 0;
  153. }
  154. if (!SkRRectPriv::ReadFromBuffer(&buffer, &rrect)) {
  155. return 0;
  156. }
  157. if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
  158. return 0;
  159. }
  160. this->reset();
  161. this->addRRect(rrect, rrectDir, SkToUInt(start));
  162. this->setFillType(fillType);
  163. buffer.skipToAlign4();
  164. return buffer.pos();
  165. }
  166. size_t SkPath::readFromMemory_EQ4(const void* storage, size_t length) {
  167. SkRBuffer buffer(storage, length);
  168. uint32_t packed;
  169. if (!buffer.readU32(&packed)) {
  170. return 0;
  171. }
  172. SkASSERT(extract_version(packed) == 4);
  173. switch (extract_serializationtype(packed)) {
  174. case SerializationType::kRRect:
  175. return this->readAsRRect(storage, length);
  176. case SerializationType::kGeneral:
  177. break; // fall through
  178. default:
  179. return 0;
  180. }
  181. int32_t pts, cnx, vbs;
  182. if (!buffer.readS32(&pts) || !buffer.readS32(&cnx) || !buffer.readS32(&vbs)) {
  183. return 0;
  184. }
  185. const SkPoint* points = buffer.skipCount<SkPoint>(pts);
  186. const SkScalar* conics = buffer.skipCount<SkScalar>(cnx);
  187. const uint8_t* verbs = buffer.skipCount<uint8_t>(vbs);
  188. buffer.skipToAlign4();
  189. if (!buffer.isValid()) {
  190. return 0;
  191. }
  192. SkASSERT(buffer.pos() <= length);
  193. #define CHECK_POINTS_CONICS(p, c) \
  194. do { \
  195. if (p && ((pts -= p) < 0)) { \
  196. return 0; \
  197. } \
  198. if (c && ((cnx -= c) < 0)) { \
  199. return 0; \
  200. } \
  201. } while (0)
  202. SkPath tmp;
  203. tmp.setFillType(extract_filltype(packed));
  204. tmp.incReserve(pts);
  205. for (int i = vbs - 1; i >= 0; --i) {
  206. switch (verbs[i]) {
  207. case kMove_Verb:
  208. CHECK_POINTS_CONICS(1, 0);
  209. tmp.moveTo(*points++);
  210. break;
  211. case kLine_Verb:
  212. CHECK_POINTS_CONICS(1, 0);
  213. tmp.lineTo(*points++);
  214. break;
  215. case kQuad_Verb:
  216. CHECK_POINTS_CONICS(2, 0);
  217. tmp.quadTo(points[0], points[1]);
  218. points += 2;
  219. break;
  220. case kConic_Verb:
  221. CHECK_POINTS_CONICS(2, 1);
  222. tmp.conicTo(points[0], points[1], *conics++);
  223. points += 2;
  224. break;
  225. case kCubic_Verb:
  226. CHECK_POINTS_CONICS(3, 0);
  227. tmp.cubicTo(points[0], points[1], points[2]);
  228. points += 3;
  229. break;
  230. case kClose_Verb:
  231. tmp.close();
  232. break;
  233. default:
  234. return 0; // bad verb
  235. }
  236. }
  237. #undef CHECK_POINTS_CONICS
  238. if (pts || cnx) {
  239. return 0; // leftover points and/or conics
  240. }
  241. *this = std::move(tmp);
  242. return buffer.pos();
  243. }
  244. size_t SkPath::readFromMemory_LE3(const void* storage, size_t length) {
  245. SkRBuffer buffer(storage, length);
  246. int32_t packed;
  247. if (!buffer.readS32(&packed)) {
  248. return 0;
  249. }
  250. unsigned version = extract_version(packed);
  251. SkASSERT(version <= 3);
  252. FillType fillType = extract_filltype(packed);
  253. if (version >= kPathPrivTypeEnumVersion) {
  254. switch (extract_serializationtype(packed)) {
  255. case SerializationType::kRRect:
  256. return this->readAsRRect(storage, length);
  257. case SerializationType::kGeneral:
  258. // Fall through to general path deserialization
  259. break;
  260. default:
  261. return 0;
  262. }
  263. }
  264. if (version >= kPathPrivLastMoveToIndex_Version && !buffer.readS32(&fLastMoveToIndex)) {
  265. return 0;
  266. }
  267. // These are written into the serialized data but we no longer use them in the deserialized
  268. // path. If convexity is corrupted it may cause the GPU backend to make incorrect
  269. // rendering choices, possibly crashing. We set them to unknown so that they'll be recomputed if
  270. // requested.
  271. fConvexity = kUnknown_Convexity;
  272. fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
  273. fFillType = fillType;
  274. fIsVolatile = 0;
  275. SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
  276. if (!pathRef) {
  277. return 0;
  278. }
  279. fPathRef.reset(pathRef);
  280. SkDEBUGCODE(this->validate();)
  281. buffer.skipToAlign4();
  282. return buffer.pos();
  283. }