rasterhandleallocator.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright 2011 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "gm/gm.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkPixmap.h"
  11. #include "include/core/SkRasterHandleAllocator.h"
  12. #include "src/core/SkMakeUnique.h"
  13. class GraphicsPort {
  14. protected:
  15. SkCanvas* fCanvas;
  16. public:
  17. GraphicsPort(SkCanvas* canvas) : fCanvas(canvas) {}
  18. virtual ~GraphicsPort() {}
  19. void save() { fCanvas->save(); }
  20. void saveLayer(const SkRect& bounds, SkAlpha alpha) {
  21. fCanvas->saveLayerAlpha(&bounds, alpha);
  22. }
  23. void restore() { fCanvas->restore(); }
  24. void translate(float x, float y) { fCanvas->translate(x, y); }
  25. void scale(float s) { fCanvas->scale(s, s); }
  26. void clip(const SkRect& r) { fCanvas->clipRect(r); }
  27. void drawOval(const SkRect& r, SkColor c) {
  28. SkPaint p;
  29. p.setColor(c);
  30. fCanvas->drawOval(r, p);
  31. }
  32. virtual void drawRect(const SkRect& r, SkColor c) {
  33. SkPaint p;
  34. p.setColor(c);
  35. fCanvas->drawRect(r, p);
  36. }
  37. SkCanvas* peekCanvas() const { return fCanvas; }
  38. };
  39. #ifdef SK_BUILD_FOR_MAC
  40. #include "include/utils/mac/SkCGUtils.h"
  41. class CGGraphicsPort : public GraphicsPort {
  42. public:
  43. CGGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
  44. void drawRect(const SkRect& r, SkColor c) override {
  45. CGContextRef cg = (CGContextRef)fCanvas->accessTopRasterHandle();
  46. CGColorRef color = CGColorCreateGenericRGB(SkColorGetR(c)/255.f,
  47. SkColorGetG(c)/255.f,
  48. SkColorGetB(c)/255.f,
  49. SkColorGetA(c)/255.f);
  50. CGContextSetFillColorWithColor(cg, color);
  51. CGContextFillRect(cg, CGRectMake(r.x(), r.y(), r.width(), r.height()));
  52. }
  53. };
  54. static CGAffineTransform matrix_to_transform(CGContextRef cg, const SkMatrix& ctm) {
  55. SkMatrix matrix;
  56. matrix.setScale(1, -1);
  57. matrix.postTranslate(0, SkIntToScalar(CGBitmapContextGetHeight(cg)));
  58. matrix.preConcat(ctm);
  59. return CGAffineTransformMake(matrix[SkMatrix::kMScaleX],
  60. matrix[SkMatrix::kMSkewY],
  61. matrix[SkMatrix::kMSkewX],
  62. matrix[SkMatrix::kMScaleY],
  63. matrix[SkMatrix::kMTransX],
  64. matrix[SkMatrix::kMTransY]);
  65. }
  66. class Allocator_CG : public SkRasterHandleAllocator {
  67. public:
  68. Allocator_CG() {}
  69. bool allocHandle(const SkImageInfo& info, Rec* rec) override {
  70. // let CG allocate the pixels
  71. CGContextRef cg = SkCreateCGContext(SkPixmap(info, nullptr, 0));
  72. if (!cg) {
  73. return false;
  74. }
  75. rec->fReleaseProc = [](void* pixels, void* ctx){ CGContextRelease((CGContextRef)ctx); };
  76. rec->fReleaseCtx = cg;
  77. rec->fPixels = CGBitmapContextGetData(cg);
  78. rec->fRowBytes = CGBitmapContextGetBytesPerRow(cg);
  79. rec->fHandle = cg;
  80. CGContextSaveGState(cg); // balanced each time updateContext is called
  81. return true;
  82. }
  83. void updateHandle(Handle hndl, const SkMatrix& ctm, const SkIRect& clip) override {
  84. CGContextRef cg = (CGContextRef)hndl;
  85. CGContextRestoreGState(cg);
  86. CGContextSaveGState(cg);
  87. CGContextClipToRect(cg, CGRectMake(clip.x(), clip.y(), clip.width(), clip.height()));
  88. CGContextConcatCTM(cg, matrix_to_transform(cg, ctm));
  89. }
  90. };
  91. #define MyPort CGGraphicsPort
  92. #define MyAllocator Allocator_CG
  93. #elif defined(SK_BUILD_FOR_WIN)
  94. #include "src/core/SkLeanWindows.h"
  95. static RECT toRECT(const SkIRect& r) {
  96. return { r.left(), r.top(), r.right(), r.bottom() };
  97. }
  98. class GDIGraphicsPort : public GraphicsPort {
  99. public:
  100. GDIGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
  101. void drawRect(const SkRect& r, SkColor c) override {
  102. HDC hdc = (HDC)fCanvas->accessTopRasterHandle();
  103. COLORREF cr = RGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));// SkEndian_Swap32(c) >> 8;
  104. RECT rounded = toRECT(r.round());
  105. FillRect(hdc, &rounded, CreateSolidBrush(cr));
  106. // Assuming GDI wrote zeros for alpha, this will or-in 0xFF for alpha
  107. SkPaint paint;
  108. paint.setBlendMode(SkBlendMode::kDstATop);
  109. fCanvas->drawRect(r, paint);
  110. }
  111. };
  112. // We use this static factory function instead of the regular constructor so
  113. // that we can create the pixel data before calling the constructor. This is
  114. // required so that we can call the base class' constructor with the pixel
  115. // data.
  116. static bool Create(int width, int height, bool is_opaque, SkRasterHandleAllocator::Rec* rec) {
  117. BITMAPINFOHEADER hdr;
  118. memset(&hdr, 0, sizeof(hdr));
  119. hdr.biSize = sizeof(BITMAPINFOHEADER);
  120. hdr.biWidth = width;
  121. hdr.biHeight = -height; // Minus means top-down bitmap.
  122. hdr.biPlanes = 1;
  123. hdr.biBitCount = 32;
  124. hdr.biCompression = BI_RGB; // No compression.
  125. hdr.biSizeImage = 0;
  126. hdr.biXPelsPerMeter = 1;
  127. hdr.biYPelsPerMeter = 1;
  128. void* pixels;
  129. HBITMAP hbitmap = CreateDIBSection(nullptr, (const BITMAPINFO*)&hdr, 0, &pixels, 0, 0);
  130. if (!hbitmap) {
  131. return false;
  132. }
  133. size_t row_bytes = width * sizeof(SkPMColor);
  134. sk_bzero(pixels, row_bytes * height);
  135. HDC hdc = CreateCompatibleDC(nullptr);
  136. if (!hdc) {
  137. DeleteObject(hbitmap);
  138. return false;
  139. }
  140. SetGraphicsMode(hdc, GM_ADVANCED);
  141. HGDIOBJ origBitmap = SelectObject(hdc, hbitmap);
  142. struct ReleaseContext {
  143. HDC hdc;
  144. HGDIOBJ hbitmap;
  145. };
  146. rec->fReleaseProc = [](void*, void* context) {
  147. ReleaseContext* ctx = static_cast<ReleaseContext*>(context);
  148. HBITMAP hbitmap = static_cast<HBITMAP>(SelectObject(ctx->hdc, ctx->hbitmap));
  149. DeleteObject(hbitmap);
  150. DeleteDC(ctx->hdc);
  151. delete ctx;
  152. };
  153. rec->fReleaseCtx = new ReleaseContext{hdc, origBitmap};
  154. rec->fPixels = pixels;
  155. rec->fRowBytes = row_bytes;
  156. rec->fHandle = hdc;
  157. return true;
  158. }
  159. /**
  160. * Subclass of SkRasterHandleAllocator that returns an HDC as its "handle".
  161. */
  162. class GDIAllocator : public SkRasterHandleAllocator {
  163. public:
  164. GDIAllocator() {}
  165. bool allocHandle(const SkImageInfo& info, Rec* rec) override {
  166. SkASSERT(info.colorType() == kN32_SkColorType);
  167. return Create(info.width(), info.height(), info.isOpaque(), rec);
  168. }
  169. void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
  170. HDC hdc = static_cast<HDC>(handle);
  171. XFORM xf;
  172. xf.eM11 = ctm[SkMatrix::kMScaleX];
  173. xf.eM21 = ctm[SkMatrix::kMSkewX];
  174. xf.eDx = ctm[SkMatrix::kMTransX];
  175. xf.eM12 = ctm[SkMatrix::kMSkewY];
  176. xf.eM22 = ctm[SkMatrix::kMScaleY];
  177. xf.eDy = ctm[SkMatrix::kMTransY];
  178. SetWorldTransform(hdc, &xf);
  179. RECT clip_bounds_RECT = toRECT(clip_bounds);
  180. HRGN hrgn = CreateRectRgnIndirect(&clip_bounds_RECT);
  181. int result = SelectClipRgn(hdc, hrgn);
  182. SkASSERT(result != ERROR);
  183. result = DeleteObject(hrgn);
  184. SkASSERT(result != 0);
  185. }
  186. };
  187. #define MyPort GDIGraphicsPort
  188. #define MyAllocator GDIAllocator
  189. #endif
  190. DEF_SIMPLE_GM(rasterallocator, canvas, 600, 300) {
  191. auto doDraw = [](GraphicsPort* port) {
  192. SkAutoCanvasRestore acr(port->peekCanvas(), true);
  193. port->drawRect({0, 0, 256, 256}, SK_ColorRED);
  194. port->save();
  195. port->translate(30, 30);
  196. port->drawRect({0, 0, 30, 30}, SK_ColorBLUE);
  197. port->drawOval({10, 10, 20, 20}, SK_ColorWHITE);
  198. port->restore();
  199. port->saveLayer({50, 50, 100, 100}, 0x80);
  200. port->drawRect({55, 55, 95, 95}, SK_ColorGREEN);
  201. port->restore();
  202. port->clip({150, 50, 200, 200});
  203. port->drawRect({0, 0, 256, 256}, 0xFFCCCCCC);
  204. };
  205. // TODO: this common code fails pic-8888 and serialize-8888
  206. sk_ignore_unused_variable(doDraw);
  207. //GraphicsPort skiaPort(canvas);
  208. //doDraw(&skiaPort);
  209. #ifdef MyAllocator
  210. const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
  211. std::unique_ptr<SkCanvas> nativeCanvas =
  212. SkRasterHandleAllocator::MakeCanvas(skstd::make_unique<MyAllocator>(), info);
  213. MyPort nativePort(nativeCanvas.get());
  214. doDraw(&nativePort);
  215. SkPixmap pm;
  216. nativeCanvas->peekPixels(&pm);
  217. SkBitmap bm;
  218. bm.installPixels(pm);
  219. canvas->drawBitmap(bm, 280, 0, nullptr);
  220. #endif
  221. }