785586af7d
The SKTextBlob serialization code that is tested by Skia is unused by Chrome. The serialization code that is used by Chrome is untested by Skia. Remove the unused code; test the used code. The code path introduced nearly a year ago, likely for slimming paint, attempts to make text blobs smarter by allowing the reuse of typefaces. Maybe there needs to be a Chrome bug / feature request to use this? If if turns out there is no interest to do so, This CL aligns used interfaces with tests. R=reed@google.com,fmalita@google.com,bungeman@google.com Bug: skia:6818 Change-Id: I9b3ec0c326495322986ba26f20f901bcb208be73 Reviewed-on: https://skia-review.googlesource.com/141542 Reviewed-by: Cary Clark <caryclark@skia.org> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Ben Wagner <bungeman@google.com> Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Cary Clark <caryclark@skia.org> Auto-Submit: Cary Clark <caryclark@skia.org>
245 lines
9.4 KiB
C++
245 lines
9.4 KiB
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.
|
|
*/
|
|
|
|
#ifndef SkTextBlob_DEFINED
|
|
#define SkTextBlob_DEFINED
|
|
|
|
#include "../private/SkTemplates.h"
|
|
#include "../private/SkAtomics.h"
|
|
#include "SkPaint.h"
|
|
#include "SkString.h"
|
|
#include "SkRefCnt.h"
|
|
|
|
struct SkSerialProcs;
|
|
struct SkDeserialProcs;
|
|
|
|
/** \class SkTextBlob
|
|
|
|
SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
|
|
*/
|
|
class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
|
|
public:
|
|
/**
|
|
* Returns a conservative blob bounding box.
|
|
*/
|
|
const SkRect& bounds() const { return fBounds; }
|
|
|
|
/**
|
|
* Return a non-zero, unique value representing the text blob.
|
|
*/
|
|
uint32_t uniqueID() const { return fUniqueID; }
|
|
|
|
static sk_sp<SkTextBlob> MakeAsDrawText(
|
|
const void* text, size_t byteLength, const SkPaint& paint);
|
|
|
|
enum GlyphPositioning : uint8_t {
|
|
kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
|
|
kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
|
|
kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
|
|
};
|
|
|
|
/**
|
|
* Similar to serialize above, but writes directly into |memory|. Returns bytes written or 0u
|
|
* if serialization failed due to insufficient size.
|
|
*/
|
|
size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const;
|
|
|
|
sk_sp<SkData> serialize(const SkSerialProcs& procs) const;
|
|
|
|
static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size,
|
|
const SkDeserialProcs& procs);
|
|
|
|
private:
|
|
friend class SkNVRefCnt<SkTextBlob>;
|
|
class RunRecord;
|
|
|
|
explicit SkTextBlob(const SkRect& bounds);
|
|
|
|
~SkTextBlob();
|
|
|
|
// Memory for objects of this class is created with sk_malloc rather than operator new and must
|
|
// be freed with sk_free.
|
|
void operator delete(void* p);
|
|
void* operator new(size_t);
|
|
void* operator new(size_t, void* p);
|
|
|
|
static unsigned ScalarsPerGlyph(GlyphPositioning pos);
|
|
|
|
// Call when this blob is part of the key to a cache entry. This allows the cache
|
|
// to know automatically those entries can be purged when this SkTextBlob is deleted.
|
|
void notifyAddedToCache(uint32_t cacheID) const {
|
|
fCacheID.store(cacheID);
|
|
}
|
|
|
|
friend class SkGlyphRunList;
|
|
friend class GrTextBlobCache;
|
|
friend class SkTextBlobBuilder;
|
|
friend class SkTextBlobPriv;
|
|
friend class SkTextBlobRunIterator;
|
|
|
|
const SkRect fBounds;
|
|
const uint32_t fUniqueID;
|
|
mutable SkAtomic<uint32_t> fCacheID;
|
|
|
|
SkDEBUGCODE(size_t fStorageSize;)
|
|
|
|
// The actual payload resides in externally-managed storage, following the object.
|
|
// (see the .cpp for more details)
|
|
|
|
typedef SkRefCnt INHERITED;
|
|
};
|
|
|
|
/** \class SkTextBlobBuilder
|
|
|
|
Helper class for constructing SkTextBlobs.
|
|
*/
|
|
class SK_API SkTextBlobBuilder {
|
|
public:
|
|
SkTextBlobBuilder();
|
|
|
|
~SkTextBlobBuilder();
|
|
|
|
/**
|
|
* Returns an immutable SkTextBlob for the current runs/glyphs,
|
|
* or nullptr if no runs were allocated.
|
|
*
|
|
* The builder is reset and can be reused.
|
|
*/
|
|
sk_sp<SkTextBlob> make();
|
|
|
|
/**
|
|
* Glyph and position buffers associated with a run.
|
|
*
|
|
* A run is a sequence of glyphs sharing the same font metrics
|
|
* and positioning mode.
|
|
*
|
|
* If textByteCount is 0, utf8text and clusters will be NULL (no
|
|
* character information will be associated with the glyphs).
|
|
*
|
|
* utf8text will point to a buffer of size textByteCount bytes.
|
|
*
|
|
* clusters (if not NULL) will point to an array of size count.
|
|
* For each glyph, give the byte-offset into the text for the
|
|
* first byte in the first character in that glyph's cluster.
|
|
* Each value in the array should be an integer less than
|
|
* textByteCount. Values in the array should either be
|
|
* monotonically increasing (left-to-right text) or monotonically
|
|
* decreasing (right-to-left text). This definiton is conviently
|
|
* the same as used by Harfbuzz's hb_glyph_info_t::cluster field,
|
|
* except that Harfbuzz interleaves glyphs and clusters.
|
|
*/
|
|
struct RunBuffer {
|
|
SkGlyphID* glyphs;
|
|
SkScalar* pos;
|
|
char* utf8text;
|
|
uint32_t* clusters;
|
|
};
|
|
|
|
/**
|
|
* Allocates a new default-positioned run and returns its writable glyph buffer
|
|
* for direct manipulation.
|
|
*
|
|
* @param font The font to be used for this run.
|
|
* @param count Number of glyphs.
|
|
* @param x,y Position within the blob.
|
|
* @param textByteCount length of the original UTF-8 text that
|
|
* corresponds to this sequence of glyphs. If 0,
|
|
* text will not be included in the textblob.
|
|
* @param lang Language code, currently unimplemented.
|
|
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
|
|
* be used when computing the blob bounds, to avoid re-measuring.
|
|
*
|
|
* @return A writable glyph buffer, valid until the next allocRun() or
|
|
* build() call. The buffer is guaranteed to hold @count@ glyphs.
|
|
*/
|
|
const RunBuffer& allocRunText(const SkPaint& font,
|
|
int count,
|
|
SkScalar x,
|
|
SkScalar y,
|
|
int textByteCount,
|
|
SkString lang,
|
|
const SkRect* bounds = nullptr);
|
|
const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
|
|
const SkRect* bounds = nullptr) {
|
|
return this->allocRunText(font, count, x, y, 0, SkString(), bounds);
|
|
}
|
|
|
|
/**
|
|
* Allocates a new horizontally-positioned run and returns its writable glyph and position
|
|
* buffers for direct manipulation.
|
|
*
|
|
* @param font The font to be used for this run.
|
|
* @param count Number of glyphs.
|
|
* @param y Vertical offset within the blob.
|
|
* @param textByteCount length of the original UTF-8 text that
|
|
* corresponds to this sequence of glyphs. If 0,
|
|
* text will not be included in the textblob.
|
|
* @param lang Language code, currently unimplemented.
|
|
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
|
|
* be used when computing the blob bounds, to avoid re-measuring.
|
|
*
|
|
* @return Writable glyph and position buffers, valid until the next allocRun()
|
|
* or build() call. The buffers are guaranteed to hold @count@ elements.
|
|
*/
|
|
const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y,
|
|
int textByteCount, SkString lang,
|
|
const SkRect* bounds = nullptr);
|
|
const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
|
|
const SkRect* bounds = nullptr) {
|
|
return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds);
|
|
}
|
|
|
|
/**
|
|
* Allocates a new fully-positioned run and returns its writable glyph and position
|
|
* buffers for direct manipulation.
|
|
*
|
|
* @param font The font to be used for this run.
|
|
* @param count Number of glyphs.
|
|
* @param textByteCount length of the original UTF-8 text that
|
|
* corresponds to this sequence of glyphs. If 0,
|
|
* text will not be included in the textblob.
|
|
* @param lang Language code, currently unimplemented.
|
|
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
|
|
* be used when computing the blob bounds, to avoid re-measuring.
|
|
*
|
|
* @return Writable glyph and position buffers, valid until the next allocRun()
|
|
* or build() call. The glyph buffer and position buffer are
|
|
* guaranteed to hold @count@ and 2 * @count@ elements, respectively.
|
|
*/
|
|
const RunBuffer& allocRunTextPos(const SkPaint& font, int count,
|
|
int textByteCount, SkString lang,
|
|
const SkRect* bounds = nullptr);
|
|
const RunBuffer& allocRunPos(const SkPaint& font, int count,
|
|
const SkRect* bounds = nullptr) {
|
|
return this->allocRunTextPos(font, count, 0, SkString(), bounds);
|
|
}
|
|
|
|
private:
|
|
void reserve(size_t size);
|
|
void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
|
|
int count, int textBytes, SkPoint offset, const SkRect* bounds);
|
|
bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
|
|
uint32_t count, SkPoint offset);
|
|
void updateDeferredBounds();
|
|
|
|
static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
|
|
static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
|
|
|
|
SkAutoTMalloc<uint8_t> fStorage;
|
|
size_t fStorageSize;
|
|
size_t fStorageUsed;
|
|
|
|
SkRect fBounds;
|
|
int fRunCount;
|
|
bool fDeferredBounds;
|
|
size_t fLastRun; // index into fStorage
|
|
|
|
RunBuffer fCurrentRunBuffer;
|
|
};
|
|
|
|
#endif // SkTextBlob_DEFINED
|