用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2514 lines
71 KiB

#include <core\SkShader.h>
#include <core\SkDevice.h>
#include <effects\SkDashPathEffect.h>
#include <effects\SkGradientShader.h>
#include <effects\SkBlurMaskFilter.h>
#include "../skia/src/effects/SkBlurMask.h"
#include "../skia/include/core/SkGraphics.h"
#include <gdialpha.h>
#include "drawtext-skia.h"
#include "render-skia.h"
#include "trace.h"
#include "skia2rop2.h"
#include "PathEffect-Skia.h"
#include "PathMeasure-Skia.h"
#include <tchar.h>
#include <algorithm>
#include <vector>
#include <map>
#define getTotalClip internal_private_getTotalClip
// #include <vld.h>
#ifndef PI //PI
#define PI ((float)3.141592654f)
#endif
namespace SOUI
{
//PS_SOLID
const float ps_solid[] ={1.0f,0.0f};
const float ps_dash[] ={5.0f,5.0f};
const float ps_dot[] ={1.0f,4.0f};
const float ps_dashdot[] ={4.0f,1.0f,1.0f,1.0f};
const float ps_dashdotdot[] ={4.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
const struct LineDashEffect
{
const float *fDash;
int nCount;
}LINEDASHEFFECT[] =
{
{ps_solid,ARRAYSIZE(ps_solid)},
{ps_dash,ARRAYSIZE(ps_dash)},
{ps_dot,ARRAYSIZE(ps_dot)},
{ps_dashdot,ARRAYSIZE(ps_dashdot)},
{ps_dashdotdot,ARRAYSIZE(ps_dashdotdot)},
};
bool String2Bool(const SStringW & value)
{
SASSERT(!value.IsEmpty());
return !(value == L"false" || value == L"0");
}
SkIRect toSkIRect(LPCRECT pRc)
{
SkIRect rc={pRc->left,pRc->top,pRc->right,pRc->bottom};
return rc;
}
SkRect toSkRect(LPCRECT pRc)
{
SkIRect rc={pRc->left,pRc->top,pRc->right,pRc->bottom};
return SkRect::Make(rc);
}
void SkRect2RECT(const SkRect & rcIn, RECT * rcOut)
{
rcOut->left = (int)rcIn.fLeft;
rcOut->top = (int)rcIn.fTop;
rcOut->right = (int)(rcIn.fRight + 0.5f);
rcOut->bottom = (int)(rcIn.fBottom + 0.5f);
}
void InflateSkRect(SkRect *pRect,SkScalar dx,SkScalar dy)
{
pRect->fLeft -= dx;
pRect->fRight += dx;
pRect->fTop -= dy;
pRect->fBottom += dy;
}
int RectWid(LPCRECT pRc){return pRc->right-pRc->left;}
int RectHei(LPCRECT pRc){return pRc->bottom-pRc->top;}
#define PS_ENDCAP_ROUND 0x00000000
#define PS_ENDCAP_SQUARE 0x00000100
#define PS_ENDCAP_FLAT 0x00000200
#define PS_ENDCAP_MASK 0x00000F00
#define PS_JOIN_ROUND 0x00000000
#define PS_JOIN_BEVEL 0x00001000
#define PS_JOIN_MITER 0x00002000
#define PS_JOIN_MASK 0x0000F000
#define PS_COSMETIC 0x00000000
#define PS_GEOMETRIC 0x00010000
#define PS_TYPE_MASK 0x000F0000
class SLineDashEffect
{
public:
SLineDashEffect(int iStyle):pDashPathEffect(NULL)
{
iStyle = iStyle&PS_STYLE_MASK;
if(iStyle>=PS_SOLID && iStyle<=PS_DASHDOTDOT)
{
const LineDashEffect *pEff=&LINEDASHEFFECT[iStyle];
pDashPathEffect=SkDashPathEffect::Create(pEff->fDash,pEff->nCount,0.0f);
}
}
~SLineDashEffect()
{
if(pDashPathEffect) pDashPathEffect->unref();
}
SkDashPathEffect * Get() const{return pDashPathEffect;}
private:
SkDashPathEffect * pDashPathEffect;
};
class SStrokeCap{
public:
SStrokeCap(int iStyle){
iStyle = iStyle & PS_ENDCAP_MASK;
switch(iStyle)
{
case PS_ENDCAP_ROUND: m_Cap = SkPaint::kRound_Cap;break;
case PS_ENDCAP_SQUARE: m_Cap = SkPaint::kSquare_Cap;break;
case PS_ENDCAP_FLAT:default: m_Cap = SkPaint::kDefault_Cap; break;
}
}
SkPaint::Cap Get() const
{
return m_Cap;
}
private:
SkPaint::Cap m_Cap;
};
class SStrokeJoin{
public:
SStrokeJoin(int iStyle){
iStyle = iStyle & PS_JOIN_MASK;
switch(iStyle)
{
case PS_JOIN_ROUND: m_Join = SkPaint::kRound_Join;break;
case PS_JOIN_BEVEL: m_Join = SkPaint::kBevel_Join;break;
case PS_JOIN_MITER:default: m_Join = SkPaint::kDefault_Join; break;
}
}
SkPaint::Join Get() const
{
return m_Join;
}
private:
SkPaint::Join m_Join;
};
//////////////////////////////////////////////////////////////////////////
// SRenderFactory_Skia
SRenderFactory_Skia::SRenderFactory_Skia()
{
SkGraphics::Init();
SkGraphics::SetFontCacheCountLimit(500);//cache up to 500 font resource.
}
SRenderFactory_Skia::~SRenderFactory_Skia()
{
SkGraphics::Term();
}
BOOL SRenderFactory_Skia::CreateRenderTarget( IRenderTarget ** ppRenderTarget ,int nWid,int nHei)
{
*ppRenderTarget = new SRenderTarget_Skia(this, nWid, nHei);
return TRUE;
}
BOOL SRenderFactory_Skia::CreateFont( IFont ** ppFont , const LOGFONT &lf )
{
*ppFont = new SFont_Skia(this,&lf);
return TRUE;
}
BOOL SRenderFactory_Skia::CreateBitmap( IBitmap ** ppBitmap )
{
*ppBitmap = new SBitmap_Skia(this);
return TRUE;
}
BOOL SRenderFactory_Skia::CreateRegion( IRegion **ppRgn )
{
*ppRgn = new SRegion_Skia(this);
return TRUE;
}
BOOL SRenderFactory_Skia::CreatePath(IPath ** ppPath)
{
*ppPath = new SPath_Skia(this);
return TRUE;
}
BOOL SRenderFactory_Skia::CreatePathEffect(REFGUID guidEffect,IPathEffect ** ppPathEffect)
{
* ppPathEffect = NULL;
if(guidEffect == __uuidof(ICornerPathEffect))
{
*ppPathEffect = (IPathEffect*) new SPathEffect_Corner();
}else if(guidEffect == __uuidof(IDashPathEffect))
{
*ppPathEffect = (IPathEffect *) new SPathEffect_Dash();
}else if(guidEffect == __uuidof(IDiscretePathEffect))
{
*ppPathEffect = (IPathEffect *) new SPathEffect_Discrete();
}
return (*ppPathEffect) != NULL;
}
BOOL SRenderFactory_Skia::CreatePathMeasure(IPathMeasure ** ppPathMeasure)
{
*ppPathMeasure = new SPathMeasure_Skia;
return TRUE;
}
HRESULT SRenderFactory_Skia::CreateBlurMaskFilter(float radius, IMaskFilter::SkBlurStyle style,IMaskFilter::SkBlurFlags flag,IMaskFilter ** ppMaskFilter)
{
SkMaskFilter *pMaskFilter = SkBlurMaskFilter::Create(::SkBlurStyle(style),SkBlurMaskFilter::ConvertRadiusToSigma(radius),flag);
if(!pMaskFilter)
return E_OUTOFMEMORY;
*ppMaskFilter = new SMaskFilter_Skia(pMaskFilter);
return S_OK;
}
HRESULT SRenderFactory_Skia::CreateEmbossMaskFilter(float direction[3], float ambient, float specular, float blurRadius,IMaskFilter ** ppMaskFilter)
{
SkMaskFilter *pMaskFilter=SkBlurMaskFilter::CreateEmboss(direction,ambient,specular,SkBlurMaskFilter::ConvertRadiusToSigma(blurRadius));
if(!pMaskFilter)
return E_OUTOFMEMORY;
*ppMaskFilter = new SMaskFilter_Skia(pMaskFilter);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////
// SRenderTarget_Skia
SRenderTarget_Skia::SRenderTarget_Skia( IRenderFactory* pRenderFactory ,int nWid,int nHei)
:m_SkCanvas(NULL)
,m_curColor(0xFF000000)//默认黑色
,m_hGetDC(0)
,m_uGetDCFlag(0)
,m_bAntiAlias(true)
,m_xferMode(kSrcOver_Mode)
{
m_ptOrg.fX=m_ptOrg.fY=0.0f;
m_pRenderFactory = pRenderFactory;
m_SkCanvas = new SkCanvas();
m_paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
m_paint.setAntiAlias(true);
m_paint.setLCDRenderText(true);
m_paint.setStyle(SkPaint::kStrokeAndFill_Style);
CreatePen(PS_SOLID,SColor(0,0,0).toCOLORREF(),1,&m_defPen);
SelectObject(m_defPen);
CreateSolidColorBrush(SColor(0,0,0).toCOLORREF(),&m_defBrush);
SelectObject(m_defBrush);
LOGFONT lf={0};
lf.lfHeight=20;
_tcscpy(lf.lfFaceName,_T("宋体"));
pRenderFactory->CreateFont(&m_defFont,lf);
SelectObject(m_defFont);
pRenderFactory->CreateBitmap(&m_defBmp);
m_defBmp->Init(nWid,nHei);
SelectObject(m_defBmp);
SAutoRefPtr<IPen> pPen;
CreatePen(PS_SOLID,SColor(0,0,0).toCOLORREF(),1,&pPen);
SelectObject(pPen);
}
SRenderTarget_Skia::~SRenderTarget_Skia()
{
if(m_SkCanvas) delete m_SkCanvas;
}
HRESULT SRenderTarget_Skia::CreateCompatibleRenderTarget( SIZE szTarget,IRenderTarget **ppRenderTarget )
{
SRenderTarget_Skia *pRT = new SRenderTarget_Skia(m_pRenderFactory,szTarget.cx,szTarget.cy);
*ppRenderTarget = pRT;
return S_OK;
}
HRESULT SRenderTarget_Skia::CreatePen( int iStyle,COLORREF cr,int cWidth,IPen ** ppPen )
{
*ppPen = new SPen_Skia(m_pRenderFactory,iStyle,cr,cWidth);
return S_OK;
}
HRESULT SRenderTarget_Skia::CreateSolidColorBrush( COLORREF cr,IBrush ** ppBrush )
{
*ppBrush = SBrush_Skia::CreateSolidBrush(m_pRenderFactory,cr);
return S_OK;
}
HRESULT SRenderTarget_Skia::CreateBitmapBrush( IBitmap *pBmp,IBrush ** ppBrush )
{
SBitmap_Skia *pBmpSkia = (SBitmap_Skia*)pBmp;
*ppBrush = SBrush_Skia::CreateBitmapBrush(m_pRenderFactory,pBmpSkia->GetSkBitmap());
return S_OK;
}
HRESULT SRenderTarget_Skia::CreateRegion(IRegion ** ppRegion)
{
return m_pRenderFactory->CreateRegion(ppRegion)?S_OK:E_OUTOFMEMORY;
}
HRESULT SRenderTarget_Skia::Resize( SIZE sz )
{
m_curBmp->Init(sz.cx,sz.cy);
delete m_SkCanvas;
m_SkCanvas = new SkCanvas(m_curBmp->GetSkBitmap());
return S_OK;
}
HRESULT SRenderTarget_Skia::PushClipRect( LPCRECT pRect ,UINT mode/*=RGN_AND*/)
{
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->save();
m_SkCanvas->clipRect(skrc,SRegion_Skia::RGNMODE2SkRgnOP(mode));
return S_OK;
}
HRESULT SRenderTarget_Skia::PushClipRegion( IRegion *pRegion ,UINT mode/*=RGN_AND*/)
{
SRegion_Skia * rgn_skia=(SRegion_Skia*)pRegion;
SkRegion rgn=rgn_skia->GetRegion();
rgn.translate((int)m_ptOrg.fX,(int)m_ptOrg.fY);
m_SkCanvas->save();
m_SkCanvas->clipRegion(rgn,SRegion_Skia::RGNMODE2SkRgnOP(mode));
return S_OK;
}
HRESULT SRenderTarget_Skia::PopClip()
{
m_SkCanvas->restore();
return S_OK;
}
HRESULT SRenderTarget_Skia::ExcludeClipRect( LPCRECT pRc )
{
SkRect skrc=toSkRect(pRc);
skrc.offset(m_ptOrg);
m_SkCanvas->clipRect(skrc,SkRegion::kDifference_Op);
return S_OK;
}
HRESULT SRenderTarget_Skia::IntersectClipRect( LPCRECT pRc )
{
SkRect skrc=toSkRect(pRc);
skrc.offset(m_ptOrg);
m_SkCanvas->clipRect(skrc,SkRegion::kIntersect_Op);
return S_OK;
}
HRESULT SRenderTarget_Skia::SaveClip( int *pnState )
{
int nState=m_SkCanvas->save();
if(pnState) *pnState=nState;
return S_OK;
}
HRESULT SRenderTarget_Skia::RestoreClip( int nState/*=-1*/ )
{
m_SkCanvas->restoreToCount(nState);
return S_OK;
}
HRESULT SRenderTarget_Skia::GetClipRegion( IRegion **ppRegion )
{
SRegion_Skia *pRgn=new SRegion_Skia(m_pRenderFactory);
SkRegion rgn = m_SkCanvas->getTotalClip();
//需要将rect的viewOrg还原
rgn.translate((int)-m_ptOrg.fX,(int)-m_ptOrg.fY);
pRgn->SetRegion(rgn);
*ppRegion = pRgn;
return S_OK;
}
HRESULT SRenderTarget_Skia::GetClipBox(LPRECT prc)
{
SkRect skrc;
m_SkCanvas->getClipBounds(&skrc);
//需要将rect的viewOrg还原
skrc.offset(-m_ptOrg);
prc->left=(LONG)skrc.fLeft;
prc->top=(LONG)skrc.fTop;
prc->right=(LONG)skrc.fRight;
prc->bottom=(LONG)skrc.fBottom;
//需要4周缩小一个单位才是和GDI相同的剪裁区
::InflateRect(prc,-1,-1);
return S_OK;
}
HRESULT SRenderTarget_Skia::BitBlt( LPCRECT pRcDest,IRenderTarget *pRTSour,int xSrc,int ySrc,DWORD dwRop/*=SRCCOPY*/)
{
SkPaint paint=m_paint;
paint.setStyle(SkPaint::kFill_Style);
SetPaintXferMode(paint,dwRop);
SRenderTarget_Skia *pRtSourSkia=(SRenderTarget_Skia*)pRTSour;
const SkBitmap & bmpSrc=pRtSourSkia->m_curBmp->GetSkBitmap();
POINT ptSourViewport;
pRtSourSkia->GetViewportOrg(&ptSourViewport);
xSrc += ptSourViewport.x;
ySrc += ptSourViewport.y;
SkIRect isrc={xSrc,ySrc,xSrc + pRcDest->right-pRcDest->left,ySrc+pRcDest->bottom-pRcDest->top};
SkRect skrc=toSkRect(pRcDest);
skrc.offset(m_ptOrg);
m_SkCanvas->drawBitmapRect(bmpSrc,&isrc,skrc,&paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawText( LPCTSTR pszText,int cchLen,LPRECT pRc,UINT uFormat)
{
if(cchLen<0) cchLen= _tcslen(pszText);
if(cchLen==0)
{
if(uFormat & DT_CALCRECT)
{
pRc->right=pRc->left;
pRc->bottom=pRc->top;
}
return S_OK;
}
SStringW strW=S_CT2W(SStringT(pszText,cchLen));
SkPaint txtPaint = m_paint;
SFont_Skia *pFont = m_curFont;
txtPaint.setTypeface(pFont->GetFont());
txtPaint.setTextSize(SkIntToScalar(abs(pFont->TextSize())));
txtPaint.setUnderlineText(pFont->IsUnderline());
txtPaint.setStrikeThruText(pFont->IsStrikeOut());
txtPaint.setStyle(SkPaint::kStrokeAndFill_Style);
if(pFont->GetBlurFilter())
{
txtPaint.setMaskFilter(pFont->GetBlurFilter());
}
if(uFormat & DT_CENTER)
txtPaint.setTextAlign(SkPaint::kCenter_Align);
else if(uFormat & DT_RIGHT)
txtPaint.setTextAlign(SkPaint::kRight_Align);
else
txtPaint.setTextAlign(SkPaint::kLeft_Align);
SkRect skrc=toSkRect(pRc);
skrc.offset(m_ptOrg);
skrc=DrawText_Skia(m_SkCanvas,strW,strW.GetLength(),skrc,txtPaint,uFormat);
if(uFormat & DT_CALCRECT)
{
pRc->left=(int)skrc.fLeft;
pRc->top=(int)skrc.fTop;
pRc->right=(int)skrc.fRight;
pRc->bottom=(int)skrc.fBottom;
}
return S_OK;
}
HRESULT SRenderTarget_Skia::MeasureText( LPCTSTR pszText,int cchLen, SIZE *psz )
{
SkPaint txtPaint = m_paint;
txtPaint.setTypeface(m_curFont->GetFont());
txtPaint.setTextSize(SkIntToScalar(abs(m_curFont->TextSize())));
SStringW strW=S_CT2W(SStringT(pszText,cchLen));
psz->cx = (int)txtPaint.measureText(strW,strW.GetLength()*sizeof(wchar_t));
SkPaint::FontMetrics metrics;
txtPaint.getFontMetrics(&metrics);
psz->cy = (int)(metrics.fBottom-metrics.fTop);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawRectangle(LPCRECT pRect)
{
SkPaint paint=m_paint;
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
SStrokeCap strokeCap(m_curPen->GetStyle());
paint.setStrokeCap(strokeCap.Get());
SStrokeJoin strokeJoin(m_curPen->GetStyle());
paint.setStrokeJoin(strokeJoin.Get());
if(m_bAntiAlias)
{
paint.setAntiAlias(true);
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth()-0.5f);
}else
{
paint.setAntiAlias(false);
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
paint.setStyle(SkPaint::kStroke_Style);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
InflateSkRect(&skrc,-0.5f,-0.5f);
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillRectangle(LPCRECT pRect)
{
SkPaint paint=m_paint;
if(m_curBrush->IsBitmap())
{
paint.setFilterBitmap(true);
paint.setShader(SkShader::CreateBitmapShader(m_curBrush->GetBitmap(),SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->unref();
}else
{
paint.setFilterBitmap(false);
paint.setColor(SColor(m_curBrush->GetColor()).toARGB());
}
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
InflateSkRect(&skrc,-0.5f,-0.5f);
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawRoundRect( LPCRECT pRect,POINT pt )
{
SkPaint paint=m_paint;
SetPaintXferMode(paint,m_xferMode);
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
paint.setStyle(SkPaint::kStroke_Style);
if(m_bAntiAlias)
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth()-0.5f);
}else
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
SkRect skrc=toSkRect(pRect);
InflateSkRect(&skrc,-0.5f,-0.5f);//要缩小0.5显示效果才和GDI一致。
skrc.offset(m_ptOrg);
m_SkCanvas->drawRoundRect(skrc,(SkScalar)pt.x,(SkScalar)pt.y,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillRoundRect( LPCRECT pRect,POINT pt )
{
SkPaint paint=m_paint;
if(m_curBrush->IsBitmap())
{
paint.setFilterBitmap(true);
paint.setShader(SkShader::CreateBitmapShader(m_curBrush->GetBitmap(),SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->unref();
}else
{
paint.setFilterBitmap(false);
paint.setColor(SColor(m_curBrush->GetColor()).toARGB());
}
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
InflateSkRect(&skrc,-0.5f,-0.5f);//要缩小0.5显示效果才和GDI一致。
skrc.offset(m_ptOrg);
m_SkCanvas->drawRoundRect(skrc,(SkScalar)pt.x,(SkScalar)pt.y,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillSolidRoundRect(LPCRECT pRect,POINT pt,COLORREF cr)
{
SkPaint paint=m_paint;
paint.setFilterBitmap(false);
paint.setColor(SColor(cr).toARGB());
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
InflateSkRect(&skrc,-0.5f,-0.5f);//要缩小0.5显示效果才和GDI一致。
skrc.offset(m_ptOrg);
m_SkCanvas->drawRoundRect(skrc,(SkScalar)pt.x,(SkScalar)pt.y,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawLines(LPPOINT pPt,size_t nCount)
{
SkPoint *pts=new SkPoint[nCount];
for(size_t i=0; i<nCount; i++ )
{
pts[i].fX = (SkScalar)pPt[i].x;
pts[i].fY = (SkScalar)pPt[i].y;
}
SkPoint::Offset(pts,nCount,m_ptOrg);
SkPaint paint=m_paint;
if(m_bAntiAlias)
{
SkScalar wid = m_curPen->GetWidth();
if(wid>1.0f) wid-=0.5f;
paint.setStrokeWidth(wid);
}else
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
SStrokeCap strokeCap(m_curPen->GetStyle());
paint.setStrokeCap(strokeCap.Get());
SStrokeJoin strokeJoin(m_curPen->GetStyle());
paint.setStrokeJoin(strokeJoin.Get());
paint.setStyle(SkPaint::kStroke_Style);
m_SkCanvas->drawPoints(SkCanvas::kPolygon_PointMode,nCount,pts,paint);
delete []pts;
return S_OK;
}
HRESULT SRenderTarget_Skia::TextOut( int x, int y, LPCTSTR lpszString, int nCount)
{
if(nCount<0) nCount= _tcslen(lpszString);
SStringW strW=S_CT2W(SStringT(lpszString,nCount));
SkPaint txtPaint =m_paint;
txtPaint.setStyle(SkPaint::kStrokeAndFill_Style);
txtPaint.setTypeface(m_curFont->GetFont());
txtPaint.setTextSize(SkIntToScalar(abs(m_curFont->TextSize())));
txtPaint.setUnderlineText(m_curFont->IsUnderline());
txtPaint.setStrikeThruText(m_curFont->IsStrikeOut());
SkPaint::FontMetrics metrics;
txtPaint.getFontMetrics(&metrics);
SkScalar fx = m_ptOrg.fX + x;
SkScalar fy = m_ptOrg.fY + y;
fy -= metrics.fTop;
m_SkCanvas->drawText((LPCWSTR)strW,strW.GetLength()*2,fx,fy,txtPaint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawIconEx( int xLeft, int yTop, HICON hIcon, int cxWidth,int cyWidth,UINT diFlags )
{
HDC hdc=GetDC(0);
ICONINFO ii={0};
::GetIconInfo(hIcon,&ii);
SASSERT(ii.hbmColor);
BITMAP bm;
::GetObject(ii.hbmColor,sizeof(bm),&bm);
ALPHAINFO ai;
RECT rc={xLeft,yTop,xLeft+cxWidth,yTop+cyWidth};
if(bm.bmBitsPixel!=32)
{
CGdiAlpha::AlphaBackup(hdc,&rc,ai);
}
BOOL bRet=::DrawIconEx(hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,0,NULL,diFlags);
if(bm.bmBitsPixel!=32)
{
CGdiAlpha::AlphaRestore(ai);
}
if(ii.hbmColor) DeleteObject(ii.hbmColor);
if(ii.hbmMask) DeleteObject(ii.hbmMask);
ReleaseDC(hdc);
return bRet?S_OK:S_FALSE;
}
HRESULT SRenderTarget_Skia::DrawBitmap(LPCRECT pRcDest,IBitmap *pBitmap,int xSrc,int ySrc,BYTE byAlpha/*=0xFF*/ )
{
SBitmap_Skia *pBmp = (SBitmap_Skia*)pBitmap;
const SkBitmap & bmp=pBmp->GetSkBitmap();
SIZE szBmp = pBmp->Size();
int nWid= (std::min)(pRcDest->right-pRcDest->left,szBmp.cx);
int nHei= (std::min)(pRcDest->bottom-pRcDest->top,szBmp.cy);
RECT rcSrc={xSrc,ySrc,xSrc+nWid,ySrc+nHei};
RECT rcDst={pRcDest->left,pRcDest->top,pRcDest->left+nWid,pRcDest->top+nHei};
SkRect skrcSrc= toSkRect(&rcSrc);
SkRect skrcDst = toSkRect(&rcDst);
skrcDst.offset(m_ptOrg);
SkPaint paint=m_paint;
BYTE oldAlpha = paint.getAlpha();
paint.setAlpha(byAlpha);
m_SkCanvas->drawBitmapRectToRect(bmp,&skrcSrc,skrcDst,&paint);
paint.setAlpha(oldAlpha);
return S_OK;
}
HRESULT SRenderTarget_Skia::AlphaBlend( LPCRECT pRcDest,IRenderTarget *pRTSrc,LPCRECT pRcSrc,BYTE byAlpha )
{
IBitmap *pBmp=(IBitmap*) pRTSrc->GetCurrentObject(OT_BITMAP);
if(!pBmp) return S_FALSE;
RECT rcSrc = *pRcSrc;
POINT ptSrcOrg;
pRTSrc->GetViewportOrg(&ptSrcOrg);
SRenderTarget_Skia * pRTSrc_Skia=(SRenderTarget_Skia*)pRTSrc;
SkMatrix mtx = pRTSrc_Skia->m_SkCanvas->getTotalMatrix();
if(!mtx.isIdentity())
{
SkRect rc=toSkRect(&rcSrc);
mtx.mapRect(&rc);
SkRect2RECT(rc,&rcSrc);
}
OffsetRect(&rcSrc,ptSrcOrg.x,ptSrcOrg.y);
return DrawBitmapEx(pRcDest,pBmp,&rcSrc,EM_STRETCH,byAlpha);
}
HRESULT SRenderTarget_Skia::DrawBitmapEx( LPCRECT pRcDest,IBitmap *pBitmap,LPCRECT pRcSrc,UINT expendMode, BYTE byAlpha/*=0xFF*/ )
{
UINT expendModeLow = LOWORD(expendMode);
const SkMatrix & m = m_SkCanvas->getTotalMatrix();
if(m.isIdentity() && ( expendModeLow == EM_NULL || (RectWid(pRcDest)==RectWid(pRcSrc) && RectHei(pRcDest)==RectHei(pRcSrc))))
return DrawBitmap(pRcDest,pBitmap,pRcSrc->left,pRcSrc->top,byAlpha);
SBitmap_Skia *pBmp = (SBitmap_Skia*)pBitmap;
const SkBitmap & bmp=pBmp->GetSkBitmap();
RECT rcSour={0,0,bmp.width(),bmp.height()};
if(!pRcSrc) pRcSrc = &rcSour;
SkRect rcSrc = toSkRect(pRcSrc);
SkRect rcDest= toSkRect(pRcDest);
rcDest.offset(m_ptOrg);
SkPaint paint=m_paint;
BYTE oldAlpha = paint.getAlpha();
paint.setAlpha(byAlpha);
SkPaint::FilterLevel fl = (SkPaint::FilterLevel)HIWORD(expendMode);//SkPaint::kNone_FilterLevel;
paint.setFilterLevel(fl);
if(expendModeLow == EM_STRETCH)
{
m_SkCanvas->drawBitmapRectToRect(bmp,&rcSrc,rcDest,&paint);
}else
{
PushClipRect(pRcDest,RGN_AND);
SkIRect rcSrc = toSkIRect(pRcSrc);
SkRect rcSubDest={0.0f,0.0f,(float)rcSrc.width(),(float)rcSrc.height()};
for(float y=rcDest.fTop;y<rcDest.fBottom;y+=rcSrc.height())
{
rcSubDest.offsetTo(rcDest.fLeft,y);
for(float x=rcDest.fLeft;x<rcDest.fRight;x += rcSrc.width())
{
m_SkCanvas->drawBitmapRect(bmp,&rcSrc,rcSubDest,&paint);
rcSubDest.offset((float)rcSrc.width(),0.0f);
}
}
PopClip();
}
paint.setAlpha(oldAlpha);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawBitmap9Patch( LPCRECT pRcDest,IBitmap *pBitmap,LPCRECT pRcSrc,LPCRECT pRcSourMargin,UINT expendMode,BYTE byAlpha/*=0xFF*/ )
{
int xDest[4] = {pRcDest->left,pRcDest->left+pRcSourMargin->left,pRcDest->right-pRcSourMargin->right,pRcDest->right};
int xSrc[4] = {pRcSrc->left,pRcSrc->left+pRcSourMargin->left,pRcSrc->right-pRcSourMargin->right,pRcSrc->right};
int yDest[4] = {pRcDest->top,pRcDest->top+pRcSourMargin->top,pRcDest->bottom-pRcSourMargin->bottom,pRcDest->bottom};
int ySrc[4] = {pRcSrc->top,pRcSrc->top+pRcSourMargin->top,pRcSrc->bottom-pRcSourMargin->bottom,pRcSrc->bottom};
//首先保证九宫分割正常
if(!(xSrc[0] <= xSrc[1] && xSrc[1] <= xSrc[2] && xSrc[2] <= xSrc[3])) return S_FALSE;
if(!(ySrc[0] <= ySrc[1] && ySrc[1] <= ySrc[2] && ySrc[2] <= ySrc[3])) return S_FALSE;
//调整目标位置
int nDestWid=pRcDest->right-pRcDest->left;
int nDestHei=pRcDest->bottom-pRcDest->top;
if((pRcSourMargin->left + pRcSourMargin->right) > nDestWid)
{//边缘宽度大于目标宽度的处理
if(pRcSourMargin->left >= nDestWid)
{//只绘制左边部分
xSrc[1] = xSrc[2] = xSrc[3] = xSrc[0]+nDestWid;
xDest[1] = xDest[2] = xDest[3] = xDest[0]+nDestWid;
}else if(pRcSourMargin->right >= nDestWid)
{//只绘制右边部分
xSrc[0] = xSrc[1] = xSrc[2] = xSrc[3]-nDestWid;
xDest[0] = xDest[1] = xDest[2] = xDest[3]-nDestWid;
}else
{//先绘制左边部分,剩余的用右边填充
int nRemain=xDest[3]-xDest[1];
xSrc[2] = xSrc[3]-nRemain;
xDest[2] = xDest[3]-nRemain;
}
}
if(pRcSourMargin->top + pRcSourMargin->bottom > nDestHei)
{
if(pRcSourMargin->top >= nDestHei)
{//只绘制上边部分
ySrc[1] = ySrc[2] = ySrc[3] = ySrc[0]+nDestHei;
yDest[1] = yDest[2] = yDest[3] = yDest[0]+nDestHei;
}else if(pRcSourMargin->bottom >= nDestHei)
{//只绘制下边部分
ySrc[0] = ySrc[1] = ySrc[2] = ySrc[3]-nDestHei;
yDest[0] = yDest[1] = yDest[2] = yDest[3]-nDestHei;
}else
{//先绘制左边部分,剩余的用右边填充
int nRemain=yDest[3]-yDest[1];
ySrc[2] = ySrc[3]-nRemain;
yDest[2] = yDest[3]-nRemain;
}
}
//定义绘制模式
UINT mode[3][3]={
{EM_NULL,expendMode,EM_NULL},
{expendMode,expendMode,expendMode},
{EM_NULL,expendMode,EM_NULL}
};
for(int y=0;y<3;y++)
{
if(ySrc[y] == ySrc[y+1]) continue;
for(int x=0;x<3;x++)
{
if(xSrc[x] == xSrc[x+1]) continue;
RECT rcSrc = {xSrc[x],ySrc[y],xSrc[x+1],ySrc[y+1]};
RECT rcDest ={xDest[x],yDest[y],xDest[x+1],yDest[y+1]};
DrawBitmapEx(&rcDest,pBitmap,&rcSrc,mode[y][x],byAlpha);
}
}
return S_OK;
}
IRenderObj * SRenderTarget_Skia::GetCurrentObject( OBJTYPE uType )
{
IRenderObj *pRet=NULL;
switch(uType)
{
case OT_BITMAP:
pRet=m_curBmp;
break;
case OT_PEN:
pRet=m_curPen;
break;
case OT_BRUSH:
pRet=m_curBrush;
break;
case OT_FONT:
pRet=m_curFont;
break;
}
return pRet;
}
HRESULT SRenderTarget_Skia::SelectDefaultObject(OBJTYPE objType,IRenderObj ** ppOldObj /*= NULL*/)
{
IRenderObj *pDefObj = NULL;
switch(objType)
{
case OT_BITMAP: pDefObj = m_defBmp;break;
case OT_PEN: pDefObj = m_defPen;break;
case OT_BRUSH: pDefObj = m_defBrush;break;
case OT_FONT: pDefObj = m_defFont;break;
default:return E_INVALIDARG;
}
if(pDefObj == GetCurrentObject(objType))
return S_FALSE;
return SelectObject(pDefObj,ppOldObj);
}
HRESULT SRenderTarget_Skia::SelectObject( IRenderObj *pObj,IRenderObj ** ppOldObj /*= NULL*/ )
{
SAutoRefPtr<IRenderObj> pRet;
switch(pObj->ObjectType())
{
case OT_BITMAP:
pRet=m_curBmp;
m_curBmp=(SBitmap_Skia*)pObj;
//重新生成clip
SASSERT(m_SkCanvas);
delete m_SkCanvas;
m_SkCanvas = new SkCanvas(m_curBmp->GetSkBitmap());
break;
case OT_PEN:
pRet=m_curPen;
m_curPen=(SPen_Skia*)pObj;
break;
case OT_BRUSH:
pRet=m_curBrush;
m_curBrush=(SBrush_Skia*)pObj;
break;
case OT_FONT:
pRet=m_curFont;
m_curFont=(SFont_Skia*)pObj;
break;
}
if(pRet && ppOldObj)
{//由调用者调用Release释放该RenderObj
pRet->AddRef();
*ppOldObj = pRet;
}
return S_OK;
}
HRESULT SRenderTarget_Skia::OffsetViewportOrg( int xOff, int yOff, LPPOINT lpPoint )
{
SkMatrix mtx=m_SkCanvas->getTotalMatrix();
SkPoint ptOff={(SkScalar)xOff,(SkScalar)yOff};
if(lpPoint)
{
lpPoint->x = (LONG)m_ptOrg.fX;
lpPoint->y = (LONG)m_ptOrg.fY;
}
m_ptOrg.offset(ptOff.fX,ptOff.fY);
return S_OK;
}
HRESULT SRenderTarget_Skia::GetViewportOrg( LPPOINT lpPoint )
{
if(lpPoint)
{
lpPoint->x = (LONG)m_ptOrg.fX;
lpPoint->y = (LONG)m_ptOrg.fY;
}
return S_OK;
}
HRESULT SRenderTarget_Skia::SetViewportOrg( POINT pt )
{
m_ptOrg.fX = SkIntToScalar(pt.x);
m_ptOrg.fY = SkIntToScalar(pt.y);
return S_OK;
}
HDC SRenderTarget_Skia::GetDC( UINT uFlag )
{
if(m_hGetDC) return m_hGetDC;
HBITMAP bmp=m_curBmp->GetGdiBitmap();//bmp可能为NULL
HDC hdc_desk = ::GetDC(NULL);
m_hGetDC = CreateCompatibleDC(hdc_desk);
::ReleaseDC(NULL,hdc_desk);
::SelectObject(m_hGetDC,bmp);
if(m_SkCanvas->isClipEmpty())
{
::IntersectClipRect(m_hGetDC,0,0,0,0);
}else if(m_SkCanvas->isClipRect())
{
SkRect rcClip;
m_SkCanvas->getClipBounds(&rcClip);
RECT rc = {(int)rcClip.left(),(int)rcClip.top(),(int)rcClip.right(),(int)rcClip.bottom()};
::InflateRect(&rc,-1,-1);//注意需要向内缩小一个象素
::IntersectClipRect(m_hGetDC,rc.left,rc.top,rc.right,rc.bottom);
}else
{
SkRegion rgn = m_SkCanvas->getTotalClip();
SkRegion::Iterator it(rgn);
int nCount=0;
for(;!it.done();it.next())
{
nCount++;
}
it.rewind();
int nSize=sizeof(RGNDATAHEADER)+nCount*sizeof(RECT);
RGNDATA *rgnData=(RGNDATA*)malloc(nSize);
memset(rgnData,0,nSize);
rgnData->rdh.dwSize= sizeof(RGNDATAHEADER);
rgnData->rdh.iType = RDH_RECTANGLES;
rgnData->rdh.nCount=nCount;
rgnData->rdh.rcBound.right=m_curBmp->Width();
rgnData->rdh.rcBound.bottom=m_curBmp->Height();
nCount=0;
LPRECT pRc=(LPRECT)rgnData->Buffer;
for(;!it.done();it.next())
{
SkIRect skrc=it.rect();
RECT rc = {skrc.fLeft,skrc.fTop,skrc.fRight,skrc.fBottom};
pRc[nCount++]= rc;
}
HRGN hRgn=ExtCreateRegion(NULL,nSize,rgnData);
free(rgnData);
::SelectClipRgn(m_hGetDC,hRgn);
DeleteObject(hRgn);
}
::SetGraphicsMode(m_hGetDC,GM_ADVANCED);
::SetViewportOrgEx(m_hGetDC,(int)m_ptOrg.x(),(int)m_ptOrg.y(),NULL);
SkMatrix mtx=m_SkCanvas->getTotalMatrix();
XFORM xForm = { mtx.get(IxForm::kMScaleX),mtx.get(IxForm::kMSkewY),
mtx.get(IxForm::kMSkewX),mtx.get(IxForm::kMScaleY),
mtx.get(IxForm::kMTransX),mtx.get(IxForm::kMTransY) };
::SetWorldTransform(m_hGetDC,&xForm);
m_uGetDCFlag = uFlag;
return m_hGetDC;
}
void SRenderTarget_Skia::ReleaseDC( HDC hdc )
{
if(hdc == m_hGetDC)
{
DeleteDC(hdc);
m_hGetDC = 0;
m_uGetDCFlag =0;
}
}
HRESULT SRenderTarget_Skia::GradientFillEx( LPCRECT pRect,const POINT* pts,COLORREF *colors,float *pos,int nCount,BYTE byAlpha/*=0xFF*/ )
{
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
SkPoint *skPts = new SkPoint[nCount];
SkColor *skColors= new SkColor[nCount];
for(int i=0;i<nCount;i++)
{
skPts[i].iset(pts[i].x,pts[i].y);
skPts[i].offset(m_ptOrg.x(),m_ptOrg.y());
skColors[i] = SColor(colors[i],byAlpha).toARGB();
}
SkShader *pShader = SkGradientShader::CreateLinear(skPts, skColors, pos,nCount,SkShader::kMirror_TileMode);
SkPaint paint=m_paint;
paint.setShader(pShader)->unref();
m_SkCanvas->drawRect(skrc,paint);
delete []skColors;
delete []skPts;
return S_OK;
}
static bool fequal(float a,float b)
{
return fabs(a-b)< 0.0000001f;
}
HRESULT SRenderTarget_Skia::GradientFill2(LPCRECT pRect,GradientType type,COLORREF crStart,COLORREF crCenter,COLORREF crEnd,float fLinearAngle,float fCenterX,float fCenterY,int nRadius,BYTE byAlpha/*=0xff*/)
{
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
SkColor *skColors= new SkColor[3];
skColors[0]=SColor(crStart,byAlpha).toARGB();
skColors[1]=SColor(crCenter,byAlpha).toARGB();
skColors[2]=SColor(crEnd,byAlpha).toARGB();
SkShader *pShader = NULL;
SkScalar wid = skrc.width();
SkScalar hei = skrc.height();
SkScalar halfWid = wid/2;
SkScalar halfHei = hei/2;
if(type == linear)
{
SkPoint *skPts = new SkPoint[3];
skPts[1].set(halfWid,halfHei);
if(fequal(fLinearAngle,90.0f) || fequal(fLinearAngle,270.0f))
{//90度
skPts[0].set(halfWid,0.0f);
skPts[2].set(halfWid,hei);
}else if(fequal(fLinearAngle,0.0f) || fequal(fLinearAngle,180.0f))
{//水平方向
skPts[0].set(0.f ,halfHei);
skPts[2].set(wid,halfHei);
}else
{//其它角度
float angleInRadians = PI*fLinearAngle/180;
double tanAngle = tan(angleInRadians);
SkPoint pt1a,pt2a;//与左右两条边相交的位置
SkPoint pt1b,pt2b;//与上下两条边相关的位置
pt1a.fX=-halfWid,pt2a.fX=halfWid;
pt1b.fY=-halfHei,pt2b.fY=halfHei;
pt1a.fY= (SkScalar)(-halfWid*tanAngle);
pt2a.fY = -pt1a.fY;
pt1b.fX = (SkScalar)(-halfHei/tanAngle);
pt2b.fX = -pt1b.fX;
if(pt2a.fY > halfHei)
{//using pt1a,pt2a
skPts[0] = pt1a;
skPts[2] = pt2a;
}else
{//using pt1b,pt2b
skPts[0]=pt1b;
skPts[2]=pt2b;
}
}
pShader = SkGradientShader::CreateLinear(skPts, skColors, NULL,3,SkShader::kRepeat_TileMode);
delete []skPts;
}else if(type == radial)
{
SkPoint skCenter;
skCenter.set(halfWid,halfHei);
pShader = SkGradientShader::CreateRadial(skCenter,SkScalar(nRadius),skColors,NULL,3,SkShader::kRepeat_TileMode);
}else if(type==sweep)
{
SkPoint skCenter;
skCenter.set(halfWid,halfHei);
pShader = SkGradientShader::CreateSweep(SkScalar(+fCenterX*wid),SkScalar(fCenterY*hei),skColors,NULL,3);
}
delete []skColors;
if(!pShader)
{
return E_INVALIDARG;
}
SkPaint paint=m_paint;
paint.setShader(pShader)->unref();
SkPoint skOffset = {skrc.left(),skrc.top()};
m_SkCanvas->translate(skOffset.x(),skOffset.y());
skrc.offset(-skOffset.x(),-skOffset.y());
m_SkCanvas->drawRect(skrc,paint);
m_SkCanvas->translate(-skOffset.x(),-skOffset.y());
return S_OK;
}
HRESULT SRenderTarget_Skia::GradientFill( LPCRECT pRect,BOOL bVert,COLORREF crBegin,COLORREF crEnd,BYTE byAlpha/*=0xFF*/ )
{
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
SkPoint pts[2];
pts[0].set(skrc.left(),skrc.top());
if (bVert)
{
pts[1].set(skrc.left(),skrc.bottom());
}
else
{
pts[1].set(skrc.right(),skrc.top());
}
SColor cr1(crBegin,byAlpha);
SColor cr2(crEnd,byAlpha);
const SkColor colors[2] = {cr1.toARGB(),cr2.toARGB()};
SkShader *pShader = SkGradientShader::CreateLinear(pts, colors, NULL,2,SkShader::kMirror_TileMode);
SkPaint paint=m_paint;
paint.setShader(pShader);
pShader->unref();
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillSolidRect( LPCRECT pRect,COLORREF cr )
{
SkPaint paint=m_paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SColor(cr).toARGB());
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::ClearRect( LPCRECT pRect,COLORREF cr )
{
SkPaint paint=m_paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SColor(cr).toARGB());
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::InvertRect(LPCRECT pRect)
{
SkPaint paint=m_paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setXfermode(new ProcXfermode(ProcXfermode::Rop2_Invert));
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawRect(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawEllipse( LPCRECT pRect )
{
SkPaint paint=m_paint;
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
paint.setStyle(SkPaint::kStroke_Style);
if(m_bAntiAlias)
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth()-0.5f);
}else
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawOval(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillEllipse( LPCRECT pRect )
{
SkPaint paint=m_paint;
if(m_curBrush->IsBitmap())
{
paint.setFilterBitmap(true);
paint.setShader(SkShader::CreateBitmapShader(m_curBrush->GetBitmap(),SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->unref();
}else
{
paint.setFilterBitmap(false);
paint.setColor(SColor(m_curBrush->GetColor()).toARGB());
}
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawOval(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillSolidEllipse(LPCRECT pRect,COLORREF cr)
{
SkPaint paint=m_paint;
paint.setFilterBitmap(false);
paint.setColor(SColor(cr).toARGB());
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawOval(skrc,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawArc( LPCRECT pRect,float startAngle,float sweepAngle,bool useCenter )
{
SkPaint paint=m_paint;
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
SStrokeCap strokeCap(m_curPen->GetStyle());
paint.setStrokeCap(strokeCap.Get());
paint.setStyle(SkPaint::kStroke_Style);
if(m_bAntiAlias)
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth()-0.5f);
}else
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
SkRect skrc = toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawArc(skrc,startAngle,sweepAngle,useCenter,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillArc( LPCRECT pRect,float startAngle,float sweepAngle )
{
SkPaint paint=m_paint;
if(m_curBrush->IsBitmap())
{
paint.setFilterBitmap(true);
paint.setShader(SkShader::CreateBitmapShader(m_curBrush->GetBitmap(),SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->unref();
}else
{
paint.setFilterBitmap(false);
paint.setColor(SColor(m_curBrush->GetColor()).toARGB());
}
paint.setStyle(SkPaint::kFill_Style);
SkRect skrc=toSkRect(pRect);
skrc.offset(m_ptOrg);
m_SkCanvas->drawArc(skrc,startAngle, sweepAngle,true,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::SetTransform(const float matrix[9], float oldMatrix[9])
{
SASSERT(matrix);
if(oldMatrix) GetTransform(oldMatrix);
SkMatrix m;
m.setAll(matrix[IxForm::kMScaleX], matrix[IxForm::kMSkewX],matrix[IxForm::kMTransX],
matrix[IxForm::kMSkewY],matrix[IxForm::kMScaleY],matrix[IxForm::kMTransY],
matrix[IxForm::kMPersp0], matrix[IxForm::kMPersp1], matrix[IxForm::kMPersp2]
);
m.preTranslate(-m_ptOrg.fX, -m_ptOrg.fY);
m.postTranslate(m_ptOrg.fX, m_ptOrg.fY);
m_SkCanvas->setMatrix(m);
return S_OK;
}
HRESULT SRenderTarget_Skia::GetTransform(float matrix[9]) const
{
SASSERT(matrix);
const SkMatrix & m = m_SkCanvas->getTotalMatrix();
matrix[IxForm::kMScaleX] = m.getScaleX();
matrix[IxForm::kMSkewX] = m.getSkewX();
matrix[IxForm::kMTransX] = m.getTranslateX();
matrix[IxForm::kMSkewY] = m.getSkewY();
matrix[IxForm::kMScaleY] = m.getScaleY();
matrix[IxForm::kMTransY] = m.getTranslateY();
matrix[IxForm::kMPersp0] = m.getPerspX();
matrix[IxForm::kMPersp1] = m.getPerspY();
matrix[IxForm::kMPersp2] = m.get(SkMatrix::kMPersp2);
return S_OK;
}
COLORREF SRenderTarget_Skia::GetPixel( int x, int y )
{
if(!m_curBmp) return CR_INVALID;
const COLORREF *pBits = (const COLORREF*)m_curBmp->GetPixelBits();
POINT pt;
GetViewportOrg(&pt);
x += pt.x;
y += pt.y;
if(x<0 || x >= (int)m_curBmp->Width() || y<0 || y>= (int)m_curBmp->Height())
return CR_INVALID;
return pBits[y*m_curBmp->Width()+x];
}
COLORREF SRenderTarget_Skia::SetPixel( int x, int y, COLORREF cr )
{
if(!m_curBmp) return CR_INVALID;
COLORREF *pBits = (COLORREF*)m_curBmp->LockPixelBits();
POINT pt;
GetViewportOrg(&pt);
x += pt.x;
y += pt.y;
if(x >= (int)m_curBmp->Width() || y>= (int)m_curBmp->Height())
return CR_INVALID;
COLORREF crRet = pBits[y*m_curBmp->Width()+x];
pBits[y*m_curBmp->Width()+x] = cr;
m_curBmp->UnlockPixelBits(pBits);
return crRet;
}
HRESULT SRenderTarget_Skia::PushClipPath(const IPath * path, UINT mode, bool doAntiAlias /*= false*/)
{
const SPath_Skia * path2 = (const SPath_Skia *)path;
m_SkCanvas->clipPath(path2->m_skPath,SRegion_Skia::RGNMODE2SkRgnOP(mode),doAntiAlias);
return S_OK;
}
HRESULT SRenderTarget_Skia::DrawPath(const IPath * path, IPathEffect * pathEffect)
{
const SPath_Skia * path2 = (const SPath_Skia *)path;
SkPaint paint=m_paint;
paint.setColor(SColor(m_curPen->GetColor()).toARGB());
SLineDashEffect skDash(m_curPen->GetStyle());
paint.setPathEffect(skDash.Get());
SStrokeCap strokeCap(m_curPen->GetStyle());
paint.setStrokeCap(strokeCap.Get());
SStrokeJoin strokeJoin(m_curPen->GetStyle());
paint.setStrokeJoin(strokeJoin.Get());
paint.setStyle(SkPaint::kStroke_Style);
if(m_bAntiAlias)
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth()-0.5f);
}else
{
paint.setStrokeWidth((SkScalar)m_curPen->GetWidth());
}
if(pathEffect!=NULL)
{
SkPathEffect * skPathEffect = (SkPathEffect*)pathEffect->GetRealPathEffect();
paint.setPathEffect(skPathEffect);
}
SkPath skPath;
path2->m_skPath.offset(m_ptOrg.fX,m_ptOrg.fY,&skPath);
m_SkCanvas->drawPath(skPath,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::FillPath(const IPath * path)
{
const SPath_Skia * path2 = (const SPath_Skia *)path;
SkPaint paint=m_paint;
if(m_curBrush->IsBitmap())
{
paint.setFilterBitmap(true);
paint.setShader(SkShader::CreateBitmapShader(m_curBrush->GetBitmap(),SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->unref();
}else
{
paint.setFilterBitmap(false);
paint.setColor(SColor(m_curBrush->GetColor()).toARGB());
}
paint.setStyle(SkPaint::kFill_Style);
SkPath skPath;
path2->m_skPath.offset(m_ptOrg.fX,m_ptOrg.fY,&skPath);
m_SkCanvas->drawPath(skPath,paint);
return S_OK;
}
HRESULT SRenderTarget_Skia::PushLayer(const RECT * pRect,BYTE byAlpha)
{
int nLayerId = -1;
SkRect skBound = toSkRect(pRect);
if(byAlpha==0xFF)
nLayerId = m_SkCanvas->saveLayer(&skBound,NULL);
else
nLayerId = m_SkCanvas->saveLayerAlpha(&skBound,byAlpha);
m_lstLayerId.AddTail(nLayerId);
return S_OK;
}
HRESULT SRenderTarget_Skia::PopLayer()
{
if(m_lstLayerId.IsEmpty())
return E_INVALIDARG;
int nLayerID = m_lstLayerId.RemoveTail();
m_SkCanvas->restoreToCount(nLayerID);
return S_OK;
}
HRESULT SRenderTarget_Skia::SetXfermode(int mode,int *pOldMode/* =NULL */)
{
if(pOldMode) *pOldMode = m_xferMode;
m_xferMode = mode;
SetPaintXferMode(m_paint,m_xferMode);
return S_OK;
}
bool SRenderTarget_Skia::SetPaintXferMode(SkPaint & paint,int nRopMode)
{
bool bRet = true;
switch(nRopMode)
{
case kSrcCopy:
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
break;
case kDstInvert:
paint.setXfermode(new ProcXfermode(ProcXfermode::Rop2_Invert));
break;
case kSrcInvert:
paint.setXfermode(new ProcXfermode(ProcXfermode::Rop2_Xor));
break;
case kSrcAnd:
paint.setXfermode(new ProcXfermode(ProcXfermode::Rop2_And));
break;
default:
if(nRopMode >= kClear_Mode && nRopMode<=kLuminosity_Mode)
paint.setXfermodeMode((SkXfermode::Mode)nRopMode);
else
bRet = false;
break;
}
return bRet;
}
BOOL SRenderTarget_Skia::SetAntiAlias(BOOL bAntilias)
{
BOOL bRet = m_bAntiAlias;
m_bAntiAlias = !!bAntilias;
m_paint.setAntiAlias(m_bAntiAlias);
return bRet;
}
COLORREF SRenderTarget_Skia::GetTextColor()
{
return m_curColor.toCOLORREF();
}
COLORREF SRenderTarget_Skia::SetTextColor(COLORREF color)
{
COLORREF crOld=m_curColor.toCOLORREF();
m_curColor.setRGB(color);
m_paint.setColor(m_curColor.toARGB());
return crOld;
}
IMaskFilter* SRenderTarget_Skia::GetMaskFilter()
{
return m_curMaskFilter;
}
void SRenderTarget_Skia::SetMaskFilter(IMaskFilter *pMaskFilter)
{
m_curMaskFilter = pMaskFilter;
SMaskFilter_Skia *pMaskFilter2 = (SMaskFilter_Skia*)pMaskFilter;
if(pMaskFilter2)
{
m_paint.setMaskFilter(pMaskFilter2->m_maskFilter);
}
else
{
m_paint.setMaskFilter(NULL);
}
}
//////////////////////////////////////////////////////////////////////////
// SBitmap_Skia
static int s_cBmp = 0;
SBitmap_Skia::SBitmap_Skia( IRenderFactory *pRenderFac ) :TSkiaRenderObjImpl<IBitmap>(pRenderFac),m_hBmp(0)
{
// STRACE(L"bitmap new; objects = %d",++s_cBmp);
}
SBitmap_Skia::~SBitmap_Skia()
{
m_bitmap.reset();
if(m_hBmp) DeleteObject(m_hBmp);
// STRACE(L"bitmap delete objects = %d",--s_cBmp);
}
HBITMAP SBitmap_Skia::CreateGDIBitmap( int nWid,int nHei,void ** ppBits )
{
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWid;
bmi.bmiHeader.biHeight = -nHei; // top-down image
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
HDC hdc=GetDC(NULL);
//LPVOID pBits=NULL;
HBITMAP hBmp=CreateDIBSection(hdc,&bmi,DIB_RGB_COLORS,ppBits,0,0);
ReleaseDC(NULL,hdc);
return hBmp;
}
HRESULT SBitmap_Skia::Init( int nWid,int nHei ,const LPVOID pBits/*=NULL*/)
{
m_bitmap.reset();
m_bitmap.setInfo(SkImageInfo::Make(nWid,nHei,kN32_SkColorType,kPremul_SkAlphaType));
if(m_hBmp) DeleteObject(m_hBmp);
LPVOID pBmpBits=NULL;
m_hBmp=CreateGDIBitmap(nWid,nHei,&pBmpBits);
if(!m_hBmp) return E_OUTOFMEMORY;
if(pBits)
{
memcpy(pBmpBits,pBits,nWid*nHei*4);
}else
{
memset(pBmpBits,0,nWid*nHei*4);
}
m_bitmap.setPixels(pBmpBits);
return S_OK;
}
HRESULT SBitmap_Skia::Init( IImgFrame *pFrame )
{
UINT uWid=0,uHei =0;
pFrame->GetSize(&uWid,&uHei);
if(m_hBmp) DeleteObject(m_hBmp);
m_bitmap.reset();
m_bitmap.setInfo(SkImageInfo::Make(uWid, uHei,kN32_SkColorType,kPremul_SkAlphaType));
void * pBits=NULL;
m_hBmp = CreateGDIBitmap(uWid,uHei,&pBits);
if(!m_hBmp) return E_OUTOFMEMORY;
m_bitmap.setPixels(pBits);
const int stride = m_bitmap.rowBytes();
pFrame->CopyPixels(NULL, stride, stride * uHei,
reinterpret_cast<BYTE*>(m_bitmap.getPixels()));
return S_OK;
}
HRESULT SBitmap_Skia::LoadFromFile( LPCTSTR pszFileName)
{
SAutoRefPtr<IImgX> imgDecoder;
GetRenderFactory()->GetImgDecoderFactory()->CreateImgX(&imgDecoder);
if(imgDecoder->LoadFromFile(S_CT2W(pszFileName))==0) return S_FALSE;
return ImgFromDecoder(imgDecoder);
}
HRESULT SBitmap_Skia::LoadFromMemory(LPBYTE pBuf,size_t szLen)
{
SAutoRefPtr<IImgX> imgDecoder;
GetRenderFactory()->GetImgDecoderFactory()->CreateImgX(&imgDecoder);
if(imgDecoder->LoadFromMemory(pBuf,szLen)==0) return S_FALSE;
return ImgFromDecoder(imgDecoder);
}
HRESULT SBitmap_Skia::ImgFromDecoder(IImgX *imgDecoder)
{
IImgFrame *pFrame=imgDecoder->GetFrame(0);
UINT uWid=0,uHei =0;
pFrame->GetSize(&uWid,&uHei);
if(m_hBmp) DeleteObject(m_hBmp);
m_bitmap.reset();
m_bitmap.setInfo(SkImageInfo::Make(uWid, uHei,kN32_SkColorType,kPremul_SkAlphaType));
void * pBits=NULL;
m_hBmp = CreateGDIBitmap(uWid,uHei,&pBits);
if(!m_hBmp) return E_OUTOFMEMORY;
m_bitmap.setPixels(pBits);
const int stride = m_bitmap.rowBytes();
pFrame->CopyPixels(NULL, stride, stride * uHei,
reinterpret_cast<BYTE*>(m_bitmap.getPixels()));
return S_OK;
}
UINT SBitmap_Skia::Width() const
{
return m_bitmap.width();
}
UINT SBitmap_Skia::Height() const
{
return m_bitmap.height();
}
SIZE SBitmap_Skia::Size() const
{
SIZE sz={m_bitmap.width(),m_bitmap.height()};
return sz;
}
LPVOID SBitmap_Skia::LockPixelBits()
{
return m_bitmap.getPixels();
}
void SBitmap_Skia::UnlockPixelBits( LPVOID pBuf)
{
BITMAP bm;
GetObject(m_hBmp,sizeof(bm),&bm);
memcpy(bm.bmBits,pBuf,Width()*Height()*4);
m_bitmap.setPixels(pBuf);
}
const LPVOID SBitmap_Skia::GetPixelBits() const
{
return m_bitmap.getPixels();
}
//////////////////////////////////////////////////////////////////////////
static int s_cRgn =0;
SRegion_Skia::SRegion_Skia( IRenderFactory *pRenderFac )
:TSkiaRenderObjImpl<IRegion>(pRenderFac)
{
// STRACE(L"region new; objects = %d",++s_cRgn);
}
SRegion_Skia::~SRegion_Skia()
{
// STRACE(L"region delete; objects = %d",--s_cRgn);
}
void SRegion_Skia::CombineRect( LPCRECT lprect,int nCombineMode )
{
m_rgn.op(toSkIRect(lprect),RGNMODE2SkRgnOP(nCombineMode));
}
void SRegion_Skia::CombineRoundRect(LPCRECT lprect, POINT ptRadius, int nCombineMode)
{
SkPath skPath;
skPath.addRoundRect(toSkRect(lprect),SkScalar(ptRadius.x),SkScalar(ptRadius.y));
SkRegion clip;
clip.setRect(lprect->left,lprect->top,lprect->right,lprect->bottom);
SkRegion rgn;
rgn.setPath(skPath,clip);
m_rgn.op(rgn,RGNMODE2SkRgnOP(nCombineMode));
}
void SRegion_Skia::CombineEllipse(LPCRECT lprect , int nCombineMode)
{
SkPath skPath;
skPath.addOval(toSkRect(lprect));
SkRegion clip;
clip.setRect(lprect->left,lprect->top,lprect->right,lprect->bottom);
SkRegion rgn;
rgn.setPath(skPath,clip);
m_rgn.op(rgn,RGNMODE2SkRgnOP(nCombineMode));
}
void SRegion_Skia::CombinePolygon(const POINT * pts, int count, int nPolygonMode, int nCombineMode)
{
SkPoint *spts = new SkPoint[count];
RECT rc = { 0 };
for (int i = 0; i < count; i++)
{
if (rc.left > pts[i].x) rc.left = pts[i].x;
if (rc.right < pts[i].x) rc.right = pts[i].x;
if (rc.top > pts[i].y) rc.top = pts[i].y;
if (rc.bottom < pts[i].y) rc.bottom = pts[i].y;
spts[i].iset(pts[i].x, pts[i].y);
}
SkPath skPath;
skPath.addPoly(spts, count, true);
delete[]spts;
SkRegion clip;
clip.setRect(rc.left, rc.top, rc.right, rc.bottom);
SkRegion rgn;
rgn.setPath(skPath, clip);
m_rgn.op(rgn, RGNMODE2SkRgnOP(nCombineMode));
}
void SRegion_Skia::CombineRgn(const IRegion * pRgnSrc,int nCombineMode)
{
const SRegion_Skia * pRgnSrc2 = (const SRegion_Skia*)pRgnSrc;
m_rgn.op(pRgnSrc2->GetRegion(),RGNMODE2SkRgnOP(nCombineMode));
}
BOOL SRegion_Skia::PtInRegion( POINT pt ) const
{
return m_rgn.contains(pt.x,pt.y);
}
BOOL SRegion_Skia::RectInRegion( LPCRECT lprect ) const
{
SASSERT(lprect);
return m_rgn.intersects(toSkIRect(lprect));
}
void SRegion_Skia::GetRgnBox( LPRECT lprect ) const
{
SASSERT(lprect);
SkIRect rc=m_rgn.getBounds();
lprect->left=rc.left();
lprect->top=rc.top();
lprect->right=rc.right();
lprect->bottom=rc.bottom();
}
BOOL SRegion_Skia::IsEmpty() const
{
return m_rgn.isEmpty();
}
BOOL SRegion_Skia::IsEqual(const IRegion *testRgn) const
{
const SRegion_Skia * pRgnTest = (const SRegion_Skia*)testRgn;
return m_rgn == pRgnTest->m_rgn;
}
void SRegion_Skia::Offset( POINT pt )
{
m_rgn.translate(pt.x,pt.y);
}
SkRegion SRegion_Skia::GetRegion() const
{
return m_rgn;
}
void SRegion_Skia::SetRegion( const SkRegion & rgn )
{
m_rgn=rgn;
}
SkRegion::Op SRegion_Skia::RGNMODE2SkRgnOP( UINT mode )
{
SkRegion::Op op = SkRegion::kReplace_Op;
switch(mode)
{
case RGN_COPY: op = SkRegion::kReplace_Op;break;
case RGN_AND: op = SkRegion::kIntersect_Op;break;
case RGN_OR: op = SkRegion::kUnion_Op;break;
case RGN_DIFF: op = SkRegion::kDifference_Op;break;
case RGN_XOR: op = SkRegion::kXOR_Op;break;
default:SASSERT(FALSE);break;
}
return op;
}
void SRegion_Skia::Clear()
{
m_rgn.setEmpty();
}
//////////////////////////////////////////////////////////////////////////
// SFont_Skia
SStringT FindPropValue(const SStringT & strProp, const SStringT & strKey)
{
SStringT strValue;
int nPos1 = strProp.Find(strKey);
if(nPos1!=-1)
{
nPos1+=strKey.GetLength();
if(nPos1<strProp.GetLength() && strProp[nPos1]==_T(':'))
{
nPos1++;
int nPos2=strProp.Find(_T(','),nPos1);
if(nPos2==-1) nPos2=strProp.GetLength();
strValue=strProp.Mid(nPos1,nPos2-nPos1);
}
}
return strValue;
}
static int s_cFont =0;
SFont_Skia::SFont_Skia( IRenderFactory * pRenderFac,const LOGFONT * plf)
:TSkiaRenderObjImpl<IFont>(pRenderFac)
,m_skFont(NULL)
,m_blurStyle((SkBlurStyle)-1)
,m_blurRadius(0.0f)
,m_blurFilter(NULL)
{
memcpy(&m_lf,plf,sizeof(LOGFONT));
#ifdef UNICODE
SStringA strFace=S_CT2A(plf->lfFaceName,CP_UTF8);
#else
SStringA strFace=S_CT2A(plf->lfFaceName,CP_ACP);
#endif
BYTE style=SkTypeface::kNormal;
if(plf->lfItalic) style |= SkTypeface::kItalic;
if(plf->lfWeight == FW_BOLD) style |= SkTypeface::kBold;
m_skFont=SkTypeface::CreateFromName(strFace,(SkTypeface::Style)style,plf->lfCharSet);
// STRACE(L"font new: objects = %d", ++s_cFont);
}
SFont_Skia::~SFont_Skia()
{
if(m_blurFilter) m_blurFilter->unref();
if(m_skFont) m_skFont->unref();
// STRACE(L"font delete: objects = %d", --s_cFont);
}
void SFont_Skia::OnInitFinished(pugi::xml_node xmlNode)
{
(xmlNode);
if(m_blurStyle != -1 && m_blurRadius > 0.0f)
{
m_blurFilter = SkBlurMaskFilter::Create(m_blurStyle,
SkBlurMask::ConvertRadiusToSigma(m_blurRadius));
}
}
BOOL SFont_Skia::UpdateFont(const LOGFONT *plf)
{
if(!m_skFont) return FALSE;
memcpy(&m_lf,plf,sizeof(LOGFONT));
#ifdef UNICODE
SStringA strFace=S_CT2A(plf->lfFaceName,CP_UTF8);
#else
SStringA strFace=S_CT2A(plf->lfFaceName,CP_ACP);
#endif
BYTE style=SkTypeface::kNormal;
if(plf->lfItalic) style |= SkTypeface::kItalic;
if(plf->lfWeight == FW_BOLD) style |= SkTypeface::kBold;
m_skFont->unref();
m_skFont=SkTypeface::CreateFromName(strFace,(SkTypeface::Style)style);
return TRUE;
}
namespace RENDER_SKIA
{
BOOL SCreateInstance( IObjRef ** ppRenderFactory )
{
*ppRenderFactory = new SRenderFactory_Skia;
return TRUE;
}
}
//////////////////////////////////////////////////////////////////////////
static int s_cPath =0;
SPath_Skia::SPath_Skia(IRenderFactory *pRenderFac)
:TSkiaRenderObjImpl<IPath>(pRenderFac)
{
// STRACE(L"path new; objects = %d",++s_cPath);
}
SPath_Skia::~SPath_Skia()
{
// STRACE(L"path delete; objects = %d",--s_cPath);
}
const OBJTYPE SPath_Skia::ObjectType() const
{
return OT_PATH;
}
IPath::FillType SPath_Skia::getFillType() const
{
return (IPath::FillType)m_skPath.getFillType();
}
void SPath_Skia::setFillType(IPath::FillType ft)
{
m_skPath.setFillType((SkPath::FillType)ft);
}
bool SPath_Skia::isInverseFillType() const
{
return m_skPath.isInverseFillType();
}
void SPath_Skia::toggleInverseFillType()
{
m_skPath.toggleInverseFillType();
}
IPath::Convexity SPath_Skia::getConvexity() const
{
return (IPath::Convexity)m_skPath.getConvexity();
}
void SPath_Skia::setConvexity(Convexity c)
{
m_skPath.setConvexity((SkPath::Convexity)c);
}
bool SPath_Skia::isConvex() const
{
return m_skPath.isConvex();
}
bool SPath_Skia::isOval(RECT* rect) const
{
SkRect skRect;
bool bRet = m_skPath.isOval(&skRect);
if(rect && bRet)
{
SkRect2RECT(skRect,rect);
}
return bRet;
}
void SPath_Skia::reset()
{
m_skPath.reset();
}
void SPath_Skia::rewind()
{
m_skPath.rewind();
}
bool SPath_Skia::isEmpty() const
{
return m_skPath.isEmpty();
}
bool SPath_Skia::isFinite() const
{
return m_skPath.isFinite();
}
bool SPath_Skia::isLine(POINT line[2]) const
{
SkPoint skLine[2];
bool bRet = m_skPath.isLine(skLine);
if(bRet)
{
line[0].x = (int)skLine[0].fX;
line[0].y = (int)skLine[0].fY;
line[1].x = (int)skLine[1].fX;
line[1].x = (int)skLine[1].fY;
}
return bRet;
}
bool SPath_Skia::isRect(RECT* rect) const
{
SkRect skRect;
bool bRet = m_skPath.isRect(&skRect);
if(rect && bRet)
{
SkRect2RECT(skRect,rect);
}
return bRet;
}
bool SPath_Skia::isRect(bool* isClosed, Direction* direction) const
{
return m_skPath.isRect(isClosed,(SkPath::Direction*)direction);
}
int SPath_Skia::countPoints() const
{
return m_skPath.countPoints();
}
fPoint SPath_Skia::getPoint(int index) const
{
SkPoint ret = m_skPath.getPoint(index);
fPoint pt = {ret.fX,ret.fY};
return pt;
}
int SPath_Skia::getPoints(fPoint points[], int max) const
{
SASSERT(points);
SkPoint *pts = new SkPoint[max];
int nRet = m_skPath.getPoints(pts,max);
for(int i=0;i<nRet;i++)
{
points[i].fX = pts[i].fX;
points[i].fY = pts[i].fY;
}
delete []pts;
return nRet;
}
int SPath_Skia::countVerbs() const
{
return m_skPath.countVerbs();
}
int SPath_Skia::getVerbs(BYTE verbs[], int max) const
{
return m_skPath.getVerbs(verbs,max);
}
RECT SPath_Skia::getBounds() const
{
const SkRect &rc = m_skPath.getBounds();
RECT rcRet;
SkRect2RECT(rc,&rcRet);
return rcRet;
}
void SPath_Skia::moveTo(float x, float y)
{
m_skPath.moveTo(x,y);
}
void SPath_Skia::rMoveTo(float dx, float dy)
{
m_skPath.rMoveTo(dx,dy);
}
void SPath_Skia::lineTo(float x, float y)
{
m_skPath.lineTo(x,y);
}
void SPath_Skia::rLineTo(float dx, float dy)
{
m_skPath.rLineTo(dx,dy);
}
void SPath_Skia::quadTo(float x1, float y1, float x2, float y2)
{
m_skPath.quadTo(x1,y1,x2,y2);
}
void SPath_Skia::rQuadTo(float dx1, float dy1, float dx2, float dy2)
{
m_skPath.rQuadTo(dx1,dy1,dx2,dy2);
}
void SPath_Skia::conicTo(float x1, float y1, float x2, float y2, float w)
{
m_skPath.conicTo(x1,y1,x2,y2,w);
}
void SPath_Skia::rConicTo(float dx1, float dy1, float dx2, float dy2, float w)
{
m_skPath.rConicTo(dx1,dy1,dx2,dy2,w);
}
void SPath_Skia::cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
{
m_skPath.cubicTo(x1,y1,x2,y2,x3,y3);
}
void SPath_Skia::rCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
{
m_skPath.rCubicTo(dx1,dy1,dx2,dy2,dx3,dy3);
}
void SPath_Skia::arcTo(const RECT& oval, float startAngle, float sweepAngle, bool forceMoveTo)
{
SkRect skOval = toSkRect(&oval);
m_skPath.arcTo(skOval,startAngle,sweepAngle,forceMoveTo);
}
void SPath_Skia::arcTo(float x1, float y1, float x2, float y2, float radius)
{
m_skPath.arcTo(x1,y1,x2,y2,radius);
}
void SPath_Skia::close()
{
m_skPath.close();
}
void SPath_Skia::addRect(const RECT& rect, Direction dir /*= kCW_Direction*/)
{
SkRect skRc = toSkRect(&rect);
m_skPath.addRect(skRc,(SkPath::Direction)dir);
}
void SPath_Skia::addRect(float left, float top, float right, float bottom, Direction dir /*= kCW_Direction*/)
{
m_skPath.addRect(left,top,right,bottom,(SkPath::Direction)dir);
}
void SPath_Skia::addOval(const RECT& oval, Direction dir /*= kCW_Direction*/)
{
SkRect skRc = toSkRect(&oval);
m_skPath.addOval(skRc,(SkPath::Direction)dir);
}
void SPath_Skia::addCircle(float x, float y, float radius, Direction dir /*= kCW_Direction*/)
{
m_skPath.addCircle(x,y,radius,(SkPath::Direction)dir);
}
void SPath_Skia::addArc(const RECT& oval, float startAngle, float sweepAngle)
{
SkRect skRc = toSkRect(&oval);
m_skPath.addArc(skRc,startAngle,sweepAngle);
}
void SPath_Skia::addRoundRect(const RECT& rect, float rx, float ry, Direction dir /*= kCW_Direction*/)
{
SkRect skRc = toSkRect(&rect);
m_skPath.addRoundRect(skRc,rx,ry,(SkPath::Direction)dir);
}
void SPath_Skia::addRoundRect(const RECT& rect, const float radii[], Direction dir /*= kCW_Direction*/)
{
SkRect skRc = toSkRect(&rect);
m_skPath.addRoundRect(skRc,radii,(SkPath::Direction)dir);
}
void SPath_Skia::addPoly(const POINT pts[], int count, bool close)
{
SkPoint *skPts = new SkPoint[count];
for(int i=0;i<count;i++)
{
skPts[i].fX = (float)pts[i].x;
skPts[i].fY = (float)pts[i].y;
}
m_skPath.addPoly(skPts,count,close);
delete []skPts;
}
void SPath_Skia::addPath(const IPath * src, float dx, float dy, AddPathMode mode /*= kAppend_AddPathMode*/)
{
const SPath_Skia *skSrc = (const SPath_Skia*)src;
m_skPath.addPath(skSrc->m_skPath,dx,dy,(SkPath::AddPathMode)mode);
}
void SPath_Skia::reverseAddPath(const IPath* src)
{
const SPath_Skia *skSrc = (const SPath_Skia*)src;
m_skPath.reverseAddPath(skSrc->m_skPath);
}
void SPath_Skia::offset(float dx, float dy)
{
m_skPath.offset(dx,dy);
}
void SPath_Skia::transform(const IxForm * xForm)
{
SkMatrix mat;
mat.setAll(xForm->GetValue(IxForm::kMScaleX),
xForm->GetValue(IxForm::kMSkewX),
xForm->GetValue(IxForm::kMTransX),
xForm->GetValue(IxForm::kMSkewY),
xForm->GetValue(IxForm::kMScaleY),
xForm->GetValue(IxForm::kMTransY),
xForm->GetValue(IxForm::kMPersp0),
xForm->GetValue(IxForm::kMPersp1),
xForm->GetValue(IxForm::kMPersp2));
m_skPath.transform(mat);
}
bool SPath_Skia::getLastPt(POINT* lastPt) const
{
SkPoint pt;
bool bRet = m_skPath.getLastPt(&pt);
if(lastPt)
{
lastPt->x = (int)pt.fX;
lastPt->y = (int)pt.fY;
}
return bRet;
}
void SPath_Skia::setLastPt(float x, float y)
{
m_skPath.setLastPt(x,y);
}
void SPath_Skia::addString(LPCTSTR pszText,int nLen, float x,float y, const IFont *pFont)
{
const SFont_Skia *pFontSkia = (const SFont_Skia *)pFont;
if(nLen < 0) nLen = _tcslen(pszText);
SkPaint paint;
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
paint.setTypeface(pFontSkia->GetFont());
const LOGFONT *plf = pFont->LogFont();
paint.setTextSize(SkIntToScalar(abs(plf->lfHeight)));
paint.setUnderlineText(!!plf->lfUnderline);
paint.setStrikeThruText(!!plf->lfStrikeOut);
SkPath path;
#ifdef _UNICODE
paint.getTextPath(pszText,nLen,0.0f,0.0f,&path);
#else
SStringW str=S_CT2W(SStringT(pszText,nLen));
paint.getTextPath((LPCWSTR)str,str.GetLength(),0.0f,0.0f,&path);
#endif
m_skPath.addPath(path,x,y,SkPath::kAppend_AddPathMode);
}
static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
const SkPoint& toPoint) {
if (segmentPoints.empty()) {
segmentPoints.push_back(SkPoint::Make(0, 0));
lengths.push_back(0);
}
else if (segmentPoints.back() == toPoint) {
return; // Empty line
}
float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint);
segmentPoints.push_back(toPoint);
lengths.push_back(length);
}
typedef SkPoint(*bezierCalculation)(float t, const SkPoint* points);
static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) {
float oneMinusT = 1 - t;
float oneMinusTSquared = oneMinusT * oneMinusT;
float oneMinusTCubed = oneMinusTSquared * oneMinusT;
float tSquared = t * t;
float tCubed = tSquared * t;
return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1)
+ (3 * oneMinusT * tSquared * p2) + (tCubed * p3);
}
static SkPoint cubicBezierCalculation(float t, const SkPoint* points) {
float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(),
points[2].x(), points[3].x());
float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(),
points[2].y(), points[3].y());
return SkPoint::Make(x, y);
}
static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) {
float oneMinusT = 1 - t;
return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2));
}
static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) {
float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x());
float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y());
return SkPoint::Make(x, y);
}
// Subdivide a section of the Bezier curve, set the mid-point and the mid-t value.
// Returns true if further subdivision is necessary as defined by errorSquared.
static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction,
float t0, const SkPoint &p0, float t1, const SkPoint &p1,
float& midT, SkPoint &midPoint, float errorSquared) {
midT = (t1 + t0) / 2;
float midX = (p1.x() + p0.x()) / 2;
float midY = (p1.y() + p0.y()) / 2;
midPoint = (*bezierFunction)(midT, points);
float xError = midPoint.x() - midX;
float yError = midPoint.y() - midY;
float midErrorSquared = (xError * xError) + (yError * yError);
return midErrorSquared > errorSquared;
}
static void addBezier(const SkPoint* points,
bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints,
std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) {
typedef std::map<float, SkPoint> PointMap;
PointMap tToPoint;
tToPoint[0] = (*bezierFunction)(0, points);
tToPoint[1] = (*bezierFunction)(1, points);
PointMap::iterator iter = tToPoint.begin();
PointMap::iterator next = iter;
++next;
while (next != tToPoint.end()) {
bool needsSubdivision = true;
SkPoint midPoint;
do {
float midT;
needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
iter->second, next->first, next->second, midT, midPoint, errorSquared);
if (!needsSubdivision && doubleCheckDivision) {
SkPoint quarterPoint;
float quarterT;
needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared);
if (needsSubdivision) {
// Found an inflection point. No need to double-check.
doubleCheckDivision = false;
}
}
if (needsSubdivision) {
next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint));
}
} while (needsSubdivision);
iter = next;
next++;
}
// Now that each division can use linear interpolation with less than the allowed error
for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) {
addLine(segmentPoints, lengths, iter->second);
}
}
static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
const SkPoint& point) {
float length = 0;
if (!lengths.empty()) {
length = lengths.back();
}
segmentPoints.push_back(point);
lengths.push_back(length);
}
static void createVerbSegments(SkPath::Verb verb, const SkPoint* points,
std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) {
switch (verb) {
case SkPath::kMove_Verb:
addMove(segmentPoints, lengths, points[0]);
break;
case SkPath::kClose_Verb:
addLine(segmentPoints, lengths, points[0]);
break;
case SkPath::kLine_Verb:
addLine(segmentPoints, lengths, points[1]);
break;
case SkPath::kQuad_Verb:
addBezier(points, quadraticBezierCalculation, segmentPoints, lengths,
errorSquared, false);
break;
case SkPath::kCubic_Verb:
addBezier(points, cubicBezierCalculation, segmentPoints, lengths,
errorSquared, true);
break;
default:
// Leave element as NULL, Conic sections are not supported.
break;
}
}
IPathInfo* SPath_Skia::approximate(float acceptableError)
{
SkPath::Iter pathIter(m_skPath, false);
SkPath::Verb verb;
SkPoint points[4];
std::vector<SkPoint> segmentPoints;
std::vector<float> lengths;
float errorSquared = acceptableError * acceptableError;
while ((verb = pathIter.next(points, false)) != SkPath::kDone_Verb) {
createVerbSegments(verb, points, segmentPoints, lengths, errorSquared);
}
if (segmentPoints.empty()) {
int numVerbs = m_skPath.countVerbs();
if (numVerbs == 1) {
addMove(segmentPoints, lengths, m_skPath.getPoint(0));
}
else {
// Invalid or empty path. Fall back to point(0,0)
addMove(segmentPoints, lengths, SkPoint());
}
}
float totalLength = lengths.back();
if (totalLength == 0) {
// Lone Move instructions should still be able to animate at the same value.
segmentPoints.push_back(segmentPoints.back());
lengths.push_back(1);
totalLength = 1;
}
size_t numPoints = segmentPoints.size();
size_t approximationArraySize = numPoints * 3;
int nLen = approximationArraySize;
SPathInfo_Skia * pInfo = new SPathInfo_Skia(numPoints);
float* approximation = pInfo->buffer();
int approximationIndex = 0;
for (size_t i = 0; i < numPoints; i++) {
const SkPoint& point = segmentPoints[i];
approximation[approximationIndex++] = lengths[i] / totalLength;
approximation[approximationIndex++] = point.x();
approximation[approximationIndex++] = point.y();
}
return pInfo;
}
SPathInfo_Skia::SPathInfo_Skia(int points):mPoints(points),mData(new float[points*3])
{
}
SPathInfo_Skia::~SPathInfo_Skia()
{
delete []mData;
}
int SPathInfo_Skia::pointNumber() const
{
return mPoints;
}
const float * SPathInfo_Skia::data() const
{
return mData;
}
float * SPathInfo_Skia::buffer()
{
return mData;
}
//--------------------------------------------------------------------------------
SMaskFilter_Skia::SMaskFilter_Skia(SkMaskFilter *maskFilter):m_maskFilter(maskFilter)
{
}
SMaskFilter_Skia::~SMaskFilter_Skia()
{
if(m_maskFilter)
{
m_maskFilter->unref();
}
}
}//end of namespace SOUI