// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "../../../include/fxge/fx_ge.h"
//#define _SKIA_SUPPORT_
#if defined(_SKIA_SUPPORT_)
#include "../../../include/fxcodec/fx_codec.h"


//#define _FOXIT_DEBUG_
//#define _FOXIT_BENCHMARK_

extern "C" {
	extern void FX_OUTPUT_LOG_FUNC(const char*, ...);
	extern int FX_GET_TICK_FUNC();
};

#ifdef _FOXIT_DEBUG_
#define FOXIT_DEBUG1(msg) FX_OUTPUT_LOG_FUNC(msg)
#define FOXIT_DEBUG2(msg,para) FX_OUTPUT_LOG_FUNC(msg,para)
#define FOXIT_DEBUG3(msg,para1,para2) FX_OUTPUT_LOG_FUNC(msg,para1,para2)
#define FOXIT_DEBUG4(msg,para1,para2,para3) FX_OUTPUT_LOG_FUNC(msg,para1,para2,para3)
#define FOXIT_DEBUG5(msg,para1,para2,para3,param4) FX_OUTPUT_LOG_FUNC(msg,para1,para2,para3,param4)
#else
#define FOXIT_DEBUG1(msg)
#define FOXIT_DEBUG2(msg,para)
#define FOXIT_DEBUG3(msg,para1,para2)
#define FOXIT_DEBUG4(msg,para1,para2,para3)
#define FOXIT_DEBUG5(msg,para1,para2,para3,param4)
#endif

#include "SkDashPathEffect.h"
#include "SkTLazy.h"
#include "SkScan.h"
#include "SkRasterClip.h"
#include "SkStroke.h"


#include "fx_skia_blitter_new.h"
#include "../agg/fx_agg_driver.h"
#include "fx_skia_device.h"
/// Run-length-encoded supersampling antialiased blitter.
class SuperBlitter_skia
{
public:
	static void DrawPath(const SkPath& srcPath, SkBlitter* blitter,  const SkRasterClip& rect, const SkPaint& origPaint);
};
FX_BOOL FxSkDrawTreatAsHairline(const SkPaint& paint, SkScalar* coverage) {
	if (SkPaint::kStroke_Style != paint.getStyle())
		return FALSE;
	FXSYS_assert(coverage);
	SkScalar strokeWidth = paint.getStrokeWidth();
	if (0 == strokeWidth) {
		*coverage = SK_Scalar1;
		return TRUE;
	}
	// if we get here, we need to try to fake a thick-stroke with a modulated
	// hairline
	if (!paint.isAntiAlias())
		return FALSE;
	if (strokeWidth <= SK_Scalar1) {
		*coverage = strokeWidth;
		return TRUE;
	}
	return FALSE;
}

void SuperBlitter_skia::DrawPath(const SkPath& srcPath, SkBlitter* blitter, const SkRasterClip& rect, const SkPaint& origPaint) 
{
	SkPath*		pathPtr = (SkPath*)&srcPath;
	bool		doFill = true;
	SkPath		tmpPath;
	SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
	{
		SkScalar coverage;
		if (FxSkDrawTreatAsHairline(origPaint, &coverage)) {
			if (SK_Scalar1 == coverage) {
				paint.writable()->setStrokeWidth(0);
			} else if (1) {//xfermodeSupportsCoverageAsAlpha(xfer), we not use blend mode here, xfer aways NULL.
				U8CPU newAlpha;
				// this is the old technique, which we preserve for now so
				// we don't change previous results (testing)
				// the new way seems fine, its just (a tiny bit) different
				int scale = (int)SkScalarMul(coverage, 256);
				newAlpha = origPaint.getAlpha() * scale >> 8;
				SkPaint* writablePaint = paint.writable();
				writablePaint->setStrokeWidth(0);
				writablePaint->setAlpha(newAlpha);
			}
		}
	}
	if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
		SkIRect devBounds = rect.getBounds();
		// outset to have slop for antialasing and hairlines
		devBounds.outset(1, 1);
		SkRect cullRect = SkRect::Make(devBounds);
		doFill = paint->getFillPath(*pathPtr, &tmpPath, &cullRect);
		pathPtr = &tmpPath;
	}
	// avoid possibly allocating a new path in transform if we can
	SkPath* devPathPtr = pathPtr;
	void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
	if (doFill) {
		if (paint->isAntiAlias()) {
			proc = SkScan::AntiFillPath;
		} else {
			proc = SkScan::FillPath;
		}
	} else {	// hairline
		if (paint->isAntiAlias()) {
			proc = SkScan::AntiHairPath;
		} else {
			proc = SkScan::HairPath;
		}
	}
	proc(*devPathPtr, rect, blitter);
}

