• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fixed_size_data_vector.h"
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/fx_memory_wrappers.h"
14 #include "core/fxcrt/zip.h"
15 #include "core/fxge/cfx_graphstatedata.h"
16 #include "core/fxge/cfx_path.h"
17 #include "core/fxge/cfx_renderdevice.h"
18 #include "core/fxge/dib/cfx_dibitmap.h"
19 
20 #ifndef CGFLOAT_IS_DOUBLE
21 #error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers
22 #endif
23 
24 FX_DATA_PARTITION_EXCEPTION(CGPoint);
25 
CreateGraphics(const RetainPtr<CFX_DIBitmap> & pBitmap)26 void* CQuartz2D::CreateGraphics(const RetainPtr<CFX_DIBitmap>& pBitmap) {
27   if (!pBitmap)
28     return nullptr;
29   CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little;
30   switch (pBitmap->GetFormat()) {
31     case FXDIB_Format::kBgrx:
32       bmpInfo |= kCGImageAlphaNoneSkipFirst;
33       break;
34     case FXDIB_Format::kBgra:
35     default:
36       return nullptr;
37   }
38   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
39   CGContextRef context = CGBitmapContextCreate(
40       pBitmap->GetWritableBuffer().data(), pBitmap->GetWidth(),
41       pBitmap->GetHeight(), 8, pBitmap->GetPitch(), colorSpace, bmpInfo);
42   CGColorSpaceRelease(colorSpace);
43   return context;
44 }
45 
DestroyGraphics(void * graphics)46 void CQuartz2D::DestroyGraphics(void* graphics) {
47   if (graphics)
48     CGContextRelease((CGContextRef)graphics);
49 }
50 
CreateFont(pdfium::span<const uint8_t> font_data)51 void* CQuartz2D::CreateFont(pdfium::span<const uint8_t> font_data) {
52   CGDataProviderRef data_provider = CGDataProviderCreateWithData(
53       nullptr, font_data.data(), font_data.size(), nullptr);
54   if (!data_provider) {
55     return nullptr;
56   }
57 
58   CGFontRef cg_font = CGFontCreateWithDataProvider(data_provider);
59   CGDataProviderRelease(data_provider);
60   return cg_font;
61 }
62 
DestroyFont(void * font)63 void CQuartz2D::DestroyFont(void* font) {
64   CGFontRelease((CGFontRef)font);
65 }
66 
SetGraphicsTextMatrix(void * graphics,const CFX_Matrix & matrix)67 void CQuartz2D::SetGraphicsTextMatrix(void* graphics,
68                                       const CFX_Matrix& matrix) {
69   if (!graphics)
70     return;
71   CGContextRef context = reinterpret_cast<CGContextRef>(graphics);
72   CGFloat ty = CGBitmapContextGetHeight(context) - matrix.f;
73   CGContextSetTextMatrix(
74       context, CGAffineTransformMake(matrix.a, matrix.b, matrix.c, matrix.d,
75                                      matrix.e, ty));
76 }
77 
DrawGraphicsString(void * graphics,void * font,float font_size,pdfium::span<uint16_t> glyph_indices,pdfium::span<CGPoint> glyph_positions,FX_ARGB argb)78 bool CQuartz2D::DrawGraphicsString(void* graphics,
79                                    void* font,
80                                    float font_size,
81                                    pdfium::span<uint16_t> glyph_indices,
82                                    pdfium::span<CGPoint> glyph_positions,
83                                    FX_ARGB argb) {
84   if (!graphics)
85     return false;
86 
87   CGContextRef context = (CGContextRef)graphics;
88   CGContextSetFont(context, (CGFontRef)font);
89   CGContextSetFontSize(context, font_size);
90 
91   const FX_BGRA_STRUCT<uint8_t> bgra = ArgbToBGRAStruct(argb);
92   CGContextSetRGBFillColor(context, bgra.red / 255.f, bgra.green / 255.f,
93                            bgra.blue / 255.f, bgra.alpha / 255.f);
94   CGContextSaveGState(context);
95 #if CGFLOAT_IS_DOUBLE
96   auto glyph_positions_cg =
97       FixedSizeDataVector<CGPoint>::Uninit(glyph_positions.size());
98   for (auto [input, output] :
99        fxcrt::Zip(glyph_positions, glyph_positions_cg.span())) {
100     output.x = input.x;
101     output.y = input.y;
102   }
103   const CGPoint* glyph_positions_cg_ptr = glyph_positions_cg.span().data();
104 #else
105   const CGPoint* glyph_positions_cg_ptr = glyph_positions.data();
106 #endif
107   CGContextShowGlyphsAtPositions(
108       context, reinterpret_cast<CGGlyph*>(glyph_indices.data()),
109       glyph_positions_cg_ptr, glyph_positions.size());
110   CGContextRestoreGState(context);
111   return true;
112 }
113