示例#1
0
        protected void CreatePathShape()
        {
            if (Path != null && !drawable.Bounds.IsEmpty)
            {
                drawable.Shape = new PathShape(Path, drawable.Bounds.Width(), drawable.Bounds.Height());
            }
            else
            {
                drawable.Shape = null;
            }

            // Find the path bounds.
            // Can't use ComputeFounds on the path because that includes Bezier control points.
            // Need to obtain the fill path first.
            if (Path != null)
            {
                using (droidGraphics.Path fillPath = new droidGraphics.Path())
                {
                    drawable.Paint.StrokeWidth = 0.01f;
                    drawable.Paint.SetStyle(droidGraphics.Paint.Style.Stroke);
                    drawable.Paint.GetFillPath(Path, fillPath);
                    fillPath.ComputeBounds(pathFillBounds, false);
                    drawable.Paint.StrokeWidth = strokeWidth;
                }
            }
            else
            {
                pathFillBounds.SetEmpty();
            }

            fillShader = null;              // really only necessary for LinearGradientBrush
            CalculatePathStrokeBounds();
        }
示例#2
0
		public Shader createShader() {
			if(this.mShader != null) {
				return this.mShader;
			}

			if(!this.mSVGGradientStopsBuilt) {
				this.buildSVGGradientStopsArrays();
			}

			Shader.TileMode tileMode = this.getTileMode();
			if(this.mLinear) {
				float x1 =this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_X1, true, 0f);
				float x2 = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_X2, true, 0f);
				float y1 = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_Y1, true, 0f);
				float y2 = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_Y2, true, 0f);

				this.mShader = new LinearGradient(x1, y1, x2, y2, this.mSVGGradientStopsColors, this.mSVGGradientStopsPositions, tileMode);
			} else {
				float centerX = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_CENTER_X, true, 0f);
				float centerY = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_CENTER_Y, true, 0f);
				float radius = this.mSVGAttributes.getFloatAttribute(SVGConstants.ATTRIBUTE_RADIUS, true, 0f);

				this.mShader = new RadialGradient(centerX, centerY, radius, this.mSVGGradientStopsColors, this.mSVGGradientStopsPositions, tileMode);
			}
			this.mMatrix = this.getTransform();
			if (this.mMatrix != null) {
				this.mShader.SetLocalMatrix(this.mMatrix);
			}

			return this.mShader;
		}
示例#3
0
 public void SetStretch(Stretch stretch)
 {
     this.stretch = stretch;
     fillShader   = null;
     strokeShader = null;
     Invalidate();
 }
			public SampleView (Context context) : base (context)
			{
				Focusable = true;

				Stream input = context.Resources.OpenRawResource (Resource.Drawable.app_sample_code);
				
				mBitmap = BitmapFactory.DecodeStream (input);
				mBitmap2 = mBitmap.ExtractAlpha ();
				mBitmap3 = Bitmap.CreateBitmap (200, 200, Bitmap.Config.Alpha8);
				DrawIntoBitmap (mBitmap3);

				mShader = new LinearGradient (0, 0, 100, 70, new int[] {
                                         Color.Red, Color.Green, Color.Blue },
							     null, Shader.TileMode.Mirror);
			}
