{
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getHeader(headerName);
    }

package com.zyd.blog.util;

import com.zyd.blog.framework.holder.RequestHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0
 * @website https://docs.zhyd.me
 * @date 2018/4/18 11:48
 * @since 1.0
 */
public class RequestUtil {

    public static String getParameters() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        Enumeration<String> paraNames = request.getParameterNames();
        if (paraNames == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        while (paraNames.hasMoreElements()) {
            String paraName = paraNames.nextElement();
            sb.append("&").append(paraName).append("=").append(request.getParameter(paraName));
        }
        return sb.toString();
    }

    public static Map<String, String[]> getParametersMap() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return new HashMap<>();
        }
        return request.getParameterMap();
    }

    public static String getHeader(String headerName)

    public static String getReferer() {
        return getHeader("Referer");
    }

    public static String getUa() {
        return getHeader("User-Agent");
    }

    public static String getIp() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return IpUtil.getRealIp(request);
    }

    public static String getRequestUrl() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getRequestURL().toString();
    }

    public static String getMethod() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getMethod();
    }

    public static boolean isAjax(HttpServletRequest request) {
        if (null == request) {
            request = RequestHolder.getRequest();
        }
        if (null == request) {
            return false;
        }
        return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With")) || request.getParameter("ajax") != null;
    }
}


package com.zyd.blog.util;

import com.zyd.blog.framework.holder.RequestHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0
 * @website https://docs.zhyd.me
 * @date 2018/4/18 11:48
 * @since 1.0
 */
public class RequestUtil {

    public static String getParameters() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        Enumeration<String> paraNames = request.getParameterNames();
        if (paraNames == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        while (paraNames.hasMoreElements()) {
            String paraName = paraNames.nextElement();
            sb.append("&").append(paraName).append("=").append(request.getParameter(paraName));
        }
        return sb.toString();
    }

    public static Map<String, String[]> getParametersMap() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return new HashMap<>();
        }
        return request.getParameterMap();
    }

    public static String getHeader(String headerName) {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getHeader(headerName);
    }

    public static String getReferer() {
        return getHeader("Referer");
    }

    public static String getUa() {
        return ge

    }

    public static String getIp() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return IpUtil.getRealIp(request);
    }

    public static String getRequestUrl() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getRequestURL().toString();
    }

    public static String getMethod() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getMethod();
    }

    public static boolean isAjax(HttpServletRequest request) {
        if (null == request) {
            request = RequestHolder.getRequest();
        }
        if (null == request) {
            return false;
        }
        return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With")) || request.getParameter("ajax") != null;
    }
}


while (paraNames.hasMoreElements()) {
            String paraName = paraNames.nextElement();
            sb.append("&").append(paraName).append("=").append(request.getParameter(paraName));
        }

package com.zyd.blog.util;

import com.zyd.blog.framework.holder.RequestHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0
 * @website https://docs.zhyd.me
 * @date 2018/4/18 11:48
 * @since 1.0
 */
public class RequestUtil {

    public static String getParameters() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        Enumeration<String> paraNames = request.getParameterNames();
        if (paraNames == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();

        return sb.toString();
    }

    public static Map<String, String[]> getParametersMap() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return new HashMap<>();
        }
        return request.getParameterMap();
    }

    public static String getHeader(String headerName) {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getHeader(headerName);
    }

    public static String getReferer() {
        return getHeader("Referer");
    }

    public static String getUa() {
        return getHeader("User-Agent");
    }

    public static String getIp() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return IpUtil.getRealIp(request);
    }

    public static String getRequestUrl() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getRequestURL().toString();
    }

    public static String getMethod() {
        HttpServletRequest request = RequestHolder.getRequest();
        if (null == request) {
            return null;
        }
        return request.getMethod();
    }

    public static boolean isAjax(HttpServletRequest request) {
        if (null == request) {
            request = RequestHolder.getRequest();
        }
        if (null == request) {
            return false;
        }
        return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With")) || request.getParameter("ajax") != null;
    }
}


package Hardware.CPU.Intel8086.Register;

public final class Reg8Hi extends Reg8 {

    public Reg8Hi(String name, Reg16 reg) {
        super(name, reg);
    }

{
        return m_reg.getValue() >> 8;
    }

