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

Quelle  SkRecordCanvas.cpp

  Sprache: C
 

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


#include "src/core/SkRecordCanvas.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkRect.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkVertices.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "include/private/chromium/Slug.h"
#include "src/core/SkBigPicture.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkRecord.h"
#include "src/core/SkRecords.h"
#include "src/text/GlyphRun.h"
#include "src/utils/SkPatchUtils.h"

#include <cstdint>
#include <cstring>
#include <memory>
#include <new>

class SkBlender;
class SkMesh;
class SkPath;
class SkRRect;
class SkRegion;
class SkSurfaceProps;
enum class SkBlendMode;
enum class SkClipOp;
struct SkDrawShadowRec;

using namespace skia_private;

SkDrawableList::~SkDrawableList() {
    for (SkDrawable* p : fArray) {
        p->unref();
    }
    fArray.reset();
}

SkBigPicture::SnapshotArray* SkDrawableList::newDrawableSnapshot() {
    const int count = fArray.size();
    if (0 == count) {
        return nullptr;
    }
    AutoTMalloc<const SkPicture*> pics(count);
    for (int i = 0; i < count; ++i) {
        pics[i] = fArray[i]->makePictureSnapshot().release();
    }
    return new SkBigPicture::SnapshotArray(pics.release(), count);
}

void SkDrawableList::append(SkDrawable* drawable) { *fArray.append() = SkRef(drawable); }

///////////////////////////////////////////////////////////////////////////////////////////////

static SkIRect safe_picture_bounds(const SkRect& bounds) {
    SkIRect picBounds = bounds.roundOut();
    // roundOut() saturates the float edges to +/-SK_MaxS32FitsInFloat (~2billion), but this is
    // large enough that width/height calculations will overflow, leading to negative dimensions.
    static constexpr int32_t kSafeEdge = SK_MaxS32FitsInFloat / 2 - 1;
    static constexpr SkIRect kSafeBounds = {-kSafeEdge, -kSafeEdge, kSafeEdge, kSafeEdge};
    static_assert((kSafeBounds.fRight - kSafeBounds.fLeft) >= 0 &&
                  (kSafeBounds.fBottom - kSafeBounds.fTop) >= 0);
    if (!picBounds.intersect(kSafeBounds)) {
        picBounds.setEmpty();
    }
    return picBounds;
}

SkRecordCanvas::SkRecordCanvas(SkRecord* record, int width, int height)
        : SkCanvasVirtualEnforcer<SkNoDrawCanvas>(width, height)
        , fApproxBytesUsedBySubPictures(0)
        , fRecord(record) {
    SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
}

SkRecordCanvas::SkRecordCanvas(SkRecord* record, const SkRect& bounds)
        : SkCanvasVirtualEnforcer<SkNoDrawCanvas>(safe_picture_bounds(bounds))
        , fApproxBytesUsedBySubPictures(0)
        , fRecord(record) {
    SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
}

void SkRecordCanvas::reset(SkRecord* record, const SkRect& bounds) {
    this->forgetRecord();
    fRecord = record;
    this->resetCanvas(safe_picture_bounds(bounds));
    SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
}

void SkRecordCanvas::forgetRecord() {
    fDrawableList.reset(nullptr);
    fApproxBytesUsedBySubPictures = 0;
    fRecord = nullptr;
}

// To make appending to fRecord a little less verbose.
template <typename T, typename... Args> void SkRecordCanvas::append(Args&&... args) {
    new (fRecord->append<T>()) T{std::forward<Args>(args)...};
}

// For methods which must call back into SkNoDrawCanvas.
#define INHERITED(method, ...) this->SkNoDrawCanvas::method(__VA_ARGS__)

// Use copy() only for optional arguments, to be copied if present or skipped if not.
// (For most types we just pass by value and let copy constructors do their thing.)
template <typename T> T* SkRecordCanvas::copy(const T* src) {
    if (nullptr == src) {
        return nullptr;
    }
    return new (fRecord->alloc<T>()) T(*src);
}