class CSkia_PathData 
{
public:
	CSkia_PathData() {}
	~CSkia_PathData() {}
	SkPath			m_PathData;

	void			BuildPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device);
};

void CSkia_PathData::BuildPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device)
{
	const CFX_PathData* pFPath = pPathData;
	int nPoints = pFPath->GetPointCount();
	FX_PATHPOINT* pPoints = pFPath->GetPoints();
	for (int i = 0; i < nPoints; i ++) {
		FX_FIXFLOAT x = pPoints[i].m_PointX, y = pPoints[i].m_PointY;
		if (pObject2Device) pObject2Device->Transform(x, y);
		int point_type = pPoints[i].m_Flag & FXPT_TYPE;
		if (point_type == FXPT_MOVETO) {
			m_PathData.moveTo(x, y);
		} else if (point_type == FXPT_LINETO) {
			if (pPoints[i-1].m_Flag == FXPT_MOVETO && (i == nPoints-1 || pPoints[i+1].m_Flag == FXPT_MOVETO) &&
					FXSYS_abs(pPoints[i].m_PointX - pPoints[i-1].m_PointX) < 0.4f && FXSYS_abs(pPoints[i].m_PointY - pPoints[i-1].m_PointY)< 0.4f)
				// PDF line includes the destination point, unlike Windows line.
				// We received some PDF which actually draws zero length lines. TESTDOC: summer cha show.pdf
				// Therefore, we have to extend the line by 0.4 pixel here.
				// But only for standalone segment. TESTDOC: bug #1434 - maze.pdf; TESTDOC: bug#1508 di704P_QIG_111.pdf 
				x += 0.4;
			// TODO: we should actually tell skia vertex generator to process zero length stroked line 
			// (only butts are drawn)
			m_PathData.lineTo(x, y);
		} else if (point_type == FXPT_BEZIERTO) {
			FX_FIXFLOAT x2 = pPoints[i+1].m_PointX, y2 = pPoints[i+1].m_PointY;
			FX_FIXFLOAT x3 = pPoints[i+2].m_PointX, y3 = pPoints[i+2].m_PointY;
			if (pObject2Device){
				pObject2Device->Transform(x2, y2);
				pObject2Device->Transform(x3, y3);
			}
			m_PathData.cubicTo(x, y, x2, y2, x3, y3);
			i += 2;
		}
		if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE) m_PathData.close();
	}
}

