blob: ca7541a623c75e09e5dd2fa20a33aafe574dab4d [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkGlyphBuffer_DEFINED
#define SkGlyphBuffer_DEFINED
#include "src/core/SkGlyph.h"
#include "src/core/SkZip.h"
class SkStrikeForGPU;
struct SkGlyphPositionRoundingSpec;
// A memory format that allows an SkPackedGlyphID, SkGlyph*, and SkPath* to occupy the same
// memory. This allows SkPackedGlyphIDs as input, and SkGlyph*/SkPath* as output using the same
// memory.
class SkGlyphVariant {
public:
SkGlyphVariant() : fV{nullptr} { }
SkGlyphVariant& operator= (SkPackedGlyphID packedID) {
fV.packedID = packedID;
SkDEBUGCODE(fTag = kPackedID);
return *this;
}
SkGlyphVariant& operator= (SkGlyph* glyph) {
fV.glyph = glyph;
SkDEBUGCODE(fTag = kGlyph);
return *this;
}
SkGlyphVariant& operator= (const SkPath* path) {
fV.path = path;
SkDEBUGCODE(fTag = kPath);
return *this;
}
SkGlyph* glyph() const {
SkASSERT(fTag == kGlyph);
return fV.glyph;
}
const SkPath* path() const {
SkASSERT(fTag == kPath);
return fV.path;
}
SkPackedGlyphID packedID() const {
SkASSERT(fTag == kPackedID);
return fV.packedID;
}
operator SkPackedGlyphID() const { return this->packedID(); }
operator SkGlyph*() const { return this->glyph(); }
operator const SkPath*() const { return this->path(); }
private:
union {
SkGlyph* glyph;
const SkPath* path;
SkPackedGlyphID packedID;
} fV;
#ifdef SK_DEBUG
enum {
kEmpty,
kPackedID,
kGlyph,
kPath
} fTag{kEmpty};
#endif
};
// A buffer for converting SkPackedGlyph to SkGlyph* or SkPath*. Initially the buffer contains
// SkPackedGlyphIDs, but those are used to lookup SkGlyph*/SkPath* which are then copied over the
// SkPackedGlyphIDs.
class SkDrawableGlyphBuffer {
public:
void ensureSize(size_t size);
// Load the buffer with SkPackedGlyphIDs and positions in source space.
void startSource(const SkZip<const SkGlyphID, const SkPoint>& source, SkPoint origin);
// Load the buffer with SkPackedGlyphIDs and positions using the device transform.
void startDevice(
const SkZip<const SkGlyphID, const SkPoint>& source,
SkPoint origin, const SkMatrix& viewMatrix,
const SkGlyphPositionRoundingSpec& roundingSpec);
// The input of SkPackedGlyphIDs
SkZip<SkGlyphVariant, SkPoint> input() {
SkASSERT(fPhase == kInput);
SkDEBUGCODE(fPhase = kProcess);
return SkZip<SkGlyphVariant, SkPoint>{fInputSize, fMultiBuffer, fPositions};
}
// Store the glyph in the next drawable slot, using the position information located at index
// from.
void push_back(SkGlyph* glyph, size_t from) {
SkASSERT(fPhase == kProcess);
SkASSERT(fDrawableSize <= from);
fPositions[fDrawableSize] = fPositions[from];
fMultiBuffer[fDrawableSize] = glyph;
fDrawableSize++;
}
// Store the path in the next drawable slot, using the position information located at index
// from.
void push_back(const SkPath* path, size_t from) {
SkASSERT(fPhase == kProcess);
SkASSERT(fDrawableSize <= from);
fPositions[fDrawableSize] = fPositions[from];
fMultiBuffer[fDrawableSize] = path;
fDrawableSize++;
}
// The result after a series of push_backs of drawable SkGlyph* or SkPath*.
SkZip<SkGlyphVariant, SkPoint> drawable() {
SkASSERT(fPhase == kProcess);
SkDEBUGCODE(fPhase = kDraw);
return SkZip<SkGlyphVariant, SkPoint>{fDrawableSize, fMultiBuffer, fPositions};
}
void reset();
private:
size_t fMaxSize{0};
size_t fInputSize{0};
size_t fDrawableSize{0};
SkAutoTMalloc<SkGlyphVariant> fMultiBuffer;
SkAutoTMalloc<SkPoint> fPositions;
#ifdef SK_DEBUG
enum {
kReset,
kInput,
kProcess,
kDraw
} fPhase{kReset};
#endif
};
#endif // SkGlyphBuffer_DEFINED