protected override void OnDraw(Android.Graphics.Canvas canvas) { // if our render buffers are not valid, generate them if (CurrWidth != this.LayoutParameters.Width || CurrHeight != this.LayoutParameters.Height) { CreateTextBitmaps(this.LayoutParameters.Width, this.LayoutParameters.Height); CreateResultBitmaps(this.LayoutParameters.Width, this.LayoutParameters.Height); CurrWidth = this.LayoutParameters.Width; CurrHeight = this.LayoutParameters.Height; } // keep the spot light centered on the image float xPos = (LayoutParameters.Width / 2) - ((AlphaMask.Width / 2) * MaskScale); float yPos = (LayoutParameters.Height / 2) - ((AlphaMask.Height / 2) * MaskScale); // update the text's transform for the mask scale. // The text's transform should be the inverse of the Canvas' values TextTransform.SetScale(1.0f / MaskScale, 1.0f / MaskScale); TextTransform.PreTranslate(-xPos, -yPos); TextPaint.Shader.SetLocalMatrix(TextTransform); // clear the bitmap before re-rendering. (NOT EFFICIENT _AT_ _ALL_) ResultBmp.SetPixels(new int[ResultBmp.RowBytes * ResultBmp.Height], 0, ResultBmp.RowBytes, 0, 0, ResultBmp.Width, ResultBmp.Height); // save / restore the canvas settings so we don't accumulate the scale ResultCanvas.Save(); ResultCanvas.Translate(xPos, yPos); ResultCanvas.Scale(MaskScale, MaskScale); // render the alpha mask'd text to our result bmp ResultCanvas.DrawBitmap(AlphaMask, 0, 0, TextPaint); // restore the canvas values for next time. ResultCanvas.Restore(); // and to the actual android buffer, render our result canvas.DrawBitmap(ResultBmp, 0, 0, null); }