Beispiel #1
0
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect,
                        const AffineTransform& patternTransform,
                        const FloatPoint& phase, CompositeOperator compositeOp,
                        const FloatRect& destRect)
{
    SkBitmapRef* image = this->nativeImageForCurrentFrame();
    if (!image) { // If it's too early we won't have an image yet.
        return;
    }
    
    // in case we get called with an incomplete bitmap
    const SkBitmap& bitmap = image->bitmap();
    if (bitmap.getPixels() == NULL && bitmap.pixelRef() == NULL) {
        return;
    }
    
    SkRect  dstR;    
    android_setrect(&dstR, destRect);
    if (dstR.isEmpty()) {
        return;
    }
    
    SkCanvas*   canvas = ctxt->platformContext()->mCanvas;
    SkPaint     paint;
    
    SkShader* shader = SkShader::CreateBitmapShader(bitmap,
                                                    SkShader::kRepeat_TileMode,
                                                    SkShader::kRepeat_TileMode);
    paint.setShader(shader)->unref();
    // now paint is the only owner of shader
    paint.setPorterDuffXfermode(android_convert_compositeOp(compositeOp));
    paint.setFilterBitmap(true);
    
    SkMatrix matrix(patternTransform);
    
    float scaleX = (float)image->origWidth() / bitmap.width();
    float scaleY = (float)image->origHeight() / bitmap.height();
    matrix.preScale(SkFloatToScalar(scaleX), SkFloatToScalar(scaleY));
    
    matrix.postTranslate(SkFloatToScalar(phase.x()),
                         SkFloatToScalar(phase.y()));
    shader->setLocalMatrix(matrix);
    canvas->drawRect(dstR, paint);
    
#ifdef TRACE_SUBSAMPLED_BITMAPS
    if (bitmap.width() != image->origWidth() ||
        bitmap.height() != image->origHeight()) {
        SkDebugf("--- Image::drawPattern [%d %d] orig [%d %d] dst [%g %g]\n",
                 bitmap.width(), bitmap.height(),
                 image->origWidth(), image->origHeight(),
                 SkScalarToFloat(dstR.width()), SkScalarToFloat(dstR.height()));
    }
#endif
}
SkShader* Gradient::getShader(SkShader::TileMode mode)
{
    if (NULL == m_gradient)
        m_gradient = new PlatformGradientRec;
    else if (mode == m_gradient->m_tileMode)
        return m_gradient->m_shader;

    // need to ensure that the m_stops array is sorted. We call getColor()
    // which, as a side effect, does the sort.
    // TODO: refactor Gradient.h to formally expose a sort method
    {
        float r, g, b, a;
        this->getColor(0, &r, &g, &b, &a);
    }

    SkPoint pts[2] = { m_p0, m_p1 };    // convert to SkPoint

    const size_t count = m_stops.size();
    SkAutoMalloc    storage(count * (sizeof(SkColor) + sizeof(SkScalar)));
    SkColor*        colors = (SkColor*)storage.get();
    SkScalar*       pos = (SkScalar*)(colors + count);

    Vector<ColorStop>::iterator iter = m_stops.begin();
    for (int i = 0; iter != m_stops.end(); i++) {
        pos[i] = SkFloatToScalar(iter->stop);
        colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red),
                                   F2B(iter->green), F2B(iter->blue));
        ++iter;
    }

    SkShader* s;
    if (m_radial)
        s = SkGradientShader::CreateTwoPointRadial(pts[0],
                                                   SkFloatToScalar(m_r0),
                                                   pts[1],
                                                   SkFloatToScalar(m_r1),
                                                   colors, pos, count, mode);
    else
        s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode);

    if (NULL == s)
        s = new SkColorShader(0);

    // zap our previous shader, if present
    SkSafeUnref(m_gradient->m_shader);
    m_gradient->m_shader = s;
    m_gradient->m_tileMode = mode;
    SkMatrix matrix = m_gradientSpaceTransformation;
    s->setLocalMatrix(matrix);

    return s;
}
	ImageView() {
        SkImageRef_GlobalPool::SetRAMBudget(32 * 1024);
        
        int i, N = SK_ARRAY_COUNT(gNames);
        fBitmaps = new SkBitmap[N];
        
        for (i = 0; i < N; i++) {
            SkString str("/skimages/");
            str.append(gNames[i]);
            SkFILEStream* stream = new SkFILEStream(str.c_str());
            
            SetImageRef(&fBitmaps[i], stream, SkBitmap::kNo_Config, gNames[i]);
            if (i & 1)
                fBitmaps[i].buildMipMap();
            stream->unref();
        }
        
        fShader = SkShader::CreateBitmapShader(fBitmaps[5],
                                               SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);
        
        if (true) {
            SkMatrix m;
            
            m.setRotate(SkIntToScalar(30));
            fShader->setLocalMatrix(m);
        }
        
#if 0
        SkImageRef::DumpPool();
        for (i = 0; i < N; i++) {
            SkBitmap& bm = fBitmaps[i];

            SkDebugf("<%s> addr=%p", gNames[i], bm.getPixels());
            bool success = bm.lockPixels();
            SkDebugf(" addr=%d", bm.getPixels());
            if (success)
                bm.unlockPixels();
            SkDebugf(" addr=%p", bm.getPixels());
            success = bm.lockPixels();
            SkDebugf(" addr=%d", bm.getPixels());
            if (success)
                bm.unlockPixels();            
            SkDebugf("\n");
        }
        SkImageRef::DumpPool();
#endif
    }
