还有许多问题,关键是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/