Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: include/core/SkTextBlob.h

Issue 473633002: SkTextBlob (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: SkRecord plumbing + partial blob bounds logic Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/core/SkCanvas.h ('k') | samplecode/SampleText.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « include/core/SkCanvas.h ('k') | samplecode/SampleText.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698