Chromium Code Reviews| Index: include/core/SkTextBlob.h |
| diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4077c61eb6138586023f0a6750094a2702bf8b67 |
| --- /dev/null |
| +++ b/include/core/SkTextBlob.h |
| @@ -0,0 +1,182 @@ |
| +/* |
| + * 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 "SkPaint.h" |
| +#include "SkRefCnt.h" |
| +#include "SkTArray.h" |
| +#include "SkTDArray.h" |
| + |
| +/** \class SkTextBlob |
| + |
| + SkTextBlob combines multiple text runs into an immutable, ref-counted structure. |
| +*/ |
| +class SkTextBlob : public SkRefCnt { |
| +public: |
| + virtual ~SkTextBlob(); |
| + |
| + /** Specifies the glyph positioning mode. |
| + */ |
| + enum Positioning { |
| + 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. |
| + }; |
| + |
| + /** \struct RunInfo |
| + |
| + A run is a sequence of (optionally positioned) glyphs sharing the same font metrics |
| + and positioning mode. |
| + */ |
| + struct RunInfo { |
| + uint32_t glyphCount; |
| + Positioning positioning; |
| + const uint16_t* glyphs; |
| + const SkScalar* pos; |
| + const SkPaint* font; |
|
jbroman
2014/08/19 17:39:16
nit: Why not "const SkPaint&"? Is this a sign that
f(malita)
2014/08/20 01:21:57
Good point -- done.
|
| + |
| + RunInfo(uint32_t c, Positioning m, const uint16_t* g, const SkScalar* p, const SkPaint *f) |
| + : glyphCount(c), positioning(m), glyphs(g), pos(p), font(f) { } |
| + }; |
| + |
| + /** |
| + * Returns the blob bounding box. |
| + */ |
| + const SkRect& bounds() const { return fBounds; } |
| + |
| + /** |
| + * Return a non-zero, unique value representing the text blob. |
| + */ |
| + uint32_t uniqueID() const; |
| + |
| + /** |
| + * Returns the number of runs in this blob. |
| + */ |
| + unsigned runs() const { return fRuns ? fRuns->count() : 0; } |
| + |
| + /** |
| + * Returns a RunInfo struct for the given run index. |
| + */ |
| + const RunInfo runInfo(unsigned runIndex) const; |
|
jbroman
2014/08/19 17:39:16
Returning a const struct is meaningless (it's the
f(malita)
2014/08/20 01:21:57
Removed from the API.
|
| + |
| +private: |
|
robertphillips
2014/08/19 15:06:47
// This is ... ?
f(malita)
2014/08/20 01:21:57
Done.
|
| + struct Run { |
| + uint32_t count; |
| + uint32_t glyphStart; // index into fGlyphBuffer |
| + uint32_t posStart; // index into fPosBuffer |
| + SkPaint font; |
| + Positioning positioning; |
| + }; |
| + |
| + SkTextBlob(const uint16_t* glyphs, const SkScalar* pos, const SkTArray<Run>* runs, |
| + const SkRect& bounds); |
| + friend class SkTextBlobBuilder; |
| + |
| + const uint16_t* fGlyphBuffer; |
|
jbroman
2014/08/19 17:39:16
Any reason not to use SkAutoTMalloc or something s
f(malita)
2014/08/20 01:21:57
Done.
|
| + const SkScalar* fPosBuffer; |
| + const SkTArray<Run>* fRuns; |
| + const SkRect fBounds; |
| + |
| + mutable uint32_t fUniqueID; |
|
jbroman
2014/08/19 17:39:16
Why "mutable"? Making this lazy kind of scares me
f(malita)
2014/08/20 01:21:58
(this is the same pattern used by other Skia ID-ed
|
| +}; |
| + |
| +/** \class SkTextBlobBuilder |
| + |
| + Helper class for constructing SkTextBlobs. |
|
robertphillips
2014/08/19 15:06:47
// Expected use is:
// SkTextBlobBuilder tbb;
|
| + */ |
| +class SkTextBlobBuilder { |
| +private: |
|
robertphillips
2014/08/19 15:06:47
// This class ...
specifically what sort of API i
f(malita)
2014/08/20 01:21:57
Removed.
|
| + class RunBuilderBase { |
| + public: |
| + RunBuilderBase(SkTextBlobBuilder* blobBuilder) : fBlobBuilder(blobBuilder) { } |
| + |
| + protected: |
| + SkTextBlobBuilder* fBlobBuilder; |
| + }; |
| + |
| +public: |
| + /** |
| + * @param runs The number of runs to be added, if known. This is a storage hint and |
| + * not a limit. |
| + */ |
| + SkTextBlobBuilder(unsigned runs = 0); |
| + |
| + ~SkTextBlobBuilder(); |
| + |
| + template <SkTextBlob::Positioning> |
| + class RunBuilder : public RunBuilderBase { }; |
| + |
| + /** |
| + * Start a text run for the given font and positioning mode. |
| + * |
| + * @param glyphCount The number of glyphs in this run, if known. This is a storage hint |
| + * and not a limit. |
| + * @param bounds The bounding box for this run, if known. If non-null, it will be used |
| + * in the blob bounding box computation -- otherwise the builder will |
| + * measure the run. |
| + * @return A specialized builder for this run. The run builder is only valid |
| + * until the next startRun() or build() call. |
| + */ |
| + template <SkTextBlob::Positioning POS> |
| + RunBuilder<POS> startRun(const SkPaint& font, unsigned glyphCount = 0, |
|
jbroman
2014/08/19 17:39:15
What do we get by making this a two-step process (
jbroman
2014/08/19 17:39:16
Why document the glyphCount and bounds arguments,
f(malita)
2014/08/20 01:21:57
Done.
f(malita)
2014/08/20 01:21:57
The latter forces clients to format data in a Skia
|
| + const SkRect* bounds = NULL) { |
|
robertphillips
2014/08/19 15:06:47
this->
f(malita)
2014/08/20 01:21:57
Done.
|
| + ensureRun(font, POS, glyphCount, bounds); |
| + return RunBuilder<POS>(this); |
| + } |
| + |
| + /** |
| + * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and |
| + * can be reused. |
| + */ |
| + const SkTextBlob* build(); |
| + |
| +private: |
| + void ensureRun(const SkPaint& font, SkTextBlob::Positioning positioning, unsigned count, |
| + const SkRect* runBounds); |
| + void updateRunBounds(); |
| + |
| + SkTDArray<uint16_t> fGlyphBuffer; |
| + SkTDArray<SkScalar> fPosBuffer; |
| + SkTArray<SkTextBlob::Run>* fRuns; |
| + |
| + SkRect fBounds; |
| + bool fDeferredRunBounds; |
| +}; |
| + |
| +template<> |
| +class SkTextBlobBuilder::RunBuilder<SkTextBlob::kDefault_Positioning> : public RunBuilderBase { |
| +public: |
| + RunBuilder(SkTextBlobBuilder* blobBuilder) : RunBuilderBase(blobBuilder) { } |
| + |
| + void addGlyph(uint16_t glyph); |
| + void addGlyphs(const uint16_t glyphs[], size_t count); |
| +}; |
| + |
|
robertphillips
2014/08/19 15:06:47
// The Y-value will be supplied in the using SkCan
|
| +template<> |
| +class SkTextBlobBuilder::RunBuilder<SkTextBlob::kHorizontal_Positioning> : public RunBuilderBase { |
| +public: |
| + RunBuilder(SkTextBlobBuilder* blobBuilder) : RunBuilderBase(blobBuilder) { } |
| + |
| + void addGlyph(uint16_t glyph, SkScalar x); |
|
jbroman
2014/08/19 17:39:16
Would we ever want to add a singular glyph? If it'
|
| + void addGlyphs(const uint16_t glyphs[], const SkScalar xPos[], size_t count); |
| +}; |
| + |
|
robertphillips
2014/08/19 15:06:47
// All the supplied positions are relative to the
|
| +template<> |
| +class SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning> : public RunBuilderBase { |
| +public: |
| + RunBuilder(SkTextBlobBuilder* blobBuilder) : RunBuilderBase(blobBuilder) { } |
| + |
| + void addGlyph(uint16_t glyph, SkScalar x, SkScalar y); |
|
robertphillips
2014/08/19 15:06:48
const SkPoint&
|
| + void addGlyph(uint16_t glyph, SkPoint pos); |
| + void addGlyphs(const uint16_t glyphs[], const SkScalar xPos[], const SkScalar yPos[], |
| + size_t count); |
|
robertphillips
2014/08/19 15:06:47
pox ?
|
| + void addGlyphs(const uint16_t glyphs[], const SkPoint pox[], size_t count); |
|
jbroman
2014/08/19 17:39:16
What does this method do, given this is the "full
|
| +}; |
| + |
| +#endif // SkTextBlob_DEFINED |