Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/skia/skia/src/utils/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 7 kB image not shown  

Quelle  SkMultiPictureDocument.cpp

  Sprache: C
 

/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "include/docs/SkMultiPictureDocument.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkDocument.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkStream.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTo.h"
#include "include/utils/SkNWayCanvas.h"
#include "src/utils/SkMultiPictureDocumentPriv.h"

#include <algorithm>
#include <climits>
#include <cstdint>
#include <cstring>
#include <functional>
#include <utility>

using namespace skia_private;

/*
  File format:
      BEGINNING_OF_FILE:
        kMagic
        uint32_t version_number (==2)
        uint32_t page_count
        {
          float sizeX
          float sizeY
        } * page_count
        skp file
*/


namespace {
// The unique file signature for this file type.
static constexpr char kMagic[] = "Skia Multi-Picture Doc\n\n";

static constexpr char kEndPage[] = "SkMultiPictureEndPage";

static constexpr uint32_t kVersion = 2;

static constexpr uint32_t kMaxDimension = 1 << 16;

static SkSize join(const TArray<SkSize>& sizes) {
    SkSize joined = {00};
    for (SkSize s : sizes) {
        joined = SkSize{std::max(joined.width(), s.width()), std::max(joined.height(), s.height())};
    }
    return joined;
}

struct MultiPictureDocument final : public SkDocument {
    const SkSerialProcs fProcs;
    SkPictureRecorder fPictureRecorder;
    SkSize fCurrentPageSize;
    TArray<sk_sp<SkPicture>> fPages;
    TArray<SkSize> fSizes;
    std::function<void(const SkPicture*)> fOnEndPage;
    MultiPictureDocument(SkWStream* s,
                         const SkSerialProcs* procs,
                         std::function<void(const SkPicture*)> onEndPage)
            : SkDocument(s)
            , fProcs(procs ? *procs : SkSerialProcs())
            , fOnEndPage(std::move(onEndPage)) {}

    ~MultiPictureDocument() override { this->close(); }

    SkCanvas* onBeginPage(SkScalar w, SkScalar h) override {
        fCurrentPageSize.set(w, h);
        return fPictureRecorder.beginRecording(w, h);
    }
    void onEndPage() override {
        fSizes.push_back(fCurrentPageSize);
        sk_sp<SkPicture> lastPage = fPictureRecorder.finishRecordingAsPicture();
        fPages.push_back(lastPage);
        if (fOnEndPage) {
            fOnEndPage(lastPage.get());
        }
    }
    void onClose(SkWStream* wStream) override {
        SkASSERT(wStream);
        SkASSERT(wStream->bytesWritten() == 0);
        wStream->writeText(kMagic);
        wStream->write32(kVersion);
        wStream->write32(SkToU32(fPages.size()));
        for (SkSize s : fSizes) {
            wStream->write(&s, sizeof(s));
        }
        SkSize bigsize = join(fSizes);
        SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
        for (const sk_sp<SkPicture>& page : fPages) {
            c->drawPicture(page);
            // Annotations must include some data.
            c->drawAnnotation(SkRect::MakeEmpty(), kEndPage, SkData::MakeWithCString("X"));
        }
        sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
        p->serialize(wStream, &fProcs);
        fPages.clear();
        fSizes.clear();
    }
    void onAbort() override {
        fPages.clear();
        fSizes.clear();
    }
};

struct PagerCanvas : public SkNWayCanvas {
    SkPictureRecorder fRecorder;
    SkDocumentPage* fDst;
    int fCount;
    int fIndex = 0;
    PagerCanvas(SkISize wh, SkDocumentPage* dst, int count)
            : SkNWayCanvas(wh.width(), wh.height()), fDst(dst), fCount(count) {
        this->nextCanvas();
    }
    void nextCanvas() {
        if (fIndex < fCount) {
            SkRect bounds = SkRect::MakeSize(fDst[fIndex].fSize);
            this->addCanvas(fRecorder.beginRecording(bounds));
        }
    }
    void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override {
        if (0 == strcmp(key, kEndPage)) {
            this->removeAll();
            if (fIndex < fCount) {
                fDst[fIndex].fPicture = fRecorder.finishRecordingAsPicture();
                ++fIndex;
            }
            this->nextCanvas();
        } else {
            this->SkNWayCanvas::onDrawAnnotation(r, key, d);
        }
    }
};

}  // namespace

namespace SkMultiPictureDocument {
sk_sp<SkDocument> Make(SkWStream* dst,
                       const SkSerialProcs* procs,
                       std::function<void(const SkPicture*)> onEndPage) {
    return sk_make_sp<MultiPictureDocument>(dst, procs, std::move(onEndPage));
}

int ReadPageCount(SkStreamSeekable* src) {
    if (!src) {
        return 0;
    }
    src->seek(0);
    const size_t size = sizeof(kMagic) - 1;
    char buffer[size];
    if (size != src->read(buffer, size) || 0 != memcmp(kMagic, buffer, size)) {
        src = nullptr;
        return 0;
    }
    uint32_t versionNumber;
    if (!src->readU32(&versionNumber) || versionNumber != kVersion) {
        return 0;
    }
    uint32_t pageCount;
    if (!src->readU32(&pageCount) || pageCount > (INT_MAX / sizeof(SkSize))) {
        return 0;
    }
    // leave stream position right here.
    return SkTo<int>(pageCount);
}

bool ReadPageSizes(SkStreamSeekable* src,
                   SkDocumentPage* dstArray,
                   int dstArrayCount) {
    if (!dstArray || dstArrayCount < 1) {
        return false;
    }
    int pageCount = ReadPageCount(src);
    if (pageCount < 1 || pageCount != dstArrayCount) {
        return false;
    }
    if (src->hasLength() && src->getLength() < (static_cast<size_t>(pageCount) * sizeof(SkSize))) {
        return false;  // not enough memory to read all the sizes
    }
    for (int i = 0; i < pageCount; ++i) {
        SkSize& s = dstArray[i].fSize;
        if (sizeof(s) != src->read(&s, sizeof(s))) {
            return false;
        }
        if (s.isEmpty() || s.width() >= kMaxDimension || s.height() >= kMaxDimension) {
            return false;  // invalid sizes
        }
    }
    // leave stream position right here.
    return true;
}

bool Read(SkStreamSeekable* src,
          SkDocumentPage* dstArray,
          int dstArrayCount,
          const SkDeserialProcs* procs) {
    if (!ReadPageSizes(src, dstArray, dstArrayCount)) {
        return false;
    }
    SkSize joined = {0.0f, 0.0f};
    for (int i = 0; i < dstArrayCount; ++i) {
        joined = SkSize{std::max(joined.width(), dstArray[i].fSize.width()),
                        std::max(joined.height(), dstArray[i].fSize.height())};
    }

    auto picture = SkPicture::MakeFromStream(src, procs);
    if (!picture) {
        return false;
    }

    PagerCanvas canvas(joined.toCeil(), dstArray, dstArrayCount);
    // Must call playback(), not drawPicture() to reach
    // PagerCanvas::onDrawAnnotation().
    picture->playback(&canvas);
    if (canvas.fIndex != dstArrayCount) {
        SkDEBUGF("Malformed SkMultiPictureDocument: canvas.fIndex=%d dstArrayCount=%d\n",
            canvas.fIndex, dstArrayCount);
    }
    return true;
}
}  // namespace SkMultiPictureDocument

Messung V0.5 in Prozent
C=93 H=90 G=91

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.