示例#5
0
        // Set from above and when stroke width or style changes
        void CalculatePathStrokeBounds()
        {
            if (Path != null)
            {
                using (droidGraphics.Path strokePath = new droidGraphics.Path())
                {
                    drawable.Paint.SetStyle(droidGraphics.Paint.Style.Stroke);
                    drawable.Paint.GetFillPath(Path, strokePath);
                    strokePath.ComputeBounds(pathStrokeBounds, false);
                }
            }
            else
            {
                pathStrokeBounds.SetEmpty();
            }

            strokeShader = null;        // really only necessary of LinearGradientBrush
            Invalidate();
        }
		private void drawAlphaPanel(Canvas canvas) {
			/*
		 * Will be drawn with hw acceleration, very fast.
		 */

			if(!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;

			RectF rect = mAlphaRect;

			if(BORDER_WIDTH_PX > 0){
				//TODO: cross check the color

				byte[] byteArr = BitConverter.GetBytes (mBorderColor);
				mBorderPaint.Color = Color.Argb (byteArr [0], byteArr [1], byteArr [2], byteArr [3]);
//				mBorderPaint.Color = mBorderColor;
				canvas.DrawRect(rect.Left - BORDER_WIDTH_PX, 
					rect.Top - BORDER_WIDTH_PX, 
					rect.Right + BORDER_WIDTH_PX, 
					rect.Bottom + BORDER_WIDTH_PX, 
					mBorderPaint);		
			}


			mAlphaPattern.Draw(canvas);

			float[] hsv = new float[]{mHue,mSat,mVal};
			Color color = Color.HSVToColor(hsv);
			Color acolor = Color.HSVToColor(0, hsv);

			mAlphaShader = new LinearGradient(rect.Left, rect.Top, rect.Right, rect.Top, 
				color, acolor, Android.Graphics.Shader.TileMode.Clamp);


			mAlphaPaint.SetShader(mAlphaShader);

			canvas.DrawRect(rect, mAlphaPaint);

			if(mAlphaSliderText != null && !mAlphaSliderText.Equals("")){
				canvas.DrawText(mAlphaSliderText, rect.CenterX(), rect.CenterY() + 4 * mDensity, mAlphaTextPaint);
			}

			float rectWidth = 4 * mDensity / 2;

			Point p = alphaToPoint(mAlpha);

			RectF r = new RectF();
			r.Left = p.X - rectWidth;
			r.Right = p.X + rectWidth;
			r.Top = rect.Top - RECTANGLE_TRACKER_OFFSET;
			r.Bottom = rect.Bottom + RECTANGLE_TRACKER_OFFSET;

			canvas.DrawRoundRect(r, 2, 2, mHueAlphaTrackerPaint);
		}
		private void drawHuePanel(Canvas canvas){
			/*
		 * Drawn with hw acceleration, very fast.
		 */

			//long start = SystemClock.elapsedRealtime();

			RectF rect = mHueRect;

			if(BORDER_WIDTH_PX > 0) {
				//TODO: Cross check the color setting

				byte[] byteArr = BitConverter.GetBytes (mBorderColor);
				mBorderPaint.Color = Color.Argb (byteArr [0], byteArr [1], byteArr [2], byteArr [3]);
//				mBorderPaint.Color = mBorderColor;
				canvas.DrawRect(rect.Left - BORDER_WIDTH_PX, 
					rect.Top - BORDER_WIDTH_PX, 
					rect.Right + BORDER_WIDTH_PX, 
					rect.Bottom + BORDER_WIDTH_PX, 
					mBorderPaint);		
			}

			if (mHueShader == null) {
				//The hue shader has either not yet been created or the view has been resized.
				mHueShader = new LinearGradient(0, 0, 0, rect.Height(), buildHueColorArray(), null, Android.Graphics.Shader.TileMode.Clamp);
				mHuePaint.SetShader(mHueShader);			
			}

			canvas.DrawRect(rect, mHuePaint);

			float rectHeight = 4 * mDensity / 2;

			Point p = hueToPoint(mHue);

			RectF r = new RectF();
			r.Left = rect.Left - RECTANGLE_TRACKER_OFFSET;
			r.Right = rect.Right + RECTANGLE_TRACKER_OFFSET;
			r.Top = p.Y - rectHeight;
			r.Bottom = p.Y + rectHeight;


			canvas.DrawRoundRect(r, 2, 2, mHueAlphaTrackerPaint);

			//Log.d("mColorPicker", "Draw Time Hue: " + (SystemClock.elapsedRealtime() - start) + "ms");

		}
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (null != _satValPaint)
                {
                    _satValPaint.Dispose();
                    _satValPaint = null;
                }
                if (null != _satValTrackerPaint)
                {
                    _satValTrackerPaint.Dispose();
                    _satValTrackerPaint = null;
                }
                if (null != _huePaint)
                {
                    _huePaint.Dispose();
                    _huePaint = null;
                }
                if (null != _hueTrackerPaint)
                {
                    _hueTrackerPaint.Dispose();
                    _hueTrackerPaint = null;
                }
                if (null != _alphaPaint)
                {
                    _alphaPaint.Dispose();
                    _alphaPaint = null;
                }
                if (null != _alphaTextPaint)
                {
                    _alphaTextPaint.Dispose();
                    _alphaTextPaint = null;
                }
                if (null != _hueShader)
                {
                    _hueShader.Dispose();
                    _hueShader = null;
                }
                if (null != _borderPaint)
                {
                    _borderPaint.Dispose();
                    _borderPaint = null;
                }
                if (null != _valShader)
                {
                    _valShader.Dispose();
                    _valShader = null;
                }
                if (null != _satShader)
                {
                    _satShader.Dispose();
                    _satShader = null;
                }
                if (null != _alphaShader)
                {
                    _alphaShader.Dispose();
                    _alphaShader = null;
                }
                if (null != _alphaPattern)
                {
                    _alphaPattern.Dispose();
                    _alphaPattern = null;
                }
            }

            GC.Collect();

            base.Dispose(disposing);
        }
