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 <memory>
8 #include <vector>
9 
10 #include "core/fxcrt/fx_system.h"
11 
12 #include "core/fxge/apple/apple_int.h"
13 #include "core/fxge/cfx_cliprgn.h"
14 #include "core/fxge/cfx_font.h"
15 #include "core/fxge/cfx_gemodule.h"
16 #include "core/fxge/cfx_glyphbitmap.h"
17 #include "core/fxge/cfx_glyphcache.h"
18 #include "core/fxge/cfx_renderdevice.h"
19 #include "core/fxge/cfx_substfont.h"
20 #include "core/fxge/dib/cfx_dibitmap.h"
21 #include "core/fxge/fx_freetype.h"
22 #include "core/fxge/text_char_pos.h"
23 #include "third_party/base/span.h"
24 
25 #ifndef _SKIA_SUPPORT_
26 #include "core/fxge/agg/fx_agg_driver.h"
27 #endif
28 
29 #ifndef _SKIA_SUPPORT_
30 
31 namespace {
32 
DoNothing(void * info,const void * data,size_t size)33 void DoNothing(void* info, const void* data, size_t size) {}
34 
CGDrawGlyphRun(CGContextRef pContext,int nChars,const TextCharPos * pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t argb)35 bool CGDrawGlyphRun(CGContextRef pContext,
36                     int nChars,
37                     const TextCharPos* pCharPos,
38                     CFX_Font* pFont,
39                     const CFX_Matrix& mtObject2Device,
40                     float font_size,
41                     uint32_t argb) {
42   if (nChars == 0)
43     return true;
44 
45   bool bNegSize = font_size < 0;
46   if (bNegSize)
47     font_size = -font_size;
48 
49   CFX_Matrix new_matrix = mtObject2Device;
50   CQuartz2D& quartz2d =
51       static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
52           ->m_quartz2d;
53   if (!pFont->GetPlatformFont()) {
54     if (pFont->GetPsName() == "DFHeiStd-W5")
55       return false;
56 
57     pdfium::span<const uint8_t> span = pFont->GetFontSpan();
58     pFont->SetPlatformFont(quartz2d.CreateFont(span.data(), span.size()));
59     if (!pFont->GetPlatformFont())
60       return false;
61   }
62   std::vector<uint16_t> glyph_indices(nChars);
63   std::vector<CGPoint> glyph_positions(nChars);
64   for (int i = 0; i < nChars; i++) {
65     glyph_indices[i] =
66         pCharPos[i].m_ExtGID ? pCharPos[i].m_ExtGID : pCharPos[i].m_GlyphIndex;
67     if (bNegSize)
68       glyph_positions[i].x = -pCharPos[i].m_Origin.x;
69     else
70       glyph_positions[i].x = pCharPos[i].m_Origin.x;
71     glyph_positions[i].y = pCharPos[i].m_Origin.y;
72   }
73   if (bNegSize) {
74     new_matrix.a = -new_matrix.a;
75     new_matrix.c = -new_matrix.c;
76   } else {
77     new_matrix.b = -new_matrix.b;
78     new_matrix.d = -new_matrix.d;
79   }
80   quartz2d.SetGraphicsTextMatrix(pContext, new_matrix);
81   return quartz2d.DrawGraphicsString(pContext, pFont->GetPlatformFont(),
82                                      font_size, glyph_indices.data(),
83                                      glyph_positions.data(), nChars, argb);
84 }
85 
86 }  // namespace
87 
InitPlatform()88 void CFX_AggDeviceDriver::InitPlatform() {
89   CQuartz2D& quartz2d =
90       static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
91           ->m_quartz2d;
92   m_pPlatformGraphics = quartz2d.CreateGraphics(m_pBitmap);
93 }
94 
DestroyPlatform()95 void CFX_AggDeviceDriver::DestroyPlatform() {
96   CQuartz2D& quartz2d =
97       static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
98           ->m_quartz2d;
99   if (m_pPlatformGraphics) {
100     quartz2d.DestroyGraphics(m_pPlatformGraphics);
101     m_pPlatformGraphics = nullptr;
102   }
103 }
104 
DrawDeviceText(int nChars,const TextCharPos * pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t argb)105 bool CFX_AggDeviceDriver::DrawDeviceText(int nChars,
106                                          const TextCharPos* pCharPos,
107                                          CFX_Font* pFont,
108                                          const CFX_Matrix& mtObject2Device,
109                                          float font_size,
110                                          uint32_t argb) {
111   if (!pFont)
112     return false;
113 
114   bool bBold = pFont->IsBold();
115   if (!bBold && pFont->GetSubstFont() &&
116       pFont->GetSubstFont()->m_Weight >= 500 &&
117       pFont->GetSubstFont()->m_Weight <= 600) {
118     return false;
119   }
120   for (int i = 0; i < nChars; i++) {
121     if (pCharPos[i].m_bGlyphAdjust)
122       return false;
123   }
124   CGContextRef ctx = CGContextRef(m_pPlatformGraphics);
125   if (!ctx)
126     return false;
127 
128   CGContextSaveGState(ctx);
129   CGContextSetTextDrawingMode(ctx, kCGTextFillClip);
130   CGRect rect_cg;
131   CGImageRef pImageCG = nullptr;
132   if (m_pClipRgn) {
133     rect_cg =
134         CGRectMake(m_pClipRgn->GetBox().left, m_pClipRgn->GetBox().top,
135                    m_pClipRgn->GetBox().Width(), m_pClipRgn->GetBox().Height());
136     RetainPtr<CFX_DIBitmap> pClipMask = m_pClipRgn->GetMask();
137     if (pClipMask) {
138       CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData(
139           nullptr, pClipMask->GetBuffer(),
140           pClipMask->GetPitch() * pClipMask->GetHeight(), DoNothing);
141       CGFloat decode_f[2] = {255.f, 0.f};
142       pImageCG = CGImageMaskCreate(
143           pClipMask->GetWidth(), pClipMask->GetHeight(), 8, 8,
144           pClipMask->GetPitch(), pClipMaskDataProvider, decode_f, false);
145       CGDataProviderRelease(pClipMaskDataProvider);
146     }
147   } else {
148     rect_cg = CGRectMake(0, 0, m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
149   }
150   rect_cg = CGContextConvertRectToDeviceSpace(ctx, rect_cg);
151   if (pImageCG)
152     CGContextClipToMask(ctx, rect_cg, pImageCG);
153   else
154     CGContextClipToRect(ctx, rect_cg);
155 
156   bool ret = CGDrawGlyphRun(ctx, nChars, pCharPos, pFont, mtObject2Device,
157                             font_size, argb);
158   if (pImageCG)
159     CGImageRelease(pImageCG);
160   CGContextRestoreGState(ctx);
161   return ret;
162 }
163 
164 #endif  // _SKIA_SUPPORT_
165 
InitPlatform()166 void CFX_GlyphCache::InitPlatform() {}
167 
DestroyPlatform()168 void CFX_GlyphCache::DestroyPlatform() {}
169 
RenderGlyph_Nativetext(const CFX_Font * pFont,uint32_t glyph_index,const CFX_Matrix & matrix,uint32_t dest_width,int anti_alias)170 std::unique_ptr<CFX_GlyphBitmap> CFX_GlyphCache::RenderGlyph_Nativetext(
171     const CFX_Font* pFont,
172     uint32_t glyph_index,
173     const CFX_Matrix& matrix,
174     uint32_t dest_width,
175     int anti_alias) {
176   return nullptr;
177 }
178 
ReleasePlatformResource()179 void CFX_Font::ReleasePlatformResource() {
180   if (m_pPlatformFont) {
181     CQuartz2D& quartz2d =
182         static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
183             ->m_quartz2d;
184     quartz2d.DestroyFont(m_pPlatformFont);
185     m_pPlatformFont = nullptr;
186   }
187 }
188