// 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->m_pPlatformFont) {
        if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {
            return FALSE;
        }
        pFont->m_pPlatformFont = quartz2d.CreateFont(pFont->m_pFontData, pFont->m_dwSize);
        if (NULL == pFont->m_pPlatformFont) {
            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->m_pPlatformFont,
                                       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_
