Skia翻页效果的改写感谢何明桂的分享代码(第一版)

还有许多问题,关键是Gradient的修改。先保存下现有成果。

Page.h

#pragma once

#include "SkPreConfig.h"
#include "SkCanvas.h"
#include "SkRect.h"
#include "SkStream.h"
#include "SkPoint.h"
#include "SkGradientShader.h"  //SkGradientShader渐变色绘制(用于阴影)
#include "SkPath.h"            //路径,用于路径裁剪
#include "SkColorMatrix.h"
#include "SkColorMatrixFilter.h"
#include "SkImageDecoder.h"
#include "utils/skcamera.h"
//#include "skMath.h"

class CPage
{
public:
	CPage(void);
	~CPage(void);
	void CreateShader();
	void CalcCornerXY(float x,float y);
	BOOL DoTouchEvent();
	SkPoint GetCross(SkPoint p1,SkPoint p2,SkPoint p3,SkPoint p4);
	void CalcPoints();
	//void DrawCurrentPageArea(SkCanvas *canvas, SkBitmap *bitmap, SkPath *path);
	void DrawCurrentPageArea(SkCanvas *canvas, SkBitmap *bitmap);
	void DrawNextPageAreaAndShadow(SkCanvas *canvas, SkBitmap *bitmap);
	void SetBitmaps(SkBitmap *bm1, SkBitmap *bm2);

	void SetScreen(int w, int h);
	void DrawCurrentPageShadow(SkCanvas *canvas);
	void DrawCurrentBackArea(SkCanvas *canvas, SkBitmap *bitmap);
	void StartAnimation(int delayMillis);
	void AbortAnimation();
	BOOL CanDragOver();
	BOOL DragToRight();
	//void DrawPage(SkCanvas *canvas);
	void DrawPage(SkCanvas *canvas,SkPoint touch);
	BOOL LButtonDown(SkCanvas *canvas,SkPoint pt);
	BOOL MouseMove(SkCanvas *canvas,SkPoint pt);
	BOOL LButtonUp(SkCanvas *canvas,SkPoint pt);

	int mCornerX ; // 拖拽点对应的页脚
	int mCornerY ;

private:
	int mWidth;  //屏幕宽度 800
	int mHeight; //屏幕高度 480


	SkPath mPath0; //裁剪路径
	SkPath mPath1;

	SkBitmap *mCurPageBitmap ; // 当前页,由使用者传入
	SkBitmap *mNextPageBitmap ;

	SkPoint mTouch; // 拖拽点
	SkPoint mBezierStart1; // 贝塞尔曲线起始点
	SkPoint mBezierControl1 ; // 贝塞尔曲线控制点
	SkPoint mBeziervertex1 ; // 贝塞尔曲线顶点
	SkPoint mBezierEnd1  ; // 贝塞尔曲线结束点

	SkPoint mBezierStart2  ; // 另一条贝塞尔曲线
	SkPoint mBezierControl2  ;
	SkPoint mBeziervertex2  ;
	SkPoint mBezierEnd2 ;


	float mMiddleX;
	float mMiddleY;
	float mDegrees;
	float mTouchToCornerDis;
	SkColorMatrixFilter *mpColorMatrixFilter;
	SkMatrix mMatrix;
	//float[] mMatrixArray = { 0, 0, 0, 0, 0, 0, 0, 0, 1.0f };
	
	float mMatrixArray[9] ;

	boolean mIsRTandLB; // 是否属于右上左下
	//float mMaxLength = (float) Math.hypot(mWidth, mHeight);计算直角三角形协边
	float mMaxLength ;//屏幕对角线
	//int[] mBackShadowColors;
	//int[] mFrontShadowColors;
	//int * mBackShadowColors;
	//int * mFrontShadowColors;
	SkShader *mBackShadowDrawableLR;
	SkShader *mBackShadowDrawableRL;
	SkShader *mFolderShadowDrawableLR;
	SkShader *mFolderShadowDrawableRL;

	SkShader *mFrontShadowDrawableHBT;
	SkShader *mFrontShadowDrawableHTB;
	SkShader *mFrontShadowDrawableVLR;
	SkShader *mFrontShadowDrawableVRL;

	SkPaint mPaint;
	HWND mHwnd;
};

  Page.cpp

