/// <summary> /// Scrolls the specified widget to the specified coordinates, except /// constrains the X scrolling position to the horizontal regions of /// the text that will be visible after scrolling to the specified /// Y position. /// </summary> /// <remarks> /// Scrolls the specified widget to the specified coordinates, except /// constrains the X scrolling position to the horizontal regions of /// the text that will be visible after scrolling to the specified /// Y position. /// </remarks> public static void scrollTo(android.widget.TextView widget, android.text.Layout layout , int x, int y) { int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom( ); int top = layout.getLineForVertical(y); int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding); int left = int.MaxValue; int right = 0; android.text.Layout.Alignment? a = layout.getParagraphAlignment(top); bool ltr = layout.getParagraphDirection(top) > 0; { for (int i = top; i <= bottom; i++) { left = (int)System.Math.Min(left, layout.getLineLeft(i)); right = (int)System.Math.Max(right, layout.getLineRight(i)); } } int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight (); int availableWidth = widget.getWidth() - hoizontalPadding; int actualWidth = right - left; if (actualWidth < availableWidth) { if (a == android.text.Layout.Alignment.ALIGN_CENTER) { x = left - ((availableWidth - actualWidth) / 2); } else { if ((ltr && (a == android.text.Layout.Alignment.ALIGN_OPPOSITE)) || (a == android.text.Layout.Alignment .ALIGN_RIGHT)) { // align_opposite does NOT mean align_right, we need the paragraph // direction to resolve it to left or right x = left - (availableWidth - actualWidth); } else { x = left; } } } else { x = System.Math.Min(x, right - availableWidth); x = System.Math.Max(x, left); } widget.scrollTo(x, y); }
/// <summary> /// Returns an immutable bitmap from subset of the source bitmap, /// transformed by the optional matrix. /// </summary> /// <remarks> /// Returns an immutable bitmap from subset of the source bitmap, /// transformed by the optional matrix. It is /// initialized with the same density as the original bitmap. /// </remarks> /// <param name="source">The bitmap we are subsetting</param> /// <param name="x">The x coordinate of the first pixel in source</param> /// <param name="y">The y coordinate of the first pixel in source</param> /// <param name="width">The number of pixels in each row</param> /// <param name="height">The number of rows</param> /// <param name="m">Optional matrix to be applied to the pixels</param> /// <param name="filter"> /// true if the source should be filtered. /// Only applies if the matrix contains more than just /// translation. /// </param> /// <returns>A bitmap that represents the specified subset of source</returns> /// <exception cref="System.ArgumentException"> /// if the x, y, width, height values are /// outside of the dimensions of the source bitmap. /// </exception> public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap source , int x, int y, int width, int height, android.graphics.Matrix m, bool filter) { checkXYSign(x, y); checkWidthHeight(width, height); if (x + width > source.getWidth()) { throw new System.ArgumentException("x + width must be <= bitmap.width()"); } if (y + height > source.getHeight()) { throw new System.ArgumentException("y + height must be <= bitmap.height()"); } // check if we can just return our argument unchanged if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() && height == source.getHeight() && (m == null || m.isIdentity())) { return source; } int neww = width; int newh = height; android.graphics.Canvas canvas = new android.graphics.Canvas(); android.graphics.Bitmap bitmap; android.graphics.Paint paint; android.graphics.Rect srcR = new android.graphics.Rect(x, y, x + width, y + height ); android.graphics.RectF dstR = new android.graphics.RectF(0, 0, width, height); android.graphics.Bitmap.Config newConfig = android.graphics.Bitmap.Config.ARGB_8888; android.graphics.Bitmap.Config config = source.getConfig(); // GIF files generate null configs, assume ARGB_8888 if (config != null) { switch (config) { case android.graphics.Bitmap.Config.RGB_565: { newConfig = android.graphics.Bitmap.Config.RGB_565; break; } case android.graphics.Bitmap.Config.ALPHA_8: { newConfig = android.graphics.Bitmap.Config.ALPHA_8; break; } case android.graphics.Bitmap.Config.ARGB_4444: case android.graphics.Bitmap.Config.ARGB_8888: default: { //noinspection deprecation newConfig = android.graphics.Bitmap.Config.ARGB_8888; break; } } } if (m == null || m.isIdentity()) { bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha()); paint = null; } else { // not needed bool transformed = !m.rectStaysRect(); android.graphics.RectF deviceR = new android.graphics.RectF(); m.mapRect(deviceR, dstR); neww = Sharpen.Util.Round(deviceR.width()); newh = Sharpen.Util.Round(deviceR.height()); bitmap = createBitmap(neww, newh, transformed ? android.graphics.Bitmap.Config.ARGB_8888 : newConfig, transformed || source.hasAlpha()); canvas.translate(-deviceR.left, -deviceR.top); canvas.concat(m); paint = new android.graphics.Paint(); paint.setFilterBitmap(filter); if (transformed) { paint.setAntiAlias(true); } } // The new bitmap was created from a known bitmap source so assume that // they use the same density bitmap.mDensity = source.mDensity; canvas.setBitmap(bitmap); canvas.drawBitmap(source, srcR, dstR, paint); canvas.setBitmap(null); return bitmap; }
/// <summary>Returns an immutable bitmap from the source bitmap.</summary> /// <remarks> /// Returns an immutable bitmap from the source bitmap. The new bitmap may /// be the same object as source, or a copy may have been made. It is /// initialized with the same density as the original bitmap. /// </remarks> public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap src) { return createBitmap(src, 0, 0, src.getWidth(), src.getHeight()); }
/// <summary>Creates a new bitmap, scaled from an existing bitmap.</summary> /// <remarks>Creates a new bitmap, scaled from an existing bitmap.</remarks> /// <param name="src">The source bitmap.</param> /// <param name="dstWidth">The new bitmap's desired width.</param> /// <param name="dstHeight">The new bitmap's desired height.</param> /// <param name="filter">true if the source should be filtered.</param> /// <returns>the new scaled bitmap.</returns> public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap src, int dstWidth, int dstHeight, bool filter) { android.graphics.Matrix m; lock (typeof(android.graphics.Bitmap)) { // small pool of just 1 matrix m = sScaleMatrix; sScaleMatrix = null; } if (m == null) { m = new android.graphics.Matrix(); } int width = src.getWidth(); int height = src.getHeight(); float sx = dstWidth / (float)width; float sy = dstHeight / (float)height; m.setScale(sx, sy); android.graphics.Bitmap b = android.graphics.Bitmap.createBitmap(src, 0, 0, width , height, m, filter); lock (typeof(android.graphics.Bitmap)) { // do we need to check for null? why not just assign everytime? if (sScaleMatrix == null) { sScaleMatrix = m; } } return b; }
private static android.graphics.Bitmap finishDecode(android.graphics.Bitmap bm, android.graphics.Rect outPadding, android.graphics.BitmapFactory.Options opts) { if (bm == null || opts == null) { return bm; } int density = opts.inDensity; if (density == 0) { return bm; } bm.setDensity(density); int targetDensity = opts.inTargetDensity; if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { return bm; } byte[] np = bm.getNinePatchChunk(); bool isNinePatch = np != null && android.graphics.NinePatch.isNinePatchChunk(np); if (opts.inScaled || isNinePatch) { float scale = targetDensity / (float)density; // TODO: This is very inefficient and should be done in native by Skia android.graphics.Bitmap oldBitmap = bm; bm = android.graphics.Bitmap.createScaledBitmap(oldBitmap, (int)(bm.getWidth() * scale + 0.5f), (int)(bm.getHeight() * scale + 0.5f), true); oldBitmap.recycle(); if (isNinePatch) { np = nativeScaleNinePatch(np, scale, outPadding); bm.setNinePatchChunk(np); } bm.setDensity(targetDensity); } return bm; }
/// <summary>Draw the picture, stretched to fit into the dst rectangle.</summary> /// <remarks>Draw the picture, stretched to fit into the dst rectangle.</remarks> public virtual void drawPicture(android.graphics.Picture picture, android.graphics.Rect dst) { save(); translate(dst.left, dst.top); if (picture.getWidth() > 0 && picture.getHeight() > 0) { scale((float)dst.width() / picture.getWidth(), (float)dst.height() / picture.getHeight ()); } drawPicture(picture); restore(); }
/// <returns>The center of the given view.</returns> private static int getCenterOfView(android.view.View view) { return view.getLeft() + view.getWidth() / 2; }
private int getInnerWidth(android.widget.TextView widget) { return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight (); }