tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SkPath_serial.cpp (9098B)


      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 
      8 #include "include/core/SkData.h"
      9 #include "include/core/SkPath.h"
     10 #include "include/core/SkPathTypes.h"
     11 #include "include/core/SkRRect.h"
     12 #include "include/core/SkRect.h"
     13 #include "include/core/SkRefCnt.h"
     14 #include "include/core/SkScalar.h"
     15 #include "include/private/SkPathRef.h"
     16 #include "include/private/base/SkAssert.h"
     17 #include "include/private/base/SkDebug.h"
     18 #include "include/private/base/SkPoint_impl.h"
     19 #include "include/private/base/SkTPin.h"
     20 #include "include/private/base/SkTo.h"
     21 #include "src/base/SkAutoMalloc.h"
     22 #include "src/base/SkBuffer.h"
     23 #include "src/base/SkSafeMath.h"
     24 #include "src/core/SkPathEnums.h"
     25 #include "src/core/SkPathPriv.h"
     26 #include "src/core/SkRRectPriv.h"
     27 
     28 #include <cstddef>
     29 #include <cstdint>
     30 #include <optional>
     31 
     32 enum SerializationOffsets {
     33    kType_SerializationShift = 28,       // requires 4 bits
     34    kDirection_SerializationShift = 26,  // requires 2 bits
     35    kFillType_SerializationShift = 8,    // requires 8 bits
     36    // low-8-bits are version
     37    kVersion_SerializationMask = 0xFF,
     38 };
     39 
     40 enum SerializationVersions {
     41    // kPathPrivFirstDirection_Version = 1,
     42    // kPathPrivLastMoveToIndex_Version = 2,
     43    // kPathPrivTypeEnumVersion = 3,
     44    kJustPublicData_Version = 4,            // introduced Feb/2018
     45    kVerbsAreStoredForward_Version = 5,     // introduced Sept/2019
     46 
     47    kMin_Version     = kJustPublicData_Version,
     48    kCurrent_Version = kVerbsAreStoredForward_Version
     49 };
     50 
     51 enum SerializationType {
     52    kGeneral = 0,
     53    kRRect = 1
     54 };
     55 
     56 static unsigned extract_version(uint32_t packed) {
     57    return packed & kVersion_SerializationMask;
     58 }
     59 
     60 static SkPathFillType extract_filltype(uint32_t packed) {
     61    return static_cast<SkPathFillType>((packed >> kFillType_SerializationShift) & 0x3);
     62 }
     63 
     64 static SerializationType extract_serializationtype(uint32_t packed) {
     65    return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
     66 }
     67 
     68 ///////////////////////////////////////////////////////////////////////////////////////////////////
     69 
     70 size_t SkPath::writeToMemoryAsRRect(void* storage) const {
     71    SkRRect rrect;
     72    SkPathDirection firstDir;
     73    unsigned start;
     74 
     75    if (auto oinfo = fPathRef->isOval()) {
     76        rrect.setOval(oinfo->fBounds);
     77        firstDir = oinfo->fDirection;
     78        // Convert to rrect start indices.
     79        start = oinfo->fStartIndex * 2;
     80    } else if (auto rinfo = fPathRef->isRRect()) {
     81        rrect = rinfo->fRRect;
     82        firstDir = rinfo->fDirection;
     83        start = rinfo->fStartIndex;
     84    } else {
     85        return 0;
     86    }
     87 
     88    // packed header, rrect, start index.
     89    const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
     90    if (!storage) {
     91        return sizeNeeded;
     92    }
     93 
     94    int32_t packed = (fFillType << kFillType_SerializationShift) |
     95                     ((int)firstDir << kDirection_SerializationShift) |
     96                     (SerializationType::kRRect << kType_SerializationShift) |
     97                     kCurrent_Version;
     98 
     99    SkWBuffer buffer(storage);
    100    buffer.write32(packed);
    101    SkRRectPriv::WriteToBuffer(rrect, &buffer);
    102    buffer.write32(SkToS32(start));
    103    buffer.padToAlign4();
    104    SkASSERT(sizeNeeded == buffer.pos());
    105    return buffer.pos();
    106 }
    107 
    108 size_t SkPath::writeToMemory(void* storage) const {
    109    SkDEBUGCODE(this->validate();)
    110 
    111    if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
    112        return bytes;
    113    }
    114 
    115    int32_t packed = (fFillType << kFillType_SerializationShift) |
    116                     (SerializationType::kGeneral << kType_SerializationShift) |
    117                     kCurrent_Version;
    118 
    119    int32_t pts = fPathRef->countPoints();
    120    int32_t cnx = fPathRef->countWeights();
    121    int32_t vbs = fPathRef->countVerbs();
    122 
    123    SkSafeMath safe;
    124    size_t size = 4 * sizeof(int32_t);
    125    size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
    126    size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
    127    size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
    128    size = safe.alignUp(size, 4);
    129    if (!safe) {
    130        return 0;
    131    }
    132    if (!storage) {
    133        return size;
    134    }
    135 
    136    SkWBuffer buffer(storage);
    137    buffer.write32(packed);
    138    buffer.write32(pts);
    139    buffer.write32(cnx);
    140    buffer.write32(vbs);
    141    buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
    142    buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
    143    buffer.write(fPathRef->verbsBegin(), vbs * sizeof(uint8_t));
    144    buffer.padToAlign4();
    145 
    146    SkASSERT(buffer.pos() == size);
    147    return size;
    148 }
    149 
    150 sk_sp<SkData> SkPath::serialize() const {
    151    size_t size = this->writeToMemory(nullptr);
    152    sk_sp<SkData> data = SkData::MakeUninitialized(size);
    153    this->writeToMemory(data->writable_data());
    154    return data;
    155 }
    156 
    157 //////////////////////////////////////////////////////////////////////////////////////////////////
    158 // reading
    159 
    160 size_t SkPath::readAsRRect(const void* storage, size_t length) {
    161    SkRBuffer buffer(storage, length);
    162    uint32_t packed;
    163    if (!buffer.readU32(&packed)) {
    164        return 0;
    165    }
    166 
    167    SkASSERT(extract_serializationtype(packed) == SerializationType::kRRect);
    168 
    169    uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
    170    SkPathFillType fillType = extract_filltype(packed);
    171 
    172    SkPathDirection rrectDir;
    173    SkRRect rrect;
    174    int32_t start;
    175    switch (dir) {
    176        case (int)SkPathFirstDirection::kCW:
    177            rrectDir = SkPathDirection::kCW;
    178            break;
    179        case (int)SkPathFirstDirection::kCCW:
    180            rrectDir = SkPathDirection::kCCW;
    181            break;
    182        default:
    183            return 0;
    184    }
    185    if (!SkRRectPriv::ReadFromBuffer(&buffer, &rrect)) {
    186        return 0;
    187    }
    188    if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
    189        return 0;
    190    }
    191    this->reset();
    192    this->addRRect(rrect, rrectDir, SkToUInt(start));
    193    this->setFillType(fillType);
    194    buffer.skipToAlign4();
    195    return buffer.pos();
    196 }
    197 
    198 #ifndef SK_HIDE_PATH_EDIT_METHODS
    199 size_t SkPath::readFromMemory(const void* storage, size_t length) {
    200    size_t bytesRead = 0;
    201    if (auto path = SkPath::ReadFromMemory(storage, length, &bytesRead)) {
    202        *this = path.value();
    203    }
    204    return bytesRead;
    205 }
    206 #endif
    207 
    208 #define RETURN_PATH_AND_BYTES(p, b) \
    209    do { if (bytesRead) { *bytesRead = b; }; return p; } while (0)
    210 
    211 std::optional<SkPath> SkPath::ReadFromMemory(const void* storage, size_t length, size_t* bytesRead) {
    212    SkRBuffer buffer(storage, length);
    213    uint32_t packed;
    214    if (!buffer.readU32(&packed)) {
    215        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    216    }
    217    unsigned version = extract_version(packed);
    218 
    219    const bool verbsAreForward = (version == kVerbsAreStoredForward_Version);
    220    if (!verbsAreForward && version != kJustPublicData_Version) SK_UNLIKELY {
    221        // Old/unsupported version.
    222        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    223    }
    224 
    225    SkPath path;
    226    size_t tmp;
    227    switch (extract_serializationtype(packed)) {
    228        case SerializationType::kRRect:
    229            tmp = path.readAsRRect(storage, length);
    230            RETURN_PATH_AND_BYTES(path, tmp);
    231        case SerializationType::kGeneral:
    232            break;  // fall out
    233        default:
    234            RETURN_PATH_AND_BYTES(std::nullopt, 0);
    235    }
    236 
    237    // To minimize the number of reads done a structure with the counts is used.
    238    struct {
    239      uint32_t pts, cnx, vbs;
    240    } counts;
    241    if (!buffer.read(&counts, sizeof(counts))) {
    242        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    243    }
    244 
    245    const SkPoint* points = buffer.skipCount<SkPoint>(counts.pts);
    246    const SkScalar* conics = buffer.skipCount<SkScalar>(counts.cnx);
    247    const SkPathVerb* verbs = buffer.skipCount<SkPathVerb>(counts.vbs);
    248    buffer.skipToAlign4();
    249    if (!buffer.isValid()) {
    250        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    251    }
    252    SkASSERT(buffer.pos() <= length);
    253 
    254    if (counts.vbs == 0) {
    255        if (counts.pts == 0 && counts.cnx == 0) {
    256            path.setFillType(extract_filltype(packed));
    257            if (bytesRead) {
    258                *bytesRead = buffer.pos();
    259            }
    260            return path;
    261        }
    262        // No verbs but points and/or conic weights is a not a valid path.
    263        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    264    }
    265 
    266    SkAutoMalloc reversedStorage;
    267    if (!verbsAreForward) SK_UNLIKELY {
    268        SkPathVerb* tmpVerbs = (SkPathVerb*)reversedStorage.reset(counts.vbs);
    269        for (unsigned i = 0; i < counts.vbs; ++i) {
    270            tmpVerbs[i] = verbs[counts.vbs - i - 1];
    271        }
    272        verbs = tmpVerbs;
    273    }
    274 
    275    SkSpan<const SkPathVerb> verbSpan{verbs, counts.vbs};
    276    SkPathVerbAnalysis analysis = SkPathPriv::AnalyzeVerbs(verbSpan);
    277 
    278    if (!analysis.valid || analysis.points != counts.pts || analysis.weights != counts.cnx) {
    279        RETURN_PATH_AND_BYTES(std::nullopt, 0);
    280    }
    281    path = SkPathPriv::MakePath(analysis, points, verbSpan, conics,
    282                                extract_filltype(packed), false);
    283 
    284    RETURN_PATH_AND_BYTES(path,buffer.pos());
    285 }
    286 
    287 #undef RETURN_PATH_AND_BYTES