#include "StdAfx.h"
#include "Page.h"
#include "math.h"
#define PI (3.141592653)
CPage::CPage(void)
{
	mWidth = 800;
	mHeight = 480;
	mCornerX = 0;
	mCornerY = 0;
	mCurPageBitmap = NULL;
	mNextPageBitmap = NULL;

	mMaxLength = _hypot(mWidth,mHeight);

	CreateShader();
	mPaint.setStyle(SkPaint::Style::kFill_Style);
	//SkColorMatrix cm;
	float farray[] = {0.55f,0,    0,    0,		80.0f,// 0-4
					  0,    0.55f,0,    0,		80.0f,// 5-9
					  0,    0,    0.55f,0,		80.0f,//10-14
					  0,	0,	  0,	0.2f,	0};	  //15-19	
	
	//原来用数组farray初始化ColorMatrix,再用
	//ColorMatrix初始化ColorMatrixColorFilter,
	//这里直接用数组farray初始化SkColorMatrixFilter
	//ColorMatrix是5*4矩阵?分别代表RGBA的Scale?
	mpColorMatrixFilter =new SkColorMatrixFilter(farray);
	mTouch.fX = 0.01f;
	mTouch.fY = 0.01f; //不让x,y为0,否则在点计算时会有问题

	for (int i=0;i<9;i++)
	{
		mMatrixArray[i] = 0;
	}
	mMatrixArray[8] = 1.0f;
}

CPage::~CPage(void)
{
}

//创建阴影的GradientDrawable
void CPage::CreateShader()
{
	SkPoint pt[2];
	pt[0].set(0,0);
	pt[1].set(50,50);
	SkColor color[] = {0x111111 ,0xb0333333};
	mFolderShadowDrawableRL = SkGradientShader::CreateLinear(pt,color,NULL,2,SkShader::TileMode::kClamp_TileMode);
	//mFolderShadowDrawableLR  ;

	//int backShadowColors[] ={ 0xff111111, 0x111111 };
	//mBackShadowDrawableRL ;
	//mBackShadowDrawableLR  ;

	//int frontShadowColors[] ={ 0x80111111, 0x111111 };

	//mFrontShadowDrawableVLR ;
	//mFrontShadowDrawableVRL ;
	//mFrontShadowDrawableHTB ;
	//mFrontShadowDrawableHBT ;

}
// 计算拖拽点对应的拖拽脚
void CPage::CalcCornerXY(float x,float y)
{
	if (x<=mWidth/2)
		mCornerX = 0;
	else
		mCornerX =mWidth;

	if(y <=mHeight/2)
		mCornerY =0;
	else
		mCornerY =mHeight;

	if ((0 == mCornerX && mCornerY == mHeight)//左下角
		||(mCornerX == mWidth && 0 == mCornerY))    //右上
		mIsRTandLB = TRUE;
	else
		mIsRTandLB = FALSE;
}
BOOL CPage::DoTouchEvent()
{
	//可以只处理 mousemove/lbuttonup?
	//LBUTTONDUP中判断是否翻页
	return TRUE;
}
//
SkPoint CPage::GetCross(SkPoint p1,SkPoint p2,SkPoint p3,SkPoint p4)
{
	SkPoint CrossP ;
	float a1 = (p2.fY - p1.fY)/(p2.fX - p1.fX);
	float b1 = ((p1.fX * p2.fY) - p2.fX*p1.fY)/(p1.fX - p2.fX);

	float a2 = (p4.fY-p3.fY)/(p4.fX-p3.fX);
	float b2 = ((p3.fX*p4.fY)-(p4.fX*p3.fY))/(p3.fX-p4.fX);

	CrossP.fX = (b2-b1)/(a1-a2);
	CrossP.fY =a1*CrossP.fX +b1;
	return CrossP;
}
void  CPage::CalcPoints()
{
	mMiddleX = (mTouch.fX + mCornerX)/2;
	mMiddleY = (mTouch.fY + mCornerY)/2;

	mBezierControl1.fX = mMiddleX -(mCornerY -mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
	mBezierControl1.fY = mCornerY;

	mBezierControl2.fX = mCornerX;
	mBezierControl2.fY = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);

	mBezierStart1.fX = mBezierControl1.fX - (mCornerX - mBezierControl1.fX)/ 2;
	mBezierStart1.fY = mCornerY;
	// 当mBezierStart1.x < 0或者mBezierStart1.x > 480时  //800
	// 如果继续翻页,会出现BUG故在此限制
	if (mTouch.fX > 0 && mTouch.fX < mWidth) 
	{
		if (mBezierStart1.fX < 0 || mBezierStart1.fX > mWidth) 
		{
			if (mBezierStart1.fX < 0)
				mBezierStart1.fX = mWidth - mBezierStart1.fX;

			float f1 = abs(mCornerX - mTouch.fX);
			float f2 = mWidth * f1 / mBezierStart1.fX;
			mTouch.fX = abs(mCornerX - f2);

			float f3 = abs(mCornerX - mTouch.fX) * abs(mCornerY - mTouch.fY) / f1;
			mTouch.fY = abs(mCornerY - f3);

			mMiddleX = (mTouch.fX + mCornerX) / 2;
			mMiddleY = (mTouch.fY + mCornerY) / 2;

			mBezierControl1.fX = mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
			mBezierControl1.fY = mCornerY;

			mBezierControl2.fX = mCornerX;
			mBezierControl2.fY = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
			// Log.i("hmg", "mTouchX --> " + mTouch.x + "  mTouchY-->  "
			// + mTouch.y);
			// Log.i("hmg", "mBezierControl1.x--  " + mBezierControl1.x
			// + "  mBezierControl1.y -- " + mBezierControl1.y);
			// Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x
			// + "  mBezierControl2.y -- " + mBezierControl2.y);
			mBezierStart1.fX = mBezierControl1.fX - (mCornerX - mBezierControl1.fX) / 2;
		}
	}
	mBezierStart2.fX = mCornerX;
	mBezierStart2.fY = mBezierControl2.fY - (mCornerY - mBezierControl2.fY) / 2;

	mTouchToCornerDis = (float)_hypot((mTouch.fX - mCornerX),(mTouch.fY - mCornerY));

	mBezierEnd1 = GetCross(mTouch, mBezierControl1, mBezierStart1,mBezierStart2);
	mBezierEnd2 = GetCross(mTouch, mBezierControl2, mBezierStart1,mBezierStart2);

	// Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "
	// + mBezierEnd1.y);
	// Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "
	// + mBezierEnd2.y);

	/*
	* mBeziervertex1.x 推导
	* ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于
	* (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4
	*/
	mBeziervertex1.fX = (mBezierStart1.fX + 2 * mBezierControl1.fX + mBezierEnd1.fX) / 4;
	mBeziervertex1.fY = (2 * mBezierControl1.fY + mBezierStart1.fY + mBezierEnd1.fY) / 4;
	mBeziervertex2.fX = (mBezierStart2.fX + 2 * mBezierControl2.fX + mBezierEnd2.fX) / 4;
	mBeziervertex2.fY = (2 * mBezierControl2.fY + mBezierStart2.fY + mBezierEnd2.fY) / 4;
	
}
//void CPage::DrawCurrentPageArea(SkCanvas *canvas, SkBitmap *bitmap, SkPath *path)
void CPage::DrawCurrentPageArea(SkCanvas *canvas, SkBitmap *bitmap)
{
	mPath0.reset();
	mPath0.moveTo(mBezierStart1.fX, mBezierStart1.fY);
	mPath0.quadTo(mBezierControl1.fX, mBezierControl1.fY, mBezierEnd1.fX,mBezierEnd1.fY);
	mPath0.lineTo(mTouch.fX, mTouch.fY);
	mPath0.lineTo(mBezierEnd2.fX, mBezierEnd2.fY);
	mPath0.quadTo(mBezierControl2.fX, mBezierControl2.fY, mBezierStart2.fX,mBezierStart2.fY);
	mPath0.lineTo(mCornerX, mCornerY);
	mPath0.close();

	canvas->save();
	canvas->clipPath(mPath0, SkRegion::Op::kXOR_Op);
	SkPaint paint;
	paint.setAntiAlias(true);   //设置为无锯齿
	canvas->drawBitmap(*bitmap, 0, 0, &paint);
	canvas->restore();
}

