1 
2 #include "RkCairoImageBackendCanvas.h"
3 #include "RkCanvasInfo.h"
4 #include "RkLog.h"
5 
RkCairoImageBackendCanvas(const RkSize & size,RkImage::Format format,const unsigned char * data)6 RkCairoImageBackendCanvas::RkCairoImageBackendCanvas(const RkSize &size,
7                                                      RkImage::Format format,
8                                                      const unsigned char *data)
9         : canvasInfo{nullptr}
10         , imageSize{size}
11 {
12 #ifdef RK_OS_WIN
13 #elif RK_OS_MAC
14 #else // X11
15         auto cairoFormat = toCairoFormat(format);
16         if (cairoFormat != CAIRO_FORMAT_INVALID && imageSize.width() > 0 && imageSize.height() > 0) {
17                 canvasInfo = std::make_unique<RkCanvasInfo>();
18                 auto stride = cairo_format_stride_for_width(cairoFormat, imageSize.width());
19                 if (data == nullptr)
20                         imageData = std::vector<unsigned char>(imageSize.width() * imageSize.height() * pixelLength(format), 0);
21                 else
22                         imageData.assign(data, data + imageSize.width() * imageSize.height() * pixelLength(format));
23                 canvasInfo->cairo_surface = cairo_image_surface_create_for_data(imageData.data(),
24                                                                                 CAIRO_FORMAT_ARGB32,
25                                                                                 imageSize.width(),
26                                                                                 imageSize.height(),
27                                                                                 stride);
28         }
29 #endif
30 }
31 
~RkCairoImageBackendCanvas()32 RkCairoImageBackendCanvas::~RkCairoImageBackendCanvas()
33 {
34         if (canvasInfo)
35                 cairo_surface_destroy(canvasInfo->cairo_surface);
36 }
37 
toCairoFormat(RkImage::Format format) const38 cairo_format_t RkCairoImageBackendCanvas::toCairoFormat(RkImage::Format format) const
39 {
40         switch (format)
41         {
42         case RkImage::Format::ARGB32: return CAIRO_FORMAT_ARGB32;
43         case RkImage::Format::RGB32:  return CAIRO_FORMAT_RGB24;
44         default: return CAIRO_FORMAT_INVALID;
45         }
46 }
47 
pixelLength(RkImage::Format format) const48 int RkCairoImageBackendCanvas::pixelLength(RkImage::Format format) const
49 {
50         switch (format)
51         {
52         case RkImage::Format::ARGB32:
53         case RkImage::Format::RGB32:  return 4;
54         default: return 1;
55         }
56 }
57 
size() const58 const RkSize& RkCairoImageBackendCanvas::size() const
59 {
60         return imageSize;
61 }
62 
isNull() const63 bool RkCairoImageBackendCanvas::isNull() const
64 {
65         return canvasInfo == nullptr;
66 }
67 
data()68 unsigned char* RkCairoImageBackendCanvas::data()
69 {
70         return imageData.data();
71 }
72 
dataCopy() const73 std::vector<unsigned char> RkCairoImageBackendCanvas::dataCopy() const
74 {
75         return imageData;
76 }
77 
getCanvasInfo() const78 RkCanvasInfo* RkCairoImageBackendCanvas::getCanvasInfo() const
79 {
80         return canvasInfo.get();
81 }
82 
fill(const RkColor & color)83 void RkCairoImageBackendCanvas::fill(const RkColor &color)
84 {
85         unsigned char *data = imageData.data();
86         for (decltype(imageData.size()) i = 0; i < imageData.size() - 4; i += 4) {
87                 *(data + i)     = color.red();
88                 *(data + i + 1) = color.green();
89                 *(data + i + 2) = color.blue();
90                 *(data + i + 3) = color.alpha();
91         }
92 }
93