    @Override
    public void setValue(int value) {
        m_reg.setValue((m_reg.getValue() & 0x00ff) | ((value & 0xff) << 8));
    }
}


{
        m_reg.setValue((m_reg.getValue() & 0x00ff) | ((value & 0xff) << 8));
    }

package Hardware.CPU.Intel8086.Register;

public final class Reg8Hi extends Reg8 {

    public Reg8Hi(String name, Reg16 reg) {
        super(name, reg);
    }

    @Override
    public int getValue() {
        return m_reg.getValue() >> 8;
    }

    @Override
    public void setValue(int value)


package Hardware.CPU.Intel8086.Register;

public final class Reg8Hi extends Reg8 {

    public Reg8Hi(String name, Reg16 reg) {
        super(name, reg);
    }

    @Override
    public int getValue() {
        return m_r

    }

    @Override
    public void setValue(int value) {
        m_reg.setValue((m_reg.getValue() & 0x00ff) | ((value & 0xff) << 8));
    }
}


public BaseElementBehavior parser(BaseElement baseElement)

/**
 * @author kenshin
 * @author ych
 */
package org.foxbpm.engine.impl.bpmn.parser.model;

import org.foxbpm.engine.impl.bpmn.behavior.BaseElementBehavior;
import org.foxbpm.model.BaseElement;

public abstract class FlowNodeParser extends FlowElementParser {

{
        return super.parser(baseElement);
    }
}


{
        return super.parser(baseElement);
    }

/**
 * @author kenshin
 * @author ych
 */
package org.foxbpm.engine.impl.bpmn.parser.model;

import org.foxbpm.engine.impl.bpmn.behavior.BaseElementBehavior;
import org.foxbpm.model.BaseElement;

public abstract class FlowNodeParser extends FlowElementParser {

    public BaseElementBehavior parser(BaseElement baseElement)


/**
 * @author kenshin
 * @author ych
 */
package org.foxbpm.engine.impl.bpmn.parser.model;

import org.foxbpm.engine.impl.bpmn.behavior.BaseElementBehavior;
import org.foxbpm.model.BaseElement;

public abstract class FlowNodeParser extends FlowElementParser {