void CPage::DrawNextPageAreaAndShadow(SkCanvas *canvas, SkBitmap *bitmap)
{
	mPath1.reset();
	mPath1.moveTo(mBezierStart1.fX, mBezierStart1.fY);
	mPath1.lineTo(mBeziervertex1.fX, mBeziervertex1.fY);
	mPath1.lineTo(mBeziervertex2.fX, mBeziervertex2.fY);
	mPath1.lineTo(mBezierStart2.fX, mBezierStart2.fY);
	mPath1.lineTo(mCornerX, mCornerY);
	mPath1.close();

	mDegrees = (float)(atan2(mBezierControl1.fX - mCornerX, mBezierControl2.fY - mCornerY))*180/PI;

	int leftx;
	int rightx;
	SkShader *mBackShadowDrawable;
	if (mIsRTandLB)
	{
		leftx = (int) (mBezierStart1.fX);
		rightx = (int) (mBezierStart1.fX + mTouchToCornerDis / 4);
		mBackShadowDrawable = mBackShadowDrawableLR;  //从左到又显示阴影
	}
	else
	{
		leftx = (int) (mBezierStart1.fX - mTouchToCornerDis / 4);
		rightx = (int) mBezierStart1.fX;
		mBackShadowDrawable = mBackShadowDrawableRL;  //从右到左显示阴影
	}
	mBackShadowDrawable = mFolderShadowDrawableRL;
	canvas->save();
	canvas->clipPath(mPath0);
	canvas->clipPath(mPath1, SkRegion::Op::kIntersect_Op);
	canvas->drawBitmap(*bitmap, 0, 0, NULL);

	canvas->translate(mBezierStart1.fX, mBezierStart1.fY);
	canvas->rotate(mDegrees);
	canvas->translate(-mBezierStart1.fX, -mBezierStart1.fY);

	//mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.fY, rightx,(int)(mMaxLength + mBezierStart1.fY));
	//mBackShadowDrawable.draw(canvas);
	// Skia没有实现?
	SkPaint paint;
	paint.setAntiAlias(true);   //设置为无锯齿
	paint.setShader(mBackShadowDrawable);
	canvas->drawRectCoords(leftx, (int) mBezierStart1.fY, rightx,(int)(mMaxLength + mBezierStart1.fY),paint);

	canvas->restore();
}
void CPage::SetBitmaps(SkBitmap *bm1, SkBitmap *bm2)
{
	mCurPageBitmap = bm1;
	mNextPageBitmap = bm2;
}

