xref: /aosp_15_r20/external/pdfium/core/fxge/apple/fx_quartz_device.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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