示例#9
0
 // Methods called from ShapeRenderer
 public void SetFillColor(object color)
 {
     fill       = color;
     fillShader = null;
     Invalidate();
 }
示例#10
0
        private void drawHuePanel(Canvas canvas)
        {
            /*
             * Drawn with hw acceleration, very fast.
             */

            //long start = SystemClock.elapsedRealtime();

            RectF rect = mHueRect;

            if (BORDER_WIDTH_PX > 0)
            {
                mBorderPaint.Color = new Color((int)mBorderColor);
                canvas.DrawRect(rect.Left - BORDER_WIDTH_PX,
                        rect.Top - BORDER_WIDTH_PX,
                        rect.Right + BORDER_WIDTH_PX,
                        rect.Bottom + BORDER_WIDTH_PX,
                        mBorderPaint);
            }

            if (mHueShader == null)
            {
                //The hue shader has either not yet been created or the view has been resized.
                mHueShader = new LinearGradient(0, 0, 0, rect.Height(), buildHueColorArray(), null, Shader.TileMode.Clamp);
                mHuePaint.SetShader(mHueShader);
            }

            canvas.DrawRect(rect, mHuePaint);

            float rectHeight = 4 * mDensity / 2;

            Point p = hueToPoint(mHue);

            RectF r = new RectF
            {
                Left = rect.Left - RECTANGLE_TRACKER_OFFSET,
                Right = rect.Right + RECTANGLE_TRACKER_OFFSET,
                Top = p.Y - rectHeight,
                Bottom = p.Y + rectHeight
            };

            canvas.DrawRoundRect(r, 2, 2, mHueAlphaTrackerPaint);

            //Log.d("mColorPicker", "Draw Time Hue: " + (SystemClock.elapsedRealtime() - start) + "ms");
        }
        private void DrawSatValPanel(Canvas canvas)
        {
            #if __ANDROID_11__
            if (Android.OS.Build.VERSION.SdkInt > Android.OS.BuildVersionCodes.Honeycomb)
            {
                RootView.SetLayerType(LayerType.Software, null);
            }
            #endif
            
            var rect = _satValRect;

		    if(BorderWidthPx > 0){
			    _borderPaint.Color = _borderColor;
                canvas.DrawRect(_drawingRect.Left, _drawingRect.Top, rect.Right + BorderWidthPx, rect.Bottom + BorderWidthPx, _borderPaint);
		    }

		    if (_valShader == null) {
                _valShader = new LinearGradient(rect.Left, rect.Top, rect.Left, rect.Bottom,
					    Color.Argb(255,255,255,255), Color.Argb(255,0,0,0), Shader.TileMode.Clamp);
		    }

		    var rgb = ColorUtils.ColorFromHSV(_hue/360f,1f,1f);

		    using (_satShader = new LinearGradient(rect.Left, rect.Top, rect.Right, rect.Top,
				    Color.Argb(255,255,255,255), rgb, Shader.TileMode.Clamp))
            {
		        var mShader = new ComposeShader(_valShader, _satShader, PorterDuff.Mode.Multiply);
		        _satValPaint.SetShader(mShader);

		        canvas.DrawRect(rect, _satValPaint);
            }
		    var p = SatValToPoint(_sat, _val);

		    _satValTrackerPaint.Color = Color.Argb(255,0,0,0);
		    canvas.DrawCircle(p.X, p.Y, _paletteCircleTrackerRadius - 1f * _density, _satValTrackerPaint);

		    _satValTrackerPaint.Color = Color.Argb(255, 221, 221, 221);
            canvas.DrawCircle(p.X, p.Y, _paletteCircleTrackerRadius, _satValTrackerPaint);    
	    }
        private void DrawSatValPanel(Canvas canvas)
        {
		    var rect = _satValRect;

		    if(BorderWidthPx > 0){
			    _borderPaint.Color = _borderColor;
                canvas.DrawRect(_drawingRect.Left, _drawingRect.Top, rect.Right + BorderWidthPx, rect.Bottom + BorderWidthPx, _borderPaint);
		    }

		    if (_valShader == null) {
                _valShader = new LinearGradient(rect.Left, rect.Top, rect.Left, rect.Bottom,
					    Color.Argb(255,255,255,255), Color.Argb(255,0,0,0), Shader.TileMode.Clamp);
		    }

		    var rgb = ColorUtils.ColorFromHSV(_hue/360f,1f,1f);

		    using (_satShader = new LinearGradient(rect.Left, rect.Top, rect.Right, rect.Top,
				    Color.Argb(255,255,255,255), rgb, Shader.TileMode.Clamp))
            {
		        var mShader = new ComposeShader(_valShader, _satShader, PorterDuff.Mode.Multiply);
		        _satValPaint.SetShader(mShader);

		        canvas.DrawRect(rect, _satValPaint);
            }
		    var p = SatValToPoint(_sat, _val);

		    _satValTrackerPaint.Color = Color.Argb(255,0,0,0);
		    canvas.DrawCircle(p.X, p.Y, _paletteCircleTrackerRadius - 1f * _density, _satValTrackerPaint);

		    _satValTrackerPaint.Color = Color.Argb(255, 221, 221, 221);
            canvas.DrawCircle(p.X, p.Y, _paletteCircleTrackerRadius, _satValTrackerPaint);    
	    }
