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

#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_

#include "core/fxge/agg/fx_agg_driver.h"
#include "core/fxge/apple/apple_int.h"
#include "core/fxge/dib/dib_int.h"
#include "core/fxge/ge/fx_text_int.h"
#include "core/include/fxge/fx_freetype.h"
#include "core/include/fxge/fx_ge_apple.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,
    uint32_t glyph_index,
    const CFX_Matrix* 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_Matrix* pObject2Device,
                               FX_FLOAT font_size,
                               uint32_t argb,
                               int alpha_flag,
                               void* pIccTransform) {
  if (nChars == 0) {
    return TRUE;
  }
  CFX_Matrix 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<uint16_t, 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_Matrix* pObject2Device,
                                            FX_FLOAT font_size,
                                            uint32_t 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_