// This copy() is for arrays.
// It will work with POD or non-POD, though currently we only use it for POD.
template <typename T> T* SkRecordCanvas::copy(const T src[], size_t count) {
    if (nullptr == src) {
        return nullptr;
    }
    T* dst = fRecord->alloc<T>(count);
    for (size_t i = 0; i < count; i++) {
        new (dst + i) T(src[i]);
    }
    return dst;
}

// Specialization for copying strings, using memcpy.
// This measured around 2x faster for copying code points,
// but I found no corresponding speedup for other arrays.
template <> char* SkRecordCanvas::copy(const char src[], size_t count) {
    if (nullptr == src) {
        return nullptr;
    }
    char* dst = fRecord->alloc<char>(count);
    memcpy(dst, src, count);
    return dst;
}

// As above, assuming and copying a terminating \0.
template <> char* SkRecordCanvas::copy(const char* src) { return this->copy(src, strlen(src) 1); }

void SkRecordCanvas::onDrawPaint(const SkPaint& paint) {
    this->append<SkRecords::DrawPaint>(paint);
}

void SkRecordCanvas::onDrawBehind(const SkPaint& paint) {
    this->append<SkRecords::DrawBehind>(paint);
}

void SkRecordCanvas::onDrawPoints(PointMode mode,
                                  size_t count,
                                  const SkPoint pts[],
                                  const SkPaint& paint) {
    this->append<SkRecords::DrawPoints>(paint, mode, SkToUInt(count), this->copy(pts, count));
}

void SkRecordCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
    this->append<SkRecords::DrawRect>(paint, rect);
}

void SkRecordCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
    this->append<SkRecords::DrawRegion>(paint, region);
}

void SkRecordCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
    this->append<SkRecords::DrawOval>(paint, oval);
}

void SkRecordCanvas::onDrawArc(const SkRect& oval,
                               SkScalar startAngle,
                               SkScalar sweepAngle,
                               bool useCenter,
                               const SkPaint& paint) {
    this->append<SkRecords::DrawArc>(paint, oval, startAngle, sweepAngle, useCenter);
}

void SkRecordCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
    this->append<SkRecords::DrawRRect>(paint, rrect);
}

void SkRecordCanvas::onDrawDRRect(const SkRRect& outer,
                                  const SkRRect& inner,
                                  const SkPaint& paint) {
    this->append<SkRecords::DrawDRRect>(paint, outer, inner);
}

void SkRecordCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
    if (!fDrawableList) {
        fDrawableList = std::make_unique<SkDrawableList>();
    }
    fDrawableList->append(drawable);
    this->append<SkRecords::DrawDrawable>(
            this->copy(matrix), drawable->getBounds(), fDrawableList->count() - 1);
}

void SkRecordCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
    this->append<SkRecords::DrawPath>(paint, path);
}

void SkRecordCanvas::onDrawImage2(const SkImage* image,
                                  SkScalar x,
                                  SkScalar y,
                                  const SkSamplingOptions& sampling,
                                  const SkPaint* paint) {
    this->append<SkRecords::DrawImage>(this->copy(paint), sk_ref_sp(image), x, y, sampling);
}

void SkRecordCanvas::onDrawImageRect2(const SkImage* image,
                                      const SkRect& src,
                                      const SkRect& dst,
                                      const SkSamplingOptions& sampling,
                                      const SkPaint* paint,
                                      SrcRectConstraint constraint) {
    this->append<SkRecords::DrawImageRect>(
            this->copy(paint), sk_ref_sp(image), src, dst, sampling, constraint);
}