Beispiel #4
0
static void copybits(SkCanvas* canvas, const SkBitmap& bm, const SkRect& dst, const SkPaint& paint)
{
	SkRect		src;
	SkMatrix	matrix;

	src.set(0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()));
	if (matrix.setRectToRect(src, dst))
	{
		SkPaint	  p(paint);
		SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kNo_FilterType, SkShader::kClamp_TileMode);
		p.setShader(shader)->unref();

		shader->setLocalMatrix(matrix);
		canvas->drawRect(dst, p);
	}
}
Beispiel #5
0
static SkShader* createChecker() {
//    SkColor colors[] = { 0xFFFDFDFD, 0xFFF4F4F4 };
    SkColor colors[] = { 0xFFFFFFFF, 0xFFFFFFFF };
    SkBitmap bm;
    bm.allocN32Pixels(2, 2);
    bm.lockPixels();
    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(colors[0]);
    *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(colors[1]);
    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);

    SkMatrix m;
    m.setScale(12, 12);
    s->setLocalMatrix(m);
    return s;
}
void PlatformGraphicsContextSkia::drawBitmapPattern(
        const SkBitmap& bitmap, const SkMatrix& matrix,
        CompositeOperator compositeOp, const FloatRect& destRect)
{
    SkShader* shader = SkShader::CreateBitmapShader(bitmap,
                                                    SkShader::kRepeat_TileMode,
                                                    SkShader::kRepeat_TileMode);
    shader->setLocalMatrix(matrix);
    SkPaint paint;
    setupPaintCommon(&paint);
    paint.setAlpha(getNormalizedAlpha());
    paint.setShader(shader)->unref();
    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
    fixPaintForBitmapsThatMaySeam(&paint);
    mCanvas->drawRect(destRect, paint);
}
Beispiel #7
0
static SkShader* make_bg_shader() {
    SkBitmap bm;
    bm.allocN32Pixels(2, 2);
    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
    *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
                                                             0xCC, 0xCC);

    SkShader* s = SkShader::CreateBitmapShader(bm,
                                               SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);

    SkMatrix m;
    m.setScale(SkIntToScalar(6), SkIntToScalar(6));
    s->setLocalMatrix(m);
    return s;
}
Beispiel #8
0
static void setBitmapDash(SkPaint* paint, int width) {
    SkColor c = paint->getColor();

    SkBitmap bm;
    bm.allocN32Pixels(2, 1);
    bm.lockPixels();
    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
                                            SkColorGetG(c), SkColorGetB(c));
    *bm.getAddr32(1, 0) = 0;
    bm.unlockPixels();

    SkMatrix matrix;
    matrix.setScale(SkIntToScalar(width), SK_Scalar1);

    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kClamp_TileMode);
    s->setLocalMatrix(matrix);

    paint->setShader(s)->unref();
}
static void drawmarshmallow(SkCanvas* canvas) {
    SkBitmap bitmap;
    SkPaint paint;
    SkRect r;
    SkMatrix m;

    SkImageDecoder::DecodeFile("/Users/reed/Downloads/3elfs.jpg", &bitmap);
    SkShader* s = SkShader::CreateBitmapShader(bitmap,
                                               SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);
    paint.setShader(s)->unref();
    m.setTranslate(SkIntToScalar(250), SkIntToScalar(134));
    s->setLocalMatrix(m);

    r.set(SkIntToScalar(250),
          SkIntToScalar(134),
          SkIntToScalar(250 + 449),
          SkIntToScalar(134 + 701));
    paint.setFlags(2);

    canvas->drawRect(r, paint);
}
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
        int width,
        bool grammar)
{
    if (paintingDisabled())
        return;

    // Create the pattern we'll use to draw the underline.
    static SkBitmap* misspellBitmap = 0;
    if (!misspellBitmap) {
        // We use a 2-pixel-high misspelling indicator because that seems to be
        // what WebKit is designed for, and how much room there is in a typical
        // page for it.
        const int rowPixels = 32;  // Must be multiple of 4 for pattern below.
        const int colPixels = 2;
        misspellBitmap = new SkBitmap;
        misspellBitmap->setConfig(SkBitmap::kARGB_8888_Config,
                                  rowPixels, colPixels);
        misspellBitmap->allocPixels();

        misspellBitmap->eraseARGB(0, 0, 0, 0);
        const uint32_t lineColor = 0xFFFF0000;  // Opaque red.
        const uint32_t antiColor = 0x60600000;  // Semitransparent red.

        // Pattern:  X o   o X o   o X
        //             o X o   o X o
        uint32_t* row1 = misspellBitmap->getAddr32(0, 0);
        uint32_t* row2 = misspellBitmap->getAddr32(0, 1);
        for (int x = 0; x < rowPixels; x++) {
            switch (x % 4) {
            case 0:
                row1[x] = lineColor;
                break;
            case 1:
                row1[x] = antiColor;
                row2[x] = antiColor;
                break;
            case 2:
                row2[x] = lineColor;
                break;
            case 3:
                row1[x] = antiColor;
                row2[x] = antiColor;
                break;
            }
        }
    }

    // Offset it vertically by 1 so that there's some space under the text.
    SkScalar originX = SkIntToScalar(pt.x());
    SkScalar originY = SkIntToScalar(pt.y()) + 1;

    // Make a shader for the bitmap with an origin of the box we'll draw. This
    // shader is refcounted and will have an initial refcount of 1.
    SkShader* shader = SkShader::CreateBitmapShader(
                           *misspellBitmap, SkShader::kRepeat_TileMode,
                           SkShader::kRepeat_TileMode);
    SkMatrix matrix;
    matrix.reset();
    matrix.postTranslate(originX, originY);
    shader->setLocalMatrix(matrix);

    // Assign the shader to the paint & release our reference. The paint will
    // now own the shader and the shader will be destroyed when the paint goes
    // out of scope.
    SkPaint paint;
    paint.setShader(shader);
    shader->unref();

    SkRect rect;
    rect.set(originX,
             originY,
             originX + SkIntToScalar(width),
             originY + SkIntToScalar(misspellBitmap->height()));
    platformContext()->canvas()->drawRect(rect, paint);
}
Beispiel #11
0
void Image::drawPattern(GraphicsContext* context,
                        const FloatRect& floatSrcRect,
                        const AffineTransform& patternTransform,
                        const FloatPoint& phase,
                        ColorSpace styleColorSpace,
                        CompositeOperator compositeOp,
                        const FloatRect& destRect)
{
    FloatRect normSrcRect = normalizeRect(floatSrcRect);
    if (destRect.isEmpty() || normSrcRect.isEmpty())
        return; // nothing to draw

    NativeImageSkia* bitmap = nativeImageForCurrentFrame();
    if (!bitmap)
        return;

    SkIRect srcRect = enclosingIntRect(normSrcRect);

    // Figure out what size the bitmap will be in the destination. The
    // destination rect is the bounds of the pattern, we need to use the
    // matrix to see how big it will be.
    float destBitmapWidth, destBitmapHeight;
    TransformDimensions(patternTransform, srcRect.width(), srcRect.height(),
                        &destBitmapWidth, &destBitmapHeight);

    // Compute the resampling mode.
    ResamplingMode resampling;
    if (context->platformContext()->isAccelerated() || context->platformContext()->printing())
        resampling = RESAMPLE_LINEAR;
    else
        resampling = computeResamplingMode(context->platformContext(), *bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight);

    // Load the transform WebKit requested.
    SkMatrix matrix(patternTransform);

    SkShader* shader;
    if (resampling == RESAMPLE_AWESOME) {
        // Do nice resampling.
        int width = static_cast<int>(destBitmapWidth);
        int height = static_cast<int>(destBitmapHeight);
        SkBitmap resampled = bitmap->resizedBitmap(srcRect, width, height);
        shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);

        // Since we just resized the bitmap, we need to undo the scale set in
        // the image transform.
        matrix.setScaleX(SkIntToScalar(1));
        matrix.setScaleY(SkIntToScalar(1));
    } else {
        // No need to do nice resampling.
        SkBitmap srcSubset;
        bitmap->bitmap().extractSubset(&srcSubset, srcRect);
        shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
    }

    // We also need to translate it such that the origin of the pattern is the
    // origin of the destination rect, which is what WebKit expects. Skia uses
    // the coordinate system origin as the base for the patter. If WebKit wants
    // a shifted image, it will shift it from there using the patternTransform.
    float adjustedX = phase.x() + normSrcRect.x() *
                      narrowPrecisionToFloat(patternTransform.a());
    float adjustedY = phase.y() + normSrcRect.y() *
                      narrowPrecisionToFloat(patternTransform.d());
    matrix.postTranslate(SkFloatToScalar(adjustedX),
                         SkFloatToScalar(adjustedY));
    shader->setLocalMatrix(matrix);

    SkPaint paint;
    paint.setShader(shader)->unref();
    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
    paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);

    context->platformContext()->paintSkPaint(destRect, paint);
}
Beispiel #12
0
void
DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                      const Point &aDest,
                                      const Color &aColor,
                                      const Point &aOffset,
                                      Float aSigma,
                                      CompositionOp aOperator)
{
    MarkChanged();
    mCanvas->save(SkCanvas::kMatrix_SaveFlag);
    mCanvas->resetMatrix();

    uint32_t blurFlags = SkBlurMaskFilter::kHighQuality_BlurFlag |
                         SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
    const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
    SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
    SkMatrix matrix;
    matrix.reset();
    matrix.setTranslateX(SkFloatToScalar(aDest.x));
    matrix.setTranslateY(SkFloatToScalar(aDest.y));
    shader->setLocalMatrix(matrix);
    SkLayerDrawLooper* dl = new SkLayerDrawLooper;
    SkLayerDrawLooper::LayerInfo info;
    info.fPaintBits |= SkLayerDrawLooper::kShader_Bit;
    SkPaint *layerPaint = dl->addLayer(info);
    layerPaint->setShader(shader);

    info.fPaintBits = 0;
    info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit;
    info.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit;
    info.fColorMode = SkXfermode::kDst_Mode;
    info.fOffset.set(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
    info.fPostTranslate = true;

    SkMaskFilter* mf = SkBlurMaskFilter::Create(aSigma, SkBlurMaskFilter::kNormal_BlurStyle, blurFlags);
    SkColor color = ColorToSkColor(aColor, 1);
    SkColorFilter* cf = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);


    layerPaint = dl->addLayer(info);
    SkSafeUnref(layerPaint->setMaskFilter(mf));
    SkSafeUnref(layerPaint->setColorFilter(cf));
    layerPaint->setColor(color);

    // TODO: This is using the rasterizer to calculate an alpha mask
    // on both the shadow and normal layers. We should fix this
    // properly so it only happens for the shadow layer
    SkLayerRasterizer *raster = new SkLayerRasterizer();
    SkPaint maskPaint;
    SkSafeUnref(maskPaint.setShader(shader));
    raster->addLayer(maskPaint, 0, 0);

    SkPaint paint;
    paint.setAntiAlias(true);
    SkSafeUnref(paint.setRasterizer(raster));
    paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
    SkSafeUnref(paint.setLooper(dl));

    SkRect rect = RectToSkRect(Rect(Float(aDest.x), Float(aDest.y),
                                    Float(bitmap.width()), Float(bitmap.height())));
    mCanvas->drawRect(rect, paint);
    mCanvas->restore();
}
void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style)
{
    if (paintingDisabled())
        return;

    // Create the pattern we'll use to draw the underline.
    int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0;
    static SkBitmap* misspellBitmap[2] = { 0, 0 };
    if (!misspellBitmap[index]) {
#if PLATFORM(CHROMIUM) && OS(DARWIN)
        // Match the artwork used by the Mac.
        const int rowPixels = 4;
        const int colPixels = 3;
#else
        // We use a 2-pixel-high misspelling indicator because that seems to be
        // what WebKit is designed for, and how much room there is in a typical
        // page for it.
        const int rowPixels = 32;  // Must be multiple of 4 for pattern below.
        const int colPixels = 2;
#endif
        misspellBitmap[index] = new SkBitmap;
        misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config,
                                         rowPixels, colPixels);
        misspellBitmap[index]->allocPixels();

        misspellBitmap[index]->eraseARGB(0, 0, 0, 0);
#if PLATFORM(CHROMIUM) && OS(DARWIN)
        const uint32_t colors[2][6] = {
            { 0x2A2A0600, 0x57571000, 0xA8A81B00, 0xBFBF1F00, 0x70701200, 0xE0E02400 },
            { 0x2A001503, 0x57002A08, 0xA800540D, 0xBF005F0F, 0x70003809, 0xE0007012 }
        };
        const uint32_t transparentColor = 0x00000000;

        // Pattern: a b a   a b a
        //          c d c   c d c
        //          e f e   e f e
        for (int x = 0; x < colPixels; ++x) {
            uint32_t* row = misspellBitmap[index]->getAddr32(0, x);
            row[0] = colors[index][x * 2];
            row[1] = colors[index][x * 2 + 1];
            row[2] = colors[index][x * 2];
            row[3] = transparentColor;
        }
#else
        static const uint32_t lineColors[2] = {
            0xFF << SK_A32_SHIFT | 0xFF << SK_R32_SHIFT, // Opaque red.
            0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Opaque gray.
        };
        static const uint32_t antiColors[2] = {
            0x60 << SK_A32_SHIFT | 0x60 << SK_R32_SHIFT, // Semitransparent red
            0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Semitransparent gray
        };
        const uint32_t lineColor = lineColors[index];
        const uint32_t antiColor = antiColors[index];

        // Pattern:  X o   o X o   o X
        //             o X o   o X o
        uint32_t* row1 = misspellBitmap[index]->getAddr32(0, 0);
        uint32_t* row2 = misspellBitmap[index]->getAddr32(0, 1);
        for (int x = 0; x < rowPixels; x++) {
            switch (x % 4) {
            case 0:
                row1[x] = lineColor;
                break;
            case 1:
                row1[x] = antiColor;
                row2[x] = antiColor;
                break;
            case 2:
                row2[x] = lineColor;
                break;
            case 3:
                row1[x] = antiColor;
                row2[x] = antiColor;
                break;
            }
        }
#endif
    }

    SkScalar originX = WebCoreFloatToSkScalar(pt.x());