示例#13
0
 public void SetStrokeColor(object color)
 {
     stroke       = color;
     strokeShader = null;
     Invalidate();
 }
示例#14
0
        /**
         * Set if the user is allowed to adjust the alpha panel. Default is false.
         * If it is set to false no alpha will be set.
         * @param visible
         */
        public void setAlphaSliderVisible(bool visible)
        {
            if (mShowAlphaPanel != visible)
            {
                mShowAlphaPanel = visible;

                /*
                 * Reset all shader to force a recreation.
                 * Otherwise they will not look right after
                 * the size of the view has changed.
                 */
                mValShader = null;
                mSatShader = null;
                mHueShader = null;
                ;

                RequestLayout();
            }
        }
        private void DrawHuePanel(Canvas canvas)
        {
		    var rect = _hueRect;

            if (BorderWidthPx > 0)
            {
			    _borderPaint.Color = _borderColor;
                canvas.DrawRect(rect.Left - BorderWidthPx,
                        rect.Top - BorderWidthPx,
                        rect.Right + BorderWidthPx,
                        rect.Bottom + BorderWidthPx,
					    _borderPaint);
		    }

		    if (_hueShader == null) {
                using(_hueShader = 
                    new LinearGradient(rect.Left, rect.Top, rect.Left, rect.Bottom, BuildHueColorArray(), null, Shader.TileMode.Clamp))
                    _huePaint.SetShader(_hueShader);
		    }

		    canvas.DrawRect(rect, _huePaint);

		    var rectHeight = 4 * _density / 2;

		    var p = HueToPoint(_hue);

            var r = new RectF
                        {
                            Left = rect.Left - _rectangleTrackerOffset,
                            Right = rect.Right + _rectangleTrackerOffset,
                            Top = p.Y - rectHeight,
                            Bottom = p.Y + rectHeight
                        };

            canvas.DrawRoundRect(r, 2, 2, _hueTrackerPaint);
	    }
