Move SkGpuDevice::internalDrawPath to GrBlurUtils::drawPathWithMaskFilter
This CL is ugly but it: removes the stored SkGpuDevice back pointer from GrTextContext (at the cost of passing more parameters) moves SkGpuDevice::internalDrawPath to GrDrawContext::drawPathFull Unfortunately, the GrTextContext-derived classes still need the SkGpuDevice for filterTextFlags calls but I will try removing that in a separate CL. Review URL: https://codereview.chromium.org/1157773003
This commit is contained in:
parent
24a366a037
commit
ccb1b57510
@ -83,6 +83,8 @@
|
||||
'<(skia_src_path)/gpu/GrBatchTest.h',
|
||||
'<(skia_src_path)/gpu/GrBlend.cpp',
|
||||
'<(skia_src_path)/gpu/GrBlend.h',
|
||||
'<(skia_src_path)/gpu/GrBlurUtils.cpp',
|
||||
'<(skia_src_path)/gpu/GrBlurUtils.h',
|
||||
'<(skia_src_path)/gpu/GrBufferAllocPool.cpp',
|
||||
'<(skia_src_path)/gpu/GrBufferAllocPool.h',
|
||||
'<(skia_src_path)/gpu/GrCaps.cpp',
|
||||
|
@ -480,11 +480,9 @@ private:
|
||||
* render target and the context. Caller assumes the ownership
|
||||
* of the returned object. The returned object must be deleted
|
||||
* before the context is destroyed.
|
||||
* TODO we can possibly bury this behind context, but we need to be able to use the
|
||||
* drawText_asPaths logic on SkGpuDevice
|
||||
* TODO bury this behind context!
|
||||
*/
|
||||
GrTextContext* createTextContext(GrRenderTarget*,
|
||||
SkGpuDevice*,
|
||||
const SkDeviceProperties&,
|
||||
bool enableDistanceFieldFonts);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GrBatchFontCache.h"
|
||||
#include "GrBatchTarget.h"
|
||||
#include "GrBatchTest.h"
|
||||
#include "GrBlurUtils.h"
|
||||
#include "GrDefaultGeoProcFactory.h"
|
||||
#include "GrDrawContext.h"
|
||||
#include "GrFontScaler.h"
|
||||
@ -94,10 +95,9 @@ static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
|
||||
// Distance field text in textblobs
|
||||
|
||||
GrAtlasTextContext::GrAtlasTextContext(GrContext* context,
|
||||
SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& properties,
|
||||
bool enableDistanceFields)
|
||||
: INHERITED(context, gpuDevice, properties)
|
||||
: INHERITED(context, properties)
|
||||
, fDistanceAdjustTable(SkNEW_ARGS(DistanceAdjustTable, (properties.gamma()))) {
|
||||
// We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
|
||||
// vertexStride
|
||||
@ -196,10 +196,9 @@ void GrAtlasTextContext::DistanceAdjustTable::buildDistanceAdjustTable(float gam
|
||||
}
|
||||
|
||||
GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
|
||||
SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& props,
|
||||
bool enableDistanceFields) {
|
||||
return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props, enableDistanceFields));
|
||||
return SkNEW_ARGS(GrAtlasTextContext, (context, props, enableDistanceFields));
|
||||
}
|
||||
|
||||
bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
|
||||
@ -345,9 +344,10 @@ inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run,
|
||||
return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc());
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
|
||||
const SkPaint& skPaint, const SkMatrix& viewMatrix,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
void GrAtlasTextContext::drawTextBlob(SkGpuDevice* gpuDevice, GrRenderTarget* rt,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob* blob,
|
||||
SkScalar x, SkScalar y,
|
||||
SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
|
||||
// If we have been abandoned, then don't draw
|
||||
if (fContext->abandoned()) {
|
||||
@ -411,8 +411,8 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
|
||||
fCache->remove(cacheBlob);
|
||||
cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint,
|
||||
kGrayTextVASize)));
|
||||
this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y,
|
||||
drawFilter, clipRect, rt, clip, grPaint);
|
||||
this->regenerateTextBlob(gpuDevice, cacheBlob, skPaint, grPaint.getColor(), viewMatrix,
|
||||
blob, x, y, drawFilter, clipRect, rt, clip, grPaint);
|
||||
} else {
|
||||
// If we can reuse the blob, then make sure we update the blob's viewmatrix, and x/y
|
||||
// offsets
|
||||
@ -428,12 +428,12 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
|
||||
} else {
|
||||
cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
|
||||
}
|
||||
this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y,
|
||||
drawFilter, clipRect, rt, clip, grPaint);
|
||||
this->regenerateTextBlob(gpuDevice, cacheBlob, skPaint, grPaint.getColor(), viewMatrix,
|
||||
blob, x, y, drawFilter, clipRect, rt, clip, grPaint);
|
||||
}
|
||||
|
||||
cacheBlob->fPaintColor = skPaint.getColor();
|
||||
this->flush(drawContext, blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
|
||||
this->flush(gpuDevice, drawContext, blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
|
||||
clip, viewMatrix, clipBounds, x, y, transX, transY);
|
||||
}
|
||||
|
||||
@ -472,7 +472,7 @@ inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
|
||||
void GrAtlasTextContext::regenerateTextBlob(SkGpuDevice* gpuDevice, BitmapTextBlob* cacheBlob,
|
||||
const SkPaint& skPaint, GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
@ -500,7 +500,7 @@ void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
|
||||
continue;
|
||||
}
|
||||
|
||||
runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
|
||||
runPaint.setFlags(gpuDevice->filterTextFlags(runPaint));
|
||||
|
||||
// setup vertex / glyphIndex for the new run
|
||||
if (run > 0) {
|
||||
@ -775,12 +775,12 @@ GrAtlasTextContext::createDrawPosTextBlob(GrRenderTarget* rt, const GrClip& clip
|
||||
return blob;
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
|
||||
void GrAtlasTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
|
||||
GrDrawContext* drawContext = fContext->drawContext();
|
||||
if (drawContext) {
|
||||
SkAutoTUnref<BitmapTextBlob> blob(
|
||||
this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
|
||||
@ -789,13 +789,13 @@ void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
|
||||
}
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
|
||||
void GrAtlasTextContext::onDrawPosText(GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& regionClipBounds) {
|
||||
GrDrawContext* drawContext = fContext->drawContext();
|
||||
if (drawContext) {
|
||||
SkAutoTUnref<BitmapTextBlob> blob(
|
||||
this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
|
||||
@ -2043,7 +2043,9 @@ private:
|
||||
float fGamma;
|
||||
};
|
||||
|
||||
void GrAtlasTextContext::flushRunAsPaths(const SkTextBlob::RunIterator& it, const SkPaint& skPaint,
|
||||
void GrAtlasTextContext::flushRunAsPaths(SkGpuDevice* gpuDevice, GrDrawContext* drawContext,
|
||||
GrRenderTarget* rt, const SkTextBlob::RunIterator& it,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
|
||||
const SkIRect& clipBounds, SkScalar x, SkScalar y) {
|
||||
SkPaint runPaint = skPaint;
|
||||
@ -2057,20 +2059,23 @@ void GrAtlasTextContext::flushRunAsPaths(const SkTextBlob::RunIterator& it, cons
|
||||
return;
|
||||
}
|
||||
|
||||
runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
|
||||
runPaint.setFlags(gpuDevice->filterTextFlags(runPaint));
|
||||
|
||||
switch (it.positioning()) {
|
||||
case SkTextBlob::kDefault_Positioning:
|
||||
this->drawTextAsPath(runPaint, viewMatrix, (const char *)it.glyphs(),
|
||||
this->drawTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
|
||||
(const char *)it.glyphs(),
|
||||
textLen, x + offset.x(), y + offset.y(), clipBounds);
|
||||
break;
|
||||
case SkTextBlob::kHorizontal_Positioning:
|
||||
this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs(),
|
||||
this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
|
||||
(const char*)it.glyphs(),
|
||||
textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
|
||||
clipBounds);
|
||||
break;
|
||||
case SkTextBlob::kFull_Positioning:
|
||||
this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs(),
|
||||
this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
|
||||
(const char*)it.glyphs(),
|
||||
textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
|
||||
break;
|
||||
}
|
||||
@ -2140,8 +2145,9 @@ inline void GrAtlasTextContext::flushRun(GrDrawContext* drawContext,
|
||||
}
|
||||
}
|
||||
|
||||
inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
|
||||
const SkPaint& skPaint,
|
||||
inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob,
|
||||
GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
SkScalar transX, SkScalar transY,
|
||||
const SkIRect& clipBounds) {
|
||||
if (!cacheBlob->fBigGlyphs.count()) {
|
||||
@ -2161,12 +2167,13 @@ inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend
|
||||
SkMatrix translate = cacheBlob->fViewMatrix;
|
||||
translate.postTranslate(bigGlyph.fVx, bigGlyph.fVy);
|
||||
|
||||
fGpuDevice->internalDrawPath(bigGlyph.fPath, skPaint, translate, &pathMatrix, clipBounds,
|
||||
false);
|
||||
GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, bigGlyph.fPath,
|
||||
skPaint, translate, &pathMatrix, clipBounds, false);
|
||||
}
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::flush(GrDrawContext* drawContext,
|
||||
void GrAtlasTextContext::flush(SkGpuDevice* gpuDevice,
|
||||
GrDrawContext* drawContext,
|
||||
const SkTextBlob* blob,
|
||||
BitmapTextBlob* cacheBlob,
|
||||
GrRenderTarget* rt,
|
||||
@ -2188,7 +2195,8 @@ void GrAtlasTextContext::flush(GrDrawContext* drawContext,
|
||||
SkTextBlob::RunIterator it(blob);
|
||||
for (int run = 0; !it.done(); it.next(), run++) {
|
||||
if (cacheBlob->fRuns[run].fDrawAsPaths) {
|
||||
this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBounds, x, y);
|
||||
this->flushRunAsPaths(gpuDevice, drawContext, rt, it, clip, skPaint,
|
||||
drawFilter, viewMatrix, clipBounds, x, y);
|
||||
continue;
|
||||
}
|
||||
cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
|
||||
@ -2197,7 +2205,7 @@ void GrAtlasTextContext::flush(GrDrawContext* drawContext,
|
||||
}
|
||||
|
||||
// Now flush big glyphs
|
||||
this->flushBigGlyphs(cacheBlob, rt, skPaint, transX, transY, clipBounds);
|
||||
this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, transX, transY, clipBounds);
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::flush(GrDrawContext* drawContext,
|
||||
@ -2216,7 +2224,7 @@ void GrAtlasTextContext::flush(GrDrawContext* drawContext,
|
||||
}
|
||||
|
||||
// Now flush big glyphs
|
||||
this->flushBigGlyphs(cacheBlob, rt, skPaint, 0, 0, clipBounds);
|
||||
this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, 0, 0, clipBounds);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -2234,7 +2242,7 @@ BATCH_TEST_DEFINE(TextBlobBatch) {
|
||||
// We don't yet test the fall back to paths in the GrTextContext base class. This is mostly
|
||||
// because we don't really want to have a gpu device here.
|
||||
// We enable distance fields by twiddling a knob on the paint
|
||||
gTextContext = GrAtlasTextContext::Create(context, NULL, gDeviceProperties, false);
|
||||
gTextContext = GrAtlasTextContext::Create(context, gDeviceProperties, false);
|
||||
}
|
||||
|
||||
// create dummy render target
|
||||
|
@ -34,26 +34,25 @@ class GrTextBlobCache;
|
||||
*/
|
||||
class GrAtlasTextContext : public GrTextContext {
|
||||
public:
|
||||
static GrAtlasTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&,
|
||||
static GrAtlasTextContext* Create(GrContext*, const SkDeviceProperties&,
|
||||
bool enableDistanceFields);
|
||||
|
||||
private:
|
||||
GrAtlasTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&,
|
||||
bool enableDistanceFields);
|
||||
GrAtlasTextContext(GrContext*, const SkDeviceProperties&, bool enableDistanceFields);
|
||||
~GrAtlasTextContext() override {}
|
||||
|
||||
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
const SkPaint&, const SkMatrix& viewMatrix) override;
|
||||
|
||||
void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const char text[], size_t byteLength,
|
||||
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
|
||||
void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix,
|
||||
void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
const SkPaint&, const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& regionClipBounds) override;
|
||||
void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
|
||||
void drawTextBlob(SkGpuDevice*, GrRenderTarget*, const GrClip&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
|
||||
SkDrawFilter*, const SkIRect& clipBounds) override;
|
||||
|
||||
@ -272,7 +271,9 @@ private:
|
||||
size_t vertexStride, bool useVertexColor,
|
||||
GrGlyph*);
|
||||
|
||||
inline void flushRunAsPaths(const SkTextBlob::RunIterator&, const SkPaint&, SkDrawFilter*,
|
||||
inline void flushRunAsPaths(SkGpuDevice*, GrDrawContext*, GrRenderTarget*,
|
||||
const SkTextBlob::RunIterator&, const GrClip& clip,
|
||||
const SkPaint&, SkDrawFilter*,
|
||||
const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
|
||||
SkScalar y);
|
||||
inline BitmapTextBatch* createBatch(BitmapTextBlob*, const PerSubRunInfo&,
|
||||
@ -281,14 +282,15 @@ private:
|
||||
const SkPaint&);
|
||||
inline void flushRun(GrDrawContext*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
|
||||
SkScalar transX, SkScalar transY, const SkPaint&);
|
||||
inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
|
||||
const SkPaint& skPaint,
|
||||
inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrDrawContext*, GrRenderTarget*,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
SkScalar transX, SkScalar transY, const SkIRect& clipBounds);
|
||||
|
||||
// We have to flush SkTextBlobs differently from drawText / drawPosText
|
||||
void flush(GrDrawContext*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
|
||||
const GrPaint&, SkDrawFilter*, const GrClip&, const SkMatrix& viewMatrix,
|
||||
const SkIRect& clipBounds, SkScalar x, SkScalar y, SkScalar transX, SkScalar transY);
|
||||
void flush(SkGpuDevice*, GrDrawContext*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
|
||||
const SkPaint&, const GrPaint&, SkDrawFilter*, const GrClip&,
|
||||
const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y,
|
||||
SkScalar transX, SkScalar transY);
|
||||
void flush(GrDrawContext*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
|
||||
const GrPaint&, const GrClip&, const SkIRect& clipBounds);
|
||||
|
||||
@ -337,7 +339,7 @@ private:
|
||||
const BitmapTextBlob&, const SkPaint&,
|
||||
const SkMaskFilter::BlurRec&,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
|
||||
void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, GrColor,
|
||||
void regenerateTextBlob(SkGpuDevice*, BitmapTextBlob* bmp, const SkPaint& skPaint, GrColor,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
SkDrawFilter* drawFilter, const SkIRect& clipRect, GrRenderTarget*,
|
||||
|
295
src/gpu/GrBlurUtils.cpp
Normal file
295
src/gpu/GrBlurUtils.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrBlurUtils.h"
|
||||
#include "GrDrawContext.h"
|
||||
#include "GrContext.h"
|
||||
#include "effects/GrSimpleTextureEffect.h"
|
||||
#include "GrStrokeInfo.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTextureProvider.h"
|
||||
#include "SkDraw.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkMaskFilter.h"
|
||||
#include "SkPaint.h"
|
||||
|
||||
static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& rect) {
|
||||
return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
|
||||
}
|
||||
|
||||
// Draw a mask using the supplied paint. Since the coverage/geometry
|
||||
// is already burnt into the mask this boils down to a rect draw.
|
||||
// Return true if the mask was successfully drawn.
|
||||
static bool draw_mask(GrDrawContext* drawContext,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& maskRect,
|
||||
GrPaint* grp,
|
||||
GrTexture* mask) {
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
||||
matrix.postIDiv(mask->width(), mask->height());
|
||||
|
||||
grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix,
|
||||
kDevice_GrCoordSet))->unref();
|
||||
|
||||
SkMatrix inverse;
|
||||
if (!viewMatrix.invert(&inverse)) {
|
||||
return false;
|
||||
}
|
||||
drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool draw_with_mask_filter(GrDrawContext* drawContext,
|
||||
GrTextureProvider* textureProvider,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clipData,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkPath& devPath,
|
||||
SkMaskFilter* filter,
|
||||
const SkIRect& clipBounds,
|
||||
GrPaint* grp,
|
||||
SkPaint::Style style) {
|
||||
SkMask srcM, dstM;
|
||||
|
||||
if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
|
||||
SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
|
||||
return false;
|
||||
}
|
||||
SkAutoMaskFreeImage autoSrc(srcM.fImage);
|
||||
|
||||
if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) {
|
||||
return false;
|
||||
}
|
||||
// this will free-up dstM when we're done (allocated in filterMask())
|
||||
SkAutoMaskFreeImage autoDst(dstM.fImage);
|
||||
|
||||
if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we now have a device-aligned 8bit mask in dstM, ready to be drawn using
|
||||
// the current clip (and identity matrix) and GrPaint settings
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = dstM.fBounds.width();
|
||||
desc.fHeight = dstM.fBounds.height();
|
||||
desc.fConfig = kAlpha_8_GrPixelConfig;
|
||||
|
||||
SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture(
|
||||
desc, GrTextureProvider::kApprox_ScratchTexMatch));
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
|
||||
dstM.fImage, dstM.fRowBytes);
|
||||
|
||||
SkRect maskRect = SkRect::Make(dstM.fBounds);
|
||||
|
||||
return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, texture);
|
||||
}
|
||||
|
||||
// Create a mask of 'devPath' and place the result in 'mask'.
|
||||
static GrTexture* create_mask_GPU(GrContext* context,
|
||||
const SkRect& maskRect,
|
||||
const SkPath& devPath,
|
||||
const GrStrokeInfo& strokeInfo,
|
||||
bool doAA,
|
||||
int sampleCnt) {
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
desc.fWidth = SkScalarCeilToInt(maskRect.width());
|
||||
desc.fHeight = SkScalarCeilToInt(maskRect.height());
|
||||
desc.fSampleCnt = doAA ? sampleCnt : 0;
|
||||
// We actually only need A8, but it often isn't supported as a
|
||||
// render target so default to RGBA_8888
|
||||
desc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
|
||||
if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, desc.fSampleCnt > 0)) {
|
||||
desc.fConfig = kAlpha_8_GrPixelConfig;
|
||||
}
|
||||
|
||||
GrTexture* mask = context->textureProvider()->refScratchTexture(
|
||||
desc, GrTextureProvider::kApprox_ScratchTexMatch);
|
||||
if (NULL == mask) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
|
||||
|
||||
GrDrawContext* drawContext = context->drawContext();
|
||||
if (!drawContext) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true);
|
||||
|
||||
GrPaint tempPaint;
|
||||
tempPaint.setAntiAlias(doAA);
|
||||
tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
|
||||
|
||||
// setup new clip
|
||||
GrClip clip(clipRect);
|
||||
|
||||
// Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
|
||||
SkMatrix translate;
|
||||
translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
||||
drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
|
||||
return mask;
|
||||
}
|
||||
|
||||
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
|
||||
GrDrawContext* drawContext,
|
||||
GrRenderTarget* renderTarget,
|
||||
const GrClip& clip,
|
||||
const SkPath& origSrcPath,
|
||||
const SkPaint& paint,
|
||||
const SkMatrix& origViewMatrix,
|
||||
const SkMatrix* prePathMatrix,
|
||||
const SkIRect& clipBounds,
|
||||
bool pathIsMutable) {
|
||||
SkASSERT(!pathIsMutable || origSrcPath.isVolatile());
|
||||
|
||||
GrStrokeInfo strokeInfo(paint);
|
||||
|
||||
// If we have a prematrix, apply it to the path, optimizing for the case
|
||||
// where the original path can in fact be modified in place (even though
|
||||
// its parameter type is const).
|
||||
SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
|
||||
SkTLazy<SkPath> tmpPath;
|
||||
SkTLazy<SkPath> effectPath;
|
||||
SkPathEffect* pathEffect = paint.getPathEffect();
|
||||
|
||||
SkMatrix viewMatrix = origViewMatrix;
|
||||
|
||||
if (prePathMatrix) {
|
||||
// stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix.
|
||||
// The pre-path-matrix also should not affect shading.
|
||||
if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint.getShader() &&
|
||||
(strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) {
|
||||
viewMatrix.preConcat(*prePathMatrix);
|
||||
} else {
|
||||
SkPath* result = pathPtr;
|
||||
|
||||
if (!pathIsMutable) {
|
||||
result = tmpPath.init();
|
||||
result->setIsVolatile(true);
|
||||
pathIsMutable = true;
|
||||
}
|
||||
// should I push prePathMatrix on our MV stack temporarily, instead
|
||||
// of applying it here? See SkDraw.cpp
|
||||
pathPtr->transform(*prePathMatrix, result);
|
||||
pathPtr = result;
|
||||
}
|
||||
}
|
||||
// at this point we're done with prePathMatrix
|
||||
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
||||
|
||||
GrPaint grPaint;
|
||||
if (!SkPaint2GrPaint(context, renderTarget, paint, viewMatrix, true, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SkRect* cullRect = NULL; // TODO: what is our bounds?
|
||||
if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr,
|
||||
&strokeInfo, cullRect)) {
|
||||
pathPtr = effectPath.get();
|
||||
pathIsMutable = true;
|
||||
}
|
||||
|
||||
if (paint.getMaskFilter()) {
|
||||
if (!strokeInfo.isHairlineStyle()) {
|
||||
SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
|
||||
if (strokeInfo.isDashed()) {
|
||||
if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, cullRect)) {
|
||||
pathPtr = strokedPath;
|
||||
pathIsMutable = true;
|
||||
}
|
||||
strokeInfo.removeDash();
|
||||
}
|
||||
if (strokeInfo.applyToPath(strokedPath, *pathPtr)) {
|
||||
pathPtr = strokedPath;
|
||||
pathIsMutable = true;
|
||||
strokeInfo.setFillStyle();
|
||||
}
|
||||
}
|
||||
|
||||
// avoid possibly allocating a new path in transform if we can
|
||||
SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
|
||||
if (!pathIsMutable) {
|
||||
devPathPtr->setIsVolatile(true);
|
||||
}
|
||||
|
||||
// transform the path into device space
|
||||
pathPtr->transform(viewMatrix, devPathPtr);
|
||||
|
||||
SkRect maskRect;
|
||||
if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
|
||||
clipBounds,
|
||||
viewMatrix,
|
||||
&maskRect)) {
|
||||
SkIRect finalIRect;
|
||||
maskRect.roundOut(&finalIRect);
|
||||
if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
|
||||
// clipped out
|
||||
return;
|
||||
}
|
||||
|
||||
if (paint.getMaskFilter()->directFilterMaskGPU(context,
|
||||
renderTarget,
|
||||
&grPaint,
|
||||
clip,
|
||||
viewMatrix,
|
||||
strokeInfo,
|
||||
*devPathPtr)) {
|
||||
// the mask filter was able to draw itself directly, so there's nothing
|
||||
// left to do.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SkAutoTUnref<GrTexture> mask(create_mask_GPU(context,
|
||||
maskRect,
|
||||
*devPathPtr,
|
||||
strokeInfo,
|
||||
grPaint.isAntiAlias(),
|
||||
renderTarget->numSamples()));
|
||||
if (mask) {
|
||||
GrTexture* filtered;
|
||||
|
||||
if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect,
|
||||
&filtered, true)) {
|
||||
// filterMaskGPU gives us ownership of a ref to the result
|
||||
SkAutoTUnref<GrTexture> atu(filtered);
|
||||
if (draw_mask(drawContext,
|
||||
renderTarget,
|
||||
clip,
|
||||
viewMatrix,
|
||||
maskRect,
|
||||
&grPaint,
|
||||
filtered)) {
|
||||
// This path is completely drawn
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw the mask on the CPU - this is a fallthrough path in case the
|
||||
// GPU path fails
|
||||
SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style :
|
||||
SkPaint::kFill_Style;
|
||||
draw_with_mask_filter(drawContext, context->textureProvider(), renderTarget,
|
||||
clip, viewMatrix, *devPathPtr,
|
||||
paint.getMaskFilter(), clipBounds, &grPaint, style);
|
||||
return;
|
||||
}
|
||||
|
||||
drawContext->drawPath(renderTarget, clip, grPaint, viewMatrix, *pathPtr, strokeInfo);
|
||||
}
|
||||
|
40
src/gpu/GrBlurUtils.h
Normal file
40
src/gpu/GrBlurUtils.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrBlurUtils_DEFINED
|
||||
#define GrBlurUtils_DEFINED
|
||||
|
||||
class GrClip;
|
||||
class GrContext;
|
||||
class GrDrawContext;
|
||||
class GrRenderTarget;
|
||||
struct SkIRect;
|
||||
class SkMatrix;
|
||||
class SkPaint;
|
||||
class SkPath;
|
||||
|
||||
|
||||
/**
|
||||
* Blur utilities.
|
||||
*/
|
||||
namespace GrBlurUtils {
|
||||
/**
|
||||
* Draw a path handling the mask filter if present.
|
||||
*/
|
||||
void drawPathWithMaskFilter(GrContext* context,
|
||||
GrDrawContext* drawContext,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const SkPath& origSrcPath,
|
||||
const SkPaint& paint,
|
||||
const SkMatrix& origViewMatrix,
|
||||
const SkMatrix* prePathMatrix,
|
||||
const SkIRect& clipBounds,
|
||||
bool pathIsMutable);
|
||||
};
|
||||
|
||||
#endif
|
@ -244,18 +244,17 @@ void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes)
|
||||
}
|
||||
|
||||
GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
|
||||
SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties&
|
||||
leakyProperties,
|
||||
bool enableDistanceFieldFonts) {
|
||||
if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMultisampled()) {
|
||||
GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
|
||||
if (sb) {
|
||||
return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyProperties);
|
||||
return GrStencilAndCoverTextContext::Create(this, leakyProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDistanceFieldFonts);
|
||||
return GrAtlasTextContext::Create(this, leakyProperties, enableDistanceFieldFonts);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -22,21 +22,18 @@
|
||||
#include "SkTextFormatParams.h"
|
||||
|
||||
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
|
||||
SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& properties)
|
||||
: GrTextContext(context, gpuDevice, properties)
|
||||
: GrTextContext(context, properties)
|
||||
, fStroke(SkStrokeRec::kFill_InitStyle)
|
||||
, fQueuedGlyphCount(0)
|
||||
, fFallbackGlyphsIdx(kGlyphBufferSize) {
|
||||
}
|
||||
|
||||
GrStencilAndCoverTextContext*
|
||||
GrStencilAndCoverTextContext::Create(GrContext* context, SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& props) {
|
||||
GrStencilAndCoverTextContext::Create(GrContext* context, const SkDeviceProperties& props) {
|
||||
GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext,
|
||||
(context, gpuDevice, props));
|
||||
textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, gpuDevice, props,
|
||||
false);
|
||||
(context, props));
|
||||
textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, props, false);
|
||||
|
||||
return textContext;
|
||||
}
|
||||
@ -74,7 +71,7 @@ bool GrStencilAndCoverTextContext::canDraw(const GrRenderTarget* rt,
|
||||
return rec.getFormat() != SkMask::kARGB32_Format;
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt,
|
||||
void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint,
|
||||
@ -157,17 +154,19 @@ void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt,
|
||||
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
|
||||
fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
|
||||
if (glyph.fWidth) {
|
||||
this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
|
||||
this->appendGlyph(drawContext, glyph,
|
||||
SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
|
||||
}
|
||||
|
||||
fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
|
||||
fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
|
||||
}
|
||||
|
||||
this->finish();
|
||||
this->finish(drawContext);
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt,
|
||||
void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* drawContext,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint,
|
||||
@ -211,12 +210,12 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt,
|
||||
SkPoint loc;
|
||||
alignProc(tmsLoc, glyph, &loc);
|
||||
|
||||
this->appendGlyph(glyph, loc);
|
||||
this->appendGlyph(drawContext, glyph, loc);
|
||||
}
|
||||
pos += scalarsPerPosition;
|
||||
}
|
||||
|
||||
this->finish();
|
||||
this->finish(drawContext);
|
||||
}
|
||||
|
||||
static GrPathRange* get_gr_glyphs(GrContext* ctx,
|
||||
@ -409,10 +408,11 @@ bool GrStencilAndCoverTextContext::mapToFallbackContext(SkMatrix* inverse) {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
|
||||
inline void GrStencilAndCoverTextContext::appendGlyph(GrDrawContext* drawContext,
|
||||
const SkGlyph& glyph, const SkPoint& pos) {
|
||||
if (fQueuedGlyphCount >= fFallbackGlyphsIdx) {
|
||||
SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx);
|
||||
this->flush();
|
||||
this->flush(drawContext);
|
||||
}
|
||||
|
||||
// Stick the glyphs we can't draw at the end of the buffer, growing backwards.
|
||||
@ -430,17 +430,12 @@ static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) {
|
||||
return &pointArray[0].fX;
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::flush() {
|
||||
void GrStencilAndCoverTextContext::flush(GrDrawContext* drawContext) {
|
||||
if (fQueuedGlyphCount > 0) {
|
||||
SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(),
|
||||
fViewMatrix,
|
||||
fLocalMatrix));
|
||||
|
||||
GrDrawContext* drawContext = fContext->drawContext();
|
||||
if (!drawContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
drawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
|
||||
fGlyphIndices, GrPathRange::kU16_PathIndexType,
|
||||
get_xy_scalar_array(fGlyphPositions),
|
||||
@ -477,8 +472,8 @@ void GrStencilAndCoverTextContext::flush() {
|
||||
}
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::finish() {
|
||||
this->flush();
|
||||
void GrStencilAndCoverTextContext::finish(GrDrawContext* drawContext) {
|
||||
this->flush(drawContext);
|
||||
|
||||
fGlyphs->unref();
|
||||
fGlyphs = NULL;
|
||||
|
@ -23,8 +23,7 @@ class GrPathRange;
|
||||
*/
|
||||
class GrStencilAndCoverTextContext : public GrTextContext {
|
||||
public:
|
||||
static GrStencilAndCoverTextContext* Create(GrContext*, SkGpuDevice*,
|
||||
const SkDeviceProperties&);
|
||||
static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&);
|
||||
|
||||
virtual ~GrStencilAndCoverTextContext();
|
||||
|
||||
@ -68,16 +67,16 @@ private:
|
||||
SkMatrix fLocalMatrix;
|
||||
bool fUsingDeviceSpaceGlyphs;
|
||||
|
||||
GrStencilAndCoverTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
|
||||
GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
|
||||
|
||||
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
const SkPaint&, const SkMatrix& viewMatrix) override;
|
||||
|
||||
void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
|
||||
void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
@ -87,9 +86,9 @@ private:
|
||||
size_t textByteLength, RenderMode, const SkMatrix& viewMatrix,
|
||||
const SkIRect& regionClipBounds);
|
||||
bool mapToFallbackContext(SkMatrix* inverse);
|
||||
void appendGlyph(const SkGlyph&, const SkPoint&);
|
||||
void flush();
|
||||
void finish();
|
||||
void appendGlyph(GrDrawContext*, const SkGlyph&, const SkPoint&);
|
||||
void flush(GrDrawContext*);
|
||||
void finish(GrDrawContext*);
|
||||
|
||||
};
|
||||
|
||||
|
@ -6,8 +6,9 @@
|
||||
*/
|
||||
|
||||
#include "GrTextContext.h"
|
||||
#include "GrBlurUtils.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrDrawTarget.h"
|
||||
#include "GrDrawContext.h"
|
||||
#include "GrFontScaler.h"
|
||||
|
||||
#include "SkAutoKern.h"
|
||||
@ -19,11 +20,9 @@
|
||||
#include "SkTextMapStateProc.h"
|
||||
#include "SkTextToPathIter.h"
|
||||
|
||||
GrTextContext::GrTextContext(GrContext* context, SkGpuDevice* gpuDevice,
|
||||
const SkDeviceProperties& properties)
|
||||
GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties)
|
||||
: fFallbackTextContext(NULL)
|
||||
, fContext(context)
|
||||
, fGpuDevice(gpuDevice)
|
||||
, fDeviceProperties(properties) {
|
||||
}
|
||||
|
||||
@ -52,19 +51,24 @@ void GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPai
|
||||
return;
|
||||
}
|
||||
|
||||
GrDrawContext* drawContext = fContext->drawContext();
|
||||
if (!drawContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrTextContext* textContext = this;
|
||||
do {
|
||||
if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
|
||||
textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, x, y,
|
||||
clipBounds);
|
||||
textContext->onDrawText(drawContext, rt, clip, paint, skPaint, viewMatrix,
|
||||
text, byteLength, x, y, clipBounds);
|
||||
return;
|
||||
}
|
||||
textContext = textContext->fFallbackTextContext;
|
||||
} while (textContext);
|
||||
|
||||
// fall back to drawing as a path
|
||||
SkASSERT(fGpuDevice);
|
||||
this->drawTextAsPath(skPaint, viewMatrix, text, byteLength, x, y, clipBounds);
|
||||
this->drawTextAsPath(drawContext, rt, clip, skPaint, viewMatrix,
|
||||
text, byteLength, x, y, clipBounds);
|
||||
}
|
||||
|
||||
void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint,
|
||||
@ -76,10 +80,16 @@ void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const Gr
|
||||
return;
|
||||
}
|
||||
|
||||
GrDrawContext* drawContext = fContext->drawContext();
|
||||
if (!drawContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrTextContext* textContext = this;
|
||||
do {
|
||||
if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
|
||||
textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, pos,
|
||||
textContext->onDrawPosText(drawContext, rt, clip, paint, skPaint, viewMatrix,
|
||||
text, byteLength, pos,
|
||||
scalarsPerPosition, offset, clipBounds);
|
||||
return;
|
||||
}
|
||||
@ -87,12 +97,12 @@ void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const Gr
|
||||
} while (textContext);
|
||||
|
||||
// fall back to drawing as a path
|
||||
SkASSERT(fGpuDevice);
|
||||
this->drawPosTextAsPath(skPaint, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset,
|
||||
clipBounds);
|
||||
this->drawPosTextAsPath(drawContext, rt, clip, skPaint, viewMatrix, text, byteLength, pos,
|
||||
scalarsPerPosition, offset, clipBounds);
|
||||
}
|
||||
|
||||
void GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const SkPaint& skPaint,
|
||||
void GrTextContext::drawTextBlob(SkGpuDevice* gpuDevice, GrRenderTarget* rt,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob* blob,
|
||||
SkScalar x, SkScalar y,
|
||||
SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
|
||||
@ -112,7 +122,7 @@ void GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const S
|
||||
continue;
|
||||
}
|
||||
|
||||
runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
|
||||
runPaint.setFlags(gpuDevice->filterTextFlags(runPaint));
|
||||
|
||||
GrPaint grPaint;
|
||||
if (!SkPaint2GrPaint(fContext, fRenderTarget, runPaint, viewMatrix, true, &grPaint)) {
|
||||
@ -143,7 +153,9 @@ void GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const S
|
||||
}
|
||||
}
|
||||
|
||||
void GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewMatrix,
|
||||
void GrTextContext::drawTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const SkPaint& skPaint, const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
||||
const SkIRect& clipBounds) {
|
||||
SkTextToPathIter iter(text, byteLength, skPaint, true);
|
||||
@ -159,13 +171,16 @@ void GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewM
|
||||
matrix.postTranslate(xpos - prevXPos, 0);
|
||||
if (iterPath) {
|
||||
const SkPaint& pnt = iter.getPaint();
|
||||
fGpuDevice->internalDrawPath(*iterPath, pnt, viewMatrix, &matrix, clipBounds, false);
|
||||
GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *iterPath,
|
||||
pnt, viewMatrix, &matrix, clipBounds, false);
|
||||
}
|
||||
prevXPos = xpos;
|
||||
}
|
||||
}
|
||||
|
||||
void GrTextContext::drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
void GrTextContext::drawPosTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& clipBounds) {
|
||||
@ -204,7 +219,8 @@ void GrTextContext::drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix&
|
||||
|
||||
matrix[SkMatrix::kMTransX] = loc.fX;
|
||||
matrix[SkMatrix::kMTransY] = loc.fY;
|
||||
fGpuDevice->internalDrawPath(*path, paint, viewMatrix, &matrix, clipBounds, false);
|
||||
GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *path, paint,
|
||||
viewMatrix, &matrix, clipBounds, false);
|
||||
}
|
||||
}
|
||||
pos += scalarsPerPosition;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
class GrClip;
|
||||
class GrContext;
|
||||
class GrDrawTarget;
|
||||
class GrDrawContext;
|
||||
class GrFontScaler;
|
||||
class SkDrawFilter;
|
||||
class SkGpuDevice;
|
||||
@ -37,18 +37,14 @@ public:
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& clipBounds);
|
||||
virtual void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
|
||||
virtual void drawTextBlob(SkGpuDevice*, GrRenderTarget*, const GrClip&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob*,
|
||||
SkScalar x, SkScalar y,
|
||||
SkDrawFilter*, const SkIRect& clipBounds);
|
||||
|
||||
protected:
|
||||
GrTextContext* fFallbackTextContext;
|
||||
GrContext* fContext;
|
||||
// TODO we probably don't really need to store a back pointer to the owning SkGpuDevice, except
|
||||
// we need to be able to call drawPath on it in the event no other text context can draw the
|
||||
// text. We might be able to move this logic to context though. This is unreffed because
|
||||
// GrTextContext is completely owned by SkGpuDevice
|
||||
SkGpuDevice* fGpuDevice;
|
||||
SkDeviceProperties fDeviceProperties;
|
||||
|
||||
SkAutoTUnref<GrRenderTarget> fRenderTarget;
|
||||
@ -58,24 +54,28 @@ protected:
|
||||
GrPaint fPaint;
|
||||
SkPaint fSkPaint;
|
||||
|
||||
GrTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
|
||||
GrTextContext(GrContext*, const SkDeviceProperties&);
|
||||
|
||||
virtual bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
const SkPaint&, const SkMatrix& viewMatrix) = 0;
|
||||
|
||||
virtual void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
virtual void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&,
|
||||
const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const char text[], size_t byteLength,
|
||||
SkScalar x, SkScalar y, const SkIRect& clipBounds) = 0;
|
||||
virtual void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||
virtual void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&,
|
||||
const GrPaint&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& clipBounds) = 0;
|
||||
|
||||
void drawTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
void drawTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
|
||||
const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
||||
const SkIRect& clipBounds);
|
||||
void drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
void drawPosTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
|
||||
const SkPaint& origPaint, const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& clipBounds);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "SkGpuDevice.h"
|
||||
|
||||
#include "GrBlurUtils.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrDrawContext.h"
|
||||
#include "GrGpu.h"
|
||||
@ -167,8 +168,7 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
|
||||
fLegacyBitmap.setPixelRef(pr)->unref();
|
||||
|
||||
bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
|
||||
fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(),
|
||||
useDFT);
|
||||
fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT);
|
||||
fDrawContext.reset(SkRef(fContext->drawContext()));
|
||||
}
|
||||
|
||||
@ -626,145 +626,13 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// helpers for applying mask filters
|
||||
namespace {
|
||||
|
||||
// Draw a mask using the supplied paint. Since the coverage/geometry
|
||||
// is already burnt into the mask this boils down to a rect draw.
|
||||
// Return true if the mask was successfully drawn.
|
||||
bool draw_mask(GrDrawContext* drawContext,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkRect& maskRect,
|
||||
GrPaint* grp,
|
||||
GrTexture* mask) {
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
||||
matrix.postIDiv(mask->width(), mask->height());
|
||||
|
||||
grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix,
|
||||
kDevice_GrCoordSet))->unref();
|
||||
|
||||
SkMatrix inverse;
|
||||
if (!viewMatrix.invert(&inverse)) {
|
||||
return false;
|
||||
}
|
||||
drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), maskRect, inverse);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& rect) {
|
||||
return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
|
||||
}
|
||||
|
||||
bool draw_with_mask_filter(GrDrawContext* drawContext,
|
||||
GrTextureProvider* textureProvider,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clipData,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkPath& devPath,
|
||||
SkMaskFilter* filter,
|
||||
const SkIRect& clipBounds,
|
||||
GrPaint* grp,
|
||||
SkPaint::Style style) {
|
||||
SkMask srcM, dstM;
|
||||
|
||||
if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
|
||||
SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
|
||||
return false;
|
||||
}
|
||||
SkAutoMaskFreeImage autoSrc(srcM.fImage);
|
||||
|
||||
if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) {
|
||||
return false;
|
||||
}
|
||||
// this will free-up dstM when we're done (allocated in filterMask())
|
||||
SkAutoMaskFreeImage autoDst(dstM.fImage);
|
||||
|
||||
if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we now have a device-aligned 8bit mask in dstM, ready to be drawn using
|
||||
// the current clip (and identity matrix) and GrPaint settings
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = dstM.fBounds.width();
|
||||
desc.fHeight = dstM.fBounds.height();
|
||||
desc.fConfig = kAlpha_8_GrPixelConfig;
|
||||
|
||||
SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture(
|
||||
desc, GrTextureProvider::kApprox_ScratchTexMatch));
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
|
||||
dstM.fImage, dstM.fRowBytes);
|
||||
|
||||
SkRect maskRect = SkRect::Make(dstM.fBounds);
|
||||
|
||||
return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, texture);
|
||||
}
|
||||
|
||||
// Create a mask of 'devPath' and place the result in 'mask'.
|
||||
GrTexture* create_mask_GPU(GrContext* context,
|
||||
const SkRect& maskRect,
|
||||
const SkPath& devPath,
|
||||
const GrStrokeInfo& strokeInfo,
|
||||
bool doAA,
|
||||
int sampleCnt) {
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
desc.fWidth = SkScalarCeilToInt(maskRect.width());
|
||||
desc.fHeight = SkScalarCeilToInt(maskRect.height());
|
||||
desc.fSampleCnt = doAA ? sampleCnt : 0;
|
||||
// We actually only need A8, but it often isn't supported as a
|
||||
// render target so default to RGBA_8888
|
||||
desc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
|
||||
if (context->isConfigRenderable(kAlpha_8_GrPixelConfig,
|
||||
desc.fSampleCnt > 0)) {
|
||||
desc.fConfig = kAlpha_8_GrPixelConfig;
|
||||
}
|
||||
|
||||
GrTexture* mask = context->textureProvider()->refScratchTexture(
|
||||
desc, GrTextureProvider::kApprox_ScratchTexMatch);
|
||||
if (NULL == mask) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
|
||||
|
||||
GrDrawContext* drawContext = context->drawContext();
|
||||
if (!drawContext) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true);
|
||||
|
||||
GrPaint tempPaint;
|
||||
tempPaint.setAntiAlias(doAA);
|
||||
tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
|
||||
|
||||
// setup new clip
|
||||
GrClip clip(clipRect);
|
||||
|
||||
// Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
|
||||
SkMatrix translate;
|
||||
translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
|
||||
drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
|
||||
return mask;
|
||||
}
|
||||
|
||||
SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
|
||||
static SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
|
||||
SkBitmap result;
|
||||
result.setInfo(SkImageInfo::MakeN32Premul(width, height));
|
||||
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) {
|
||||
@ -772,150 +640,10 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
CHECK_SHOULD_DRAW(draw);
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext);
|
||||
|
||||
return this->internalDrawPath(origSrcPath, paint, *draw.fMatrix, prePathMatrix,
|
||||
draw.fClip->getBounds(), pathIsMutable);
|
||||
}
|
||||
|
||||
void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& paint,
|
||||
const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix,
|
||||
const SkIRect& clipBounds, bool pathIsMutable) {
|
||||
SkASSERT(!pathIsMutable || origSrcPath.isVolatile());
|
||||
|
||||
GrStrokeInfo strokeInfo(paint);
|
||||
|
||||
// If we have a prematrix, apply it to the path, optimizing for the case
|
||||
// where the original path can in fact be modified in place (even though
|
||||
// its parameter type is const).
|
||||
SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
|
||||
SkTLazy<SkPath> tmpPath;
|
||||
SkTLazy<SkPath> effectPath;
|
||||
SkPathEffect* pathEffect = paint.getPathEffect();
|
||||
|
||||
SkMatrix viewMatrix = origViewMatrix;
|
||||
|
||||
if (prePathMatrix) {
|
||||
// stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix.
|
||||
// The pre-path-matrix also should not affect shading.
|
||||
if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint.getShader() &&
|
||||
(strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) {
|
||||
viewMatrix.preConcat(*prePathMatrix);
|
||||
} else {
|
||||
SkPath* result = pathPtr;
|
||||
|
||||
if (!pathIsMutable) {
|
||||
result = tmpPath.init();
|
||||
result->setIsVolatile(true);
|
||||
pathIsMutable = true;
|
||||
}
|
||||
// should I push prePathMatrix on our MV stack temporarily, instead
|
||||
// of applying it here? See SkDraw.cpp
|
||||
pathPtr->transform(*prePathMatrix, result);
|
||||
pathPtr = result;
|
||||
}
|
||||
}
|
||||
// at this point we're done with prePathMatrix
|
||||
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
||||
|
||||
GrPaint grPaint;
|
||||
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, viewMatrix, true, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SkRect* cullRect = NULL; // TODO: what is our bounds?
|
||||
if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr,
|
||||
&strokeInfo, cullRect)) {
|
||||
pathPtr = effectPath.get();
|
||||
pathIsMutable = true;
|
||||
}
|
||||
|
||||
if (paint.getMaskFilter()) {
|
||||
if (!strokeInfo.isHairlineStyle()) {
|
||||
SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
|
||||
if (strokeInfo.isDashed()) {
|
||||
if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, cullRect)) {
|
||||
pathPtr = strokedPath;
|
||||
pathIsMutable = true;
|
||||
}
|
||||
strokeInfo.removeDash();
|
||||
}
|
||||
if (strokeInfo.applyToPath(strokedPath, *pathPtr)) {
|
||||
pathPtr = strokedPath;
|
||||
pathIsMutable = true;
|
||||
strokeInfo.setFillStyle();
|
||||
}
|
||||
}
|
||||
|
||||
// avoid possibly allocating a new path in transform if we can
|
||||
SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
|
||||
if (!pathIsMutable) {
|
||||
devPathPtr->setIsVolatile(true);
|
||||
}
|
||||
|
||||
// transform the path into device space
|
||||
pathPtr->transform(viewMatrix, devPathPtr);
|
||||
|
||||
SkRect maskRect;
|
||||
if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
|
||||
clipBounds,
|
||||
viewMatrix,
|
||||
&maskRect)) {
|
||||
SkIRect finalIRect;
|
||||
maskRect.roundOut(&finalIRect);
|
||||
if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
|
||||
// clipped out
|
||||
return;
|
||||
}
|
||||
|
||||
if (paint.getMaskFilter()->directFilterMaskGPU(fContext,
|
||||
fRenderTarget,
|
||||
&grPaint,
|
||||
fClip,
|
||||
viewMatrix,
|
||||
strokeInfo,
|
||||
*devPathPtr)) {
|
||||
// the mask filter was able to draw itself directly, so there's nothing
|
||||
// left to do.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext,
|
||||
maskRect,
|
||||
*devPathPtr,
|
||||
strokeInfo,
|
||||
grPaint.isAntiAlias(),
|
||||
fRenderTarget->numSamples()));
|
||||
if (mask) {
|
||||
GrTexture* filtered;
|
||||
|
||||
if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect, &filtered, true)) {
|
||||
// filterMaskGPU gives us ownership of a ref to the result
|
||||
SkAutoTUnref<GrTexture> atu(filtered);
|
||||
if (draw_mask(fDrawContext,
|
||||
fRenderTarget,
|
||||
fClip,
|
||||
viewMatrix,
|
||||
maskRect,
|
||||
&grPaint,
|
||||
filtered)) {
|
||||
// This path is completely drawn
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw the mask on the CPU - this is a fallthrough path in case the
|
||||
// GPU path fails
|
||||
SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style :
|
||||
SkPaint::kFill_Style;
|
||||
draw_with_mask_filter(fDrawContext, fContext->textureProvider(), fRenderTarget,
|
||||
fClip, viewMatrix, *devPathPtr,
|
||||
paint.getMaskFilter(), clipBounds, &grPaint, style);
|
||||
return;
|
||||
}
|
||||
|
||||
fDrawContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr, strokeInfo);
|
||||
GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, fRenderTarget,
|
||||
fClip, origSrcPath, paint,
|
||||
*draw.fMatrix, prePathMatrix,
|
||||
draw.fClip->getBounds(), pathIsMutable);
|
||||
}
|
||||
|
||||
static const int kBmpSmallTileSize = 1 << 10;
|
||||
@ -1931,8 +1659,8 @@ void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSca
|
||||
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix, blob, x, y, drawFilter,
|
||||
draw.fClip->getBounds());
|
||||
fTextContext->drawTextBlob(this, fRenderTarget, fClip, paint, *draw.fMatrix,
|
||||
blob, x, y, drawFilter, draw.fClip->getBounds());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -212,10 +212,6 @@ private:
|
||||
int tileSize,
|
||||
bool bicubic);
|
||||
|
||||
void internalDrawPath(const SkPath& origSrcPath, const SkPaint& paint,
|
||||
const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix,
|
||||
const SkIRect& clipBounds, bool pathIsMutable);
|
||||
|
||||
bool drawDashLine(const SkPoint pts[2], const SkPaint& paint);
|
||||
|
||||
static GrRenderTarget* CreateRenderTarget(GrContext*, SkSurface::Budgeted, const SkImageInfo&,
|
||||
|
Loading…
Reference in New Issue
Block a user