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_ext.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/fxcrt/fx_memory.h"
14#include "core/fxge/cfx_gemodule.h"
15#include "core/fxge/cfx_graphstatedata.h"
16#include "core/fxge/cfx_pathdata.h"
17#include "core/fxge/cfx_renderdevice.h"
18#include "core/fxge/dib/dib_int.h"
19#include "core/fxge/fx_freetype.h"
20#include "core/fxge/ge/fx_text_int.h"
21#include "third_party/base/ptr_util.h"
22
23#include "core/fxge/apple/apple_int.h"
24#ifndef CGFLOAT_IS_DOUBLE
25#error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers
26#endif
27
28void* CQuartz2D::createGraphics(CFX_DIBitmap* pBitmap) {
29  if (!pBitmap)
30    return nullptr;
31  CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little;
32  switch (pBitmap->GetFormat()) {
33    case FXDIB_Rgb32:
34      bmpInfo |= kCGImageAlphaNoneSkipFirst;
35      break;
36    case FXDIB_Argb:
37    default:
38      return nullptr;
39  }
40  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
41  CGContextRef context = CGBitmapContextCreate(
42      pBitmap->GetBuffer(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8,
43      pBitmap->GetPitch(), colorSpace, bmpInfo);
44  CGColorSpaceRelease(colorSpace);
45  return context;
46}
47
48void CQuartz2D::destroyGraphics(void* graphics) {
49  if (graphics)
50    CGContextRelease((CGContextRef)graphics);
51}
52
53void* CQuartz2D::CreateFont(const uint8_t* pFontData, uint32_t dwFontSize) {
54  CGDataProviderRef pDataProvider = CGDataProviderCreateWithData(
55      nullptr, pFontData, (size_t)dwFontSize, nullptr);
56  if (!pDataProvider)
57    return nullptr;
58
59  CGFontRef pCGFont = CGFontCreateWithDataProvider(pDataProvider);
60  CGDataProviderRelease(pDataProvider);
61  return pCGFont;
62}
63
64void CQuartz2D::DestroyFont(void* pFont) {
65  CGFontRelease((CGFontRef)pFont);
66}
67
68void CQuartz2D::setGraphicsTextMatrix(void* graphics, CFX_Matrix* matrix) {
69  if (!graphics || !matrix)
70    return;
71  CGContextRef context = (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
78bool CQuartz2D::drawGraphicsString(void* graphics,
79                                   void* font,
80                                   FX_FLOAT fontSize,
81                                   uint16_t* glyphIndices,
82                                   CGPoint* glyphPositions,
83                                   int32_t charsCount,
84                                   FX_ARGB argb,
85                                   CFX_Matrix* matrix) {
86  if (!graphics)
87    return false;
88  CGContextRef context = (CGContextRef)graphics;
89  CGContextSetFont(context, (CGFontRef)font);
90  CGContextSetFontSize(context, fontSize);
91  if (matrix) {
92    CGAffineTransform m = CGContextGetTextMatrix(context);
93    m = CGAffineTransformConcat(
94        m, CGAffineTransformMake(matrix->a, matrix->b, matrix->c, matrix->d,
95                                 matrix->e, matrix->f));
96    CGContextSetTextMatrix(context, m);
97  }
98  int32_t a, r, g, b;
99  ArgbDecode(argb, a, r, g, b);
100  CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f);
101  CGContextSaveGState(context);
102#if CGFLOAT_IS_DOUBLE
103  CGPoint* glyphPositionsCG = new CGPoint[charsCount];
104  for (int index = 0; index < charsCount; ++index) {
105    glyphPositionsCG[index].x = glyphPositions[index].x;
106    glyphPositionsCG[index].y = glyphPositions[index].y;
107  }
108#else
109  CGPoint* glyphPositionsCG = (CGPoint*)glyphPositions;
110#endif
111  CGContextShowGlyphsAtPositions(context, (CGGlyph*)glyphIndices,
112                                 glyphPositionsCG, charsCount);
113#if CGFLOAT_IS_DOUBLE
114  delete[] glyphPositionsCG;
115#endif
116  CGContextRestoreGState(context);
117  return true;
118}
119
120void CQuartz2D::saveGraphicsState(void* graphics) {
121  if (graphics)
122    CGContextSaveGState((CGContextRef)graphics);
123}
124
125void CQuartz2D::restoreGraphicsState(void* graphics) {
126  if (graphics)
127    CGContextRestoreGState((CGContextRef)graphics);
128}
129