bool GrStencilAndCoverTextContext::canDraw(const GrRenderTarget* rt,
                                           const GrClip& clip,
                                           const GrPaint& paint,
                                           const SkPaint& skPaint,
                                           const SkMatrix& viewMatrix) {
    if (skPaint.getRasterizer()) {
        return false;
    }
    if (skPaint.getMaskFilter()) {
        return false;
    }
    if (SkPathEffect* pe = skPaint.getPathEffect()) {
        if (pe->asADash(NULL) != SkPathEffect::kDash_DashType) {
            return false;
        }
    }

    // No hairlines unless we can map the 1 px width to the object space.
    if (skPaint.getStyle() == SkPaint::kStroke_Style
        && skPaint.getStrokeWidth() == 0
        && viewMatrix.hasPerspective()) {
        return false;
    }

    // No color bitmap fonts.
    SkScalerContext::Rec    rec;
    SkScalerContext::MakeRec(skPaint, &fDeviceProperties, NULL, &rec);
    return rec.getFormat() != SkMask::kARGB32_Format;
}
void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrRenderTargetContext* rtc,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkSurfaceProps& props,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);

    TextBlob::Iter iter(blob);
    for (TextRun *run = iter.get(), *nextRun; run; run = nextRun) {
        nextRun = iter.next();
        run->draw(context, rtc, clip, viewMatrix, props, x, y, clipBounds, fFallbackTextContext,
                  skPaint);
        run->releaseGlyphCache();
    }
}
Example #3
0
static void apply_paint_patheffect(const SkPaint& paint, Json::Value* target, bool sendBinaries) {
    SkPathEffect* pathEffect = paint.getPathEffect();
    if (pathEffect != nullptr) {
        SkPathEffect::DashInfo dashInfo;
        SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
        if (dashType == SkPathEffect::kDash_DashType) {
            dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
            pathEffect->asADash(&dashInfo);
            Json::Value dashing(Json::objectValue);
            Json::Value intervals(Json::arrayValue);
            for (int32_t i = 0; i < dashInfo.fCount; i++) {
                intervals.append(Json::Value(dashInfo.fIntervals[i]));
            }
            free(dashInfo.fIntervals);
            dashing[SKJSONCANVAS_ATTRIBUTE_INTERVALS] = intervals;
            dashing[SKJSONCANVAS_ATTRIBUTE_PHASE] = dashInfo.fPhase;
            (*target)[SKJSONCANVAS_ATTRIBUTE_DASHING] = dashing;
        }
        else {
            Json::Value jsonPathEffect;
            flatten(pathEffect, &jsonPathEffect, sendBinaries);
            (*target)[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT] = jsonPathEffect;
        }
    }
}
Example #4
0
bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
    return !SkXfermode::AsMode(paint.getXfermode(), nullptr) ||
           paint.getMaskFilter() ||
           paint.getRasterizer() ||
           paint.getPathEffect() ||
           paint.isFakeBoldText() ||
           paint.getStyle() != SkPaint::kFill_Style;
}
Example #5
0
void SkBaseDevice::drawArc(const SkDraw& draw, const SkRect& oval, SkScalar startAngle,
                           SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
    SkPath path;
    bool isFillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect();
    SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
                                  isFillNoPathEffect);
    this->drawPath(draw, path, paint);
}
Example #6
0
static bool fold_opacity_layer_color_to_paint(const SkPaint& layerPaint,
                                              bool isSaveLayer,
                                              SkPaint* paint) {
    // We assume layerPaint is always from a saveLayer.  If isSaveLayer is
    // true, we assume paint is too.

    // The alpha folding can proceed if the filter layer paint does not have properties which cause
    // the resulting filter layer to be "blended" in complex ways to the parent layer. For example,
    // looper drawing unmodulated filter layer twice and then modulating the result produces
    // different image to drawing modulated filter layer twice.
    // TODO: most likely the looper and only some xfer modes are the hard constraints
    if (paint->getXfermode() || paint->getLooper()) {
        return false;
    }

    if (!isSaveLayer && paint->getImageFilter()) {
        // For normal draws, the paint color is used as one input for the color for the draw. Image
        // filter will operate on the result, and thus we can not change the input.
        // For layer saves, the image filter is applied to the layer contents. The layer is then
        // modulated with the paint color, so it's fine to proceed with the fold for saveLayer
        // paints with image filters.
        return false;
    }

    if (paint->getColorFilter()) {
        // Filter input depends on the paint color.

        // Here we could filter the color if we knew the draw is going to be uniform color.  This
        // should be detectable as drawPath/drawRect/.. without a shader being uniform, while
        // drawBitmap/drawSprite or a shader being non-uniform. However, current matchers don't
        // give the type out easily, so just do not optimize that at the moment.
        return false;
    }

    const uint32_t layerColor = layerPaint.getColor();
    // The layer paint color must have only alpha component.
    if (SK_ColorTRANSPARENT != SkColorSetA(layerColor, SK_AlphaTRANSPARENT)) {
        return false;
    }

    // The layer paint can not have any effects.
    if (layerPaint.getPathEffect() ||
        layerPaint.getShader()      ||
        layerPaint.getXfermode()    ||
        layerPaint.getMaskFilter()  ||
        layerPaint.getColorFilter() ||
        layerPaint.getRasterizer()  ||
        layerPaint.getLooper()      ||
        layerPaint.getImageFilter()) {
        return false;
    }

    paint->setAlpha(SkMulDiv255Round(paint->getAlpha(), SkColorGetA(layerColor)));

    return true;
}
// Is the supplied paint simply a color?
static bool is_simple(const SkPaint& p) {
    return NULL == p.getPathEffect() &&
           NULL == p.getShader() &&
           NULL == p.getXfermode() &&
           NULL == p.getMaskFilter() &&
           NULL == p.getColorFilter() &&
           NULL == p.getRasterizer() &&
           NULL == p.getLooper() &&
           NULL == p.getImageFilter();
}
Example #8
0
 static bool HasAnyEffect(const SkPaint& paint) {
     return paint.getPathEffect()  ||
            paint.getShader()      ||
            paint.getXfermode()    ||
            paint.getMaskFilter()  ||
            paint.getColorFilter() ||
            paint.getRasterizer()  ||
            paint.getLooper()      ||
            paint.getImageFilter();
 }