// convert a stroking path to scanlines
static void SkRasterizeStroke(SkPaint& spaint, SkPath* dstPathData, SkPath& path_data, 
					 const CFX_AffineMatrix* pObject2Device,
					 const CFX_GraphStateData* pGraphState, FX_FIXFLOAT scale = FIX8_ONE, 
					 FX_BOOL bStrokeAdjust = FALSE, FX_BOOL bTextMode = FALSE)
{
	SkPaint::Cap cap;
	switch (pGraphState->m_LineCap) {
		case CFX_GraphStateData::LineCapRound:
			cap = SkPaint::kRound_Cap;
			break;
		case CFX_GraphStateData::LineCapSquare:
			cap = SkPaint::kSquare_Cap;
			break;
		default:
			cap = SkPaint::kButt_Cap;
			break;
	}
	SkPaint::Join join;
	switch (pGraphState->m_LineJoin) {
		case CFX_GraphStateData::LineJoinRound:
			join = SkPaint::kRound_Join;
			break;
		case CFX_GraphStateData::LineJoinBevel:
			join = SkPaint::kBevel_Join;
			break;
		default:
			join = SkPaint::kMiter_Join;
			break;
	}
	FX_FIXFLOAT width = pGraphState->m_LineWidth*scale;
	FX_FIXFLOAT unit = fix32_to_8(fixdiv_8_8_to_32(FIX8_ONE, (pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2));
	if (width <= unit) width = unit;

	if (pGraphState->m_DashArray == NULL) {
		SkStroke stroker;
		stroker.setCap(cap);
		stroker.setJoin(join);
		stroker.setMiterLimit(pGraphState->m_MiterLimit);
		stroker.setWidth(width);
		stroker.setDoFill(FALSE);
		stroker.strokePath(path_data, dstPathData);
		SkMatrix smatrix; 
		smatrix.setAll(pObject2Device->a, pObject2Device->c, pObject2Device->e, pObject2Device->b, pObject2Device->d, pObject2Device->f, 0, 0, 1);
		dstPathData->transform(smatrix);
	} else {
		int count = (pGraphState->m_DashCount+1)/2;
		SkScalar* intervals = FX_Alloc(SkScalar, count* sizeof (SkScalar));
		// Set dash pattern
		for (int i = 0; i < count; i ++) {
			FX_FIXFLOAT on = pGraphState->m_DashArray[i*2];
			if (on <= 0.000001f) on = FIX8_ONE/10;
			FX_FIXFLOAT off = i*2+1 == pGraphState->m_DashCount ? on :
					pGraphState->m_DashArray[i*2+1];
			if (off < 0) off = 0;		
			intervals[i*2]=on*scale;
			intervals[i*2+1]=off*scale;
		}
		SkDashPathEffect* pEffect = new SkDashPathEffect(intervals,count*2, pGraphState->m_DashPhase*scale);
		spaint.setPathEffect(pEffect)->unref();
		spaint.setStrokeWidth(width);
		spaint.setStrokeMiter(pGraphState->m_MiterLimit);
		spaint.setStrokeCap(cap);
		spaint.setStrokeJoin(join);
		spaint.getFillPath(path_data, dstPathData);
		SkMatrix smatrix; 
		smatrix.setAll(pObject2Device->a, pObject2Device->c, pObject2Device->e, pObject2Device->b, pObject2Device->d, pObject2Device->f, 0, 0, 1);
		dstPathData->transform(smatrix);
		FX_Free(intervals);
	}
}

CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, int dither_bits, FX_BOOL bRgbByteOrder, CFX_DIBitmap* pOriDevice, FX_BOOL bGroupKnockout)
{
	m_pAggDriver = FX_NEW CFX_AggDeviceDriver(pBitmap, dither_bits, bRgbByteOrder, pOriDevice, bGroupKnockout);
}
CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver()
{
	if (m_pAggDriver) delete m_pAggDriver;
}
FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont,
		CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, FX_FIXFLOAT font_size, FX_DWORD color, 
		int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->DrawDeviceText(nChars, pCharPos, pFont,pCache, pObject2Device, font_size, color, 
		alpha_flag, pIccTransform);
}
int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id)
{
	return m_pAggDriver->GetDeviceCaps(caps_id);
}
void CFX_SkiaDeviceDriver::SaveState()
{
	m_pAggDriver->SaveState();	
}