示例#16
0
        protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
        {
            base.OnSizeChanged(w, h, oldw, oldh);

            mDrawingRect = new RectF();
            mDrawingRect.Left = mDrawingOffset + PaddingLeft;
            mDrawingRect.Right = w - mDrawingOffset - PaddingRight;
            mDrawingRect.Top = mDrawingOffset + PaddingTop;
            mDrawingRect.Bottom = h - mDrawingOffset - PaddingBottom;

            //The need to be recreated because they depend on the size of the view.
            mValShader = null;
            mSatShader = null;
            mHueShader = null;
            ;

            setUpSatValRect();
            setUpHueRect();
            setUpAlphaRect();
        }
        private void DrawAlphaPanel(Canvas canvas){

		    if(!_showAlphaPanel || _alphaRect == null || _alphaPattern == null) return;

		    var rect = _alphaRect;

            if (BorderWidthPx > 0)
            {
			    _borderPaint.Color = _borderColor;
                canvas.DrawRect(rect.Left - BorderWidthPx,
                        rect.Top - BorderWidthPx,
                        rect.Right + BorderWidthPx,
                        rect.Bottom + BorderWidthPx,
					    _borderPaint);
		    }


		    _alphaPattern.Draw(canvas);

		    var color = ColorUtils.ColorFromHSV(_hue/360f,_sat,_val);
            var acolor = ColorUtils.ColorFromHSV(_hue/360f, _sat, _val, 0);

		    using (_alphaShader = new LinearGradient(rect.Left, rect.Top, rect.Right, rect.Top,
				    color, acolor, Shader.TileMode.Clamp))
            {
    		    _alphaPaint.SetShader(_alphaShader);

                canvas.DrawRect(rect, _alphaPaint);
            }

		    if(!string.IsNullOrEmpty(_alphaSliderText)){
                canvas.DrawText(_alphaSliderText, rect.CenterX(), rect.CenterY() + 4 * _density, _alphaTextPaint);
		    }

		    float rectWidth = 4 * _density / 2;

		    var p = AlphaToPoint(_alpha);

            var r = new RectF
                        {
                            Left = p.X - rectWidth,
                            Right = p.X + rectWidth,
                            Top = rect.Top - _rectangleTrackerOffset,
                            Bottom = rect.Bottom + _rectangleTrackerOffset
                        };

            canvas.DrawRoundRect(r, 2, 2, _hueTrackerPaint);

	    }
示例#18
0
        private void drawSatValPanel(Canvas canvas)
        {
            /*
             * Draw time for this code without using bitmap cache and hardware acceleration was around 20ms.
             * Now with the bitmap cache and the ability to use hardware acceleration we are down at 1ms as long as the hue isn't changed.
             * If the hue is changed we the sat/val rectangle will be rendered in software and it takes around 10ms.
             * But since the rest of the view will be rendered in hardware the performance gain is big!
             */

            RectF rect = mSatValRect;

            if (BORDER_WIDTH_PX > 0)
            {
                mBorderPaint.Color = new Color((int)mBorderColor);
                canvas.DrawRect(mDrawingRect.Left, mDrawingRect.Top, rect.Right + BORDER_WIDTH_PX, rect.Bottom + BORDER_WIDTH_PX, mBorderPaint);
            }

            if (mValShader == null)
            {
                //Black gradient has either not been created or the view has been resized.
                uint startColor = 0xFFFFFFFF;
                uint endColor = 0xFF000000;
                mValShader = new LinearGradient(rect.Left, rect.Top, rect.Left, rect.Bottom,
                        new Color((int)startColor), new Color((int)endColor), Shader.TileMode.Clamp);
            }

            //If the hue has changed we need to recreate the cache.
            if (mSatValBackgroundCache == null || mSatValBackgroundCache.value != mHue)
            {

                if (mSatValBackgroundCache == null)
                {
                    mSatValBackgroundCache = new BitmapCache();
                }

                //We create our bitmap in the cache if it doesn't exist.
                if (mSatValBackgroundCache.bitmap == null)
                {
                    mSatValBackgroundCache.bitmap = Bitmap.CreateBitmap((int)rect.Width(), (int)rect.Height(), Bitmap.Config.Argb8888);
                }

                //We create the canvas once so we can draw on our bitmap and the hold on to it.
                if (mSatValBackgroundCache.canvas == null)
                {
                    mSatValBackgroundCache.canvas = new Canvas(mSatValBackgroundCache.bitmap);
                }

                int rgb = Color.HSVToColor(new float[] { mHue, 1f, 1f });
                uint startColor = 0xFFFFFFFF;
                mSatShader = new LinearGradient(rect.Left, rect.Top, rect.Right, rect.Top,
                        new Color((int)startColor), new Color(rgb), Shader.TileMode.Clamp);

                ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.Multiply);
                mSatValPaint.SetShader(mShader);

                //ly we draw on our canvas, the result will be stored in our bitmap which is already in the cache.
                //Since this is drawn on a canvas not rendered on screen it will automatically not be using the hardware acceleration.
                //And this was the code that wasn't supported by hardware acceleration which mean there is no need to turn it of anymore.
                //The rest of the view will still be hardware accelerated!!
                mSatValBackgroundCache.canvas.DrawRect(0, 0, mSatValBackgroundCache.bitmap.Width, mSatValBackgroundCache.bitmap.Height, mSatValPaint);

                //We set the hue value in our cache to which hue it was drawn with,
                //then we know that if it hasn't changed we can reuse our cached bitmap.
                mSatValBackgroundCache.value = mHue;

            }

            //We draw our bitmap from the cached, if the hue has changed
            //then it was just recreated otherwise the old one will be used.
            canvas.DrawBitmap(mSatValBackgroundCache.bitmap, null, rect, null);

            Point p = satValToPoint(mSat, mVal);

            mSatValTrackerPaint.Color = Color.Black;
            canvas.DrawCircle(p.X, p.Y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);

            mSatValTrackerPaint.Color = Color.LightGray;
            canvas.DrawCircle(p.X, p.Y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
        }