#if PLATFORM(CHROMIUM) && OS(DARWIN)
    SkScalar originY = WebCoreFloatToSkScalar(pt.y());
    // Make sure to draw only complete dots.
    int rowPixels = misspellBitmap[index]->width();
    float widthMod = fmodf(width, rowPixels);
    if (rowPixels - widthMod > 1)
        width -= widthMod;
#else
    // Offset it vertically by 1 so that there's some space under the text.
    SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
#endif

    // Make a shader for the bitmap with an origin of the box we'll draw. This
    // shader is refcounted and will have an initial refcount of 1.
    SkShader* shader = SkShader::CreateBitmapShader(
        *misspellBitmap[index], SkShader::kRepeat_TileMode,
        SkShader::kRepeat_TileMode);
    SkMatrix matrix;
    matrix.reset();
    matrix.postTranslate(originX, originY);
    shader->setLocalMatrix(matrix);

    // Assign the shader to the paint & release our reference. The paint will
    // now own the shader and the shader will be destroyed when the paint goes
    // out of scope.
    SkPaint paint;
    paint.setShader(shader);
    shader->unref();

    SkRect rect;
    rect.set(originX,
             originY,
             originX + WebCoreFloatToSkScalar(width),
             originY + SkIntToScalar(misspellBitmap[index]->height()));
    platformContext()->canvas()->drawRect(rect, paint);
    platformContext()->didDrawRect(rect, paint);
}
static SkShader*
source_to_sk_shader (cairo_skia_context_t *cr,
		     const cairo_pattern_t *pattern)
{
    SkShader *shader = NULL;

    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
	return new SkColorShader (color_to_sk (solid->color));
    } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
	cairo_surface_t *surface = surface_from_pattern (pattern);

	cr->source = cairo_surface_reference (surface);

	if (surface->type == CAIRO_SURFACE_TYPE_SKIA) {
	    cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) surface;

	    shader = SkShader::CreateBitmapShader (*esurf->bitmap,
						   extend_to_sk (pattern->extend),
						   extend_to_sk (pattern->extend));
	} else {
	    SkBitmap bitmap;

	    if (! _cairo_surface_is_image (surface)) {
		cairo_status_t status;

		status = _cairo_surface_acquire_source_image (surface,
							      &cr->source_image,
							      &cr->source_extra);
		if (status)
		    return NULL;

		surface = &cr->source_image->base;
	    }

	    if (unlikely (! surface_to_sk_bitmap (surface, bitmap)))
		return NULL;

	    shader = SkShader::CreateBitmapShader (bitmap,
						   extend_to_sk (pattern->extend),
						   extend_to_sk (pattern->extend));
	}
    } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR
	       /* || pattern->type == CAIRO_PATTERN_TYPE_RADIAL */)
    {
	cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
	SkColor colors_stack[10];
	SkScalar pos_stack[10];
	SkColor *colors = colors_stack;
	SkScalar *pos = pos_stack;

	if (gradient->n_stops > 10) {
	    colors = new SkColor[gradient->n_stops];
	    pos = new SkScalar[gradient->n_stops];
	}

	for (unsigned int i = 0; i < gradient->n_stops; i++) {
	    pos[i] = CAIRO_FIXED_TO_SK_SCALAR (gradient->stops[i].offset);
	    colors[i] = color_stop_to_sk (gradient->stops[i].color);
	}

	if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
	    SkPoint points[2];

	    points[0].set (SkFloatToScalar (linear->pd1.x),
			   SkFloatToScalar (linear->pd1.y));
	    points[1].set (SkFloatToScalar (linear->pd2.x),
			   SkFloatToScalar (linear->pd2.y));
	    shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops,
						     extend_to_sk (pattern->extend));
	} else {
	    // XXX todo -- implement real radial shaders in Skia
	}

	if (gradient->n_stops > 10) {
	    delete [] colors;
	    delete [] pos;
	}
    }

    if (shader && ! _cairo_matrix_is_identity (&pattern->matrix))
	shader->setLocalMatrix (matrix_inverse_to_sk (pattern->matrix));

    return shader;
}
Beispiel #15
0
void Image::drawPattern(GraphicsContext* context,
                        const FloatRect& floatSrcRect,
                        const AffineTransform& patternTransform,
                        const FloatPoint& phase,
                        ColorSpace styleColorSpace,
                        CompositeOperator compositeOp,
                        const FloatRect& destRect)
{
#if PLATFORM(CHROMIUM)
    TRACE_EVENT0("skia", "Image::drawPattern");
#endif
    FloatRect normSrcRect = normalizeRect(floatSrcRect);
    if (destRect.isEmpty() || normSrcRect.isEmpty())
        return; // nothing to draw

    NativeImageSkia* bitmap = nativeImageForCurrentFrame();
    if (!bitmap)
        return;

    SkMatrix ctm = context->platformContext()->canvas()->getTotalMatrix();
    SkMatrix totalMatrix;
    totalMatrix.setConcat(ctm, patternTransform);

    // Figure out what size the bitmap will be in the destination. The
    // destination rect is the bounds of the pattern, we need to use the
    // matrix to see how big it will be.
    SkRect destRectTarget;
    totalMatrix.mapRect(&destRectTarget, normSrcRect);

    float destBitmapWidth = SkScalarToFloat(destRectTarget.width());
    float destBitmapHeight = SkScalarToFloat(destRectTarget.height());

    // Compute the resampling mode.
    ResamplingMode resampling;
    if (context->platformContext()->isAccelerated() || context->platformContext()->printing())
        resampling = RESAMPLE_LINEAR;
    else
        resampling = computeResamplingMode(totalMatrix, *bitmap, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight);
    resampling = limitResamplingMode(context->platformContext(), resampling);

    // Load the transform WebKit requested.
    SkMatrix matrix(patternTransform);

    SkShader* shader;
    if (resampling == RESAMPLE_AWESOME) {
        // Do nice resampling.
        float scaleX = destBitmapWidth / normSrcRect.width();
        float scaleY = destBitmapHeight / normSrcRect.height();
        SkRect scaledSrcRect;
        SkIRect enclosingScaledSrcRect;

        // The image fragment generated here is not exactly what is
        // requested. The scale factor used is approximated and image
        // fragment is slightly larger to align to integer
        // boundaries.
        SkBitmap resampled = extractScaledImageFragment(*bitmap, normSrcRect, scaleX, scaleY, &scaledSrcRect, &enclosingScaledSrcRect);
        shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);

        // Since we just resized the bitmap, we need to remove the scale
        // applied to the pixels in the bitmap shader. This means we need
        // CTM * patternTransform to have identity scale. Since we
        // can't modify CTM (or the rectangle will be drawn in the wrong
        // place), we must set patternTransform's scale to the inverse of
        // CTM scale.
        matrix.setScaleX(ctm.getScaleX() ? 1 / ctm.getScaleX() : 1);
        matrix.setScaleY(ctm.getScaleY() ? 1 / ctm.getScaleY() : 1);
    } else {
        // No need to do nice resampling.
        SkBitmap srcSubset;
        bitmap->bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect));
        shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
    }

    // We also need to translate it such that the origin of the pattern is the
    // origin of the destination rect, which is what WebKit expects. Skia uses
    // the coordinate system origin as the base for the patter. If WebKit wants
    // a shifted image, it will shift it from there using the patternTransform.
    float adjustedX = phase.x() + normSrcRect.x() *
                      narrowPrecisionToFloat(patternTransform.a());
    float adjustedY = phase.y() + normSrcRect.y() *
                      narrowPrecisionToFloat(patternTransform.d());
    matrix.postTranslate(SkFloatToScalar(adjustedX),
                         SkFloatToScalar(adjustedY));
    shader->setLocalMatrix(matrix);

    SkPaint paint;
    paint.setShader(shader)->unref();
    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
    paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);

    context->platformContext()->paintSkPaint(destRect, paint);
}
void SkDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
                              const SkRect* src, const SkRect& dst,
                              const SkPaint& paint) {
    SkMatrix    matrix;
    SkRect      bitmapBounds, tmpSrc, tmpDst;
    SkBitmap    tmpBitmap;

    bitmapBounds.isetWH(bitmap.width(), bitmap.height());

    // Compute matrix from the two rectangles
    if (src) {
        tmpSrc = *src;
    } else {
        tmpSrc = bitmapBounds;
    }
    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);

    const SkRect* dstPtr = &dst;
    const SkBitmap* bitmapPtr = &bitmap;

    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
    // needed (if the src was clipped). No check needed if src==null.
    if (src) {
        if (!bitmapBounds.contains(*src)) {
            if (!tmpSrc.intersect(bitmapBounds)) {
                return; // nothing to draw
            }
            // recompute dst, based on the smaller tmpSrc
            matrix.mapRect(&tmpDst, tmpSrc);
            dstPtr = &tmpDst;
        }

        // since we may need to clamp to the borders of the src rect within
        // the bitmap, we extract a subset.
        SkIRect srcIR;
        tmpSrc.roundOut(&srcIR);
        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
            return;
        }
        bitmapPtr = &tmpBitmap;

        // Since we did an extract, we need to adjust the matrix accordingly
        SkScalar dx = 0, dy = 0;
        if (srcIR.fLeft > 0) {
            dx = SkIntToScalar(srcIR.fLeft);
        }
        if (srcIR.fTop > 0) {
            dy = SkIntToScalar(srcIR.fTop);
        }
        if (dx || dy) {
            matrix.preTranslate(dx, dy);
        }

        SkRect extractedBitmapBounds;
        extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
        if (extractedBitmapBounds == tmpSrc) {
            // no fractional part in src, we can just call drawBitmap
            goto USE_DRAWBITMAP;
        }
    } else {
        USE_DRAWBITMAP:
        // We can go faster by just calling drawBitmap, which will concat the
        // matrix with the CTM, and try to call drawSprite if it can. If not,
        // it will make a shader and call drawRect, as we do below.
        this->drawBitmap(draw, *bitmapPtr, matrix, paint);
        return;
    }

    // construct a shader, so we can call drawRect with the dst
    SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
                                               SkShader::kClamp_TileMode,
                                               SkShader::kClamp_TileMode);
    if (NULL == s) {
        return;
    }
    s->setLocalMatrix(matrix);

    SkPaint paintWithShader(paint);
    paintWithShader.setStyle(SkPaint::kFill_Style);
    paintWithShader.setShader(s)->unref();

    // Call ourself, in case the subclass wanted to share this setup code
    // but handle the drawRect code themselves.
    this->drawRect(draw, *dstPtr, paintWithShader);
}
    virtual void onDraw(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        this->drawBG(canvas);

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            { SkXfermode::kMultiply_Mode,     "Multiply"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                   SkShader::kRepeat_TileMode,
                                                   SkShader::kRepeat_TileMode);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        s->setLocalMatrix(m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(NULL);
                canvas->drawRect(r, p);

#if 1
                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
#endif
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }
Beispiel #18
0
// test drawing with strips of fading gradient above and below
static void test_fade(SkCanvas* canvas) {
    SkAutoCanvasRestore ar(canvas, true);

    SkRect r;
    
    SkPaint p;
    p.setAlpha(0x88);

    SkAutoCanvasRestore(canvas, false);

    // create the layers

    r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
    canvas->clipRect(r);
    
    r.fBottom = SkIntToScalar(20);
    canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));

    r.fTop = SkIntToScalar(80);
    r.fBottom = SkIntToScalar(100);
    canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
    
    // now draw the "content" 

    if (true) {
        r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));

        canvas->saveLayerAlpha(&r, 0x80);

        SkPaint p;
        p.setColor(SK_ColorRED);
        p.setAntiAlias(true);
        canvas->drawOval(r, p);
        
        dump_layers("inside layer alpha", canvas);
        
        canvas->restore();
    } else {
        r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
        
        SkPaint p;
        p.setColor(SK_ColorRED);
        p.setAntiAlias(true);
        canvas->drawOval(r, p);
    }
    