void CFX_SkiaDeviceDriver::RestoreState(FX_BOOL bKeepSaved)
{
	m_pAggDriver->RestoreState(bKeepSaved);
}
void CFX_SkiaDeviceDriver::SetClipMask(rasterizer_scanline_aa& rasterizer)
{
	m_pAggDriver->SetClipMask(rasterizer);
}
void CFX_SkiaDeviceDriver::SetClipMask(SkPath& skPath, SkPaint* spaint)
{	
	SkIRect clip_box;
	clip_box.set(0, 0, fix0_to_8(GetDeviceCaps(FXDC_PIXEL_WIDTH)), fix0_to_8(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
	clip_box.intersect(m_pAggDriver->m_pClipRgn->GetBox().left, m_pAggDriver->m_pClipRgn->GetBox().top,
		m_pAggDriver->m_pClipRgn->GetBox().right, m_pAggDriver->m_pClipRgn->GetBox().bottom);

	SkPath* pathPtr = &skPath;

	SkRect path_rect = skPath.getBounds();

	clip_box.intersect(FXSYS_floor(path_rect.fLeft), FXSYS_floor(path_rect.fTop), FXSYS_floor(path_rect.fRight)+1, FXSYS_floor(path_rect.fBottom)+1);
	CFX_DIBitmapRef mask;
	CFX_DIBitmap* pThisLayer = mask.New();
	pThisLayer->Create(clip_box.width(), clip_box.height(), FXDIB_8bppMask);
	pThisLayer->Clear(0);

	CFX_SkiaA8Renderer render;
	render.Init(pThisLayer, clip_box.fLeft, clip_box.fTop);

	SkRasterClip rasterClip(clip_box);
	SuperBlitter_skia::DrawPath(skPath, (SkBlitter*)&render, rasterClip, *spaint);
	
	// Finally, we have got the mask that we need, intersect with current clip region
	m_pAggDriver->m_pClipRgn->IntersectMaskF(clip_box.fLeft, clip_box.fTop, mask);

}
FX_BOOL CFX_SkiaDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,	// path info
						const CFX_AffineMatrix* pObject2Device,	// optional transformation
						int fill_mode	// fill mode, WINDING or ALTERNATE
						)
{
	if (m_pAggDriver->m_pClipRgn == NULL)
		m_pAggDriver->m_pClipRgn = FX_NEW CFX_ClipRgn(GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));

	if (pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) {
		CFX_FloatRect rectf;
		if (pPathData->IsRect(pObject2Device, &rectf)) {
			rectf.Intersect(CFX_FloatRect(0, 0, (FX_FIXFLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), (FX_FIXFLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
			FX_RECT rect = rectf.GetOutterRect();
			m_pAggDriver->m_pClipRgn->IntersectRect(rect);
			return TRUE;
		}
	}
	CSkia_PathData path_data;
	path_data.BuildPath(pPathData, pObject2Device);
	path_data.m_PathData.close();
	path_data.m_PathData.setFillType((fill_mode&3) == FXFILL_WINDING? SkPath::kWinding_FillType:SkPath::kEvenOdd_FillType);

	SkPaint spaint;
	spaint.setColor(0xffffffff);
	spaint.setAntiAlias(TRUE);
	spaint.setStyle(SkPaint::kFill_Style);

	SetClipMask(path_data.m_PathData, &spaint);

	return TRUE;
}

FX_BOOL CFX_SkiaDeviceDriver::SetClip_PathStroke(const CFX_PathData* pPathData,	// path info
						const CFX_AffineMatrix* pObject2Device,	// optional transformation
						const CFX_GraphStateData* pGraphState	// graphic state, for pen attributes
					)
{
	if (m_pAggDriver->m_pClipRgn == NULL)
		m_pAggDriver->m_pClipRgn = FX_NEW CFX_ClipRgn(GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));

	// build path data
	CSkia_PathData path_data;
	path_data.BuildPath(pPathData, NULL);
	path_data.m_PathData.setFillType(SkPath::kWinding_FillType);

	SkPaint spaint;
	spaint.setColor(0xffffffff);
	spaint.setStyle(SkPaint::kStroke_Style);
	spaint.setAntiAlias(TRUE);

	SkPath dst_path;
	SkRasterizeStroke(spaint, &dst_path, path_data.m_PathData, pObject2Device, pGraphState, 1, FALSE, 0);
	spaint.setStyle(SkPaint::kFill_Style);
	SetClipMask(dst_path, &spaint);
	
	return TRUE;
}
FX_BOOL CFX_SkiaDeviceDriver::RenderRasterizer(rasterizer_scanline_aa& rasterizer, FX_DWORD color, FX_BOOL bFullCover, FX_BOOL bGroupKnockout,
											  int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->RenderRasterizer(rasterizer, color, bFullCover, bGroupKnockout,alpha_flag, pIccTransform);
}
FX_BOOL	CFX_SkiaDeviceDriver::RenderRasterizerSkia(SkPath& skPath, const SkPaint& origPaint, SkIRect& rect, FX_DWORD color, FX_BOOL bFullCover, FX_BOOL bGroupKnockout, 
							int alpha_flag, void* pIccTransform, FX_BOOL bFill)
{
	CFX_DIBitmap* pt = bGroupKnockout?m_pAggDriver->GetBackDrop():NULL;
	CFX_SkiaRenderer render;
	if (!render.Init(m_pAggDriver->m_pBitmap, pt, m_pAggDriver->m_pClipRgn, color, bFullCover, m_pAggDriver->m_bRgbByteOrder, alpha_flag, pIccTransform))
		return FALSE;
	
	SkRasterClip rasterClip(rect);
	SuperBlitter_skia::DrawPath(skPath, (SkBlitter*)&render,  rasterClip, origPaint);

	return TRUE;
	
}

FX_BOOL	CFX_SkiaDeviceDriver::DrawPath(const CFX_PathData* pPathData,	// path info
						const CFX_AffineMatrix* pObject2Device,	// optional transformation
						const CFX_GraphStateData* pGraphState,	// graphic state, for pen attributes
						FX_DWORD fill_color,			// fill color
						FX_DWORD stroke_color,			// stroke color
						int fill_mode,					// fill mode, WINDING or ALTERNATE. 0 for not filled
						int alpha_flag, 
						void* pIccTransform
						)
{
	if (GetBuffer() == NULL) return TRUE;
	FOXIT_DEBUG1("CFX_SkiaDeviceDriver::DrawPath: entering");
	SkIRect rect;
	rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
	if ((fill_mode & 3) && fill_color) {
		// We have to transform before building path data, otherwise we'll have flatting problem
		// when we enlarge a small path (flatten before transformed)
		// TESTDOC: Bug #5115 - DS_S1Dimpact_lr.pdf 
		// build path data
		CSkia_PathData path_data;
		path_data.BuildPath(pPathData, pObject2Device);
		//path_data.m_PathData.close();
		path_data.m_PathData.setFillType((fill_mode&3) == FXFILL_WINDING? SkPath::kWinding_FillType:SkPath::kEvenOdd_FillType);

		SkPaint spaint;
		spaint.setAntiAlias(TRUE);
		spaint.setStyle(SkPaint::kFill_Style);
		spaint.setColor(fill_color);
		if (!RenderRasterizerSkia(path_data.m_PathData, spaint, rect, fill_color, fill_mode & FXFILL_FULLCOVER, FALSE, alpha_flag, pIccTransform))
			return FALSE;	
	}

	int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_STROKE(alpha_flag) : FXARGB_A(stroke_color);

	if (pGraphState && stroke_alpha) {
		// We split the matrix into two parts: first part doing the scaling, so we won't have the
		// flatness problem, second part doing the transformation, so we don't have stroking geo problem.
		// TESTDOC: Bug #5253 - test[1].pdf 
		CFX_AffineMatrix matrix1, matrix2;
		if (pObject2Device) {
			matrix1.a = FXSYS_fabs(pObject2Device->a) > FXSYS_fabs(pObject2Device->b) ?
					FXSYS_fabs(pObject2Device->a) : FXSYS_fabs(pObject2Device->b);
			matrix1.d = matrix1.a;//FXSYS_fabs(pObject2Device->c) > FXSYS_fabs(pObject2Device->d) ?
					//pObject2Device->c : pObject2Device->d;
			matrix2.Set(pObject2Device->a/matrix1.a, pObject2Device->b/matrix1.a, 
					pObject2Device->c/matrix1.d, pObject2Device->d/matrix1.d, 
					pObject2Device->e, pObject2Device->f);
		}
		// build path data
		CSkia_PathData path_data;
		path_data.BuildPath(pPathData, &matrix1);
		path_data.m_PathData.setFillType(SkPath::kWinding_FillType);

		SkPaint spaint;
		spaint.setColor(stroke_color);
		spaint.setStyle(SkPaint::kStroke_Style);
		spaint.setAntiAlias(TRUE);
		SkPath dst_path;
		SkRasterizeStroke(spaint, &dst_path, path_data.m_PathData, &matrix2, pGraphState, matrix1.a, FALSE, 0);
		spaint.setStyle(SkPaint::kFill_Style);
		int fill_flag = FXGETFLAG_COLORTYPE(alpha_flag)<<8 | FXGETFLAG_ALPHA_STROKE(alpha_flag);
		
		if (!RenderRasterizerSkia(dst_path, spaint, rect, stroke_color, fill_mode & FXFILL_FULLCOVER, FALSE, fill_flag, pIccTransform, FALSE))
			return FALSE;
			
	}
	
	return TRUE;
}

FX_BOOL CFX_SkiaDeviceDriver::SetPixel(int x, int y, FX_DWORD color,
						int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->SetPixel(x, y, color, alpha_flag, pIccTransform);
}

FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, FX_DWORD fill_color, int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->FillRect(pRect, fill_color, alpha_flag, pIccTransform);
}

FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect)
{
	return m_pAggDriver->GetClipBox(pRect);
}