Example #9
0
bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
    if (kN32_SkColorType != fBitmap.colorType() ||
        paint.getRasterizer() ||
        paint.getPathEffect() ||
        paint.isFakeBoldText() ||
        paint.getStyle() != SkPaint::kFill_Style ||
        !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode))
    {
        return true;
    }
    return false;
}
Example #10
0
void GrTextUtils::DrawPosTextAsPath(GrContext* context,
                                    GrDrawContext* dc,
                                    const SkSurfaceProps& props,
                                    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) {
    // setup our std paint, in hopes of getting hits in the cache
    SkPaint paint(origPaint);
    SkScalar matrixScale = paint.setupForAsPaths();

    SkMatrix matrix;
    matrix.setScale(matrixScale, matrixScale);

    // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
    paint.setStyle(SkPaint::kFill_Style);
    paint.setPathEffect(nullptr);

    SkPaint::GlyphCacheProc    glyphCacheProc = paint.getGlyphCacheProc(true);
    SkAutoGlyphCache           autoCache(paint, &props, nullptr);
    SkGlyphCache*              cache = autoCache.getCache();

    const char*        stop = text + byteLength;
    SkTextAlignProc    alignProc(paint.getTextAlign());
    SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);

    // Now restore the original settings, so we "draw" with whatever style/stroking.
    paint.setStyle(origPaint.getStyle());
    paint.setPathEffect(origPaint.getPathEffect());

    while (text < stop) {
        const SkGlyph& glyph = glyphCacheProc(cache, &text);
        if (glyph.fWidth) {
            const SkPath* path = cache->findPath(glyph);
            if (path) {
                SkPoint tmsLoc;
                tmsProc(pos, &tmsLoc);
                SkPoint loc;
                alignProc(tmsLoc, glyph, &loc);

                matrix[SkMatrix::kMTransX] = loc.fX;
                matrix[SkMatrix::kMTransY] = loc.fY;
                GrBlurUtils::drawPathWithMaskFilter(context, dc, clip, *path, paint,
                                                    viewMatrix, &matrix, clipBounds, false);
            }
        }
        pos += scalarsPerPosition;
    }
}
Example #11
0
static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
    // kRespectsStroke_PaintUsage is only valid if other bits are also set
    SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage));

    const SkScalar kTextSize_Default    = 12;
    const SkScalar kTextScaleX_Default  = 1;
    const SkScalar kTextSkewX_Default   = 0;
    const SkScalar kStrokeWidth_Default = 0;
    const SkScalar kStrokeMiter_Default = 4;
    const SkColor  kColor_Default       = SK_ColorBLACK;

    unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;

    if (usage & kText_PaintUsage) {
        bits |= (paint.getTextSize() != kTextSize_Default       ? kTextSize_NonDef : 0);
        bits |= (paint.getTextScaleX() != kTextScaleX_Default   ? kTextScaleX_NonDef : 0);
        bits |= (paint.getTextSkewX() != kTextSkewX_Default     ? kTextSkewX_NonDef : 0);
        bits |= (paint.getTypeface()                            ? kTypeface_NonDef : 0);
    }

    // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8

    if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage |
                 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
        bits |= (paint.getShader()      ? kShader_NonDef : 0);
    }

    if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
        bits |= (paint.getPathEffect()  ? kPathEffect_NonDef : 0);
        bits |= (paint.getRasterizer()  ? kRasterizer_NonDef : 0);

        if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) {
            bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0);
            bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0);
        }
    }

    if (usage &
        (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage))
    {
        bits |= (paint.getMaskFilter()  ? kMaskFilter_NonDef : 0);
    }

    bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
    bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
    bits |= (paint.getDrawLooper()  ? kDrawLooper_NonDef : 0);

    return SkToU16(bits);
}
bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) {
    if (skPaint.getRasterizer()) {
        return false;
    }
    if (skPaint.getMaskFilter()) {
        return false;
    }
    if (SkPathEffect* pe = skPaint.getPathEffect()) {
        if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) {
            return false;
        }
    }
    // No hairlines. They would require new paths with customized strokes for every new draw matrix.
    return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth();
}
Example #13
0
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
                                         GrDrawContext* drawContext,
                                         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);
    // comment out the line below to determine if it is the reason that the chrome mac perf bot
    // has begun crashing
    // strokeInfo.setResScale(SkDraw::ComputeResScaleForStroking(origViewMatrix));

    // 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 (!paint.getMaskFilter() && !pathEffect && !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;)
