1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "../../../include/fxcrt/fx_ext.h"
8 #include "../../../include/fxge/fx_ge.h"
9 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
10 #include "apple_int.h"
11 #include "../../../include/fxge/fx_ge_apple.h"
12 #include "../agg/include/fxfx_agg_clip_liang_barsky.h"
13 #include "../ge/text_int.h"
14 #include "../dib/dib_int.h"
15 #include "../agg/include/fx_agg_driver.h"
16 #include "../../../include/fxge/fx_freetype.h"
17 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
InitPlatform()18 void CFX_AggDeviceDriver::InitPlatform()
19 {
20     CQuartz2D & quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
21     m_pPlatformGraphics = quartz2d.createGraphics(m_pBitmap);
22 }
DestroyPlatform()23 void CFX_AggDeviceDriver::DestroyPlatform()
24 {
25     CQuartz2D & quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
26     if (m_pPlatformGraphics) {
27         quartz2d.destroyGraphics(m_pPlatformGraphics);
28         m_pPlatformGraphics = NULL;
29     }
30 }
InitPlatform()31 void CFX_FaceCache::InitPlatform() {}
DestroyPlatform()32 void CFX_FaceCache::DestroyPlatform() {}
RenderGlyph_Nativetext(CFX_Font * pFont,FX_DWORD glyph_index,const CFX_AffineMatrix * pMatrix,int dest_width,int anti_alias)33 CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(CFX_Font *				pFont,
34         FX_DWORD					glyph_index,
35         const CFX_AffineMatrix *	pMatrix,
36         int						dest_width,
37         int						anti_alias)
38 {
39     return NULL;
40 }
_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)41 static FX_BOOL _CGDrawGlyphRun(CGContextRef               pContext,
42                                int                        nChars,
43                                const FXTEXT_CHARPOS*      pCharPos,
44                                CFX_Font*                  pFont,
45                                CFX_FontCache*             pCache,
46                                const CFX_AffineMatrix*    pObject2Device,
47                                FX_FLOAT                   font_size,
48                                FX_DWORD                   argb,
49                                int                        alpha_flag,
50                                void*                      pIccTransform)
51 {
52     if (nChars == 0) {
53         return TRUE;
54     }
55     CFX_AffineMatrix new_matrix;
56     FX_BOOL bNegSize = font_size < 0;
57     if (bNegSize) {
58         font_size = -font_size;
59     }
60     FX_FLOAT ori_x = pCharPos[0].m_OriginX, ori_y = pCharPos[0].m_OriginY;
61     new_matrix.Transform(ori_x, ori_y);
62     if (pObject2Device) {
63         new_matrix.Concat(*pObject2Device);
64     }
65     CQuartz2D& quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
66     if (!pFont->m_pPlatformFont) {
67         if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {
68             return FALSE;
69         }
70         pFont->m_pPlatformFont = quartz2d.CreateFont(pFont->m_pFontData, pFont->m_dwSize);
71         if (NULL == pFont->m_pPlatformFont) {
72             return FALSE;
73         }
74     }
75     CFX_FixedBufGrow<FX_WORD, 32> glyph_indices(nChars);
76     CFX_FixedBufGrow<CGPoint, 32> glyph_positions(nChars);
77     for (int i = 0; i < nChars; i++ ) {
78         glyph_indices[i] = pCharPos[i].m_ExtGID;
79         if (bNegSize) {
80             glyph_positions[i].x = -pCharPos[i].m_OriginX;
81         } else {
82             glyph_positions[i].x = pCharPos[i].m_OriginX;
83         }
84         glyph_positions[i].y = pCharPos[i].m_OriginY;
85     }
86     if (bNegSize) {
87         new_matrix.a = -new_matrix.a;
88     } else {
89         new_matrix.b = -new_matrix.b;
90         new_matrix.d = -new_matrix.d;
91     }
92     quartz2d.setGraphicsTextMatrix(pContext, &new_matrix);
93     return quartz2d.drawGraphicsString(pContext,
94                                        pFont->m_pPlatformFont,
95                                        font_size,
96                                        glyph_indices,
97                                        glyph_positions,
98                                        nChars,
99                                        argb,
100                                        NULL);
101 }
_DoNothing(void * info,const void * data,size_t size)102 static void _DoNothing(void *info, const void *data, size_t size) {}
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)103 FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int						 nChars,
104         const FXTEXT_CHARPOS *	 pCharPos,
105         CFX_Font *				 pFont,
106         CFX_FontCache *			 pCache,
107         const CFX_AffineMatrix * pObject2Device,
108         FX_FLOAT				 font_size,
109         FX_DWORD				 argb,
110         int alpha_flag, void* pIccTransform)
111 {
112     if (!pFont) {
113         return FALSE;
114     }
115     FX_BOOL bBold = pFont->IsBold();
116     if (!bBold && pFont->GetSubstFont() &&
117             pFont->GetSubstFont()->m_Weight >= 500 &&
118             pFont->GetSubstFont()->m_Weight <= 600) {
119         return FALSE;
120     }
121     for (int i = 0; i < nChars; i ++) {
122         if (pCharPos[i].m_bGlyphAdjust) {
123             return FALSE;
124         }
125     }
126     CGContextRef ctx = CGContextRef(m_pPlatformGraphics);
127     if (NULL == ctx) {
128         return FALSE;
129     }
130     CGContextSaveGState(ctx);
131     CGContextSetTextDrawingMode(ctx, kCGTextFillClip);
132     CGRect rect_cg;
133     CGImageRef pImageCG = NULL;
134     if (m_pClipRgn) {
135         rect_cg = CGRectMake(m_pClipRgn->GetBox().left, m_pClipRgn->GetBox().top, m_pClipRgn->GetBox().Width(), m_pClipRgn->GetBox().Height());
136         const CFX_DIBitmap*	pClipMask = m_pClipRgn->GetMask();
137         if (pClipMask) {
138             CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData(NULL,
139                     pClipMask->GetBuffer(),
140                     pClipMask->GetPitch() * pClipMask->GetHeight(),
141                     _DoNothing);
142             CGFloat decode_f[2] = {255.f, 0.f};
143             pImageCG = CGImageMaskCreate(pClipMask->GetWidth(), pClipMask->GetHeight(),
144                                          8, 8, pClipMask->GetPitch(), pClipMaskDataProvider,
145                                          decode_f, FALSE);
146             CGDataProviderRelease(pClipMaskDataProvider);
147         }
148     } else {
149         rect_cg = CGRectMake(0, 0, m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
150     }
151     rect_cg = CGContextConvertRectToDeviceSpace(ctx, rect_cg);
152     if (pImageCG) {
153         CGContextClipToMask(ctx, rect_cg, pImageCG);
154     } else {
155         CGContextClipToRect(ctx, rect_cg);
156     }
157     FX_BOOL ret = _CGDrawGlyphRun(ctx, nChars, pCharPos, pFont, pCache, pObject2Device, font_size, argb, alpha_flag, pIccTransform);
158     if (pImageCG) {
159         CGImageRelease(pImageCG);
160     }
161     CGContextRestoreGState(ctx);
162     return ret;
163 }
ReleasePlatformResource()164 void CFX_Font::ReleasePlatformResource()
165 {
166     if (m_pPlatformFont) {
167         CQuartz2D & quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
168         quartz2d.DestroyFont(m_pPlatformFont);
169         m_pPlatformFont = NULL;
170     }
171 }
172 #endif
173 #endif
174