Index: src/core/SkPaint.cpp |
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp |
index 528b1d0404507fb484ab1da564bf716f7e2a8181..07c10d5a78cd4a0a9ee8b583ffe559f38ac44130 100644 |
--- a/src/core/SkPaint.cpp |
+++ b/src/core/SkPaint.cpp |
@@ -27,12 +27,14 @@ |
#include "SkShader.h" |
#include "SkStringUtils.h" |
#include "SkStroke.h" |
+#include "SkStrokeRec.h" |
+#include "SkSurfacePriv.h" |
+#include "SkTextBlob.h" |
+#include "SkTextBlobRunIterator.h" |
#include "SkTextFormatParams.h" |
#include "SkTextToPathIter.h" |
#include "SkTLazy.h" |
#include "SkTypeface.h" |
-#include "SkStrokeRec.h" |
-#include "SkSurfacePriv.h" |
#include "SkXfermode.h" |
static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) { |
@@ -1127,23 +1129,6 @@ void SkPaint::getTextPath(const void* textData, size_t length, |
} |
} |
-int SkPaint::getTextIntercepts(const void* textData, size_t length, |
- SkScalar x, SkScalar y, const SkScalar bounds[2], |
- SkScalar* array) const { |
- SkASSERT(length == 0 || textData != nullptr); |
- if (!length) { |
- return 0; |
- } |
- |
- const char* text = (const char*) textData; |
- SkTextInterceptsIter iter(text, length, *this, bounds, x, y, |
- SkTextInterceptsIter::TextType::kText); |
- int count = 0; |
- while (iter.next(array, &count)) { |
- } |
- return count; |
-} |
- |
void SkPaint::getPosTextPath(const void* textData, size_t length, |
const SkPoint pos[], SkPath* path) const { |
SkASSERT(length == 0 || textData != nullptr); |
@@ -1173,22 +1158,89 @@ void SkPaint::getPosTextPath(const void* textData, size_t length, |
} |
} |
-int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[], |
- const SkScalar bounds[2], SkScalar* array) const { |
- SkASSERT(length == 0 || textData != nullptr); |
+template <SkTextInterceptsIter::TextType TextType, typename Func> |
+int GetTextIntercepts(const SkPaint& paint, const void* text, size_t length, |
+ const SkScalar bounds[2], SkScalar* array, Func posMaker) { |
+ SkASSERT(length == 0 || text != nullptr); |
if (!length) { |
return 0; |
} |
- const char* text = (const char*) textData; |
- SkTextInterceptsIter iter(text, length, *this, bounds, pos[0].fX, pos[0].fY, |
- SkTextInterceptsIter::TextType::kPosText); |
+ const SkPoint pos0 = posMaker(0); |
+ SkTextInterceptsIter iter(static_cast<const char*>(text), length, paint, bounds, |
+ pos0.x(), pos0.y(), TextType); |
+ |
int i = 0; |
int count = 0; |
while (iter.next(array, &count)) { |
- i++; |
- iter.setPosition(pos[i].fX, pos[i].fY); |
+ if (TextType == SkTextInterceptsIter::TextType::kPosText) { |
+ const SkPoint pos = posMaker(++i); |
+ iter.setPosition(pos.x(), pos.y()); |
+ } |
+ } |
+ |
+ return count; |
+} |
+ |
+int SkPaint::getTextIntercepts(const void* textData, size_t length, |
+ SkScalar x, SkScalar y, const SkScalar bounds[2], |
+ SkScalar* array) const { |
+ |
+ return GetTextIntercepts<SkTextInterceptsIter::TextType::kText>( |
+ *this, textData, length, bounds, array, [&x, &y] (int) -> SkPoint { |
+ return SkPoint::Make(x, y); |
+ }); |
+} |
+ |
+int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[], |
+ const SkScalar bounds[2], SkScalar* array) const { |
+ |
+ return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>( |
+ *this, textData, length, bounds, array, [&pos] (int i) -> SkPoint { |
+ return pos[i]; |
+ }); |
+} |
+ |
+int SkPaint::getPosTextHIntercepts(const void* textData, size_t length, const SkScalar xpos[], |
+ SkScalar constY, const SkScalar bounds[2], |
+ SkScalar* array) const { |
+ |
+ return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>( |
+ *this, textData, length, bounds, array, [&xpos, &constY] (int i) -> SkPoint { |
+ return SkPoint::Make(xpos[i], constY); |
+ }); |
+} |
+ |
+int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2], |
+ SkScalar* intervals) const { |
+ int count = 0; |
+ SkPaint runPaint(*this); |
+ |
+ SkTextBlobRunIterator it(blob); |
+ while (!it.done()) { |
+ it.applyFontToPaint(&runPaint); |
+ const size_t runByteCount = it.glyphCount() * sizeof(SkGlyphID); |
+ SkScalar* runIntervals = intervals ? intervals + count : nullptr; |
+ |
+ switch (it.positioning()) { |
+ case SkTextBlob::kDefault_Positioning: |
+ count += runPaint.getTextIntercepts(it.glyphs(), runByteCount, it.offset().x(), |
+ it.offset().y(), bounds, runIntervals); |
+ break; |
+ case SkTextBlob::kHorizontal_Positioning: |
+ count += runPaint.getPosTextHIntercepts(it.glyphs(), runByteCount, it.pos(), |
+ it.offset().y(), bounds, runIntervals); |
+ break; |
+ case SkTextBlob::kFull_Positioning: |
+ count += runPaint.getPosTextIntercepts(it.glyphs(), runByteCount, |
+ reinterpret_cast<const SkPoint*>(it.pos()), |
+ bounds, runIntervals); |
+ break; |
+ } |
+ |
+ it.next(); |
} |
+ |
return count; |
} |