Example #14
0
void SkBaseDevice::drawRegion(const SkDraw& draw, const SkRegion& region, const SkPaint& paint) {
    bool isNonTranslate = draw.fMatrix->getType() & ~(SkMatrix::kTranslate_Mask);
    bool complexPaint = paint.getStyle() != SkPaint::kFill_Style || paint.getMaskFilter() ||
                        paint.getPathEffect();
    bool antiAlias = paint.isAntiAlias() && (!is_int(draw.fMatrix->getTranslateX()) ||
                                             !is_int(draw.fMatrix->getTranslateY()));
    if (isNonTranslate || complexPaint || antiAlias) {
        SkPath path;
        region.getBoundaryPath(&path);
        return this->drawPath(draw, path, paint, nullptr, false);
    }

    SkRegion::Iterator it(region);
    while (!it.done()) {
        this->drawRect(draw, SkRect::Make(it.rect()), paint);
        it.next();
    }
}
static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer)
{
    buffer.writeBool(paint.isAntiAlias());
    buffer.write8(paint.getStyle());
    buffer.write8(paint.getAlpha());
    
    if (paint.getStyle() != SkPaint::kFill_Style)
    {
        buffer.writeScalar(paint.getStrokeWidth());
        buffer.writeScalar(paint.getStrokeMiter());
        buffer.write8(paint.getStrokeCap());
        buffer.write8(paint.getStrokeJoin());
    }
    
    buffer.writeFlattenable(paint.getMaskFilter());
    buffer.writeFlattenable(paint.getPathEffect());
    buffer.writeFlattenable(paint.getRasterizer());
    buffer.writeFlattenable(paint.getXfermode());
}
Example #16
0
void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path,
                           const SkPaint& paint, const SkMatrix* prePathMatrix,
                           bool pathIsMutable) {
    NOT_IMPLEMENTED(prePathMatrix != NULL, true);

    if (paint.getPathEffect()) {
        // Apply the path effect to path and draw it that way.
        SkPath noEffectPath;
        paint.getFillPath(path, &noEffectPath);

        SkPaint noEffectPaint(paint);
        SkSafeUnref(noEffectPaint.setPathEffect(NULL));
        drawPath(d, noEffectPath, noEffectPaint, NULL, true);
        return;
    }
    updateGSFromPaint(paint, false);

    SkPDFUtils::EmitPath(path, &fContent);
    SkPDFUtils::PaintPath(paint.getStyle(), path.getFillType(), &fContent);
}
Example #17
0
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
    if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
        // we're cool with the paint as is
        return false;
    }

    if (kN32_SkColorType != fBitmap.colorType() ||
        paint.getRasterizer() ||
        paint.getPathEffect() ||
        paint.isFakeBoldText() ||
        paint.getStyle() != SkPaint::kFill_Style ||
        !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
        // turn off lcd
        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
        flags->fHinting = paint.getHinting();
        return true;
    }
    // we're cool with the paint as is
    return false;
}
void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkSurfaceProps& props,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    GrPaint paint;
    if (!SkPaintToGrPaint(context, dc, skPaint, viewMatrix, &paint)) {
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);

    TextBlob::Iter iter(blob);
    for (TextRun* run = iter.get(); run; run = iter.next()) {
        // The run's "font" overrides the anti-aliasing of the passed in paint!
        paint.setAntiAlias(run->isAntiAlias());
        run->draw(context, dc, paint, clip, viewMatrix, props,  x, y,
                  clipBounds, fFallbackTextContext, skPaint);
        run->releaseGlyphCache();
    }
}
Example #19
0
void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r,
                           const SkPaint& paint) {
    if (paint.getPathEffect()) {
        // Create a path for the rectangle and apply the path effect to it.
        SkPath path;
        path.addRect(r);
        paint.getFillPath(path, &path);

        SkPaint noEffectPaint(paint);
        SkSafeUnref(noEffectPaint.setPathEffect(NULL));
        drawPath(d, path, noEffectPaint, NULL, true);
        return;
    }
    updateGSFromPaint(paint, false);

    // Skia has 0,0 at top left, pdf at bottom left.  Do the right thing.
    SkScalar bottom = r.fBottom < r.fTop ? r.fBottom : r.fTop;
    SkPDFUtils::AppendRectangle(r.fLeft, bottom, r.width(), r.height(),
                                &fContent);
    SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
                          &fContent);
}
void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkSurfaceProps& props,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    GrPaint paint;
    if (!SkPaintToGrPaint(context, skPaint, viewMatrix, dc->isGammaCorrect(), &paint)) {
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
    GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);

    TextBlob::Iter iter(blob);
    for (TextRun* run = iter.get(); run; run = iter.next()) {
        run->draw(context, dc, &pipelineBuilder, paint.getColor(), viewMatrix, props,  x, y,
                  clipBounds, fFallbackTextContext, skPaint);
        run->releaseGlyphCache();
    }
}
bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) {
    if (paint.getRasterizer()) {
        return false;
    }
    if (paint.getMaskFilter()) {
        return false;
    }
    if (paint.getPathEffect()) {
        return false;
    }

    // No hairlines unless we can map the 1 px width to the object space.
    if (paint.getStyle() == SkPaint::kStroke_Style
        && paint.getStrokeWidth() == 0
        && fContext->getMatrix().hasPerspective()) {
        return false;
    }

    // No color bitmap fonts.
    SkScalerContext::Rec    rec;
    SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
    return rec.getFormat() != SkMask::kARGB32_Format;
}
Example #22
0
bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
    if (!paint.isLCDRenderText()) {
        // we're cool with the paint as is
        return false;
    }

    if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
        paint.getShader() ||
        paint.getXfermode() || // unless its srcover
        paint.getMaskFilter() ||
        paint.getRasterizer() ||
        paint.getColorFilter() ||
        paint.getPathEffect() ||
        paint.isFakeBoldText() ||
        paint.getStyle() != SkPaint::kFill_Style) {
        // turn off lcd
        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
        flags->fHinting = paint.getHinting();
        return true;
    }
    // we're cool with the paint as is
    return false;
}
void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarget* rt,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(dc, rt, clip, skPaint, viewMatrix, skBlob, x, y,
                                           drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        INHERITED::drawTextBlob(dc, rt, clip, skPaint, viewMatrix, skBlob, x, y, drawFilter,
                                clipBounds);
        return;
    }

    if (fContext->abandoned()) {
        return;
    }

    GrPaint paint;
    if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) {
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
    GrPipelineBuilder pipelineBuilder(paint, rt, clip);

    TextBlob::Iter iter(blob);
    for (TextRun* run = iter.get(); run; run = iter.next()) {
        run->draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clipBounds,
                  fFallbackTextContext, skPaint);
    }
}
Example #24
0
void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
    SkASSERT(paint.getPathEffect() == NULL);

    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
    NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);

    SkPaint newPaint = paint;

    // PDF treats a shader as a color, so we only set one or the other.
    SkRefPtr<SkPDFShader> pdfShader;
    const SkShader* shader = newPaint.getShader();
    if (shader) {
        // PDF positions patterns relative to the initial transform, so
        // we need to apply the current transform to the shader parameters.
        SkMatrix transform = fGraphicStack[fGraphicStackIndex].fTransform;
        if (fFlipOrigin == kFlip_OriginTransform) {
            transform.postScale(1, -1);
            transform.postTranslate(0, fHeight);
        }

        // PDF doesn't support kClamp_TileMode, so we simulate it by making
        // a pattern the size of the drawing service.
        SkIRect bounds = fGraphicStack[fGraphicStackIndex].fClip.getBounds();
        pdfShader = SkPDFShader::getPDFShader(*shader, transform, bounds);
        SkSafeUnref(pdfShader.get());  // getShader and SkRefPtr both took a ref

        // A color shader is treated as an invalid shader so we don't have
        // to set a shader just for a color.
        if (pdfShader.get() == NULL) {
            newPaint.setColor(0);

            // Check for a color shader.
            SkShader::GradientInfo gradientInfo;
            SkColor gradientColor;
            gradientInfo.fColors = &gradientColor;
            gradientInfo.fColorOffsets = NULL;
            gradientInfo.fColorCount = 1;
            if (shader->asAGradient(&gradientInfo) ==
                    SkShader::kColor_GradientType) {
                newPaint.setColor(gradientColor);
            }
        }
    }

    if (pdfShader) {
        // pdfShader has been canonicalized so we can directly compare
        // pointers.
        if (fGraphicStack[fGraphicStackIndex].fShader != pdfShader.get()) {
            int resourceIndex = fShaderResources.find(pdfShader.get());
            if (resourceIndex < 0) {
                resourceIndex = fShaderResources.count();
                fShaderResources.push(pdfShader.get());
                pdfShader->ref();
            }
            fContent.writeText("/Pattern CS /Pattern cs /P");
            fContent.writeDecAsText(resourceIndex);
            fContent.writeText(" SCN /P");
            fContent.writeDecAsText(resourceIndex);
            fContent.writeText(" scn\n");
            fGraphicStack[fGraphicStackIndex].fShader = pdfShader.get();
        }
    } else {
        SkColor newColor = newPaint.getColor();
        newColor = SkColorSetA(newColor, 0xFF);
        if (fGraphicStack[fGraphicStackIndex].fShader ||
                fGraphicStack[fGraphicStackIndex].fColor != newColor) {
            emitPDFColor(newColor, &fContent);
            fContent.writeText("RG ");
            emitPDFColor(newColor, &fContent);
            fContent.writeText("rg\n");
            fGraphicStack[fGraphicStackIndex].fColor = newColor;
            fGraphicStack[fGraphicStackIndex].fShader = NULL;
        }
    }

    SkRefPtr<SkPDFGraphicState> newGraphicState =
        SkPDFGraphicState::getGraphicStateForPaint(newPaint);
    newGraphicState->unref();  // getGraphicState and SkRefPtr both took a ref.
    // newGraphicState has been canonicalized so we can directly compare
    // pointers.
    if (fGraphicStack[fGraphicStackIndex].fGraphicState !=
            newGraphicState.get()) {
        int resourceIndex = fGraphicStateResources.find(newGraphicState.get());
        if (resourceIndex < 0) {
            resourceIndex = fGraphicStateResources.count();
            fGraphicStateResources.push(newGraphicState.get());
            newGraphicState->ref();
        }
        fContent.writeText("/G");
        fContent.writeDecAsText(resourceIndex);
        fContent.writeText(" gs\n");
        fGraphicStack[fGraphicStackIndex].fGraphicState = newGraphicState.get();
    }

    if (forText) {
        if (fGraphicStack[fGraphicStackIndex].fTextScaleX !=
                newPaint.getTextScaleX()) {
            SkScalar scale = newPaint.getTextScaleX();
            SkScalar pdfScale = SkScalarMul(scale, SkIntToScalar(100));
            SkPDFScalar::Append(pdfScale, &fContent);
            fContent.writeText(" Tz\n");
            fGraphicStack[fGraphicStackIndex].fTextScaleX = scale;
        }

        if (fGraphicStack[fGraphicStackIndex].fTextFill !=
                newPaint.getStyle()) {
            SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
            SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
                              enum_must_match_value);
            SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
                              enum_must_match_value);
            fContent.writeDecAsText(newPaint.getStyle());
            fContent.writeText(" Tr\n");
            fGraphicStack[fGraphicStackIndex].fTextFill = newPaint.getStyle();
        }
    }
}
Example #25
0
void SkFlatPaint::dump() const {
    SkPaint defaultPaint;
    SkFlattenableReadBuffer buffer(fPaintData);
    SkTypeface* typeface = (SkTypeface*) buffer.readPtr();
    char pBuffer[DUMP_BUFFER_SIZE];
    char* bufferPtr = pBuffer;
    bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
        "paint: ");
    if (typeface != defaultPaint.getTypeface())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "typeface:%p ", typeface);
    SkScalar textSize = buffer.readScalar();
    if (textSize != defaultPaint.getTextSize())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textSize:%g ", SkScalarToFloat(textSize));
    SkScalar textScaleX = buffer.readScalar();
    if (textScaleX != defaultPaint.getTextScaleX())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textScaleX:%g ", SkScalarToFloat(textScaleX));
    SkScalar textSkewX = buffer.readScalar();
    if (textSkewX != defaultPaint.getTextSkewX())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textSkewX:%g ", SkScalarToFloat(textSkewX));
    const SkPathEffect* pathEffect = (const SkPathEffect*) buffer.readFlattenable();
    if (pathEffect != defaultPaint.getPathEffect())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "pathEffect:%p ", pathEffect);
    SkDELETE(pathEffect);
    const SkShader* shader = (const SkShader*) buffer.readFlattenable();
    if (shader != defaultPaint.getShader())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "shader:%p ", shader);
    SkDELETE(shader);
    const SkXfermode* xfermode = (const SkXfermode*) buffer.readFlattenable();
    if (xfermode != defaultPaint.getXfermode())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "xfermode:%p ", xfermode);
    SkDELETE(xfermode);
    const SkMaskFilter* maskFilter = (const SkMaskFilter*) buffer.readFlattenable();
    if (maskFilter != defaultPaint.getMaskFilter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "maskFilter:%p ", maskFilter);
    SkDELETE(maskFilter);
    const SkColorFilter* colorFilter = (const SkColorFilter*) buffer.readFlattenable();
    if (colorFilter != defaultPaint.getColorFilter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "colorFilter:%p ", colorFilter);
    SkDELETE(colorFilter);
    const SkRasterizer* rasterizer = (const SkRasterizer*) buffer.readFlattenable();
    if (rasterizer != defaultPaint.getRasterizer())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "rasterizer:%p ", rasterizer);
    SkDELETE(rasterizer);
    const SkDrawLooper* drawLooper = (const SkDrawLooper*) buffer.readFlattenable();
    if (drawLooper != defaultPaint.getLooper())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "drawLooper:%p ", drawLooper);
    SkDELETE(drawLooper);
    unsigned color = buffer.readU32();
    if (color != defaultPaint.getColor())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "color:0x%x ", color);
    SkScalar strokeWidth = buffer.readScalar();
    if (strokeWidth != defaultPaint.getStrokeWidth())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeWidth:%g ", SkScalarToFloat(strokeWidth));
    SkScalar strokeMiter = buffer.readScalar();
    if (strokeMiter != defaultPaint.getStrokeMiter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeMiter:%g ", SkScalarToFloat(strokeMiter));
    unsigned flags = buffer.readU16();
    if (flags != defaultPaint.getFlags())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "flags:0x%x ", flags);
    int align = buffer.readU8();
    if (align != defaultPaint.getTextAlign())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "align:0x%x ", align);
    int strokeCap = buffer.readU8();
    if (strokeCap != defaultPaint.getStrokeCap())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeCap:0x%x ", strokeCap);
    int strokeJoin = buffer.readU8();
    if (strokeJoin != defaultPaint.getStrokeJoin())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "align:0x%x ", strokeJoin);
    int style = buffer.readU8();
    if (style != defaultPaint.getStyle())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "style:0x%x ", style);
    int textEncoding = buffer.readU8();
    if (textEncoding != defaultPaint.getTextEncoding())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textEncoding:0x%x ", textEncoding);
    SkDebugf("%s\n", pBuffer);
}
Example #26
0
// Even with kEntirePaint_Bits, we always ensure that the master paint's
// text-encoding is respected, since that controls how we interpret the
// text/length parameters of a draw[Pos]Text call.
void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
                                  const LayerInfo& info) {

    uint32_t mask = info.fFlagsMask;
    dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
    dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));

    BitFlags bits = info.fPaintBits;
    SkPaint::TextEncoding encoding = dst->getTextEncoding();

    if (0 == bits) {
        return;
    }
    if (kEntirePaint_Bits == bits) {
        // we've already computed these, so save it from the assignment
        uint32_t f = dst->getFlags();
        SkColor c = dst->getColor();
        *dst = src;
        dst->setFlags(f);
        dst->setColor(c);
        dst->setTextEncoding(encoding);
        return;
    }

    if (bits & kStyle_Bit) {
        dst->setStyle(src.getStyle());
        dst->setStrokeWidth(src.getStrokeWidth());
        dst->setStrokeMiter(src.getStrokeMiter());
        dst->setStrokeCap(src.getStrokeCap());
        dst->setStrokeJoin(src.getStrokeJoin());
    }

    if (bits & kTextSkewX_Bit) {
        dst->setTextSkewX(src.getTextSkewX());
    }

    if (bits & kPathEffect_Bit) {
        dst->setPathEffect(src.getPathEffect());
    }
    if (bits & kMaskFilter_Bit) {
        dst->setMaskFilter(src.getMaskFilter());
    }
    if (bits & kShader_Bit) {
        dst->setShader(src.getShader());
    }
    if (bits & kColorFilter_Bit) {
        dst->setColorFilter(src.getColorFilter());
    }
    if (bits & kXfermode_Bit) {
        dst->setXfermode(src.getXfermode());
    }

    // we don't override these
#if 0
    dst->setTypeface(src.getTypeface());
    dst->setTextSize(src.getTextSize());
    dst->setTextScaleX(src.getTextScaleX());
    dst->setRasterizer(src.getRasterizer());
    dst->setLooper(src.getLooper());
    dst->setTextEncoding(src.getTextEncoding());
    dst->setHinting(src.getHinting());
#endif
}