    public BaseElementBehavior parser(BaseElement baseElement) {
        return super.parser(baseE


@Override
    public long getDurationUs()

package com.google.android.exoplayer2.extractor.mp3;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.MpegAudioHeader;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;

/**
 * MP3 seeker that uses metadata from a VBRI header.
 */
final class VbriSeeker implements Mp3Extractor.Seeker {

    /**
     * Returns a {@link VbriSeeker} for seeking in the stream, if required information is present.
     * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the
     * caller should reset it.
     *
     * @param mpegAudioHeader The MPEG audio header associated with the frame.
     * @param frame The data in this audio frame, with its position set to immediately after the
     *     'VBRI' tag.
     * @param position The position (byte offset) of the start of this frame in the stream.
     * @param inputLength The length of the stream in bytes.
     * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required
     *     information is not present.
     */
    public static VbriSeeker create(MpegAudioHeader mpegAudioHeader, ParsableByteArray frame, long position, long inputLength) {
        frame.skipBytes(10);
        int numFrames = frame.readInt();
        if (numFrames <= 0) {
            return null;
        }
        int sampleRate = mpegAudioHeader.sampleRate;
        long durationUs = Util.scaleLargeTimestamp(numFrames, C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate);
        int entryCount = frame.readUnsignedShort();
        int scale = frame.readUnsignedShort();
        int entrySize = frame.readUnsignedShort();
        frame.skipBytes(2);
        // Skip the frame containing the VBRI header.
        position += mpegAudioHeader.frameSize;
        // Read table of contents entries.
        long[] timesUs = new long[entryCount + 1];
        long[] positions = new long[entryCount + 1];
        timesUs[0] = 0L;
        positions[0] = position;
        for (int index = 1; index < timesUs.length; index++) {
            int segmentSize;
            switch(entrySize) {
                case 1:
                    segmentSize = frame.readUnsignedByte();
                    break;
                case 2:
                    segmentSize = frame.readUnsignedShort();
                    break;
                case 3:
                    segmentSize = frame.readUnsignedInt24();
                    break;
                case 4:
                    segmentSize = frame.readUnsignedIntToInt();
                    break;
                default:
                    return null;
            }
            position += segmentSize * scale;
            timesUs[index] = index * durationUs / entryCount;
            positions[index] = inputLength == C.LENGTH_UNSET ? position : Math.min(inputLength, position);
        }
        return new VbriSeeker(timesUs, positions, durationUs);
    }

    private final long[] timesUs;

    private final long[] positions;

    private final long durationUs;

    private VbriSeeker(long[] timesUs, long[] positions, long durationUs) {
        this.timesUs = timesUs;
        this.positions = positions;
        this.durationUs = durationUs;
    }

    @Override
    public boolean isSeekable() {
        return true;
    }

    @Override
    public long getPosition(long timeUs) {
        return positions[Util.binarySearchFloor(timesUs, timeUs, true, true)];
    }

    @Override
    public long getTimeUs(long position) {
        return timesUs[Util.binarySearchFloor(positions, position, true, true)];
    }


package com.google.android.exoplayer2.extractor.mp3;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.MpegAudioHeader;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;

/**
 * MP3 seeker that uses metadata from a VBRI header.
 */
final class VbriSeeker implements Mp3Extractor.Seeker {

    /**
     * Returns a {@link VbriSeeker} for seeking in the stream, if required information is present.
     * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the
     * caller should reset it.
     *
     * @param mpegAudioHeader The MPEG audio header associated with the frame.
     * @param frame The data in this audio frame, with its position set to immediately after the
     *     'VBRI' tag.
     * @param position The position (byte offset) of the start of this frame in the stream.
     * @param inputLength The length of the stream in bytes.
     * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required
     *     information is not present.
     */
    public static VbriSeeker create(MpegAudioHeader mpegAudioHeader, ParsableByteArray frame, long position, long inputLength) {
        frame.skipBytes(10);
        int numFrames = frame.readInt();
        if (numFrames <= 0) {
            return null;
        }
        int sampleRate = mpegAudioHeader.sampleRate;
        long durationUs = Util.scaleLargeTimestamp(numFrames, C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate);
        int entryCount = frame.readUnsignedShort();
        int scale = frame.readUnsignedShort();
        int entrySize = frame.readUnsignedShort();
        frame.skipBytes(2);
        // Skip the frame containing the VBRI header.
        position += mpegAudioHeader.frameSize;
        // Read table of contents entries.
        long[] timesUs = new long[entryCount + 1];
        long[] positions = new long[entryCount + 1];
        timesUs[0] = 0L;
        positions[0] = position;
        for (int index = 1; index < timesUs.length; index++) {
            int segmentSize;
            switch(entrySize) {
                case 1:
                    segmentSize = frame.readUnsignedByte();
                    break;
                case 2:
                    segmentSize = frame.readUnsignedShort();
                    break;
                case 3:
                    segmentSize = frame.readUnsignedInt24();
                    break;
                case 4:
                    segmentSize = frame.readUnsignedIntToInt();
                    break;
                default:
                    return null;
            }
            position += segmentSize * scale;
            timesUs[index] = index * durationUs / entryCount;
            positions[index] = inputLength == C.LENGTH_UNSET ? position : Math.min(inputLength, position);
        }
        return new VbriSeeker(timesUs, positions, durationUs);
    }

    private final long[] timesUs;

    private final long[] positions;

    private final long durationUs;

    private VbriSeeker(long[] timesUs, long[] positions, long durationUs) {
        this.timesUs = timesUs;
        this.positions = positions;
        this.durationUs = durationUs;
    }

    @Override
    public boolean isSeekable()

    @Override
    public long getPosition(long timeUs) {
        return positions[Util.binarySearchFloor(timesUs, timeUs, true, true)];
    }

    @Override
    public long getTimeUs(long position) {
        return timesUs[Util.binarySearchFloor(positions, position, true, true)];
    }

    @Override
    public long getDurationUs() {
        return durationUs;
    }
}


package com.google.android.exoplayer2.extractor.mp3;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.MpegAudioHeader;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;

/**
 * MP3 seeker that uses metadata from a VBRI header.
 */
final class VbriSeeker implements Mp3Extractor.Seeker {

    /**
     * Returns a {@link VbriSeeker} for seeking in the stream, if required information is present.
     * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the
     * caller should reset it.
     *
     * @param mpegAudioHeader The MPEG audio header associated with the frame.
     * @param frame The data in this audio frame, with its position set to immediately after the
     *     'VBRI' tag.
     * @param position The position (byte offset) of the start of this frame in the stream.
     * @param inputLength The length of the stream in bytes.
     * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required
     *     information is not present.
     */
    public static VbriSeeker create(MpegAudioHeader mpegAudioHeader, ParsableByteArray frame, long position, long inputLength) {
        frame.skipBytes

        int numFrames = frame.readInt();
        if (numFrames <= 0) {
            return null;
        }
        int sampleRate = mpegAudioHeader.sampleRate;
        long durationUs = Util.scaleLargeTimestamp(numFrames, C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate);
        int entryCount = frame.readUnsignedShort();
        int scale = frame.readUnsignedShort();
        int entrySize = frame.readUnsignedShort();
        frame.skipBytes(2);
        // Skip the frame containing the VBRI header.
        position += mpegAudioHeader.frameSize;
        // Read table of contents entries.
        long[] timesUs = new long[entryCount + 1];
        long[] positions = new long[entryCount + 1];
        timesUs[0] = 0L;
        positions[0] = position;
        for (int index = 1; index < timesUs.length; index++) {
            int segmentSize;
            switch(entrySize) {
                case 1:
                    segmentSize = frame.readUnsignedByte();
                    break;
                case 2:
                    segmentSize = frame.readUnsignedShort();
                    break;
                case 3:
                    segmentSize = frame.readUnsignedInt24();
                    break;
                case 4:
                    segmentSize = frame.readUnsignedIntToInt();
                    break;
                default:
                    return null;
            }
            position += segmentSize * scale;
            timesUs[index] = index * durationUs / entryCount;
            positions[index] = inputLength == C.LENGTH_UNSET ? position : Math.min(inputLength, position);
        }
        return new VbriSeeker(timesUs, positions, durationUs);
    }

    private final long[] timesUs;

    private final long[] positions;

    private final long durationUs;

    private VbriSeeker(long[] timesUs, long[] positions, long durationUs) {
        this.timesUs = timesUs;
        this.positions = positions;
        this.durationUs = durationUs;
    }

    @Override
    public boolean isSeekable() {
        return true;
    }

    @Override
    public long getPosition(long timeUs) {
        return positions[Util.binarySearchFloor(timesUs, timeUs, true, true)];
    }

    @Override
    public long getTimeUs(long position) {
        return timesUs[Util.binarySearchFloor(positions, position, true, true)];
    }

    @Override
    public long getDurationUs() {
        return durationUs;
    }
}


package com.sun.ts.tests.webservices12.wsdlImport.http.simple1;

import jakarta.jws.WebService;

@WebService(portName = "TestsPort", serviceName = "Simple1HttpSvc", targetNamespace = "http://Simple1HttpSvc.org/wsdl", wsdlLocation = "WEB-INF/wsdl/Simple1HttpSvc.wsdl", endpointInterface = "com.sun.ts.tests.webservices12.wsdlImport.http.simple1.Tests")
public class TestsImpl implements Tests {


package com.sun.ts.tests.webservices12.wsdlImport.http.simple1;

import jakarta.jws.WebService;

@WebService(portName = "TestsPort", serviceName = "Simple1HttpSvc", targetNamespace = "http://Simple1HttpSvc.org/wsdl", wsdlLocation = "WEB-INF/wsdl/Simple1HttpSvc.wsdl", endpointInterface = "com.sun.ts.tests.webservices12.wsdlImport.http.simple1.Tests")
public class TestsImpl implements Tests {

    public String invokeTest1()


package com.sun.ts.tests.webservices12.wsdlImport.http.simple1;

import jakarta.jws.WebService;

@WebService(portName = "TestsPort", serviceName = "Simple1HttpSvc", targetNamespace = "http://Simple1HttpSvc.org/wsdl", wsdlLocation = "WEB-INF/wsdl/Simple1HttpSvc.wsdl", endpointInterface = "com.sun.ts.tests.webservices12.wsdlImport.http.simple1.Tests")
public class TestsImpl implements Tests {

    public String invokeTest1() {
        return "He


package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化
        try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId) {
        return BitmapFactory.decodeResource(getResources(), resId);
    }

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */
    public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;
        for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }
    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

{
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


{
        return BitmapFactory.decodeResource(getResources(), resId);
    }

package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化
        try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId)

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */
    public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;
        for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }
    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化
        try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId) {
        return BitmapFactory.decodeResource(getResources(), resId);
    }

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bi

    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */
    public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;
        for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }
    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化
        try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId) {
        return BitmapFactory.decodeResource(getResources(), resId);
    }

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;
        for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }
    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }

package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化
        try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId) {
        return BitmapFactory.decodeResource(getResources(), resId);
    }

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */
    public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;

    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


try {
            points = PointUtils.getListPointByResourceJson(RoseGiftSurfaceView.this.getContext(), ASSET_LOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }

package com.meis.widget.rose;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.meis.widget.R;
import com.meis.widget.utils.PointUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Created by wenshi on 2018/6/26.
 * Description 改变自'那夕阳下的奔跑，是我逝去的青春'
 * 'http://example.com'
 */
public class RoseGiftSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 不使用时回收c层内存
    private Bitmap bitmap;

    // 画布
    private Canvas canvas;

    // 画笔
    private Paint paint;

    // 随机数
    private Random random;

    // 起点集合
    private Point[] startPoint;

    // 终点集合
    private Point[] endPoint;

    // 动画期间点集合
    private Point[] currentPoint;

    // 点集合
    private List<Point> points = new ArrayList<>();

    // 控件宽度
    private float width;

    // 控件高度
    private float height;

    private float scale = 1;

    /**
     * 偏移（非随机情况下有效）
     */
    private int offsetX;

    // y轴偏移量
    private int offsetY;

    // 属性动画
    private ValueAnimator animator;

    private int duration = 3000;

    private static final String ASSET_LOVE = "assets/json/love.json";

    public RoseGiftSurfaceView(Context context) {
        this(context, null);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoseGiftSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    // 初始化数据
    private void initData() {
        paint = new Paint();
        // paint抗锯齿
        paint.setAntiAlias(true);
        random = new Random();
        // 设置透明
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
        getHolder().addCallback(this);
        setLayerType(View.LAYER_TYPE_NONE, null);
        // 设置图片
        setImageBitmap(getBitmapByResource(R.drawable.mei_rose), 0.5F);
        // 设置点集合 性能待优化

    }

    /**
     * @param resId
     * @return
     */
    private Bitmap getBitmapByResource(@DrawableRes int resId) {
        return BitmapFactory.decodeResource(getResources(), resId);
    }

    /**
     * @param resId
     */
    public void setImageResource(@DrawableRes int resId) {
        setImageBitmap(getBitmapByResource(resId));
    }

    /**
     * @param resId
     * @param scale 缩放（图片）
     */
    public void setImageResource(@DrawableRes int resId, float scale) {
        setImageBitmap(getBitmapByResource(resId), scale);
    }

    /**
     * @param bitmap
     */
    public void setImageBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    /**
     * @param bitmap
     * @param scale  缩放（图片）
     */
    public void setImageBitmap(Bitmap bitmap, float scale) {
        this.bitmap = scaleBitmap(bitmap, scale);
    }

    /**
     * 图片按比例缩放
     *
     * @param bmp
     * @param scale
     * @return
     */
    private Bitmap scaleBitmap(Bitmap bmp, float scale) {
        int width = (int) (bmp.getWidth() * scale);
        int height = (int) (bmp.getHeight() * scale);
        return Bitmap.createScaledBitmap(bmp, width, height, true);
    }

    /**
     * 拼图的终点坐标的整体缩放
     *
     * @param scale   点坐标整体缩放
     *                1.0f 表示坐标
     * @param offsetX X 轴偏移量
     * @param offsetY Y 轴偏移量
     */
    public void setPointScale(float scale, int offsetX, int offsetY) {
        this.scale = scale;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public void setListPoint(List<Point> points) {
        this.points = points;
    }

    /**
     * 更新点集合
     *
     * @param points
     */
    private void updatePoints(List<Point> points) {
        if (verifyListEmpty(points))
            return;
        int number = points.size();
        startPoint = new Point[number];
        endPoint = new Point[number];
        currentPoint = new Point[number];
        for (int i = 0; i < number; i++) {
            endPoint[i] = new Point((int) (points.get(i).x * scale) + offsetX, (int) ((points.get(i).y + offsetY) * scale));
            startPoint[i] = random(endPoint[i].x, endPoint[i].y);
            currentPoint[i] = new Point(0, 0);
        }
    }

    private Point random(int endX, int endY) {
        int x = 0;
        int y = 0;
        if (width >= bitmap.getWidth() && height >= bitmap.getWidth()) {
            x = random.nextInt((int) (width - bitmap.getWidth() * 2)) + bitmap.getWidth();
            y = random.nextInt((int) (height - bitmap.getHeight() * 2)) + bitmap.getHeight();
        }
        if (x == endX && y == endY) {
            random(endX, endY);
        }
        return new Point(x, y);
    }

    private boolean verifyListEmpty(Collection array) {
        if (array == null || array.isEmpty()) {
            return true;
        }
        return false;
    }

    public void updateGiftSurfaceViewParams(int width, int height) {
        this.width = width;
        this.height = height;
        if (width == 0 || height == 0) {
            DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
            this.width = displayMetrics.widthPixels;
            this.height = displayMetrics.heightPixels;
        }
        setPointScale(1, (int) (this.width / 10), (int) (this.height / 3.8f));
        updatePoints(points);
    }

    public void startAnimation() {
        if (animator != null && animator.isRunning()) {
            return;
        }
        animator = ValueAnimator.ofFloat(0, 1).setDuration(duration);
        animator.setRepeatCount(-1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                getCurrentPoint((Float) animation.getAnimatedValue());
                drawBitmap();
            }
        });
        animator.start();
    }

    public void stopAnimation() {
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
    }

    private void getCurrentPoint(float valueAnimator) {
        if (startPoint == null || endPoint == null)
            return;
        for (int i = 0; i < startPoint.length; i++) {
            currentPoint[i].x = startPoint[i].x - (int) ((startPoint[i].x - endPoint[i].x) * valueAnimator);
            currentPoint[i].y = startPoint[i].y - (int) ((startPoint[i].y - endPoint[i].y) * valueAnimator);
        }
    }

    private void drawBitmap() {
        canvas = getHolder().lockCanvas();
        if (canvas != null) {
            if (currentPoint != null) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                for (int i = 0; i < currentPoint.length; i++) {
                    canvas.drawBitmap(bitmap, currentPoint[i].x - bitmap.getWidth() * .5f, currentPoint[i].y - bitmap.getHeight() * .5f, paint);
                }
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        updateGiftSurfaceViewParams(width, height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopAnimation();
    }
}


package module971packageJava0;

import java.lang.Integer;

public class Foo160 {

    Integer int0;

    Integer int1;

    public void foo0() {
        new module971packageJava0.Foo159().foo5();
    }

    public void foo1() {
        foo0();
    }

    public void foo2() {
        foo1();
    }

    public void foo3() {
        foo2();
    }

{
        foo3();
    }

    public void foo5() {
        foo4();
    }
}


package module971packageJava0;

import java.lang.Integer;

public class Foo160 {

    Integer int0;

    Integer int1;

    public void foo0() {
        new module971packageJava0.Foo159().foo5();
    }

    public void foo1() {
        foo0();
    }

    public void foo2() {
        foo1();
    }

    public void foo3()

    public void foo4() {
        foo3();
    }

    public void foo5() {
        foo4();
    }
}


package module971packageJava0;

import java.lang.Integer;

public class Foo160 {

    Integer int0;

    Integer int1;

    public void foo0() {
        new module971packageJava0.Foo159().foo5();
    }

    public void foo1() {
        fo

    }

    public void foo2() {
        foo1();
    }

    public void foo3() {
        foo2();
    }

    public void foo4() {
        foo3();
    }

    public void foo5() {
        foo4();
    }
}