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