//    return;

    dump_layers("outside layer alpha", canvas);

    // now apply an effect

    SkPaint paint;
    make_paint(&paint);
    r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
//    SkDebugf("--------- draw top grad\n");
    canvas->drawRect(r, paint);

    SkMatrix m;
    SkShader* s = paint.getShader();
    m.setScale(SK_Scalar1, -SK_Scalar1);
    m.postTranslate(0, SkIntToScalar(100));
    s->setLocalMatrix(m);
    
    r.fTop = SkIntToScalar(80);
    r.fBottom = SkIntToScalar(100);
//    SkDebugf("--------- draw bot grad\n");
    canvas->drawRect(r, paint);
}
Beispiel #19
0
    virtual void onDrawContent(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextSize(50);
            paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal));
            SkSafeUnref(paint.getTypeface());
            char buffer[10];
            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
            canvas->drawText(buffer, len, 40, 40, paint);
            return;
        }
        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);

            SkRect r0 = { 0, 0, 10.5f, 20 };
            SkRect r1 = { 10.5f, 10, 20, 30 };
            paint.setColor(SK_ColorRED);
            canvas->drawRect(r0, paint);
            paint.setColor(SK_ColorBLUE);
            canvas->drawRect(r1, paint);
            return;
        }

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                   SkShader::kRepeat_TileMode,
                                                   SkShader::kRepeat_TileMode);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        s->setLocalMatrix(m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setLCDRenderText(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);
        setNamedTypeface(&labelP, "Menlo Regular");

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, NULL);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(NULL);
                canvas->drawRect(r, p);

                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }
Beispiel #20
0
static void
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap,
                Float aAlpha = 1.0)
{
  switch (aPattern.GetType()) {
    case PatternType::COLOR: {
      Color color = static_cast<const ColorPattern&>(aPattern).mColor;
      aPaint.setColor(ColorToSkColor(color, aAlpha));
      break;
    }
    case PatternType::LINEAR_GRADIENT: {
      const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
      GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
      SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);

      if (stops->mCount >= 2) {
        SkPoint points[2];
        points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
        points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));

        SkShader* shader = SkGradientShader::CreateLinear(points, 
                                                          &stops->mColors.front(), 
                                                          &stops->mPositions.front(), 
                                                          stops->mCount, 
                                                          mode);

        if (shader) {
            SkMatrix mat;
            GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
            shader->setLocalMatrix(mat);
            SkSafeUnref(aPaint.setShader(shader));
        }

      } else {
        aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
      }
      break;
    }
    case PatternType::RADIAL_GRADIENT: {
      const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
      GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
      SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);

      if (stops->mCount >= 2) {
        SkPoint points[2];
        points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
        points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));

        SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0], 
                                                                   SkFloatToScalar(pat.mRadius1),
                                                                   points[1], 
                                                                   SkFloatToScalar(pat.mRadius2),
                                                                   &stops->mColors.front(), 
                                                                   &stops->mPositions.front(), 
                                                                   stops->mCount, 
                                                                   mode);
        if (shader) {
            SkMatrix mat;
            GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
            shader->setLocalMatrix(mat);
            SkSafeUnref(aPaint.setShader(shader));
        }

      } else {
        aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
      }
      break;
    }
    case PatternType::SURFACE: {
      const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
      aTmpBitmap = GetBitmapForSurface(pat.mSurface);
      const SkBitmap& bitmap = aTmpBitmap.mBitmap;

      SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
      SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
      SkMatrix mat;
      GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
      shader->setLocalMatrix(mat);
      SkSafeUnref(aPaint.setShader(shader));
      if (pat.mFilter == Filter::POINT) {
        aPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
      }
      break;
    }
  }
}
Beispiel #21
0
bool SVGPaintServerGradient::setup(GraphicsContext*& context, 
    const RenderObject* object, 
    SVGPaintTargetType type, 
    bool isPaintingText) const
{
    m_ownerElement->buildGradient();

    RenderStyle* style = object->style();
    bool isFilled = 
        (type & ApplyToFillTargetType) && 
         style->svgStyle()->hasFill();
    bool isStroked = 
        (type & ApplyToStrokeTargetType) && 
         style->svgStyle()->hasStroke();

    if(!gradientStops().size())
        return false;

    if(gradientStops().size()==1) {
        context->setFillColor(gradientStops()[0].second);
        return true;
    }

    // Create a gradient builder helper to generate the data 
    // we'll need to provide Skia
    SkiaGradientBuilder builder(gradientStops(), 
        isFilled ? style->svgStyle()->fillOpacity() : 
                   style->svgStyle()->strokeOpacity());

    SkShader::TileMode tile_mode;

    // Convert SVG spread modes to Skia tile modes
    switch(spreadMethod())
    {
    default:
    case SPREADMETHOD_PAD:     
        tile_mode = SkShader::kClamp_TileMode; break;
    case SPREADMETHOD_REFLECT: 
        tile_mode = SkShader::kMirror_TileMode; break;
    case SPREADMETHOD_REPEAT:  
        tile_mode = SkShader::kRepeat_TileMode; break;
    }

    SkShader* shader = NULL;

    SkMatrix matrix;

    // Calculate a matrix to transform a gradient to fit the bounding box
    if (boundingBoxMode()) {
        matrix.reset();
        SkRect rc = context->getBoundingBoxForCurrentPath(true);

        matrix.preTranslate(rc.fLeft, rc.fTop);
        matrix.preScale(rc.width(), rc.height());
        matrix.preConcat(gradientTransform());
    } else
        matrix = gradientTransform();

    if (this->type() == LinearGradientPaintServer) {
        const SVGPaintServerLinearGradient* linear = 
            static_cast<const SVGPaintServerLinearGradient*>(this);

        SkPoint pts[2];

        pts[0].fX = linear->gradientStart().x();
        pts[0].fY = linear->gradientStart().y();
        pts[1].fX = linear->gradientEnd().x();
        pts[1].fY = linear->gradientEnd().y();

        shader = SkGradientShader::CreateLinear(pts, 
            builder.colors(), builder.pos(), builder.count(), tile_mode);
    } else if (this->type() == RadialGradientPaintServer) {
        const SVGPaintServerRadialGradient* radial = 
            static_cast<const SVGPaintServerRadialGradient*>(this);

        SkPoint center;
        SkScalar radius;

        center.fX = radial->gradientCenter().x();
        center.fY = radial->gradientCenter().y();
        radius = radial->gradientRadius();

        shader = SkGradientShader::CreateRadial(
            center, radius, builder.colors(), builder.pos(), 
            builder.count(), tile_mode);

    } else {
        return false;
    }

    if (isPaintingText) {
        if (isFilled) {
            context->setTextDrawingMode(cTextFill);
        }

        if (isStroked) {
            context->setTextDrawingMode(cTextStroke);
        }
    }

    if (isStroked) {
        applyStrokeStyleToContext(context, style, object);
    }

    if (shader) {
        shader->setLocalMatrix(matrix);
        context->platformContext()->setGradient(shader);

        return true;
    }

    return false;
}