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

Unified Diff: src/core/SkTextBlob.cpp

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
« include/core/SkTextBlob.h ('K') | « src/core/SkRecords.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkTextBlob.cpp
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..690d8f45533e5aac20c5772d79c1fbbc80310b2a
--- /dev/null
+++ b/src/core/SkTextBlob.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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 "SkTextBlob.h"
+
+SkTextBlob::SkTextBlob(const uint16_t *glyphs, const SkScalar *pos, const SkTArray<Run> *runs,
+ const SkRect& bounds)
+ : fGlyphBuffer(glyphs)
+ , fPosBuffer(pos)
+ , fRuns(runs)
+ , fBounds(bounds) {
+}
+
+SkTextBlob::~SkTextBlob() {
+ sk_free(const_cast<uint16_t*>(fGlyphBuffer));
+ sk_free(const_cast<SkScalar*>(fPosBuffer));
+ SkDELETE(fRuns);
+}
+
+uint32_t SkTextBlob::uniqueID() const {
+ static int32_t gTextBlobGenerationID; // = 0;
+
+ // loop in case our global wraps around, as we never want to return SK_InvalidGenID
+ while (SK_InvalidGenID == fUniqueID) {
+ fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1;
+ }
+
+ return fUniqueID;
+}
+
+const SkTextBlob::RunInfo SkTextBlob::runInfo(unsigned runIndex) const {
+ SkASSERT(NULL != fRuns && runIndex < (unsigned)fRuns->count());
+
+ const Run& run = (*fRuns)[runIndex];
+ return RunInfo(run.count, run.positioning, fGlyphBuffer + run.glyphStart,
+ fPosBuffer + run.posStart, &run.font);
+}
+
+SkTextBlobBuilder::SkTextBlobBuilder(unsigned runs)
+ : fRuns(NULL)
+ , fDeferredRunBounds(false) {
+
+ if (runs > 0) {
+ // if the number of runs is known, size our run storage accordingly.
+ fRuns = SkNEW(SkTArray<SkTextBlob::Run>(runs));
+ }
+ fBounds.setEmpty();
+}
+
+SkTextBlobBuilder::~SkTextBlobBuilder() {
+ // unused runs
+ SkDELETE(fRuns);
+}
+
+void SkTextBlobBuilder::updateRunBounds() {
+ if (!fDeferredRunBounds) {
+ // Run bounds are up to date.
+ return;
+ }
+
+ SkASSERT(NULL != fRuns && !fRuns->empty());
+
+ // FIXME: compute run bounds.
+ SkRect runBounds = SkRect::MakeEmpty();
+
+ fBounds.join(runBounds);
+ fDeferredRunBounds = false;
+}
+
+void SkTextBlobBuilder::ensureRun(const SkPaint& font, SkTextBlob::Positioning pos,
+ unsigned count, const SkRect* runBounds) {
+ SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
+
+ if (NULL == fRuns) {
+ fRuns = SkNEW(SkTArray<SkTextBlob::Run>());
+ }
+
+ // same-font/same-positioning runs are merged
+ if (fRuns->empty() || fRuns->back().positioning != pos || fRuns->back().font != font) {
+ // former run bounds may need updating
+ updateRunBounds();
+
+ // start a new run
+ SkTextBlob::Run& newRun = fRuns->push_back();
+ newRun.count = 0;
+ newRun.glyphStart = fGlyphBuffer.count();
+ newRun.posStart = fPosBuffer.count();
+ newRun.font = font;
+ newRun.positioning = pos;
+ }
+
+ // reserve buffer storage upfront if the glyph count is known
+ if (count > 0) {
+ fGlyphBuffer.setReserve(fGlyphBuffer.count() + count);
+ SkASSERT(pos <= 2);
+ fPosBuffer.setReserve(fPosBuffer.count() + count * pos);
+ }
+
+ fDeferredRunBounds |= (NULL == runBounds);
+ // when in deferred bounds mode, we'll compute the bounds at a later time.
+ if (!fDeferredRunBounds) {
+ fBounds.join(*runBounds);
+ }
+}
+
+const SkTextBlob* SkTextBlobBuilder::build() {
+ const SkTextBlob* leBlob;
+
+ if (fGlyphBuffer.count() > 0) {
+ // we have some glyphs, construct a real blob
+ SkASSERT(NULL != fRuns && !fRuns->empty());
+
+ // last run may require deferred bounds computation
+ updateRunBounds();
+
+ // ownership of all buffers is transferred to the blob
+ leBlob = SkNEW_ARGS(SkTextBlob, (fGlyphBuffer.detach(),
+ fPosBuffer.detach(),
+ fRuns,
+ fBounds));
+ fRuns = NULL;
+ fBounds.setEmpty();
+ } else {
+ // empty blob
+ SkASSERT(NULL == fRuns || fRuns->empty());
+ SkASSERT(fBounds.isEmpty());
+
+ leBlob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty()));
+ }
+
+ return leBlob;
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kDefault_Positioning>::addGlyph(uint16_t glyph) {
+ SkASSERT(NULL != fBlobBuilder->fRuns);
+ SkASSERT(fBlobBuilder->fRuns->count() > 0);
+ SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kDefault_Positioning);
+
+ *fBlobBuilder->fGlyphBuffer.append() = glyph;
+
+ fBlobBuilder->fRuns->back().count += 1;
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kDefault_Positioning>::addGlyphs(
+ const uint16_t glyphs[], size_t count) {
+
+ for (size_t i = 0; i < count; ++i) {
+ this->addGlyph(glyphs[i]);
+ }
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kHorizontal_Positioning>::addGlyph(uint16_t glyph,
+ SkScalar x) {
+ SkASSERT(NULL != fBlobBuilder->fRuns);
+ SkASSERT(fBlobBuilder->fRuns->count() > 0);
+ SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kHorizontal_Positioning);
+
+ *fBlobBuilder->fGlyphBuffer.append() = glyph;
+ *fBlobBuilder->fPosBuffer.append() = x;
+
+ fBlobBuilder->fRuns->back().count += 1;
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kHorizontal_Positioning>::addGlyphs(
+ const uint16_t glyphs[], const SkScalar xPos[], size_t count) {
+
+ for (size_t i = 0; i < count; ++i) {
+ this->addGlyph(glyphs[i], xPos[i]);
+ }
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyph(uint16_t glyph,
+ SkScalar x,
+ SkScalar y) {
+ SkASSERT(NULL != fBlobBuilder->fRuns);
+ SkASSERT(fBlobBuilder->fRuns->count() > 0);
+ SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kFull_Positioning);
+
+ *fBlobBuilder->fGlyphBuffer.append() = glyph;
+ *fBlobBuilder->fPosBuffer.append() = x;
+ *fBlobBuilder->fPosBuffer.append() = y;
+
+ fBlobBuilder->fRuns->back().count += 1;
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyph(uint16_t glyph,
+ SkPoint pos) {
+ this->addGlyph(glyph, pos.x(), pos.y());
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyphs(
+ const uint16_t glyphs[], const SkScalar xPos[], const SkScalar yPos[], size_t count) {
+
+ for (size_t i = 0; i < count; ++i) {
+ this->addGlyph(glyphs[i], xPos[i], yPos[i]);
+ }
+}
+
+void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyphs(
+ const uint16_t glyphs[], const SkPoint pos[], size_t count) {
+
+ for (size_t i = 0; i < count; ++i) {
+ this->addGlyph(glyphs[i], pos[i].x(), pos[i].y());
+ }
+}
« include/core/SkTextBlob.h ('K') | « src/core/SkRecords.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698