拉伸无锯齿的SVG图片

来源:互联网 发布:java过滤器的原理 编辑:程序博客网 时间:2024/04/27 15:03
package com.moonlight.example;import com.larvalabs.svgandroid.SVG;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Bitmap.Config;import android.graphics.Paint.Style;import android.graphics.PorterDuff.Mode;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * @ClassName: SVGView * @Description: Scalable Vector Graphics M = moveto 相当于 android Path 里的moveTo(),用于移动起始点 L = lineto *               相当于 android Path 里的lineTo(),用于画线 H = horizontal lineto 用于画水平线 V = vertical lineto *               用于画竖直线 C = curveto 相当于cubicTo(),三次贝塞尔曲线 S = smooth curveto 同样三次贝塞尔曲线,更平滑 Q = *               quadratic Belzier curve quadTo(),二次贝塞尔曲线 T = smooth quadratic Belzier curveto *               同样二次贝塞尔曲线,更平滑 A = elliptical Arc 相当于arcTo(),用于画弧 Z = closepath 相当于closeTo(),关闭path * @author: moonlight * @date: 2016-9-19 下午4:06:15 */public class SVGView extends View {public static final String TAG = "SVGView";private Drawable sp_close, sp_scale, sp_flip;private RectF dstRect;private Paint paint_region;private TouchHelper touchHelper;private SVG svg;private Bitmap svgBitmap;private RectF srcRect;private float[] srcPts = new float[8];private float[] dstPts = new float[8];//用于svg的bitmap做旋转private Matrix svgMatrix = new Matrix();private Matrix rectMatrix = new Matrix();private ISVGAction svgAction;private float degreeTotal, flip = 1f;float[] values = new float[9];public SVGView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public SVGView(Context context) {super(context);init(context);}public void init(Context context) {sp_close = getResources().getDrawable(R.drawable.sp_close);sp_scale = getResources().getDrawable(R.drawable.sp_scale);sp_flip = getResources().getDrawable(R.drawable.sp_flip);dstRect = new RectF();srcRect = new RectF();paint_region = new Paint();paint_region.setColor(Color.BLACK);paint_region.setStyle(Style.STROKE);touchHelper = new TouchHelper();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (svg != null && svgBitmap == null) {int svg_w = svg.getPicture().getWidth();int svg_h = svg.getPicture().getHeight();int w_valid = w - sp_close.getIntrinsicWidth();int h_valid = h - sp_close.getIntrinsicHeight();if (svg_w > (w_valid) || svg_h > (h_valid)) {float scale_w = 1.0f * svg_w / w_valid;float scale_h = 1.0f * svg_h / h_valid;float scale = Math.max(scale_w, scale_h);svg_w /= scale;svg_h /= scale;}srcRect = new RectF(0, 0, svg_w, svg_h);srcPts[0] = srcRect.left;srcPts[1] = srcRect.top;srcPts[2] = srcRect.right;srcPts[3] = srcRect.top;srcPts[4] = srcRect.right;srcPts[5] = srcRect.bottom;srcPts[6] = srcRect.left;srcPts[7] = srcRect.bottom;rectMatrix.postTranslate(w / 2f - srcRect.centerX(), h / 2f - srcRect.centerY());touchHelper.lastDegree = (float) Math.toDegrees(Math.atan2(svg_h, svg_w));rectMatrix.mapRect(dstRect, srcRect);rectMatrix.mapPoints(dstPts, srcPts);changeSVGBitmap();}}@Overridepublic boolean onTouchEvent(MotionEvent event) {return touchHelper.onTouchEvent(event);}public void setSVG(SVG svg) {this.svg = svg;//可能View还没有初始化if (getWidth() != 0 && getHeight() != 0) {changeSVGBitmap();}}public enum RegionAction {MOVE, CLOSE, FINISH, SCALE, FLIP, NONE;}public RegionAction judgeRegionAction(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();//先判断四个控制点在判断移动区域if (sp_scale.getBounds().contains(x, y)) {return RegionAction.SCALE;}if (sp_close.getBounds().contains(x, y)) {return RegionAction.CLOSE;}if (sp_flip.getBounds().contains(x, y)) {return RegionAction.FLIP;}Matrix inverse = new Matrix();rectMatrix.invert(inverse);float[] pt = new float[] { x, y };inverse.mapPoints(pt);if (srcRect.contains(pt[0], pt[1])) {return RegionAction.MOVE;}return RegionAction.FINISH;}public class TouchHelper {private float lastX, lastY;private RegionAction actionRegion;private float lastDegree;public boolean onTouchEvent(MotionEvent event) {switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN:lastX = event.getX();lastY = event.getY();actionRegion = judgeRegionAction(event);break;case MotionEvent.ACTION_MOVE: {switch (actionRegion) {case MOVE: {float dx = (event.getX() - lastX);float dy = (event.getY() - lastY);regionMove(dx, dy);lastX = event.getX();lastY = event.getY();invalidate();break;}case SCALE: {regionScale(event);regionRotate(event);changeSVGBitmap();lastX = event.getX();lastY = event.getY();invalidate();break;}default:break;}}break;case MotionEvent.ACTION_UP:RegionAction actionRegionDown = judgeRegionAction(event);actionRegion = actionRegionDown == actionRegion ? actionRegionDown : RegionAction.NONE;switch (actionRegion) {case CLOSE:closeAction();break;case FINISH:finishAction();break;case FLIP:flipAction();invalidate();break;default:break;}break;default:break;}return true;}public void regionMove(float dx, float dy) {//if (dx < 0 && dstRect.left + dx < 0) {//dx = -dstRect.left;//} else if (dx > 0 && dstRect.right + dx > getWidth()) {//dx = getWidth() - (dstRect.right);//}//if (dy < 0 && dstRect.top + dy < 0) {//dy = -dstRect.top;//} else if (dy > 0 && dstRect.bottom + dy > getHeight()) {//dy = getHeight() - (dstRect.bottom);//}rectMatrix.postTranslate(dx, dy);}public void regionRotate(MotionEvent event) {float degree = (float) Math.toDegrees(Math.atan2(event.getY() - dstRect.centerY(),event.getX() - dstRect.centerX()));float degreeChange = degree - lastDegree;degreeTotal = (degreeTotal + degreeChange) % 360;rectMatrix.postRotate(degreeChange, dstRect.centerX(), dstRect.centerY());lastDegree = degree;}//基于中心点放缩public void regionScale(MotionEvent event) {float centerX = dstRect.centerX();float centerY = dstRect.centerY();float scale = (float) (Math.sqrt((event.getY() - centerY) * ((event.getY() - centerY))+ (event.getX() - centerX) * (event.getX() - centerX)) / Math.sqrt((lastY - centerY)* ((lastY - centerY)) + (lastX - centerX) * (lastX - centerX)));rectMatrix.postScale(scale, scale, centerX, centerY);svgMatrix.postScale(scale, scale);}public void finishAction() {if (svgAction != null) {svgAction.done(svgBitmap, new Rect((int) dstRect.left, (int) dstRect.top, (int) dstRect.right,(int) dstRect.bottom));}}public void closeAction() {if (svgAction != null) {svgAction.close();}}private void flipAction() {flip *= -1;//这个会变换坐标系,将x的方向翻转changeSVGBitmap();}}public void setSVGAction(ISVGAction action) {this.svgAction = action;}public interface ISVGAction {public void close();public void done(Bitmap bitmap, Rect postion);}//思路:先绘制未旋转的bmp,在去中心点做旋转操作public void changeSVGBitmap() {//变换前获得最终效果dstRectrectMatrix.mapRect(dstRect, srcRect);RectF svgRect, svgNoRotateRect;svgRect = new RectF(0, 0, (int) dstRect.width(), (int) dstRect.height());svgNoRotateRect = new RectF();svgMatrix.mapRect(svgNoRotateRect, srcRect);if (svgBitmap == null || (svgBitmap.getWidth() != svgRect.width() || svgBitmap.getHeight() != svgRect.height())) {if (svgBitmap != null)svgBitmap.recycle();svgBitmap = Bitmap.createBitmap((int) svgRect.width(), (int) svgRect.height(), Config.ARGB_4444);}//对canvas先做旋转,翻转,再做位移,注意顺序:位移最后做Canvas c = new Canvas(svgBitmap);c.drawColor(Color.TRANSPARENT, Mode.CLEAR);c.rotate(degreeTotal, svgRect.centerX(), svgRect.centerY());c.scale(flip, 1, svgRect.centerX(), svgRect.centerY());c.translate((svgRect.width() - svgNoRotateRect.width()) / 2f, (svgRect.height() - svgNoRotateRect.height()) / 2);//对svgNoRotateRect只做位移变换//Matrix m = new Matrix();//m.postTranslate((svgRect.width() - svgNoRotateRect.width()) / 2f,(svgRect.height() - svgNoRotateRect.height()) / 2);//m.mapRect(svgNoRotateRect);c.drawPicture(svg.getPicture(), svgNoRotateRect);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (svgBitmap != null) {rectMatrix.mapRect(dstRect, srcRect);rectMatrix.mapPoints(dstPts, srcPts);drawFrame(canvas);canvas.drawBitmap(svgBitmap, dstRect.centerX() - svgBitmap.getWidth() / 2f,dstRect.centerY() - svgBitmap.getHeight() / 2f, null);drawControlBtns(canvas);}}private void drawControlBtns(Canvas canvas) {setBoundsByCenterXY(sp_close, dstPts[0], dstPts[1]);sp_close.draw(canvas);setBoundsByCenterXY(sp_flip, dstPts[2], dstPts[3]);sp_flip.draw(canvas);setBoundsByCenterXY(sp_scale, dstPts[4], dstPts[5]);sp_scale.draw(canvas);}private void drawFrame(Canvas canvas) {canvas.drawLine(dstPts[0], dstPts[1], dstPts[2], dstPts[3], paint_region);canvas.drawLine(dstPts[2], dstPts[3], dstPts[4], dstPts[5], paint_region);canvas.drawLine(dstPts[4], dstPts[5], dstPts[6], dstPts[7], paint_region);canvas.drawLine(dstPts[6], dstPts[7], dstPts[0], dstPts[1], paint_region);}private void setBoundsByCenterXY(Drawable drawable, float centerX, float centerY) {drawable.setBounds((int) centerX - drawable.getIntrinsicWidth() / 2,(int) centerY - drawable.getIntrinsicHeight() / 2, (int) centerX + drawable.getIntrinsicWidth() / 2,(int) centerY + drawable.getIntrinsicHeight() / 2);}}

0 0
原创粉丝点击