package com.tencent.livebackground.customview;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import com.tencent.livebackground.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.os.SystemClock;
import android.view.SurfaceHolder;
class LiveDrawingThread extends Thread {
private boolean mRun = true;
private final int FRAME_OFFSET = 50;
private SurfaceHolder mSurfaceHolder;
private ArrayList<Particle> mParticleList = new ArrayList<Particle>();
private ArrayList<Particle> mRecycleList = new ArrayList<Particle>();
public static int mCanvasWidth;
public static int mCanvasHeight;
private Paint mPaint;
public Lock m_lock;
private Bitmap m_bitmap;
private int LIVE_MAGIN_SIZE = -100;
private Bitmap mSrc0;
private Bitmap mSrcB;
private Bitmap mDstB;
private int top = 800;
private Context mContext;
PorterDuffXfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP);
public LiveDrawingThread(SurfaceHolder mSurfaceHolder, Context context) {
mContext = context;
this.mSurfaceHolder = mSurfaceHolder;
this.mPaint = new Paint();
mPaint.setColor(Color.BLACK);
}
static Bitmap makeSrc(int w, int h) {
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
int colors[] = {0xff559bff, 0x0078b3ff};
LinearGradient mShader = new LinearGradient(0, 0, 0, 240, colors, null, TileMode.REPEAT);
p.setShader(mShader);
c.drawRect(0, 0, 480, 240, p);
return bm;
}
@Override
public void run() {
mDstB = makeSrc(480, 240);
// mDstB = makeDst(W, H);
mSrc0 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.head_bg_mobile);
mSrcB = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.head_bg_mobile_on);
while (mRun) {
Canvas c = null;
try {
long curTime = SystemClock.uptimeMillis();
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
doDraw(c);
}
long timeOffset = SystemClock.uptimeMillis() - curTime;
if (timeOffset < FRAME_OFFSET) {
sleep(FRAME_OFFSET - timeOffset);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
synchronized (mParticleList) {
if (mParticleList.size() == 0) {
try {
mParticleList.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
private void doDraw(Canvas c) {
if (c == null) {
return;
}
synchronized (mParticleList) {
mPaint.setColor(Color.BLACK);
mPaint.setAlpha(255);
c.drawRect(0, 0, mCanvasWidth, mCanvasHeight, mPaint);
mPaint.setColor(0xff366dbf);
// c.drawRect(-LIVE_MAGIN_SIZE, -LIVE_MAGIN_SIZE, mCanvasWidth+LIVE_MAGIN_SIZE, mCanvasHeight+LIVE_MAGIN_SIZE, mPaint);
// c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// c.drawColor(0x366dbf, PorterDuff.Mode.CLEAR);
// c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// c.drawBitmap(m_bitmap, 0, 0, mPaint);
mPaint.setColor(Color.GREEN);
for (int i = 0; i < mParticleList.size(); i++) {
Particle p = mParticleList.get(i);
p.draw(c, System.currentTimeMillis());
if ((p.x < -LIVE_MAGIN_SIZE && p.mGoVector.x < 0) || (p.x > mCanvasWidth + LIVE_MAGIN_SIZE && p.mGoVector.x > 0) || (p.y < -LIVE_MAGIN_SIZE && p.mGoVector.y < 0)
|| (p.y > mCanvasHeight + LIVE_MAGIN_SIZE && p.mGoVector.y > 0)
) {
Point pos = getRandomPoint();
p.init(pos.x, pos.y);
}
}
Paint paint = new Paint();
c.drawBitmap(mSrc0, 0, 0, paint);
int sc = c.saveLayer(0, 0, mCanvasWidth, mCanvasHeight, null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
c.clipRect(0, top, 480, top+240);
c.drawBitmap(mSrcB, 0, 0, paint);
paint.setXfermode(mXfermode);
c.drawBitmap(mDstB, 0, top, paint);
paint.setXfermode(null);
c.restoreToCount(sc);
top -= 3;
if(top < -240) {
top = 800;
}
}
}
private Point getRandomPoint() {
Point pos = new Point();
double localX = Math.cos(Particle.gDirection);
double localY = Math.sin(Particle.gDirection);
double randPosition = Math.random();
double radio = Math.abs(localX)/(Math.abs(localY) + Math.abs(localX));
if(randPosition > radio) {
pos.x = (int)((mCanvasWidth+2*LIVE_MAGIN_SIZE) * (randPosition - radio))-LIVE_MAGIN_SIZE;
if(localY > 0) {
pos.y = -LIVE_MAGIN_SIZE;
} else {
pos.y = mCanvasHeight + LIVE_MAGIN_SIZE;
}
} else {
pos.y = (int)((mCanvasHeight+2*LIVE_MAGIN_SIZE) * randPosition)-LIVE_MAGIN_SIZE;
if(localX > 0) {
pos.x = -LIVE_MAGIN_SIZE;
} else {
pos.x = mCanvasWidth + LIVE_MAGIN_SIZE;
}
}
if(Math.abs(pos.x) > 1000 || Math.abs(pos.y) > 1000) {
pos.x = 1000;
pos.y = 1000;
}
return pos;
}
public void stopDrawing() {
this.mRun = false;
}
public ArrayList<Particle> getParticleList() {
return mParticleList;
}
public ArrayList<Particle> getRecycleList() {
return mRecycleList;
}
public void setSurfaceSize(int width, int height) {
mCanvasWidth = width;
mCanvasHeight = height;
synchronized (mParticleList) {
if (m_bitmap != null) {
m_bitmap.recycle();
}
// Bitmap bitmap = BitmapFactory.decodeResource(m_Context.getResources(), R.drawable.pattern);
// m_bitmap = ParticleDrawingThread.createRepeater(mCanvasWidth, mCanvasHeight, bitmap);
}
}
public static Bitmap createRepeater(int width, int height, Bitmap src) {
int countX = (width + src.getWidth() - 1) / src.getWidth();
int countY = (height + src.getHeight() - 1) / src.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
for (int idy = 0; idy < countY; ++idy) {
for (int idx = 0; idx < countX; ++idx) {
canvas.drawBitmap(src, idx * src.getWidth(), idy * src.getHeight(), null);
}
}
return bitmap;
}
}