void SkRecordCanvas::onDrawImageLattice2(const SkImage* image,
                                         const Lattice& lattice,
                                         const SkRect& dst,
                                         SkFilterMode filter,
                                         const SkPaint* paint) {
    int flagCount = lattice.fRectTypes ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;
    SkASSERT(lattice.fBounds);
    this->append<SkRecords::DrawImageLattice>(this->copy(paint),
                                              sk_ref_sp(image),
                                              lattice.fXCount,
                                              this->copy(lattice.fXDivs, lattice.fXCount),
                                              lattice.fYCount,
                                              this->copy(lattice.fYDivs, lattice.fYCount),
                                              flagCount,
                                              this->copy(lattice.fRectTypes, flagCount),
                                              this->copy(lattice.fColors, flagCount),
                                              *lattice.fBounds,
                                              dst,
                                              filter);
}

void SkRecordCanvas::onDrawTextBlob(const SkTextBlob* blob,
                                    SkScalar x,
                                    SkScalar y,
                                    const SkPaint& paint) {
    this->append<SkRecords::DrawTextBlob>(paint, sk_ref_sp(blob), x, y);
}

void SkRecordCanvas::onDrawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint) {
    this->append<SkRecords::DrawSlug>(paint, sk_ref_sp(slug));
}

void SkRecordCanvas::onDrawGlyphRunList(const sktext::GlyphRunList& glyphRunList,
                                        const SkPaint& paint) {
    sk_sp<SkTextBlob> blob = sk_ref_sp(glyphRunList.blob());
    if (glyphRunList.blob() == nullptr) {
        blob = glyphRunList.makeBlob();
    }

    this->onDrawTextBlob(blob.get(), glyphRunList.origin().x(), glyphRunList.origin().y(), paint);
}

void SkRecordCanvas::onDrawPicture(const SkPicture* pic,
                                   const SkMatrix* matrix,
                                   const SkPaint* paint) {
    fApproxBytesUsedBySubPictures += pic->approximateBytesUsed();
    this->append<SkRecords::DrawPicture>(
            this->copy(paint), sk_ref_sp(pic), matrix ? *matrix : SkMatrix::I());
}

void SkRecordCanvas::onDrawVerticesObject(const SkVertices* vertices,
                                          SkBlendMode bmode,
                                          const SkPaint& paint) {
    this->append<SkRecords::DrawVertices>(
            paint, sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode);
}

void SkRecordCanvas::onDrawMesh(const SkMesh& mesh,
                                sk_sp<SkBlender> blender,
                                const SkPaint& paint) {
    this->append<SkRecords::DrawMesh>(paint, mesh, std::move(blender));
}

void SkRecordCanvas::onDrawPatch(const SkPoint cubics[12],
                                 const SkColor colors[4],
                                 const SkPoint texCoords[4],
                                 SkBlendMode bmode,
                                 const SkPaint& paint) {
    this->append<SkRecords::DrawPatch>(
            paint,
            cubics ? this->copy(cubics, SkPatchUtils::kNumCtrlPts) : nullptr,
            colors ? this->copy(colors, SkPatchUtils::kNumCorners) : nullptr,
            texCoords ? this->copy(texCoords, SkPatchUtils::kNumCorners) : nullptr,
            bmode);
}

void SkRecordCanvas::onDrawAtlas2(const SkImage* atlas,
                                  const SkRSXform xform[],
                                  const SkRect tex[],
                                  const SkColor colors[],
                                  int count,
                                  SkBlendMode mode,
                                  const SkSamplingOptions& sampling,
                                  const SkRect* cull,
                                  const SkPaint* paint) {
    this->append<SkRecords::DrawAtlas>(this->copy(paint),
                                       sk_ref_sp(atlas),
                                       this->copy(xform, count),
                                       this->copy(tex, count),
                                       this->copy(colors, count),
                                       (unsigned)count,
                                       mode,
                                       sampling,
                                       this->copy(cull));
}

void SkRecordCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec&&nbsp;rec) {
    this->append<SkRecords::DrawShadowRec>(path, rec);
}

void SkRecordCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
    this->append<SkRecords::DrawAnnotation>(rect, SkString(key), sk_ref_sp(value));
}

