Have draw(Text|PosText|PosTextH) use a single entry on the device
Handle the positioning of drawText at the canvas layer. Simplify the code by removing similar implementations. Change-Id: I8b711783435072f560e29fca1dd934fa2e345ed2 Reviewed-on: https://skia-review.googlesource.com/127131 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
f105dc71e4
commit
4225b3220e
@ -153,6 +153,8 @@ skia_core_sources = [
|
|||||||
"$_src/core/SkGlyph.cpp",
|
"$_src/core/SkGlyph.cpp",
|
||||||
"$_src/core/SkGlyphCache.cpp",
|
"$_src/core/SkGlyphCache.cpp",
|
||||||
"$_src/core/SkGlyphCache.h",
|
"$_src/core/SkGlyphCache.h",
|
||||||
|
"$_src/core/SkGlyphRun.cpp",
|
||||||
|
"$_src/core/SkGlyphRun.h",
|
||||||
"$_src/core/SkGpuBlurUtils.h",
|
"$_src/core/SkGpuBlurUtils.h",
|
||||||
"$_src/core/SkGpuBlurUtils.cpp",
|
"$_src/core/SkGpuBlurUtils.cpp",
|
||||||
"$_src/core/SkGraphics.cpp",
|
"$_src/core/SkGraphics.cpp",
|
||||||
|
@ -85,6 +85,7 @@ tests_sources = [
|
|||||||
"$_tests/GeometryTest.cpp",
|
"$_tests/GeometryTest.cpp",
|
||||||
"$_tests/GifTest.cpp",
|
"$_tests/GifTest.cpp",
|
||||||
"$_tests/GLProgramsTest.cpp",
|
"$_tests/GLProgramsTest.cpp",
|
||||||
|
"$_tests/GlyphRunTest.cpp",
|
||||||
"$_tests/GpuDrawPathTest.cpp",
|
"$_tests/GpuDrawPathTest.cpp",
|
||||||
"$_tests/GpuLayerCacheTest.cpp",
|
"$_tests/GpuLayerCacheTest.cpp",
|
||||||
"$_tests/GpuRectanizerTest.cpp",
|
"$_tests/GpuRectanizerTest.cpp",
|
||||||
|
@ -565,12 +565,6 @@ void SkBitmapDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPa
|
|||||||
BDDraw(this).drawSprite(bitmap, x, y, paint);
|
BDDraw(this).drawSprite(bitmap, x, y, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkBitmapDevice::drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) {
|
|
||||||
SkBitmapDeviceFilteredSurfaceProps props(fBitmap, paint, fSurfaceProps);
|
|
||||||
LOOP_TILER( drawText((const char*)text, len, x, y, paint, &props()), nullptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[],
|
void SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[],
|
||||||
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
|
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
|
||||||
SkBitmapDeviceFilteredSurfaceProps props(fBitmap, paint, fSurfaceProps);
|
SkBitmapDeviceFilteredSurfaceProps props(fBitmap, paint, fSurfaceProps);
|
||||||
|
@ -111,8 +111,6 @@ protected:
|
|||||||
* Does not handle text decoration.
|
* Does not handle text decoration.
|
||||||
* Decorations (underline and stike-thru) will be handled by SkCanvas.
|
* Decorations (underline and stike-thru) will be handled by SkCanvas.
|
||||||
*/
|
*/
|
||||||
void drawText(const void* text, size_t len, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint&) override;
|
|
||||||
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
||||||
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override;
|
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override;
|
||||||
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
|
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "SkDrawable.h"
|
#include "SkDrawable.h"
|
||||||
#include "SkDrawFilter.h"
|
#include "SkDrawFilter.h"
|
||||||
#include "SkDrawLooper.h"
|
#include "SkDrawLooper.h"
|
||||||
|
#include "SkGlyphCache.h"
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
#include "SkImage.h"
|
#include "SkImage.h"
|
||||||
#include "SkImage_Base.h"
|
#include "SkImage_Base.h"
|
||||||
#include "SkImageFilter.h"
|
#include "SkImageFilter.h"
|
||||||
@ -34,6 +36,7 @@
|
|||||||
#include "SkRasterHandleAllocator.h"
|
#include "SkRasterHandleAllocator.h"
|
||||||
#include "SkRRect.h"
|
#include "SkRRect.h"
|
||||||
#include "SkSpecialImage.h"
|
#include "SkSpecialImage.h"
|
||||||
|
#include "SkStrikeCache.h"
|
||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
#include "SkSurface_Base.h"
|
#include "SkSurface_Base.h"
|
||||||
#include "SkTextBlob.h"
|
#include "SkTextBlob.h"
|
||||||
@ -1075,7 +1078,8 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
|||||||
const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
|
const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
|
||||||
(saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
|
(saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
|
||||||
const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
|
const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
|
||||||
const bool trackCoverage = SkToBool(saveLayerFlags & kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag);
|
const bool trackCoverage =
|
||||||
|
SkToBool(saveLayerFlags & kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag);
|
||||||
const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
|
const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
|
||||||
preserveLCDText,
|
preserveLCDText,
|
||||||
trackCoverage,
|
trackCoverage,
|
||||||
@ -2439,10 +2443,13 @@ void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattic
|
|||||||
|
|
||||||
void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
|
void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
|
||||||
const SkPaint& paint) {
|
const SkPaint& paint) {
|
||||||
|
|
||||||
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
||||||
|
|
||||||
while (iter.next()) {
|
while (iter.next()) {
|
||||||
iter.fDevice->drawText(text, byteLength, x, y, looper.paint());
|
auto glyphRun = SkGlyphRun::MakeFromDrawText(
|
||||||
|
looper.paint(), text, byteLength, SkPoint::Make(x, y));
|
||||||
|
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOOPER_END
|
LOOPER_END
|
||||||
@ -2450,12 +2457,12 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca
|
|||||||
|
|
||||||
void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
|
void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
|
||||||
const SkPaint& paint) {
|
const SkPaint& paint) {
|
||||||
SkPoint textOffset = SkPoint::Make(0, 0);
|
|
||||||
|
|
||||||
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
||||||
|
|
||||||
while (iter.next()) {
|
while (iter.next()) {
|
||||||
iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset, looper.paint());
|
auto glyphRun = SkGlyphRun::MakeFromDrawPosText(looper.paint(), text, byteLength, pos);
|
||||||
|
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOOPER_END
|
LOOPER_END
|
||||||
@ -2464,12 +2471,12 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint
|
|||||||
void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
|
void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
|
||||||
SkScalar constY, const SkPaint& paint) {
|
SkScalar constY, const SkPaint& paint) {
|
||||||
|
|
||||||
SkPoint textOffset = SkPoint::Make(0, constY);
|
|
||||||
|
|
||||||
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
|
||||||
|
|
||||||
while (iter.next()) {
|
while (iter.next()) {
|
||||||
iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset, looper.paint());
|
auto glyphRun =
|
||||||
|
SkGlyphRun::MakeFromDrawPosTextH(looper.paint(), text, byteLength, xpos, constY);
|
||||||
|
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOOPER_END
|
LOOPER_END
|
||||||
|
@ -9,12 +9,14 @@
|
|||||||
#include "SkColorFilter.h"
|
#include "SkColorFilter.h"
|
||||||
#include "SkDraw.h"
|
#include "SkDraw.h"
|
||||||
#include "SkDrawFilter.h"
|
#include "SkDrawFilter.h"
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
#include "SkImageFilter.h"
|
#include "SkImageFilter.h"
|
||||||
#include "SkImageFilterCache.h"
|
#include "SkImageFilterCache.h"
|
||||||
#include "SkImagePriv.h"
|
#include "SkImagePriv.h"
|
||||||
#include "SkImage_Base.h"
|
#include "SkImage_Base.h"
|
||||||
#include "SkLatticeIter.h"
|
#include "SkLatticeIter.h"
|
||||||
#include "SkLocalMatrixShader.h"
|
#include "SkLocalMatrixShader.h"
|
||||||
|
#include "SkMakeUnique.h"
|
||||||
#include "SkMatrixPriv.h"
|
#include "SkMatrixPriv.h"
|
||||||
#include "SkPatchUtils.h"
|
#include "SkPatchUtils.h"
|
||||||
#include "SkPathMeasure.h"
|
#include "SkPathMeasure.h"
|
||||||
@ -157,9 +159,16 @@ void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (it.positioning()) {
|
switch (it.positioning()) {
|
||||||
case SkTextBlob::kDefault_Positioning:
|
case SkTextBlob::kDefault_Positioning: {
|
||||||
this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
|
auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
|
||||||
break;
|
auto glyphRun =
|
||||||
|
SkGlyphRun::MakeFromDrawText(runPaint,
|
||||||
|
(const char*) it.glyphs(), textLen, origin);
|
||||||
|
this->drawPosText(
|
||||||
|
it.glyphs(), textLen, glyphRun.getPositions(), 2,
|
||||||
|
SkPoint::Make(0, 0), runPaint);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SkTextBlob::kHorizontal_Positioning:
|
case SkTextBlob::kHorizontal_Positioning:
|
||||||
this->drawPosText(it.glyphs(), textLen, it.pos(), 1,
|
this->drawPosText(it.glyphs(), textLen, it.pos(), 1,
|
||||||
SkPoint::Make(x, y + offset.y()), runPaint);
|
SkPoint::Make(x, y + offset.y()), runPaint);
|
||||||
@ -243,6 +252,17 @@ void SkBaseDevice::drawImageLattice(const SkImage* image,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* info) {
|
||||||
|
SkPaint glyphPaint(paint);
|
||||||
|
glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||||
|
|
||||||
|
auto glyphs = info->copyGlyphIDs();
|
||||||
|
|
||||||
|
this->drawPosText(
|
||||||
|
glyphs.get(), info->runSize() * 2,
|
||||||
|
info->getPositions(), 2, SkPoint::Make(0, 0), glyphPaint);
|
||||||
|
}
|
||||||
|
|
||||||
void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,
|
void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,
|
||||||
const SkCanvas::Lattice& lattice, const SkRect& dst,
|
const SkCanvas::Lattice& lattice, const SkRect& dst,
|
||||||
const SkPaint& paint) {
|
const SkPaint& paint) {
|
||||||
@ -496,6 +516,8 @@ void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
|
|||||||
|
|
||||||
SkPaint localPaint(paint);
|
SkPaint localPaint(paint);
|
||||||
SkShader* shader = paint.getShader();
|
SkShader* shader = paint.getShader();
|
||||||
|
SkScalar pos[2] = {0.0f, 0.0f};
|
||||||
|
SkPoint origin = SkPoint::Make(0, 0);
|
||||||
|
|
||||||
SkMatrix localM, currM;
|
SkMatrix localM, currM;
|
||||||
const void* stopText = (const char*)text + len;
|
const void* stopText = (const char*)text + len;
|
||||||
@ -517,7 +539,7 @@ void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int subLen = proc((const char*)text);
|
int subLen = proc((const char*)text);
|
||||||
this->drawText(text, subLen, 0, 0, localPaint);
|
this->drawPosText(text, subLen, pos, 2, origin, localPaint);
|
||||||
text = (const char*)text + subLen;
|
text = (const char*)text + subLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
class SkBitmap;
|
class SkBitmap;
|
||||||
class SkDrawFilter;
|
class SkDrawFilter;
|
||||||
struct SkDrawShadowRec;
|
struct SkDrawShadowRec;
|
||||||
|
class SkGlyphRun;
|
||||||
class SkImageFilterCache;
|
class SkImageFilterCache;
|
||||||
struct SkIRect;
|
struct SkIRect;
|
||||||
class SkMatrix;
|
class SkMatrix;
|
||||||
@ -222,11 +223,7 @@ protected:
|
|||||||
* Does not handle text decoration.
|
* Does not handle text decoration.
|
||||||
* Decorations (underline and stike-thru) will be handled by SkCanvas.
|
* Decorations (underline and stike-thru) will be handled by SkCanvas.
|
||||||
*/
|
*/
|
||||||
virtual void drawText(const void* text, size_t len,
|
virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRun* info);
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) = 0;
|
|
||||||
virtual void drawPosText(const void* text, size_t len,
|
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
|
||||||
const SkPoint& offset, const SkPaint& paint) = 0;
|
|
||||||
virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
|
virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
|
||||||
virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
|
virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
|
||||||
|
|
||||||
@ -349,6 +346,10 @@ private:
|
|||||||
friend class SkSurface_Raster;
|
friend class SkSurface_Raster;
|
||||||
friend class DeviceTestingAccess;
|
friend class DeviceTestingAccess;
|
||||||
|
|
||||||
|
virtual void drawPosText(const void* text, size_t len,
|
||||||
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
|
const SkPoint& offset, const SkPaint& paint) = 0;
|
||||||
|
|
||||||
// used to change the backend's pixels (and possibly config/rowbytes)
|
// used to change the backend's pixels (and possibly config/rowbytes)
|
||||||
// but cannot change the width/height, so there should be no change to
|
// but cannot change the width/height, so there should be no change to
|
||||||
// any clip information.
|
// any clip information.
|
||||||
@ -427,7 +428,6 @@ protected:
|
|||||||
void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
|
void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
|
||||||
void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
|
void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
|
||||||
SkCanvas::SrcRectConstraint) override {}
|
SkCanvas::SrcRectConstraint) override {}
|
||||||
void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}
|
|
||||||
void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
|
void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
|
||||||
const SkPaint&) override {}
|
const SkPaint&) override {}
|
||||||
void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
|
void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
|
||||||
|
@ -1537,37 +1537,6 @@ SkScalerContextFlags SkDraw::scalerContextFlags() const {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkDraw::drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint& paint, const SkSurfaceProps* props) const {
|
|
||||||
SkASSERT(byteLength == 0 || text != nullptr);
|
|
||||||
|
|
||||||
SkDEBUGCODE(this->validate();)
|
|
||||||
|
|
||||||
// nothing to draw
|
|
||||||
if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SkScalarRec doesn't currently have a way of representing hairline stroke and
|
|
||||||
// will fill if its frame-width is 0.
|
|
||||||
if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
|
|
||||||
this->drawText_asPaths(text, byteLength, x, y, paint);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
|
|
||||||
paint, props, this->scalerContextFlags(), fMatrix);
|
|
||||||
|
|
||||||
// The Blitter Choose needs to be live while using the blitter below.
|
|
||||||
SkAutoBlitterChoose blitterChooser(*this, nullptr, paint);
|
|
||||||
SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
|
|
||||||
DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter());
|
|
||||||
|
|
||||||
SkFindAndPlaceGlyph::ProcessText(
|
|
||||||
paint.getTextEncoding(), text, byteLength,
|
|
||||||
{x, y}, *fMatrix, paint.getTextAlign(), cache.get(), drawOneGlyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, const SkScalar pos[],
|
void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, const SkScalar pos[],
|
||||||
|
@ -62,8 +62,6 @@ public:
|
|||||||
void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull,
|
void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull,
|
||||||
const SkPaint&) const;
|
const SkPaint&) const;
|
||||||
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
|
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
|
||||||
void drawText(const char text[], size_t byteLength, SkScalar x,
|
|
||||||
SkScalar y, const SkPaint& paint, const SkSurfaceProps*) const;
|
|
||||||
void drawPosText(const char text[], size_t byteLength,
|
void drawPosText(const char text[], size_t byteLength,
|
||||||
const SkScalar pos[], int scalarsPerPosition,
|
const SkScalar pos[], int scalarsPerPosition,
|
||||||
const SkPoint& offset, const SkPaint&, const SkSurfaceProps*) const;
|
const SkPoint& offset, const SkPaint&, const SkSurfaceProps*) const;
|
||||||
|
@ -130,6 +130,13 @@ const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi
|
|||||||
return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType);
|
return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkGlyphCache::getAdvances(SkSpan<SkGlyphID> glyphIDs, SkPoint advances[]) {
|
||||||
|
for (ptrdiff_t i = 0; i < glyphIDs.size(); i++) {
|
||||||
|
auto glyph = this->getGlyphIDAdvance(glyphIDs[i]);
|
||||||
|
advances[i] = SkPoint::Make(glyph.fAdvanceX, glyph.fAdvanceY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixed x, SkFixed y) {
|
SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixed x, SkFixed y) {
|
||||||
SkPackedUnicharID id(charCode, x, y);
|
SkPackedUnicharID id(charCode, x, y);
|
||||||
CharGlyphRec* rec = this->getCharGlyphRec(id);
|
CharGlyphRec* rec = this->getCharGlyphRec(id);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "SkArenaAlloc.h"
|
#include "SkArenaAlloc.h"
|
||||||
#include "SkDescriptor.h"
|
#include "SkDescriptor.h"
|
||||||
#include "SkGlyph.h"
|
#include "SkGlyph.h"
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkTHash.h"
|
#include "SkTHash.h"
|
||||||
#include "SkScalerContext.h"
|
#include "SkScalerContext.h"
|
||||||
@ -67,6 +68,8 @@ public:
|
|||||||
const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
|
const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
|
||||||
const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
|
const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
|
||||||
|
|
||||||
|
void getAdvances(SkSpan<SkGlyphID>, SkPoint[]);
|
||||||
|
|
||||||
/** Return the glyphID for the specified Unichar. If the char has already been seen, use the
|
/** Return the glyphID for the specified Unichar. If the char has already been seen, use the
|
||||||
existing cache entry. If not, ask the scalercontext to compute it for us.
|
existing cache entry. If not, ask the scalercontext to compute it for us.
|
||||||
*/
|
*/
|
||||||
|
236
src/core/SkGlyphRun.cpp
Normal file
236
src/core/SkGlyphRun.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "SkDraw.h"
|
||||||
|
#include "SkGlyphCache.h"
|
||||||
|
#include "SkMakeUnique.h"
|
||||||
|
#include "SkMSAN.h"
|
||||||
|
#include "SkPaint.h"
|
||||||
|
#include "SkPaintPriv.h"
|
||||||
|
#include "SkStrikeCache.h"
|
||||||
|
#include "SkUtils.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// A faster set implementation that does not need any initialization, and reading the set items
|
||||||
|
// is order the number of items, and not the size of the universe.
|
||||||
|
// This implementation is based on the paper by Briggs and Torczon, "An Efficient Representation
|
||||||
|
// for Sparse Sets"
|
||||||
|
class GlyphSet {
|
||||||
|
public:
|
||||||
|
GlyphSet(uint32_t glyphUniverseSize)
|
||||||
|
: fUniverseSize{glyphUniverseSize}
|
||||||
|
, fIndexes{skstd::make_unique_default<uint16_t[]>(2 * glyphUniverseSize)}
|
||||||
|
, fUniqueGlyphIDs{&fIndexes[glyphUniverseSize]} {
|
||||||
|
SkASSERT(glyphUniverseSize <= (1 << 16));
|
||||||
|
sk_msan_mark_initialized(fIndexes.get(), &fIndexes[glyphUniverseSize], "works with uninited");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t add(SkGlyphID glyphID) {
|
||||||
|
if (glyphID >= fUniverseSize) {
|
||||||
|
glyphID = kUndefGlyph;
|
||||||
|
}
|
||||||
|
auto index = fIndexes[glyphID];
|
||||||
|
if (index < fUniqueCount && fUniqueGlyphIDs[index] == glyphID) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
fUniqueGlyphIDs[fUniqueCount] = glyphID;
|
||||||
|
fIndexes[glyphID] = fUniqueCount;
|
||||||
|
fUniqueCount += 1;
|
||||||
|
return fUniqueCount - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<uint16_t, std::unique_ptr<SkGlyphID[]>> uniqueGlyphIDs() const {
|
||||||
|
auto uniqueGlyphs = skstd::make_unique_default<SkGlyphID[]>(fUniqueCount);
|
||||||
|
memcpy(uniqueGlyphs.get(), fUniqueGlyphIDs, fUniqueCount * sizeof(SkGlyphID));
|
||||||
|
return std::make_tuple(fUniqueCount, std::move(uniqueGlyphs));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr SkGlyphID kUndefGlyph{0};
|
||||||
|
const uint32_t fUniverseSize;
|
||||||
|
uint16_t fUniqueCount{0};
|
||||||
|
std::unique_ptr<uint16_t[]> fIndexes;
|
||||||
|
SkGlyphID* fUniqueGlyphIDs;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool is_aligned(const void* ptr) {
|
||||||
|
uintptr_t bits = reinterpret_cast<uintptr_t>(ptr);
|
||||||
|
return (bits & (alignof(T) - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool is_aligned_size(size_t size) {
|
||||||
|
return size % sizeof(T) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
|
||||||
|
switch (encoding) {
|
||||||
|
case SkPaint::kUTF8_TextEncoding: return SkTypeface::kUTF8_Encoding;
|
||||||
|
case SkPaint::kUTF16_TextEncoding: return SkTypeface::kUTF16_Encoding;
|
||||||
|
case SkPaint::kUTF32_TextEncoding: return SkTypeface::kUTF32_Encoding;
|
||||||
|
default: return SkTypeface::kUTF32_Encoding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using Core = std::tuple<size_t, std::unique_ptr<uint16_t[]>,
|
||||||
|
uint16_t, std::unique_ptr<SkGlyphID[]>>;
|
||||||
|
|
||||||
|
Core make_from_glyphids(size_t glyphCount, const SkGlyphID* glyphs, SkGlyphID maxGlyphID) {
|
||||||
|
if (glyphCount == 0) { return Core(0, nullptr, 0, nullptr); }
|
||||||
|
|
||||||
|
GlyphSet glyphSet{maxGlyphID};
|
||||||
|
|
||||||
|
auto denseIndex = skstd::make_unique_default<uint16_t[]>(glyphCount);
|
||||||
|
for (size_t i = 0; i < glyphCount; i++) {
|
||||||
|
denseIndex[i] = glyphSet.add(glyphs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs;
|
||||||
|
uint16_t uniqueCount;
|
||||||
|
std::tie(uniqueCount, uniqueGlyphIDs) = glyphSet.uniqueGlyphIDs();
|
||||||
|
|
||||||
|
return Core(glyphCount, std::move(denseIndex), uniqueCount, std::move(uniqueGlyphIDs));
|
||||||
|
}
|
||||||
|
|
||||||
|
Core make_from_utfn(size_t byteLength, const void* utfN, const SkTypeface& typeface,
|
||||||
|
SkTypeface::Encoding encoding) {
|
||||||
|
auto count = SkUTFN_CountUnichars(encoding, utfN, byteLength);
|
||||||
|
|
||||||
|
if (count <= 0) {
|
||||||
|
return Core(0, nullptr, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto glyphs = skstd::make_unique_default<SkGlyphID[]>(count);
|
||||||
|
|
||||||
|
// TODO: move to using cached version.
|
||||||
|
typeface.charsToGlyphs(utfN, encoding, glyphs.get(), count);
|
||||||
|
|
||||||
|
return make_from_glyphids(count, glyphs.get(), typeface.countGlyphs());
|
||||||
|
}
|
||||||
|
|
||||||
|
Core make_core(const SkPaint& paint, const void* bytes, size_t byteLength) {
|
||||||
|
auto encoding = paint.getTextEncoding();
|
||||||
|
auto typeface = SkPaintPriv::GetTypefaceOrDefault(paint);
|
||||||
|
if (encoding == SkPaint::kGlyphID_TextEncoding) {
|
||||||
|
return make_from_glyphids(
|
||||||
|
byteLength / 2, reinterpret_cast<const SkGlyphID*>(bytes), typeface->countGlyphs());
|
||||||
|
} else {
|
||||||
|
return make_from_utfn(byteLength, bytes, *typeface, convert_encoding(encoding));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
SkGlyphRun SkGlyphRun::MakeFromDrawText(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
const SkPoint origin) {
|
||||||
|
size_t runSize;
|
||||||
|
std::unique_ptr<uint16_t[]> denseIndex;
|
||||||
|
uint16_t uniqueSize;
|
||||||
|
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs;
|
||||||
|
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
|
||||||
|
|
||||||
|
if (runSize == 0) { return SkGlyphRun{}; }
|
||||||
|
|
||||||
|
auto advances = skstd::make_unique_default<SkPoint[]>(uniqueSize);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
|
||||||
|
cache->getAdvances(SkSpan<SkGlyphID>{uniqueGlyphIDs.get(), uniqueSize}, advances.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto positions = skstd::make_unique_default<SkPoint[]>(runSize);
|
||||||
|
|
||||||
|
SkPoint endOfLastGlyph = origin;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < runSize; i++) {
|
||||||
|
positions[i] = endOfLastGlyph;
|
||||||
|
endOfLastGlyph += advances[denseIndex[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
|
||||||
|
SkVector len = endOfLastGlyph - origin;
|
||||||
|
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||||
|
len.scale(SK_ScalarHalf);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < runSize; i++) {
|
||||||
|
positions[i] -= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SkGlyphRun{
|
||||||
|
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)};
|
||||||
|
}
|
||||||
|
|
||||||
|
SkGlyphRun SkGlyphRun::MakeFromDrawPosTextH(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
const SkScalar xpos[], SkScalar constY) {
|
||||||
|
size_t runSize;
|
||||||
|
std::unique_ptr<uint16_t[]> denseIndex;
|
||||||
|
uint16_t uniqueSize;
|
||||||
|
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs;
|
||||||
|
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
|
||||||
|
|
||||||
|
if (runSize == 0) { return SkGlyphRun{}; }
|
||||||
|
|
||||||
|
auto positions = skstd::make_unique_default<SkPoint[]>(runSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < runSize; i++) {
|
||||||
|
positions[i] = SkPoint::Make(xpos[i], constY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SkGlyphRun{
|
||||||
|
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)};
|
||||||
|
}
|
||||||
|
|
||||||
|
SkGlyphRun SkGlyphRun::MakeFromDrawPosText(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
const SkPoint pos[]) {
|
||||||
|
size_t runSize;
|
||||||
|
std::unique_ptr<uint16_t[]> denseIndex;
|
||||||
|
uint16_t uniqueSize;
|
||||||
|
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs;
|
||||||
|
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
|
||||||
|
|
||||||
|
if (runSize == 0) { return SkGlyphRun{}; }
|
||||||
|
|
||||||
|
auto positions = skstd::make_unique_default<SkPoint[]>(runSize);
|
||||||
|
|
||||||
|
memcpy(positions.get(), pos, sizeof(SkPoint) * runSize);
|
||||||
|
|
||||||
|
return SkGlyphRun{
|
||||||
|
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SkGlyphID[]> SkGlyphRun::copyGlyphIDs() const {
|
||||||
|
auto glyphs = skstd::make_unique_default<SkGlyphID[]>(fRunSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < fRunSize; i++) {
|
||||||
|
glyphs[i] = fUniqueGlyphs[fDenseIndex[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return glyphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkGlyphRun::SkGlyphRun(size_t runSize,
|
||||||
|
std::unique_ptr<uint16_t[]>&& denseIndex,
|
||||||
|
std::unique_ptr<SkPoint[]>&& positions,
|
||||||
|
uint16_t uniqueSize,
|
||||||
|
std::unique_ptr<SkGlyphID[]>&& uniqueGlyphIDs)
|
||||||
|
: fDenseIndex{std::move(denseIndex)}
|
||||||
|
, fPositions{std::move(positions)}
|
||||||
|
, fUniqueGlyphs{std::move(uniqueGlyphIDs)}
|
||||||
|
, fRunSize{runSize}
|
||||||
|
, fUniqueSize{uniqueSize} { }
|
72
src/core/SkGlyphRun.h
Normal file
72
src/core/SkGlyphRun.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkGlyphRunInfo_DEFINED
|
||||||
|
#define SkGlyphRunInfo_DEFINED
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SkDescriptor.h"
|
||||||
|
#include "SkMask.h"
|
||||||
|
#include "SkPath.h"
|
||||||
|
#include "SkPoint.h"
|
||||||
|
#include "SkTypes.h"
|
||||||
|
|
||||||
|
class SkGlyphRun {
|
||||||
|
public:
|
||||||
|
SkGlyphRun() = default;
|
||||||
|
SkGlyphRun(SkGlyphRun&&) = default;
|
||||||
|
static SkGlyphRun MakeFromDrawText(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
SkPoint origin);
|
||||||
|
static SkGlyphRun MakeFromDrawPosTextH(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
const SkScalar xpos[], SkScalar constY);
|
||||||
|
static SkGlyphRun MakeFromDrawPosText(
|
||||||
|
const SkPaint& paint, const void* bytes, size_t byteLength,
|
||||||
|
const SkPoint pos[]);
|
||||||
|
|
||||||
|
size_t runSize() const { return fRunSize; }
|
||||||
|
uint16_t uniqueSize() const { return fUniqueSize; }
|
||||||
|
|
||||||
|
// copyGlyphIDs is temporary glue to work with the existing system. Don't use with new code.
|
||||||
|
std::unique_ptr<SkGlyphID[]> copyGlyphIDs() const;
|
||||||
|
const SkScalar* getPositions() const {
|
||||||
|
return reinterpret_cast<const SkScalar*>(fPositions.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkGlyphRun(size_t runSize,
|
||||||
|
std::unique_ptr<uint16_t[]>&& denseIndex,
|
||||||
|
std::unique_ptr<SkPoint[]>&& positions,
|
||||||
|
uint16_t uniqueSize,
|
||||||
|
std::unique_ptr<SkGlyphID[]>&& uniqueGlyphIDs);
|
||||||
|
|
||||||
|
std::unique_ptr<uint16_t[]> fDenseIndex;
|
||||||
|
std::unique_ptr<SkPoint[]> fPositions;
|
||||||
|
std::unique_ptr<SkGlyphID[]> fUniqueGlyphs;
|
||||||
|
const size_t fRunSize{0};
|
||||||
|
const uint16_t fUniqueSize{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class SkSpan {
|
||||||
|
public:
|
||||||
|
SkSpan(const T* ptr, size_t size) : fPtr{ptr}, fSize{size} {}
|
||||||
|
SkSpan(const std::vector<T>& v) : fPtr{v.data()}, fSize{v.size()} {}
|
||||||
|
const T& operator [] (ptrdiff_t i) const { return fPtr[i]; }
|
||||||
|
const T* begin() const { return fPtr; }
|
||||||
|
const T* end() const { return fPtr + fSize; }
|
||||||
|
ptrdiff_t size() const { return fSize; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T* fPtr;
|
||||||
|
size_t fSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SkGlyphRunInfo_DEFINED
|
@ -210,16 +210,6 @@ void SkThreadedBMPDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkThreadedBMPDevice::drawText(const void* text, size_t len, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint& paint) {
|
|
||||||
char* clonedText = this->cloneArray((const char*)text, len);
|
|
||||||
SkRect drawBounds = SkRectPriv::MakeLargest(); // TODO tighter drawBounds
|
|
||||||
SkSurfaceProps prop(SkBitmapDeviceFilteredSurfaceProps(fBitmap, paint, this->surfaceProps())());
|
|
||||||
fQueue.push(drawBounds, [=](SkArenaAlloc*, const DrawState& ds, const SkIRect& tileBounds){
|
|
||||||
TileDraw(ds, tileBounds).drawText(clonedText, len, x, y, paint, &prop);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkThreadedBMPDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[],
|
void SkThreadedBMPDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[],
|
||||||
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
|
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
|
||||||
char* clonedText = this->cloneArray((const char*)text, len);
|
char* clonedText = this->cloneArray((const char*)text, len);
|
||||||
|
@ -32,9 +32,6 @@ protected:
|
|||||||
void drawPath(const SkPath&, const SkPaint&, const SkMatrix* prePathMatrix,
|
void drawPath(const SkPath&, const SkPaint&, const SkMatrix* prePathMatrix,
|
||||||
bool pathIsMutable) override;
|
bool pathIsMutable) override;
|
||||||
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) override;
|
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) override;
|
||||||
|
|
||||||
void drawText(const void* text, size_t len, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint&) override;
|
|
||||||
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
||||||
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override;
|
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override;
|
||||||
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
|
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
|
||||||
|
@ -217,20 +217,6 @@ GrOpList* GrRenderTargetContext::getOpList() {
|
|||||||
return this->getRTOpList();
|
return this->getRTOpList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
|
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y,
|
|
||||||
const SkIRect& clipBounds) {
|
|
||||||
ASSERT_SINGLE_OWNER
|
|
||||||
RETURN_IF_ABANDONED
|
|
||||||
SkDEBUGCODE(this->validate();)
|
|
||||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawText", fContext);
|
|
||||||
|
|
||||||
GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
|
|
||||||
atlasTextContext->drawText(fContext, fTextTarget.get(), clip, skPaint, viewMatrix,
|
|
||||||
fSurfaceProps, text, byteLength, x, y, clipBounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
|
void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
const SkMatrix& viewMatrix, const char text[],
|
||||||
size_t byteLength, const SkScalar pos[],
|
size_t byteLength, const SkScalar pos[],
|
||||||
|
@ -63,9 +63,6 @@ public:
|
|||||||
// we could use GrPaint except that
|
// we could use GrPaint except that
|
||||||
// * SkPaint->GrPaint conversion depends upon whether the glyphs are color or grayscale and
|
// * SkPaint->GrPaint conversion depends upon whether the glyphs are color or grayscale and
|
||||||
// this can vary within a text run.
|
// this can vary within a text run.
|
||||||
virtual void drawText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
|
|
||||||
const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
|
||||||
const SkIRect& clipBounds);
|
|
||||||
virtual void drawPosText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
|
virtual void drawPosText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
|
||||||
const char text[], size_t byteLength, const SkScalar pos[],
|
const char text[], size_t byteLength, const SkScalar pos[],
|
||||||
int scalarsPerPosition, const SkPoint& offset,
|
int scalarsPerPosition, const SkPoint& offset,
|
||||||
|
@ -1611,17 +1611,6 @@ void SkGpuDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SkGpuDevice::drawText(const void* text,
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint& paint) {
|
|
||||||
ASSERT_SINGLE_OWNER
|
|
||||||
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get());
|
|
||||||
SkDEBUGCODE(this->validate();)
|
|
||||||
|
|
||||||
fRenderTargetContext->drawText(this->clip(), paint, this->ctm(), (const char*)text, byteLength,
|
|
||||||
x, y, this->devClipBounds());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkGpuDevice::drawPosText(const void* text, size_t byteLength,
|
void SkGpuDevice::drawPosText(const void* text, size_t byteLength,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint& paint) {
|
const SkPoint& offset, const SkPaint& paint) {
|
||||||
|
@ -87,8 +87,6 @@ public:
|
|||||||
const SkPaint& paint, SkCanvas::SrcRectConstraint) override;
|
const SkPaint& paint, SkCanvas::SrcRectConstraint) override;
|
||||||
void drawSprite(const SkBitmap& bitmap, int x, int y,
|
void drawSprite(const SkBitmap& bitmap, int x, int y,
|
||||||
const SkPaint& paint) override;
|
const SkPaint& paint) override;
|
||||||
void drawText(const void* text, size_t len, SkScalar x, SkScalar y,
|
|
||||||
const SkPaint&) override;
|
|
||||||
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
||||||
int scalarsPerPos, const SkPoint& offset, const SkPaint&) override;
|
int scalarsPerPos, const SkPoint& offset, const SkPaint&) override;
|
||||||
void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
|
void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "SkFindAndPlaceGlyph.h"
|
#include "SkFindAndPlaceGlyph.h"
|
||||||
#include "SkGr.h"
|
#include "SkGr.h"
|
||||||
#include "SkGraphics.h"
|
#include "SkGraphics.h"
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
#include "SkMakeUnique.h"
|
#include "SkMakeUnique.h"
|
||||||
#include "SkMaskFilterBase.h"
|
#include "SkMaskFilterBase.h"
|
||||||
#include "SkPaintPriv.h"
|
#include "SkPaintPriv.h"
|
||||||
@ -209,11 +210,17 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
|
|||||||
shaderCaps.supportsDistanceFieldText(), fOptions)) {
|
shaderCaps.supportsDistanceFieldText(), fOptions)) {
|
||||||
switch (it.positioning()) {
|
switch (it.positioning()) {
|
||||||
case SkTextBlob::kDefault_Positioning: {
|
case SkTextBlob::kDefault_Positioning: {
|
||||||
this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
|
||||||
viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(),
|
auto glyphRun =
|
||||||
y + offset.y());
|
SkGlyphRun::MakeFromDrawText(runPaint.skPaint(),
|
||||||
|
(const char*)it.glyphs(), textLen, origin);
|
||||||
|
|
||||||
|
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||||
|
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
|
||||||
|
textLen, glyphRun.getPositions(), 2, SkPoint::Make(0,0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SkTextBlob::kHorizontal_Positioning: {
|
case SkTextBlob::kHorizontal_Positioning: {
|
||||||
SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
|
SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
|
||||||
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||||
@ -231,11 +238,17 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (it.positioning()) {
|
switch (it.positioning()) {
|
||||||
case SkTextBlob::kDefault_Positioning:
|
case SkTextBlob::kDefault_Positioning: {
|
||||||
DrawBmpText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
|
||||||
viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(),
|
auto glyphRun =
|
||||||
y + offset.y());
|
SkGlyphRun::MakeFromDrawText(
|
||||||
|
runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin);
|
||||||
|
|
||||||
|
this->DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||||
|
scalerContextFlags, viewMatrix, (const char*) it.glyphs(),
|
||||||
|
textLen, glyphRun.getPositions(), 2, SkPoint::Make(0, 0));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SkTextBlob::kHorizontal_Positioning:
|
case SkTextBlob::kHorizontal_Positioning:
|
||||||
DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
||||||
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1,
|
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1,
|
||||||
@ -251,35 +264,6 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline sk_sp<GrTextBlob>
|
|
||||||
GrTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
|
|
||||||
GrGlyphCache* glyphCache,
|
|
||||||
const GrShaderCaps& shaderCaps,
|
|
||||||
const GrTextUtils::Paint& paint,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix,
|
|
||||||
const SkSurfaceProps& props,
|
|
||||||
const char text[], size_t byteLength,
|
|
||||||
SkScalar x, SkScalar y) const {
|
|
||||||
int glyphCount = paint.skPaint().countText(text, byteLength);
|
|
||||||
if (!glyphCount) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
sk_sp<GrTextBlob> blob = blobCache->makeBlob(glyphCount, 1);
|
|
||||||
blob->initThrowawayBlob(viewMatrix, x, y);
|
|
||||||
blob->setRunPaintFlags(0, paint.skPaint().getFlags());
|
|
||||||
|
|
||||||
if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(),
|
|
||||||
fOptions)) {
|
|
||||||
this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix,
|
|
||||||
text, byteLength, x, y);
|
|
||||||
} else {
|
|
||||||
DrawBmpText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text,
|
|
||||||
byteLength, x, y);
|
|
||||||
}
|
|
||||||
return blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline sk_sp<GrTextBlob>
|
inline sk_sp<GrTextBlob>
|
||||||
GrTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
|
GrTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
|
||||||
GrGlyphCache* glyphCache,
|
GrGlyphCache* glyphCache,
|
||||||
@ -311,29 +295,6 @@ GrTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
|
|||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextContext::drawText(GrContext* context, GrTextUtils::Target* target,
|
|
||||||
const GrClip& clip, const SkPaint& skPaint,
|
|
||||||
const SkMatrix& viewMatrix, const SkSurfaceProps& props,
|
|
||||||
const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
|
||||||
const SkIRect& regionClipBounds) {
|
|
||||||
if (context->contextPriv().abandoned()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto glyphCache = context->contextPriv().getGlyphCache();
|
|
||||||
auto textBlobCache = context->contextPriv().getTextBlobCache();
|
|
||||||
|
|
||||||
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
|
|
||||||
sk_sp<GrTextBlob> blob(this->makeDrawTextBlob(
|
|
||||||
textBlobCache, glyphCache, *context->contextPriv().caps()->shaderCaps(), paint,
|
|
||||||
ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text,
|
|
||||||
byteLength, x, y));
|
|
||||||
if (blob) {
|
|
||||||
blob->flush(target, props, fDistanceAdjustTable.get(), paint,
|
|
||||||
clip, viewMatrix, regionClipBounds, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
|
void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
|
||||||
const GrClip& clip, const SkPaint& skPaint,
|
const GrClip& clip, const SkPaint& skPaint,
|
||||||
const SkMatrix& viewMatrix, const SkSurfaceProps& props,
|
const SkMatrix& viewMatrix, const SkSurfaceProps& props,
|
||||||
@ -358,41 +319,6 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextContext::DrawBmpText(GrTextBlob* blob, int runIndex,
|
|
||||||
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
|
||||||
const GrTextUtils::Paint& paint,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y) {
|
|
||||||
SkASSERT(byteLength == 0 || text != nullptr);
|
|
||||||
|
|
||||||
// nothing to draw
|
|
||||||
if (text == nullptr || byteLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the blob is set for bitmaptext
|
|
||||||
blob->setHasBitmap();
|
|
||||||
|
|
||||||
if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) {
|
|
||||||
DrawBmpTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix,
|
|
||||||
text, byteLength, x, y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sk_sp<GrTextStrike> currStrike;
|
|
||||||
auto cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix);
|
|
||||||
SkFindAndPlaceGlyph::ProcessText(paint.skPaint().getTextEncoding(), text, byteLength, {x, y},
|
|
||||||
viewMatrix, paint.skPaint().getTextAlign(), cache.get(),
|
|
||||||
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
|
|
||||||
position += rounding;
|
|
||||||
BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike,
|
|
||||||
glyph, SkScalarFloorToScalar(position.fX),
|
|
||||||
SkScalarFloorToScalar(position.fY),
|
|
||||||
paint.filteredPremulColor(), cache.get(),
|
|
||||||
SK_Scalar1, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex,
|
void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex,
|
||||||
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
||||||
@ -432,43 +358,6 @@ void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextContext::DrawBmpTextAsPaths(GrTextBlob* blob, int runIndex,
|
|
||||||
GrGlyphCache* glyphCache,
|
|
||||||
const SkSurfaceProps& props,
|
|
||||||
const GrTextUtils::Paint& origPaint,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y) {
|
|
||||||
// nothing to draw
|
|
||||||
if (text == nullptr || byteLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
|
|
||||||
SkPaint pathPaint(origPaint);
|
|
||||||
pathPaint.setStyle(SkPaint::kFill_Style);
|
|
||||||
pathPaint.setPathEffect(nullptr);
|
|
||||||
|
|
||||||
GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true);
|
|
||||||
FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint, glyphCache, iter.getPathScale());
|
|
||||||
|
|
||||||
const SkGlyph* iterGlyph;
|
|
||||||
const SkPath* iterPath;
|
|
||||||
SkScalar xpos = 0;
|
|
||||||
const char* lastText = text;
|
|
||||||
while (iter.next(&iterGlyph, &iterPath, &xpos)) {
|
|
||||||
if (iterGlyph) {
|
|
||||||
SkPoint pos = SkPoint::Make(xpos + x, y);
|
|
||||||
fallbackTextHelper.appendText(*iterGlyph, iter.getText() - lastText, lastText, pos);
|
|
||||||
} else if (iterPath) {
|
|
||||||
blob->appendPathGlyph(runIndex, *iterPath, xpos + x, y, iter.getPathScale(), false);
|
|
||||||
}
|
|
||||||
lastText = iter.getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GrTextContext::DrawBmpPosTextAsPaths(GrTextBlob* blob, int runIndex,
|
void GrTextContext::DrawBmpPosTextAsPaths(GrTextBlob* blob, int runIndex,
|
||||||
GrGlyphCache* glyphCache,
|
GrGlyphCache* glyphCache,
|
||||||
const SkSurfaceProps& props,
|
const SkSurfaceProps& props,
|
||||||
@ -678,74 +567,6 @@ void GrTextContext::InitDistanceFieldPaint(GrTextBlob* blob,
|
|||||||
*flags = SkScalerContextFlags::kNone;
|
*flags = SkScalerContextFlags::kNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextContext::drawDFText(GrTextBlob* blob, int runIndex,
|
|
||||||
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
|
||||||
const GrTextUtils::Paint& paint,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y) const {
|
|
||||||
SkASSERT(byteLength == 0 || text != nullptr);
|
|
||||||
|
|
||||||
// nothing to draw
|
|
||||||
if (text == nullptr || byteLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SkPaint& skPaint = paint.skPaint();
|
|
||||||
SkPaint::GlyphCacheProc glyphCacheProc =
|
|
||||||
SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true);
|
|
||||||
|
|
||||||
SkTArray<SkScalar> positions;
|
|
||||||
|
|
||||||
const char* textPtr = text;
|
|
||||||
SkScalar stopX = 0;
|
|
||||||
SkScalar stopY = 0;
|
|
||||||
|
|
||||||
SkAutoDescriptor desc;
|
|
||||||
SkScalerContextEffects effects;
|
|
||||||
// We apply the fake-gamma by altering the distance in the shader, so we ignore the
|
|
||||||
// passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
|
|
||||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
|
||||||
skPaint, &props, SkScalerContextFlags::kNone, nullptr, &desc, &effects);
|
|
||||||
auto typeface = SkPaintPriv::GetTypefaceOrDefault(skPaint);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto origPaintCache =
|
|
||||||
SkStrikeCache::FindOrCreateStrikeExclusive(*desc.getDesc(), effects, *typeface);
|
|
||||||
|
|
||||||
const char* stop = text + byteLength;
|
|
||||||
while (textPtr < stop) {
|
|
||||||
// don't need x, y here, since all subpixel variants will have the
|
|
||||||
// same advance
|
|
||||||
const SkGlyph& glyph = glyphCacheProc(origPaintCache.get(), &textPtr);
|
|
||||||
|
|
||||||
positions.push_back(stopX);
|
|
||||||
positions.push_back(stopY);
|
|
||||||
|
|
||||||
stopX += SkFloatToScalar(glyph.fAdvanceX);
|
|
||||||
stopY += SkFloatToScalar(glyph.fAdvanceY);
|
|
||||||
}
|
|
||||||
SkASSERT(textPtr == stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now adjust starting point depending on alignment
|
|
||||||
SkScalar alignX = stopX;
|
|
||||||
SkScalar alignY = stopY;
|
|
||||||
if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
|
|
||||||
alignX = SkScalarHalf(alignX);
|
|
||||||
alignY = SkScalarHalf(alignY);
|
|
||||||
} else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
|
|
||||||
alignX = 0;
|
|
||||||
alignY = 0;
|
|
||||||
}
|
|
||||||
x -= alignX;
|
|
||||||
y -= alignY;
|
|
||||||
SkPoint offset = SkPoint::Make(x, y);
|
|
||||||
|
|
||||||
this->drawDFPosText(blob, runIndex, glyphCache, props, paint, scalerContextFlags,
|
|
||||||
viewMatrix, text, byteLength, positions.begin(), 2, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GrTextContext::drawDFPosText(GrTextBlob* blob, int runIndex,
|
void GrTextContext::drawDFPosText(GrTextBlob* blob, int runIndex,
|
||||||
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
||||||
const GrTextUtils::Paint& paint,
|
const GrTextUtils::Paint& paint,
|
||||||
@ -936,11 +757,15 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrContext* context
|
|||||||
|
|
||||||
// right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to
|
// right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to
|
||||||
// test the text op with this unit test, that is okay.
|
// test the text op with this unit test, that is okay.
|
||||||
sk_sp<GrTextBlob> blob(textContext->makeDrawTextBlob(
|
|
||||||
|
auto origin = SkPoint::Make(x, y);
|
||||||
|
auto glyphRun = SkGlyphRun::MakeFromDrawText(skPaint, text, textLen, origin);
|
||||||
|
|
||||||
|
sk_sp<GrTextBlob> blob(textContext->makeDrawPosTextBlob(
|
||||||
context->contextPriv().getTextBlobCache(), glyphCache,
|
context->contextPriv().getTextBlobCache(), glyphCache,
|
||||||
*context->contextPriv().caps()->shaderCaps(), utilsPaint,
|
*context->contextPriv().caps()->shaderCaps(), utilsPaint,
|
||||||
GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, text,
|
GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, text,
|
||||||
static_cast<size_t>(textLen), SkIntToScalar(x), SkIntToScalar(y)));
|
static_cast<size_t>(textLen), glyphRun.getPositions(), 2, origin));
|
||||||
|
|
||||||
return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, surfaceProps,
|
return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, surfaceProps,
|
||||||
textContext->dfAdjustTable(), rtc->textTarget());
|
textContext->dfAdjustTable(), rtc->textTarget());
|
||||||
|
@ -44,9 +44,6 @@ public:
|
|||||||
|
|
||||||
static std::unique_ptr<GrTextContext> Make(const Options& options);
|
static std::unique_ptr<GrTextContext> Make(const Options& options);
|
||||||
|
|
||||||
void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
|
|
||||||
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y, const SkIRect& regionClipBounds);
|
|
||||||
void drawPosText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
|
void drawPosText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
|
||||||
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
|
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
|
||||||
size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
|
size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
|
||||||
@ -123,15 +120,6 @@ private:
|
|||||||
|
|
||||||
static bool HasLCD(const SkTextBlob*);
|
static bool HasLCD(const SkTextBlob*);
|
||||||
|
|
||||||
sk_sp<GrTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrGlyphCache*,
|
|
||||||
const GrShaderCaps&,
|
|
||||||
const GrTextUtils::Paint&,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix,
|
|
||||||
const SkSurfaceProps&,
|
|
||||||
const char text[], size_t byteLength,
|
|
||||||
SkScalar x, SkScalar y) const;
|
|
||||||
|
|
||||||
sk_sp<GrTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
|
sk_sp<GrTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
|
||||||
const GrShaderCaps&,
|
const GrShaderCaps&,
|
||||||
const GrTextUtils::Paint&,
|
const GrTextUtils::Paint&,
|
||||||
@ -144,23 +132,12 @@ private:
|
|||||||
const SkPoint& offset) const;
|
const SkPoint& offset) const;
|
||||||
|
|
||||||
// Functions for appending BMP text to GrTextBlob
|
// Functions for appending BMP text to GrTextBlob
|
||||||
static void DrawBmpText(GrTextBlob*, int runIndex, GrGlyphCache*,
|
|
||||||
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
|
||||||
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
|
|
||||||
const char text[], size_t byteLength, SkScalar x, SkScalar y);
|
|
||||||
|
|
||||||
static void DrawBmpPosText(GrTextBlob*, int runIndex, GrGlyphCache*,
|
static void DrawBmpPosText(GrTextBlob*, int runIndex, GrGlyphCache*,
|
||||||
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
||||||
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
|
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
|
||||||
const char text[], size_t byteLength, const SkScalar pos[],
|
const char text[], size_t byteLength, const SkScalar pos[],
|
||||||
int scalarsPerPosition, const SkPoint& offset);
|
int scalarsPerPosition, const SkPoint& offset);
|
||||||
|
|
||||||
static void DrawBmpTextAsPaths(GrTextBlob*, int runIndex, GrGlyphCache*,
|
|
||||||
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
|
||||||
SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix, const char text[],
|
|
||||||
size_t byteLength, SkScalar x, SkScalar y);
|
|
||||||
|
|
||||||
static void DrawBmpPosTextAsPaths(GrTextBlob*, int runIndex, GrGlyphCache*,
|
static void DrawBmpPosTextAsPaths(GrTextBlob*, int runIndex, GrGlyphCache*,
|
||||||
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
||||||
SkScalerContextFlags scalerContextFlags,
|
SkScalerContextFlags scalerContextFlags,
|
||||||
@ -170,11 +147,6 @@ private:
|
|||||||
const SkPoint& offset);
|
const SkPoint& offset);
|
||||||
|
|
||||||
// functions for appending distance field text
|
// functions for appending distance field text
|
||||||
void drawDFText(GrTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
|
|
||||||
const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags,
|
|
||||||
const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x,
|
|
||||||
SkScalar y) const;
|
|
||||||
|
|
||||||
void drawDFPosText(GrTextBlob* blob, int runIndex, GrGlyphCache*,
|
void drawDFPosText(GrTextBlob* blob, int runIndex, GrGlyphCache*,
|
||||||
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
|
||||||
SkScalerContextFlags scalerContextFlags,
|
SkScalerContextFlags scalerContextFlags,
|
||||||
|
@ -1450,12 +1450,6 @@ void SkPDFDevice::internalDrawText(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPDFDevice::drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) {
|
|
||||||
this->internalDrawText(text, len, nullptr, SkTextBlob::kDefault_Positioning,
|
|
||||||
SkPoint{x, y}, paint, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPDFDevice::drawPosText(const void* text, size_t len,
|
void SkPDFDevice::drawPosText(const void* text, size_t len,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint& paint) {
|
const SkPoint& offset, const SkPaint& paint) {
|
||||||
|
@ -95,8 +95,6 @@ public:
|
|||||||
const SkRect& dst,
|
const SkRect& dst,
|
||||||
const SkPaint&,
|
const SkPaint&,
|
||||||
SkCanvas::SrcRectConstraint) override;
|
SkCanvas::SrcRectConstraint) override;
|
||||||
void drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint&) override;
|
|
||||||
void drawPosText(const void* text, size_t len,
|
void drawPosText(const void* text, size_t len,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint&) override;
|
const SkPoint& offset, const SkPaint&) override;
|
||||||
|
@ -936,17 +936,6 @@ void SkSVGDevice::drawBitmapRect(const SkBitmap& bm, const SkRect* srcOrNull,
|
|||||||
drawBitmapCommon(MxCp(&adjustedMatrix, cs), bm, paint);
|
drawBitmapCommon(MxCp(&adjustedMatrix, cs), bm, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkSVGDevice::drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) {
|
|
||||||
AutoElement elem("text", fWriter, fResourceBucket.get(), MxCp(this), paint);
|
|
||||||
elem.addTextAttributes(paint);
|
|
||||||
|
|
||||||
SVGTextBuilder builder(text, len, paint, SkPoint::Make(x, y), 0);
|
|
||||||
elem.addAttribute("x", builder.posX());
|
|
||||||
elem.addAttribute("y", builder.posY());
|
|
||||||
elem.addText(builder.text());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkSVGDevice::drawPosText(const void* text, size_t len,
|
void SkSVGDevice::drawPosText(const void* text, size_t len,
|
||||||
const SkScalar pos[], int scalarsPerPos, const SkPoint& offset,
|
const SkScalar pos[], int scalarsPerPos, const SkPoint& offset,
|
||||||
const SkPaint& paint) {
|
const SkPaint& paint) {
|
||||||
|
@ -37,8 +37,6 @@ protected:
|
|||||||
const SkRect* srcOrNull, const SkRect& dst,
|
const SkRect* srcOrNull, const SkRect& dst,
|
||||||
const SkPaint& paint, SkCanvas::SrcRectConstraint) override;
|
const SkPaint& paint, SkCanvas::SrcRectConstraint) override;
|
||||||
|
|
||||||
void drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) override;
|
|
||||||
void drawPosText(const void* text, size_t len,
|
void drawPosText(const void* text, size_t len,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint& paint) override;
|
const SkPoint& offset, const SkPaint& paint) override;
|
||||||
|
@ -2047,63 +2047,6 @@ private:
|
|||||||
GlyphRun* const fXpsGlyphs;
|
GlyphRun* const fXpsGlyphs;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SkXPSDevice::drawText(const void* text, size_t byteLen,
|
|
||||||
SkScalar x, SkScalar y,
|
|
||||||
const SkPaint& paint) {
|
|
||||||
if (byteLen < 1) return;
|
|
||||||
|
|
||||||
if (text_must_be_pathed(paint, this->ctm())) {
|
|
||||||
SkPath path;
|
|
||||||
paint.getTextPath(text, byteLen, x, y, &path);
|
|
||||||
this->drawPath(path, paint, nullptr, true);
|
|
||||||
//TODO: add automation "text"
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypefaceUse* typeface;
|
|
||||||
HRV(CreateTypefaceUse(paint, &typeface));
|
|
||||||
|
|
||||||
auto cache =
|
|
||||||
SkStrikeCache::FindOrCreateStrikeExclusive(
|
|
||||||
paint, &this->surfaceProps(),
|
|
||||||
SkScalerContextFlags::kNone, nullptr);
|
|
||||||
|
|
||||||
// Advance width and offsets for glyphs measured in hundredths of the font em size
|
|
||||||
// (XPS Spec 5.1.3).
|
|
||||||
FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize());
|
|
||||||
GlyphRun xpsGlyphs;
|
|
||||||
xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(),
|
|
||||||
static_cast<const char*>(text), byteLen));
|
|
||||||
|
|
||||||
ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGlyphs);
|
|
||||||
|
|
||||||
SkFindAndPlaceGlyph::ProcessText(
|
|
||||||
paint.getTextEncoding(), static_cast<const char*>(text), byteLen,
|
|
||||||
SkPoint{ x, y }, SkMatrix::I(), paint.getTextAlign(), cache.get(), processOneGlyph);
|
|
||||||
|
|
||||||
if (xpsGlyphs.count() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XPS_POINT origin = {
|
|
||||||
xpsGlyphs[0].horizontalOffset / centemPerUnit,
|
|
||||||
xpsGlyphs[0].verticalOffset / -centemPerUnit,
|
|
||||||
};
|
|
||||||
xpsGlyphs[0].horizontalOffset = 0.0f;
|
|
||||||
xpsGlyphs[0].verticalOffset = 0.0f;
|
|
||||||
|
|
||||||
HRV(AddGlyphs(this->fXpsFactory.get(),
|
|
||||||
this->fCurrentXpsCanvas.get(),
|
|
||||||
typeface,
|
|
||||||
nullptr,
|
|
||||||
xpsGlyphs.begin(), xpsGlyphs.count(),
|
|
||||||
&origin,
|
|
||||||
SkScalarToFLOAT(paint.getTextSize()),
|
|
||||||
XPS_STYLE_SIMULATION_NONE,
|
|
||||||
this->ctm(),
|
|
||||||
paint));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkXPSDevice::drawPosText(const void* text, size_t byteLen,
|
void SkXPSDevice::drawPosText(const void* text, size_t byteLen,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint& paint) {
|
const SkPoint& offset, const SkPaint& paint) {
|
||||||
|
@ -97,8 +97,6 @@ protected:
|
|||||||
const SkRect* srcOrNull, const SkRect& dst,
|
const SkRect* srcOrNull, const SkRect& dst,
|
||||||
const SkPaint& paint,
|
const SkPaint& paint,
|
||||||
SkCanvas::SrcRectConstraint) override;
|
SkCanvas::SrcRectConstraint) override;
|
||||||
void drawText(const void* text, size_t len,
|
|
||||||
SkScalar x, SkScalar y, const SkPaint& paint) override;
|
|
||||||
void drawPosText(const void* text, size_t len,
|
void drawPosText(const void* text, size_t len,
|
||||||
const SkScalar pos[], int scalarsPerPos,
|
const SkScalar pos[], int scalarsPerPos,
|
||||||
const SkPoint& offset, const SkPaint& paint) override;
|
const SkPoint& offset, const SkPaint& paint) override;
|
||||||
|
20
tests/GlyphRunTest.cpp
Normal file
20
tests/GlyphRunTest.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkGlyphRun.h"
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
|
||||||
|
DEF_TEST(GlyphRunInfo, reporter) {
|
||||||
|
SkGlyphID glyphs[] = {100, 3, 240, 3, 234, 111, 3, 4, 10, 11};
|
||||||
|
uint16_t count = SK_ARRAY_COUNT(glyphs);
|
||||||
|
|
||||||
|
SkPaint paint;
|
||||||
|
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||||
|
|
||||||
|
SkGlyphRun::MakeFromDrawText(paint, glyphs, count, SkPoint::Make(0, 0));
|
||||||
|
}
|
@ -24,6 +24,9 @@
|
|||||||
#include "SkSVGCanvas.h"
|
#include "SkSVGCanvas.h"
|
||||||
#include "SkXMLWriter.h"
|
#include "SkXMLWriter.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Using the new system where devices only gets glyphs causes this to fail because the font has no
|
||||||
|
glyph to unichar data.
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
@ -49,6 +52,9 @@ void check_text_node(skiatest::Reporter* reporter,
|
|||||||
REPORTER_ASSERT(reporter, textNode != nullptr);
|
REPORTER_ASSERT(reporter, textNode != nullptr);
|
||||||
if (textNode != nullptr) {
|
if (textNode != nullptr) {
|
||||||
REPORTER_ASSERT(reporter, dom.getType(textNode) == SkDOM::kText_Type);
|
REPORTER_ASSERT(reporter, dom.getType(textNode) == SkDOM::kText_Type);
|
||||||
|
if (strcmp(expected, dom.getName(textNode)) != 0) {
|
||||||
|
SkDebugf("string fail %s == %s\n", expected, dom.getName(textNode));
|
||||||
|
}
|
||||||
REPORTER_ASSERT(reporter, strcmp(expected, dom.getName(textNode)) == 0);
|
REPORTER_ASSERT(reporter, strcmp(expected, dom.getName(textNode)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +72,9 @@ void check_text_node(skiatest::Reporter* reporter,
|
|||||||
REPORTER_ASSERT(reporter, xpos[0] == offset.x());
|
REPORTER_ASSERT(reporter, xpos[0] == offset.x());
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < xposCount; ++i) {
|
for (int i = 0; i < xposCount; ++i) {
|
||||||
|
if (xpos[i] != SkIntToScalar(expected[i])) {
|
||||||
|
SkDebugf("Bad xs %g == %g\n", xpos[i], SkIntToScalar(expected[i]));
|
||||||
|
}
|
||||||
REPORTER_ASSERT(reporter, xpos[i] == SkIntToScalar(expected[i]));
|
REPORTER_ASSERT(reporter, xpos[i] == SkIntToScalar(expected[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +112,7 @@ void test_whitespace_pos(skiatest::Reporter* reporter,
|
|||||||
std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
|
std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
|
||||||
svgCanvas->drawText(txt, len, offset.x(), offset.y(), paint);
|
svgCanvas->drawText(txt, len, offset.x(), offset.y(), paint);
|
||||||
}
|
}
|
||||||
check_text_node(reporter, dom, dom.finishParsing(), offset, 0, expected);
|
check_text_node(reporter, dom, dom.finishParsing(), offset, 2, expected);
|
||||||
|
|
||||||
{
|
{
|
||||||
SkAutoTMalloc<SkScalar> xpos(len);
|
SkAutoTMalloc<SkScalar> xpos(len);
|
||||||
@ -115,7 +124,7 @@ void test_whitespace_pos(skiatest::Reporter* reporter,
|
|||||||
std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
|
std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
|
||||||
svgCanvas->drawPosTextH(txt, len, xpos, offset.y(), paint);
|
svgCanvas->drawPosTextH(txt, len, xpos, offset.y(), paint);
|
||||||
}
|
}
|
||||||
check_text_node(reporter, dom, dom.finishParsing(), offset, 1, expected);
|
check_text_node(reporter, dom, dom.finishParsing(), offset, 2, expected);
|
||||||
|
|
||||||
{
|
{
|
||||||
SkAutoTMalloc<SkPoint> pos(len);
|
SkAutoTMalloc<SkPoint> pos(len);
|
||||||
@ -132,6 +141,7 @@ void test_whitespace_pos(skiatest::Reporter* reporter,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEF_TEST(SVGDevice_whitespace_pos, reporter) {
|
DEF_TEST(SVGDevice_whitespace_pos, reporter) {
|
||||||
static const struct {
|
static const struct {
|
||||||
const char* tst_in;
|
const char* tst_in;
|
||||||
@ -153,6 +163,7 @@ DEF_TEST(SVGDevice_whitespace_pos, reporter) {
|
|||||||
test_whitespace_pos(reporter, tests[i].tst_in, tests[i].tst_out);
|
test_whitespace_pos(reporter, tests[i].tst_in, tests[i].tst_out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void SetImageShader(SkPaint* paint, int imageWidth, int imageHeight, SkShader::TileMode xTile,
|
void SetImageShader(SkPaint* paint, int imageWidth, int imageHeight, SkShader::TileMode xTile,
|
||||||
|
Loading…
Reference in New Issue
Block a user