void CPage::SetScreen(int w, int h) 
{
	mWidth = w;
	mHeight = h;
}

//@Override
//protected void onDraw(Canvas canvas) 
//{
//	canvas.drawColor(0xFFAAAAAA);
//	calcPoints();
//	drawCurrentPageArea(canvas, mCurPageBitmap, mPath0); 当前页区域
//	drawNextPageAreaAndShadow(canvas, mNextPageBitmap);  下一页区域和阴影
//	drawCurrentPageShadow(canvas);						 当前页阴影
//	drawCurrentBackArea(canvas, mCurPageBitmap);		 当前页背影
//}


//在java中computeScroll函数中改变mTouch,这里作为参数
void CPage::DrawPage(SkCanvas *canvas,SkPoint touch)
{

	canvas->drawColor(0xFFAAAAAA);
	mTouch = touch;
	//CalcCornerXY(mTouch.fX,mTouch.fY);//放在调用处,一次移动只能调用一次
	CalcPoints();
	DrawCurrentPageArea(canvas,mCurPageBitmap);
	DrawNextPageAreaAndShadow(canvas,mNextPageBitmap);
	//DrawCurrentPageShadow(canvas);
	//DrawCurrentBackArea(canvas,mCurPageBitmap);

}
//  绘制翻起页的阴影
void CPage::DrawCurrentPageShadow(SkCanvas *canvas) 
{
	double degree;
	if (mIsRTandLB)
	{
		degree = PI/4 - atan2(mBezierControl1.fY - mTouch.fY, mTouch.fX - mBezierControl1.fX);
	}
	else 
	{
		degree = PI/ 4 - atan2(mTouch.fY - mBezierControl1.fY, mTouch.fX - mBezierControl1.fX);
	}
	// 翻起页阴影顶点与touch点的距离
	double d1 = (float) 25 * 1.414 * cos(degree);
	double d2 = (float) 25 * 1.414 * sin(degree);
	float x = (float) (mTouch.fX + d1);
	float y;
	if (mIsRTandLB)
	{
		y = (float) (mTouch.fY + d2);
	} 
	else 
	{
		y = (float) (mTouch.fY - d2);
	}
	mPath1.reset();
	mPath1.moveTo(x, y);
	mPath1.lineTo(mTouch.fX, mTouch.fY);
	mPath1.lineTo(mBezierControl1.fX, mBezierControl1.fY);
	mPath1.lineTo(mBezierStart1.fX, mBezierStart1.fY);
	mPath1.close();
	float rotateDegrees;
	canvas->save();
	canvas->clipPath(mPath0, SkRegion::Op::kXOR_Op);
	canvas->clipPath(mPath1, SkRegion::Op::kIntersect_Op);
	int leftx;
	int rightx;
	SkShader *mCurrentPageShadow;
	if (mIsRTandLB) 
	{
		leftx = (int) (mBezierControl1.fX);
		rightx = (int) mBezierControl1.fX + 25;
		//mCurrentPageShadow = mFrontShadowDrawableVLR;
	} 
	else
	{
		leftx = (int) (mBezierControl1.fX - 25);
		rightx = (int) mBezierControl1.fX + 1;
		//mCurrentPageShadow = mFrontShadowDrawableVRL;
	}
	mCurrentPageShadow = mFolderShadowDrawableRL;
//*********************************************************需要重点尝试,
	//尝试使用LinearGradient;
	//SkPaint paint;
	//paint.setShader(SkShader *shader);
	//SkShader linearShader = SkGradientShader::CreateLinear();
	//paint.setShader(linearShader);
	//中间加上旋转以及路径计算

	//mPaint.setShader(mComposeShader);  
	//canvas.drawRect(0, 0, imgwidth, imgheight, mPaint);  
	//drawRect(rect范围是下面mCurrentPageShadow.SetBounds的参数值)
	//canvas->drawRoundRect()

	//程序原来的阴影是用GradientDrawable实现
	//在android的源码中,GradientDrawable的具体实现是:graphics/drawable/GradientDrawable.java
	//ensureValidRect()函数中,如果GradiemtDrawable类型是LINEAR_GRADIENT,
	//GradientDrawable的成员mFillPaint:
	//mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,colors, st.mPositions, Shader.TileMode.CLAMP));
	//ensureValidRect()在GradientDrawable的draw(Canvas canvas)开始处调用

//**********************************************************8

	//rotateDegrees = (float) Math.toDegrees(atan2(mTouch.x - mBezierControl1.x, mBezierControl1.y - mTouch.y));
	rotateDegrees = (float)(atan2(mTouch.fX - mBezierControl1.fX, mBezierControl1.fY - mTouch.fY))*180/PI;
	
	//canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);
	canvas->translate(mBezierControl1.fX, mBezierControl1.fY);
	canvas->rotate(rotateDegrees);
	canvas->translate(-mBezierControl1.fX, -mBezierControl1.fY);

	SkPaint paint;
	paint.setShader(mCurrentPageShadow);
	canvas->drawRectCoords(leftx,(int)(mBezierControl1.fY - mMaxLength), rightx,(int)(mBezierControl1.fY),paint);
	//mCurrentPageShadow.setBounds(leftx,(int)(mBezierControl1.y - mMaxLength), rightx,(int)(mBezierControl1.y));
	//mCurrentPageShadow.draw(canvas);

	canvas->restore();

	mPath1.reset();
	mPath1.moveTo(x, y);
	mPath1.lineTo(mTouch.fX, mTouch.fY);
	mPath1.lineTo(mBezierControl2.fX, mBezierControl2.fY);
	mPath1.lineTo(mBezierStart2.fX, mBezierStart2.fY);
	mPath1.close();
	canvas->save();
	canvas->clipPath(mPath0, SkRegion::Op::kXOR_Op);
	canvas->clipPath(mPath1, SkRegion::Op::kIntersect_Op);
	if (mIsRTandLB)
	{
		leftx = (int) (mBezierControl2.fY);
		rightx = (int) (mBezierControl2.fY + 25);
		//mCurrentPageShadow = mFrontShadowDrawableHTB;
	} else {
		leftx = (int) (mBezierControl2.fY - 25);
		rightx = (int) (mBezierControl2.fY + 1);
		//mCurrentPageShadow = mFrontShadowDrawableHBT;
	}
	
	//rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y - mTouch.y, mBezierControl2.x - mTouch.x));
	rotateDegrees = (float)(atan2(mBezierControl2.fY - mTouch.fY, mBezierControl2.fX - mTouch.fX))*180/PI;
	//canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
	canvas->translate(mBezierControl2.fX, mBezierControl2.fY);
	canvas->rotate(rotateDegrees);
	canvas->translate(-mBezierControl2.fX, -mBezierControl2.fY);
	float temp;
	if (mBezierControl2.fY < 0)
		temp = mBezierControl2.fY - mHeight;
	else
		temp = mBezierControl2.fY;

	int hmg = (int) _hypot(mBezierControl2.fX, temp);
	//if (hmg > mMaxLength)
	//	mCurrentPageShadow.setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,
	//						(int)(mBezierControl2.x + mMaxLength) - hmg,rightx);
	//else
	//	mCurrentPageShadow.setBounds((int) (mBezierControl2.x - mMaxLength), leftx,
	//						(int) (mBezierControl2.x), rightx);

	// Log.i("hmg", "mBezierControl2.x   " + mBezierControl2.x
	// + "  mBezierControl2.y  " + mBezierControl2.y);
	//mCurrentPageShadow.draw(canvas);
	if (hmg > mMaxLength)
		canvas->drawRectCoords((int)(mBezierControl2.fX - 25) - hmg, leftx,(int)(mBezierControl2.fX + mMaxLength) - hmg,rightx,paint);
	else
		canvas->drawRectCoords((int)(mBezierControl2.fX - mMaxLength),leftx,(int)(mBezierControl2.fX), rightx,paint);

	canvas->restore();
}
//绘制翻起页背面
void CPage::DrawCurrentBackArea(SkCanvas *canvas, SkBitmap *bitmap) 
{
		int i = (int) (mBezierStart1.fX + mBezierControl1.fX) / 2;
		float f1 = abs(i - mBezierControl1.fX);
		int i1 = (int) (mBezierStart2.fY + mBezierControl2.fY) / 2;
		float f2 = abs(i1 - mBezierControl2.fY);
		float f3 = min(f1, f2);
		mPath1.reset();
		mPath1.moveTo(mBeziervertex2.fX, mBeziervertex2.fY);
		mPath1.lineTo(mBeziervertex1.fX, mBeziervertex1.fY);
		mPath1.lineTo(mBezierEnd1.fX, mBezierEnd1.fY);
		mPath1.lineTo(mTouch.fX, mTouch.fY);
		mPath1.lineTo(mBezierEnd2.fX, mBezierEnd2.fY);
		mPath1.close();
		SkShader *mFolderShadowDrawable;
		int left;
		int right;
		if (mIsRTandLB)
		{
			left = (int) (mBezierStart1.fX - 1);
			right = (int) (mBezierStart1.fX + f3 + 1);
			//mFolderShadowDrawable = mFolderShadowDrawableLR;
		} else 
		{
			left = (int) (mBezierStart1.fX - f3 - 1);
			right = (int) (mBezierStart1.fX + 1);
			//mFolderShadowDrawable = mFolderShadowDrawableRL;
		}
		mFolderShadowDrawable =mFolderShadowDrawableRL;
		canvas->save();
		canvas->clipPath(mPath0);
		canvas->clipPath(mPath1, SkRegion::Op::kIntersect_Op);

		mPaint.setColorFilter(mpColorMatrixFilter);

		float dis = (float)_hypot(mCornerX - mBezierControl1.fX,mBezierControl2.fY - mCornerY);
		float f8 = (mCornerX - mBezierControl1.fX) / dis;
		float f9 = (mBezierControl2.fY - mCornerY) / dis;
		mMatrixArray[0] = 1 - 2 * f9 * f9;
		mMatrixArray[1] = 2 * f8 * f9;
		mMatrixArray[3] = mMatrixArray[1];
		mMatrixArray[4] = 1 - 2 * f8 * f8;
		mMatrix.reset();
		//mMatrix.setValues(mMatrixArray);
		//mMatrix.set(mMatrixArray);
		mMatrix.preTranslate(-mBezierControl1.fX, -mBezierControl1.fY);
		mMatrix.postTranslate(mBezierControl1.fX, mBezierControl1.fY);
		//canvas.drawBitmap(bitmap, mMatrix, mPaint);
		canvas->drawBitmapMatrix(*bitmap,mMatrix,&mPaint);
		mPaint.setColorFilter(NULL);

		//canvas.rotate(mDegrees, mBezierStart1.fX, mBezierStart1.fY);
		canvas->translate(mBezierStart1.fX, mBezierStart1.fY);
		canvas->rotate(mDegrees);
		canvas->translate(-mBezierStart1.fX, -mBezierStart1.fY);

		SkPaint paint;
		paint.setShader(mFolderShadowDrawable);
		canvas->drawRectCoords(left, (int) mBezierStart1.fY, right,(int) (mBezierStart1.fY + mMaxLength),paint);
		//mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.fY, right,
		//		(int) (mBezierStart1.fY + mMaxLength));
		//mFolderShadowDrawable.draw(canvas);
		canvas->restore();
	}
