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

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../../include/fxcrt/fx_system.h"
#include "../../../include/fxge/fx_ge.h"

#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_

#include "../../../include/fxge/fx_freetype.h"
#include "../../../include/fxge/fx_ge_apple.h"
#include "../agg/include/fx_agg_driver.h"
#include "../dib/dib_int.h"
#include "../ge/text_int.h"
#include "apple_int.h"

void CFX_AggDeviceDriver::InitPlatform() {
  CQuartz2D& quartz2d =
      ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
  m_pPlatformGraphics = quartz2d.createGraphics(m_pBitmap);
}
void CFX_AggDeviceDriver::DestroyPlatform() {
  CQuartz2D& quartz2d =
      ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
  if (m_pPlatformGraphics) {
    quartz2d.destroyGraphics(m_pPlatformGraphics);
    m_pPlatformGraphics = NULL;
  }
}
void CFX_FaceCache::InitPlatform() {}
void CFX_FaceCache::DestroyPlatform() {}
CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(
    CFX_Font* pFont,
    FX_DWORD glyph_index,
    const CFX_AffineMatrix* pMatrix,
    int dest_width,
    int anti_alias) {
  return NULL;
}
static FX_BOOL _CGDrawGlyphRun(CGContextRef pContext,
                               int nChars,
                               const FXTEXT_CHARPOS* pCharPos,
                               CFX_Font* pFont,
                               CFX_FontCache* pCache,
                               const CFX_AffineMatrix* pObject2Device,
                               FX_FLOAT font_size,
                               FX_DWORD argb,
                               int alpha_flag,
                               void* pIccTransform) {
  if (nChars == 0) {
    return TRUE;
  }
  CFX_AffineMatrix new_matrix;
  FX_BOOL bNegSize = font_size < 0;
  if (bNegSize) {
    font_size = -font_size;
  }
  FX_FLOAT ori_x = pCharPos[0].m_OriginX, ori_y = pCharPos[0].m_OriginY;
  new_matrix.Transform(ori_x, ori_y);
  if (pObject2Device) {
    new_matrix.Concat(*pObject2Device);
  }
  CQuartz2D& quartz2d =
      ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
  if (!pFont->GetPlatformFont()) {
    if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {
      return FALSE;
    }
    pFont->SetPlatformFont(
        quartz2d.CreateFont(pFont->GetFontData(), pFont->GetSize()));
    if (!pFont->GetPlatformFont()) {
      return FALSE;
    }
  }
  CFX_FixedBufGrow<FX_WORD, 32> glyph_indices(nChars);
  CFX_FixedBufGrow<CGPoint, 32> glyph_positions(nChars);
  for (int i = 0; i < nChars; i++) {
    glyph_indices[i] = pCharPos[i].m_ExtGID;
    if (bNegSize) {
      glyph_positions[i].x = -pCharPos[i].m_OriginX;
    } else {
      glyph_positions[i].x = pCharPos[i].m_OriginX;
    }
    glyph_positions[i].y = pCharPos[i].m_OriginY;
  }
  if (bNegSize) {
    new_matrix.a = -new_matrix.a;
  } else {
    new_matrix.b = -new_matrix.b;
    new_matrix.d = -new_matrix.d;
  }
  quartz2d.setGraphicsTextMatrix(pContext, &new_matrix);
  return quartz2d.drawGraphicsString(pContext, pFont->GetPlatformFont(),
                                     font_size, glyph_indices, glyph_positions,
                                     nChars, argb, NULL);
}
static void _DoNothing(void* info, const void* data, size_t size) {}
FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(
    int nChars,
    const FXTEXT_CHARPOS* pCharPos,
    CFX_Font* pFont,
    CFX_FontCache* pCache,
    const CFX_AffineMatrix* pObject2Device,
    FX_FLOAT font_size,
    FX_DWORD argb,
    int alpha_flag,
    void* pIccTransform) {
  if (!pFont) {
    return FALSE;
  }
  FX_BOOL bBold = pFont->IsBold();
  if (!bBold && pFont->GetSubstFont() &&
      pFont->GetSubstFont()->m_Weight >= 500 &&
      pFont->GetSubstFont()->m_Weight <= 600) {
    return FALSE;
  }
  for (int i = 0; i < nChars; i++) {
    if (pCharPos[i].m_bGlyphAdjust) {
      return FALSE;
    }
  }
  CGContextRef ctx = CGContextRef(m_pPlatformGraphics);
  if (NULL == ctx) {
    return FALSE;
  }
  CGContextSaveGState(ctx);
  CGContextSetTextDrawingMode(ctx, kCGTextFillClip);
  CGRect rect_cg;
  CGImageRef pImageCG = NULL;
  if (m_pClipRgn) {
    rect_cg =
        CGRectMake(m_pClipRgn->GetBox().left, m_pClipRgn->GetBox().top,
                   m_pClipRgn->GetBox().Width(), m_pClipRgn->GetBox().Height());
    const CFX_DIBitmap* pClipMask = m_pClipRgn->GetMask();
    if (pClipMask) {
      CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData(
          NULL, pClipMask->GetBuffer(),
          pClipMask->GetPitch() * pClipMask->GetHeight(), _DoNothing);
      CGFloat decode_f[2] = {255.f, 0.f};
      pImageCG = CGImageMaskCreate(
          pClipMask->GetWidth(), pClipMask->GetHeight(), 8, 8,
          pClipMask->GetPitch(), pClipMaskDataProvider, decode_f, FALSE);
      CGDataProviderRelease(pClipMaskDataProvider);
    }
  } else {
    rect_cg = CGRectMake(0, 0, m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
  }
  rect_cg = CGContextConvertRectToDeviceSpace(ctx, rect_cg);
  if (pImageCG) {
    CGContextClipToMask(ctx, rect_cg, pImageCG);
  } else {
    CGContextClipToRect(ctx, rect_cg);
  }
  FX_BOOL ret =
      _CGDrawGlyphRun(ctx, nChars, pCharPos, pFont, pCache, pObject2Device,
                      font_size, argb, alpha_flag, pIccTransform);
  if (pImageCG) {
    CGImageRelease(pImageCG);
  }
  CGContextRestoreGState(ctx);
  return ret;
}
void CFX_Font::ReleasePlatformResource() {
  if (m_pPlatformFont) {
    CQuartz2D& quartz2d =
        ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
    quartz2d.DestroyFont(m_pPlatformFont);
    m_pPlatformFont = NULL;
  }
}

#endif  // _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