void SkRecordCanvas::onDrawEdgeAAQuad(const SkRect& rect,
                                      const SkPoint clip[4],
                                      QuadAAFlags aa,
                                      const SkColor4f& color,
                                      SkBlendMode mode) {
    this->append<SkRecords::DrawEdgeAAQuad>(rect, this->copy(clip, 4), aa, color, mode);
}

void SkRecordCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[],
                                           int count,
                                           const SkPoint dstClips[],
                                           const SkMatrix preViewMatrices[],
                                           const SkSamplingOptions& sampling,
                                           const SkPaint* paint,
                                           SrcRectConstraint constraint) {
    int totalDstClipCount, totalMatrixCount;
    SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);

    AutoTArray<ImageSetEntry> setCopy(count);
    for (int i = 0; i < count; ++i) {
        setCopy[i] = set[i];
    }

    this->append<SkRecords::DrawEdgeAAImageSet>(this->copy(paint),
                                                std::move(setCopy),
                                                count,
                                                this->copy(dstClips, totalDstClipCount),
                                                this->copy(preViewMatrices, totalMatrixCount),
                                                sampling,
                                                constraint);
}

void SkRecordCanvas::willSave() { this->append<SkRecords::Save>(); }

SkCanvas::SaveLayerStrategy SkRecordCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
    AutoTArray<sk_sp<SkImageFilter>> filters(rec.fFilters.size());
    for (size_t i = 0; i < rec.fFilters.size(); ++i) {
        filters[i] = rec.fFilters[i];
    }

    this->append<SkRecords::SaveLayer>(this->copy(rec.fBounds),
                                       this->copy(rec.fPaint),
                                       sk_ref_sp(rec.fBackdrop),
                                       rec.fSaveLayerFlags,
                                       SkCanvasPriv::GetBackdropScaleFactor(rec),
                                       rec.fBackdropTileMode,
                                       std::move(filters));
    return SkCanvas::kNoLayer_SaveLayerStrategy;
}

bool SkRecordCanvas::onDoSaveBehind(const SkRect* subset) {
    this->append<SkRecords::SaveBehind>(this->copy(subset));
    return false;
}

void SkRecordCanvas::didRestore() { this->append<SkRecords::Restore>(this->getTotalMatrix()); }

void SkRecordCanvas::didConcat44(const SkM44& m) { this->append<SkRecords::Concat44>(m); }

void SkRecordCanvas::didSetM44(const SkM44& m) { this->append<SkRecords::SetM44>(m); }

void SkRecordCanvas::didScale(SkScalar sx, SkScalar sy) { this->append<SkRecords::Scale>(sx, sy); }

void SkRecordCanvas::didTranslate(SkScalar dx, SkScalar dy) {
    this->append<SkRecords::Translate>(dx, dy);
}

void SkRecordCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    INHERITED(onClipRect, rect, op, edgeStyle);
    SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
    this->append<SkRecords::ClipRect>(rect, opAA);
}

void SkRecordCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    INHERITED(onClipRRect, rrect, op, edgeStyle);
    SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
    this->append<SkRecords::ClipRRect>(rrect, opAA);
}

void SkRecordCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
    INHERITED(onClipPath, path, op, edgeStyle);
    SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
    this->append<SkRecords::ClipPath>(path, opAA);
}

void SkRecordCanvas::onClipShader(sk_sp<SkShader> cs, SkClipOp op) {
    INHERITED(onClipShader, cs, op);
    this->append<SkRecords::ClipShader>(std::move(cs), op);
}

void SkRecordCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
    INHERITED(onClipRegion, deviceRgn, op);
    this->append<SkRecords::ClipRegion>(deviceRgn, op);
}

void SkRecordCanvas::onResetClip() {
    INHERITED(onResetClip);
    this->append<SkRecords::ResetClip>();
}

sk_sp<SkSurface> SkRecordCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
    return nullptr;
}

Messung V0.5 in Prozent
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© 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.