//public void computeScroll() {
//	super.computeScroll();
//	if (mScroller.computeScrollOffset()) {
//		float x = mScroller.getCurrX();
//		float y = mScroller.getCurrY();
//		mTouch.x = x;
//		mTouch.y = y;
//		postInvalidate();
//	}
//}

void CPage::StartAnimation(int delayMillis)
{
	int dx, dy;
	// dx 水平方向滑动的距离,负值会使滚动向左滚动
	// dy 垂直方向滑动的距离,负值会使滚动向上滚动
	if (mCornerX > 0) 
	{
		dx = -(int)(mWidth + mTouch.fX);
	} 
	else 
	{
		dx = (int)(mWidth - mTouch.fX + mWidth);
	}
	if (mCornerY > 0)
	{
		dy = (int) (mHeight - mTouch.fY);
	} 
	else
	{
		dy = (int) (1 - mTouch.fY); // 防止mTouch.y最终变为0
	}
	//mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,delayMillis);
}

//退出animation
void CPage::AbortAnimation()
{
	//if (!mScroller.isFinished()) 
	//{
	//	mScroller.abortAnimation();
	//}
}

BOOL CPage::CanDragOver()
{
	if (mTouchToCornerDis > mWidth / 10)
		return TRUE;
	return FALSE;
}

