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