• 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/

  • 相关阅读:
    第10.7节 Python包和子包的定义步骤
    第10.6节 Python包的概念
    第10.5节 使用__all__定义Python模块导入白名单
    第10.4节 Python模块的弱封装机制
    第10.3节 Python导入模块能否取消导入?
    第10.2节 查看导入的Python模块
    第10.1节 Python的模块及模块导入
    第10章 Python的模块和包
    第9.13节 Python文件操作总结
    OpenCV x64 vs2010 下打开摄像头录制视频写成avi(代码为转载)
  • 原文地址:https://www.cnblogs.com/ezhong/p/2261331.html
Copyright © 2020-2023  润新知