// 是否从左边翻向右边
BOOL CPage::DragToRight()
{
	if (mCornerX > 0)
		return FALSE;
	return TRUE;
}
BOOL CPage::LButtonDown(SkCanvas *canvas,SkPoint pt)
{
	CalcCornerXY(pt.fX,pt.fY);
	DrawPage(canvas,pt);
	return TRUE;
}
BOOL CPage::MouseMove(SkCanvas *canvas,SkPoint pt)
{
	DrawPage(canvas,pt);
	return TRUE;
}
BOOL CPage::LButtonUp(SkCanvas *canvas,SkPoint pt)
{
	//
	//if ()
	//{
	//}
	//pt.fX +=(1200-pt.fX);
	DrawPage(canvas,pt);
	//canvas->drawBitmap(*mNextPageBitmap,0,0,NULL);
	return TRUE;
}

  

使用:

SkPoint mTouch;

SkBitmap *pskBitmap; 
SkCanvas *pskCanvas;
BITMAPINFO *lpbmi;
HWND  g_hWnd;

SkBitmap *bkBitmap;//背景图片
SkBitmap *CurrentPageBmp;
SkBitmap *NextPageBmp;
SkCanvas *CurrentPageCanvas;
SkCanvas *NextPageCanvas;
CPage pageflip;