FX_BOOL	CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top, void* pIccTransform, FX_BOOL bDEdge)
{
	return m_pAggDriver->GetDIBits(pBitmap, left, top, pIccTransform, bDEdge);
}

FX_BOOL	CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, FX_DWORD argb, const FX_RECT* pSrcRect, int left, int top, int blend_type, 
									   int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->SetDIBits(pBitmap, argb, pSrcRect, left, top, blend_type, alpha_flag, pIccTransform);
}

FX_BOOL	CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, FX_DWORD argb, int dest_left, int dest_top, 
							int dest_width, int dest_height, const FX_RECT* pClipRect, FX_DWORD flags, 
							int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->StretchDIBits(pSource, argb, dest_left, dest_top, 
							dest_width, dest_height, pClipRect, flags, 
							alpha_flag, pIccTransform);
}

FX_BOOL	CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, int bitmap_alpha, FX_DWORD argb, 
						const CFX_AffineMatrix* pMatrix, FX_DWORD render_flags, FX_LPVOID& handle, 
						int alpha_flag, void* pIccTransform)
{
	return m_pAggDriver->StartDIBits(pSource, bitmap_alpha, argb, 
						pMatrix, render_flags, handle, alpha_flag, pIccTransform);
}

FX_BOOL	CFX_SkiaDeviceDriver::ContinueDIBits(FX_LPVOID pHandle, IFX_Pause* pPause)
{
	return m_pAggDriver->ContinueDIBits(pHandle, pPause);
}