示例#19
0
        protected override void OnDraw(droidGraphics.Canvas canvas)
        {
            base.OnDraw(canvas);

            // Prevent clipping of negative coordinates Step 2
            // TODO: Is there a better place / way to do this?
            if (Parent != null)
            {
                if (Parent.Parent as global::Android.Views.ViewGroup != null)
                {
                    (Parent.Parent as global::Android.Views.ViewGroup).SetClipChildren(false);
                }
            }

            if (Path == null)
            {
                return;
            }

            droidGraphics.Matrix stretchMatrix = ComputeStretchMatrix();

            Path.Transform(stretchMatrix);
            stretchMatrix.MapRect(pathFillBounds);
            stretchMatrix.MapRect(pathStrokeBounds);

            // Special processing for Rectangle because RadiusX, RadiusY can't be subject to Stretch transform
            if (this is RectangleDrawableView)
            {
                float radiusX = (this as RectangleDrawableView).RadiusX;
                float radiusY = (this as RectangleDrawableView).RadiusY;

                Path.Reset();
                Path.AddRoundRect(pathFillBounds, radiusX, radiusY, droidGraphics.Path.Direction.Cw);       // TODO: is the direction right?
            }

            if (fill != null)
            {
                drawable.Paint.SetStyle(droidGraphics.Paint.Style.Fill);

                if (fill is Color)
                {
                    Color fillColor = (Color)fill;

                    drawable.Paint.SetARGB((int)(255 * fillColor.A),
                                           (int)(255 * fillColor.R),
                                           (int)(255 * fillColor.G),
                                           (int)(255 * fillColor.B));
                }
                else if (fillShader == null)
                {
                    if (fill is LinearGradientBrush)
                    {
                        fillShader = CreateLinearGradient(fill as LinearGradientBrush, pathFillBounds, stretchMatrix);
                    }
                    else if (fill is ImageBrush)
                    {
                        fillShader = CreateBitmapShader(fill as ImageBrush);
                    }

                    drawable.Paint.SetShader(fillShader);
                }

                drawable.Draw(canvas);
                drawable.Paint.SetShader(null);
            }

            if (stroke != null)
            {
                drawable.Paint.SetStyle(droidGraphics.Paint.Style.Stroke);

                if (stroke is Color)
                {
                    Color strokeColor = (Color)stroke;

                    drawable.Paint.SetARGB((int)(255 * strokeColor.A),
                                           (int)(255 * strokeColor.R),
                                           (int)(255 * strokeColor.G),
                                           (int)(255 * strokeColor.B));
                }
                else if (strokeShader == null)
                {
                    if (stroke is LinearGradientBrush)
                    {
                        strokeShader = CreateLinearGradient(stroke as LinearGradientBrush, pathStrokeBounds, stretchMatrix);
                    }
                    else if (stroke is ImageBrush)
                    {
                        strokeShader = CreateBitmapShader(stroke as ImageBrush);
                    }

                    drawable.Paint.SetShader(strokeShader);
                }

                drawable.Draw(canvas);
                drawable.Paint.SetShader(null);
            }

            // Return everything back to its pre-stretched state
            droidGraphics.Matrix inverseStretchMatrix = new droidGraphics.Matrix();
            stretchMatrix.Invert(inverseStretchMatrix);

            Path.Transform(inverseStretchMatrix);
            inverseStretchMatrix.MapRect(pathFillBounds);
            inverseStretchMatrix.MapRect(pathStrokeBounds);
        }