SkRect   g_rtImg;// 图片最初按钮。

SkRect   g_rtClip;//矩阵裁剪用 ,做图片旋转时,每次旋转时的裁剪会用到上一次的裁剪范围。
//g_rtClip是共用裁剪范围,多个不同的位置共用,每次旋转前初始化为要旋转图片的原始位置

//初始化背景图片,
void MyInitBkImage(char *filename)
{
	SkFILEStream stream(filename);
	SkImageDecoder * coder = SkImageDecoder::Factory(&stream);
	if (coder)
	{
		bkBitmap = new SkBitmap();
		coder->decode(&stream,bkBitmap,SkBitmap::kRGB_565_Config,SkImageDecoder::kDecodePixels_Mode);
	}
}
SkBitmap* MyInitImage(char *imgFileName)
{
	SkBitmap *bitmap;
	SkFILEStream stream(imgFileName);
	SkImageDecoder * coder = SkImageDecoder::Factory(&stream);
	if (coder)
	{
		bitmap = new SkBitmap();
		coder->decode(&stream,bitmap,SkBitmap::kRGB_565_Config,SkImageDecoder::kDecodePixels_Mode);
		return bitmap;
	}
	return NULL;
}
//整体初始化
void MyInit()
{
	pskBitmap = new SkBitmap();
	pskBitmap->setConfig(SkBitmap::kRGB_565_Config,800,480);
	pskBitmap->allocPixels();//分配位图所占空间

	pskCanvas = new SkCanvas();
	pskCanvas->setBitmapDevice(*pskBitmap);

	lpbmi  = (BITMAPINFO*)malloc( sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(2) );

	//printf("%d,%d\n",sizeof(BITMAPINFOHEADER),sizeof(BITMAPINFO));40,44

	memset( lpbmi, 0, sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(2) );//必须同上方一直

	lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);//位图信息头大小 40字节
	lpbmi->bmiHeader.biWidth = 800;
	lpbmi->bmiHeader.biHeight = -480;
	lpbmi->bmiHeader.biPlanes = 1;
	lpbmi->bmiHeader.biBitCount = 16;              //16位位图  565模式0xF800、0x07E0、0x001F
	lpbmi->bmiHeader.biCompression = BI_BITFIELDS; //压缩参数  BI_RGB=0表示无压缩,
	lpbmi->bmiHeader.biSizeImage = 0;

	lpbmi->bmiColors[0].rgbBlue = 0;  
	lpbmi->bmiColors[0].rgbGreen = 0xF8;  //248?
	lpbmi->bmiColors[0].rgbRed = 0;  
	lpbmi->bmiColors[0].rgbReserved = 0;  

	lpbmi->bmiColors[1].rgbBlue = 0xE0;  //224
	lpbmi->bmiColors[1].rgbGreen = 0x07;  //7
	lpbmi->bmiColors[1].rgbRed = 0;  
	lpbmi->bmiColors[1].rgbReserved = 0;  

	lpbmi->bmiColors[2].rgbBlue = 0x1F;  //31
	lpbmi->bmiColors[2].rgbGreen = 0;  
	lpbmi->bmiColors[2].rgbRed = 0;  
	lpbmi->bmiColors[2].rgbReserved = 0;

	MyInitBkImage("\\USER\\skia\\bk.png");

	//MyInitBkImage("\\Storage Card\\bk.png");

	g_rtImg.setLTRB(151,214,249,346); //初始化图片位置
	//g_rtClip 在每次旋转前初始化                

	
	CurrentPageBmp = MyInitImage("\\USER\\skia\\book.png");
	NextPageBmp = MyInitImage("\\USER\\skia\\book.png");

	pageflip.SetBitmaps(CurrentPageBmp,NextPageBmp);

	CurrentPageCanvas = new SkCanvas();
	CurrentPageCanvas->setBitmapDevice(*CurrentPageBmp);
	NextPageCanvas = new SkCanvas();
	NextPageCanvas->setBitmapDevice(*NextPageBmp);

	SkPaint *paint = new SkPaint();
	paint->setTextSize(24);
	paint->setColor(SK_ColorWHITE);
	paint->setTextAlign(SkPaint::Align::kLeft_Align);
	//paint->breakText()
	for (int i=0;i<10;i++)
	{
		CurrentPageCanvas->drawText("the first page,hello ,no. 11",40,30,30+30*i,*paint);
		NextPageCanvas->drawText("Test Microsoft Visual Studio",   40,30,30+30*i,*paint);
	}
	
	

}
//画到屏幕上
void Flip()
{
	HDC dc = GetDC(g_hWnd);
	SetDIBitsToDevice(dc, 0, 0, 800, 480, 0, 0, 0, 800, pskBitmap->getPixels(), lpbmi, DIB_RGB_COLORS);
	ReleaseDC(g_hWnd,dc);
}
//画图片filename,rt为其范围,图片没有保存,每次临时加载
void DrawImage(char * filename,SkCanvas *canvas, SkRect rt, SkPaint *paint)
{
	int ti = GetTickCount();
	SkFILEStream stream(filename);
	SkImageDecoder* coder = SkImageDecoder::Factory(&stream);
	SkBitmap *bitmap;
	if (coder)
	{
		//printf(" file %s code success\n",filename);
		bitmap = new SkBitmap();
		coder->decode(&stream, bitmap, SkBitmap::kRGB_565_Config,
			SkImageDecoder::kDecodePixels_Mode);
	}
	else
	{
		printf(" file %s code fail\n",filename);
		return;
	}
	//printf("24bit800*480png,code time =%d\n",GetTickCount()-ti);//367
	ti = GetTickCount();
	canvas->drawBitmap(*bitmap,rt.fLeft, rt.fTop);
	//printf("24bit800*480png,draw time =%d\n",GetTickCount()-ti);//12
	delete bitmap;
	return;

}
void MyLButtonDown(POINT pt)
{

	float x = pt.x;
	float y = pt.y;
	SkPoint touch;
	touch.fX =x;
	touch.fY =y;

	pageflip.LButtonDown(pskCanvas,touch);
	Flip();

}
void MyMouseMove(POINT pt)
{
	float x = pt.x;
	float y = pt.y;
	SkPoint touch;
	touch.fX =x;
	touch.fY =y;

	pageflip.MouseMove(pskCanvas,touch);
	Flip();
}

  我用的win32工程。

