// 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 "core/include/fxge/fx_ge.h"

#if defined(_SKIA_SUPPORT_)
#include "core/include/fxcodec/fx_codec.h"

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

#include "core/src/fxge/agg/include/fx_agg_driver.h"
#include "fx_skia_blitter_new.h"
#include "fx_skia_device.h"

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

/// 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_Matrix* pObject2Device);
};

void CSkia_PathData::BuildPath(const CFX_PathData* pPathData,
                               const CFX_Matrix* 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_Matrix* 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) {
    int count = (pGraphState->m_DashCount + 1) / 2;
    SkScalar* intervals = FX_Alloc2D(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);
  } else {
    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);
  }
}

CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
                                           int dither_bits,
                                           FX_BOOL bRgbByteOrder,
                                           CFX_DIBitmap* pOriDevice,
                                           FX_BOOL bGroupKnockout) {
  m_pAggDriver = new CFX_AggDeviceDriver(pBitmap, dither_bits, bRgbByteOrder,
                                         pOriDevice, bGroupKnockout);
}
CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
  delete m_pAggDriver;
}
FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
                                             const FXTEXT_CHARPOS* pCharPos,
                                             CFX_Font* pFont,
                                             CFX_FontCache* pCache,
                                             const CFX_Matrix* 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_Matrix* pObject2Device,  // optional transformation
    int fill_mode                      // fill mode, WINDING or ALTERNATE
    ) {
  if (!m_pAggDriver->m_pClipRgn) {
    m_pAggDriver->m_pClipRgn = 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_Matrix* pObject2Device,      // optional transformation
    const CFX_GraphStateData* pGraphState  // graphic state, for pen attributes
    ) {
  if (!m_pAggDriver->m_pClipRgn) {
    m_pAggDriver->m_pClipRgn = 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_Matrix* 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())
    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_Matrix 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_Matrix* pMatrix,
                                          FX_DWORD render_flags,
                                          void*& 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(void* pHandle, IFX_Pause* pPause) {
  return m_pAggDriver->ContinueDIBits(pHandle, pPause);
}

void CFX_SkiaDeviceDriver::CancelDIBits(void* 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)
    return FALSE;
  SetBitmap(pBitmap);
  CFX_SkiaDeviceDriver* pDriver = 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 = new CFX_DIBitmap;
  if (!pBitmap->Create(width, height, format)) {
    delete pBitmap;
    return FALSE;
  }
  SetBitmap(pBitmap);
  CFX_SkiaDeviceDriver* pDriver =
      new CFX_SkiaDeviceDriver(pBitmap, dither_bits, FALSE, pOriDevice, FALSE);
  SetDeviceDriver(pDriver);
  return TRUE;
}
CFX_SkiaDevice::~CFX_SkiaDevice() {
  if (m_bOwnedBitmap && GetBitmap())
    delete GetBitmap();
}

#endif
