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 "core/fxcrt/fx_extension.h"
8 
9 #if !defined _SKIA_SUPPORT_ && !defined _SKIA_SUPPORT_PATHS_
10 #include "core/fxge/agg/fx_agg_driver.h"
11 #endif
12 
13 #include "core/fxge/cfx_graphstatedata.h"
14 #include "core/fxge/cfx_pathdata.h"
15 #include "core/fxge/cfx_renderdevice.h"
16 #include "core/fxge/dib/cfx_dibitmap.h"
17 #include "core/fxge/fx_freetype.h"
18 
19 #include "core/fxge/apple/apple_int.h"
20 #ifndef CGFLOAT_IS_DOUBLE
21 #error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers
22 #endif
23 
CreateGraphics(const RetainPtr<CFX_DIBitmap> & pBitmap)24 void* CQuartz2D::CreateGraphics(const RetainPtr<CFX_DIBitmap>& pBitmap) {
25   if (!pBitmap)
26     return nullptr;
27   CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little;
28   switch (pBitmap->GetFormat()) {
29     case FXDIB_Rgb32:
30       bmpInfo |= kCGImageAlphaNoneSkipFirst;
31       break;
32     case FXDIB_Argb:
33     default:
34       return nullptr;
35   }
36   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
37   CGContextRef context = CGBitmapContextCreate(
38       pBitmap->GetBuffer(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8,
39       pBitmap->GetPitch(), colorSpace, bmpInfo);
40   CGColorSpaceRelease(colorSpace);
41   return context;
42 }
43 
DestroyGraphics(void * graphics)44 void CQuartz2D::DestroyGraphics(void* graphics) {
45   if (graphics)
46     CGContextRelease((CGContextRef)graphics);
47 }
48 
CreateFont(const uint8_t * pFontData,uint32_t dwFontSize)49 void* CQuartz2D::CreateFont(const uint8_t* pFontData, uint32_t dwFontSize) {
50   CGDataProviderRef pDataProvider = CGDataProviderCreateWithData(
51       nullptr, pFontData, static_cast<size_t>(dwFontSize), nullptr);
52   if (!pDataProvider)
53     return nullptr;
54 
55   CGFontRef pCGFont = CGFontCreateWithDataProvider(pDataProvider);
56   CGDataProviderRelease(pDataProvider);
57   return pCGFont;
58 }
59 
DestroyFont(void * pFont)60 void CQuartz2D::DestroyFont(void* pFont) {
61   CGFontRelease((CGFontRef)pFont);
62 }
63 
SetGraphicsTextMatrix(void * graphics,const CFX_Matrix & matrix)64 void CQuartz2D::SetGraphicsTextMatrix(void* graphics,
65                                       const CFX_Matrix& matrix) {
66   if (!graphics)
67     return;
68   CGContextRef context = reinterpret_cast<CGContextRef>(graphics);
69   CGFloat ty = CGBitmapContextGetHeight(context) - matrix.f;
70   CGContextSetTextMatrix(
71       context, CGAffineTransformMake(matrix.a, matrix.b, matrix.c, matrix.d,
72                                      matrix.e, ty));
73 }
74 
DrawGraphicsString(void * graphics,void * font,float fontSize,uint16_t * glyphIndices,CGPoint * glyphPositions,int32_t charsCount,FX_ARGB argb)75 bool CQuartz2D::DrawGraphicsString(void* graphics,
76                                    void* font,
77                                    float fontSize,
78                                    uint16_t* glyphIndices,
79                                    CGPoint* glyphPositions,
80                                    int32_t charsCount,
81                                    FX_ARGB argb) {
82   if (!graphics)
83     return false;
84 
85   CGContextRef context = (CGContextRef)graphics;
86   CGContextSetFont(context, (CGFontRef)font);
87   CGContextSetFontSize(context, fontSize);
88 
89   int32_t a;
90   int32_t r;
91   int32_t g;
92   int32_t b;
93   std::tie(a, r, g, b) = ArgbDecode(argb);
94   CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f);
95   CGContextSaveGState(context);
96 #if CGFLOAT_IS_DOUBLE
97   CGPoint* glyphPositionsCG = new CGPoint[charsCount];
98   for (int index = 0; index < charsCount; ++index) {
99     glyphPositionsCG[index].x = glyphPositions[index].x;
100     glyphPositionsCG[index].y = glyphPositions[index].y;
101   }
102 #else
103   CGPoint* glyphPositionsCG = glyphPositions;
104 #endif
105   CGContextShowGlyphsAtPositions(context,
106                                  reinterpret_cast<CGGlyph*>(glyphIndices),
107                                  glyphPositionsCG, charsCount);
108 #if CGFLOAT_IS_DOUBLE
109   delete[] glyphPositionsCG;
110 #endif
111   CGContextRestoreGState(context);
112   return true;
113 }
114