在InitInstance函数中加上:

	g_hWnd = hWnd;

	MyInit();  //never forget
    ShowWindow(hWnd, nCmdShow);
	MoveWindow(hWnd,0,0,800,480,1);

  WndProc函数中:

		case WM_LBUTTONDOWN:
			{
				RECT rt = {700,0,800,100};
				POINT pt;
				pt.x =LOWORD(lParam);pt.y = HIWORD(lParam);
				printf("pt:x=%d,y=%d\n",pt.x,pt.y);
				printf("rt:%d,%d,%d,%d\n",rt.left,rt.top,rt.right,rt.bottom);
				if (PtInRect(&rt,pt)==TRUE)
				{
					//EndDialog(hWnd,IDOK);
					  PostQuitMessage(0);
				}
				else
				{
					printf("xxxxxxxxx\n");
				}

				MyLButtonDown(pt);
				
				//UpdateWindow(hWnd);
				
			}
			break;
		case WM_MOUSEMOVE:
			{
				RECT rt = {700,0,800,100};
				POINT pt;
				pt.x =LOWORD(lParam);pt.y = HIWORD(lParam);
				
				MyMouseMove(pt);
			}break;

  

代码效果:

ezhong的博客园:http://www.cnblogs.com/ezhong/

原文地址:https://www.cnblogs.com/ezhong/p/2261331.html