void CFX_SkiaDeviceDriver::CancelDIBits(FX_LPVOID pHandle)
{
	m_pAggDriver->CancelDIBits(pHandle);
}

CFX_SkiaDevice::CFX_SkiaDevice()
{
	m_bOwnedBitmap = FALSE;
}

FX_BOOL CFX_SkiaDevice::Attach(CFX_DIBitmap* pBitmap, int dither_bits, FX_BOOL bRgbByteOrder, CFX_DIBitmap* pOriDevice, FX_BOOL bGroupKnockout)
{
	if (pBitmap == NULL) 
		return FALSE;
	SetBitmap(pBitmap);
	CFX_SkiaDeviceDriver* pDriver = FX_NEW CFX_SkiaDeviceDriver(pBitmap, dither_bits, bRgbByteOrder, pOriDevice, bGroupKnockout);
	SetDeviceDriver(pDriver);
	return TRUE;
}

FX_BOOL CFX_SkiaDevice::Create(int width, int height, FXDIB_Format format, int dither_bits, CFX_DIBitmap* pOriDevice)
{
	m_bOwnedBitmap = TRUE;
	CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap;
	if (!pBitmap->Create(width, height, format)) {
		delete pBitmap;
		return FALSE;
	} 
	SetBitmap(pBitmap);
	CFX_SkiaDeviceDriver* pDriver =  FX_NEW CFX_SkiaDeviceDriver(pBitmap, dither_bits, FALSE, pOriDevice, FALSE);
	SetDeviceDriver(pDriver);
	return TRUE;
}
CFX_SkiaDevice::~CFX_SkiaDevice()
{
	if (m_bOwnedBitmap && GetBitmap()) delete GetBitmap();
}

#endif