123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "gm/gm.h"
- #include "include/core/SkBitmap.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkPixmap.h"
- #include "include/core/SkRasterHandleAllocator.h"
- #include "src/core/SkMakeUnique.h"
- class GraphicsPort {
- protected:
- SkCanvas* fCanvas;
- public:
- GraphicsPort(SkCanvas* canvas) : fCanvas(canvas) {}
- virtual ~GraphicsPort() {}
- void save() { fCanvas->save(); }
- void saveLayer(const SkRect& bounds, SkAlpha alpha) {
- fCanvas->saveLayerAlpha(&bounds, alpha);
- }
- void restore() { fCanvas->restore(); }
- void translate(float x, float y) { fCanvas->translate(x, y); }
- void scale(float s) { fCanvas->scale(s, s); }
- void clip(const SkRect& r) { fCanvas->clipRect(r); }
- void drawOval(const SkRect& r, SkColor c) {
- SkPaint p;
- p.setColor(c);
- fCanvas->drawOval(r, p);
- }
- virtual void drawRect(const SkRect& r, SkColor c) {
- SkPaint p;
- p.setColor(c);
- fCanvas->drawRect(r, p);
- }
- SkCanvas* peekCanvas() const { return fCanvas; }
- };
- #ifdef SK_BUILD_FOR_MAC
- #include "include/utils/mac/SkCGUtils.h"
- class CGGraphicsPort : public GraphicsPort {
- public:
- CGGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
- void drawRect(const SkRect& r, SkColor c) override {
- CGContextRef cg = (CGContextRef)fCanvas->accessTopRasterHandle();
- CGColorRef color = CGColorCreateGenericRGB(SkColorGetR(c)/255.f,
- SkColorGetG(c)/255.f,
- SkColorGetB(c)/255.f,
- SkColorGetA(c)/255.f);
- CGContextSetFillColorWithColor(cg, color);
- CGContextFillRect(cg, CGRectMake(r.x(), r.y(), r.width(), r.height()));
- }
- };
- static CGAffineTransform matrix_to_transform(CGContextRef cg, const SkMatrix& ctm) {
- SkMatrix matrix;
- matrix.setScale(1, -1);
- matrix.postTranslate(0, SkIntToScalar(CGBitmapContextGetHeight(cg)));
- matrix.preConcat(ctm);
- return CGAffineTransformMake(matrix[SkMatrix::kMScaleX],
- matrix[SkMatrix::kMSkewY],
- matrix[SkMatrix::kMSkewX],
- matrix[SkMatrix::kMScaleY],
- matrix[SkMatrix::kMTransX],
- matrix[SkMatrix::kMTransY]);
- }
- class Allocator_CG : public SkRasterHandleAllocator {
- public:
- Allocator_CG() {}
- bool allocHandle(const SkImageInfo& info, Rec* rec) override {
- // let CG allocate the pixels
- CGContextRef cg = SkCreateCGContext(SkPixmap(info, nullptr, 0));
- if (!cg) {
- return false;
- }
- rec->fReleaseProc = [](void* pixels, void* ctx){ CGContextRelease((CGContextRef)ctx); };
- rec->fReleaseCtx = cg;
- rec->fPixels = CGBitmapContextGetData(cg);
- rec->fRowBytes = CGBitmapContextGetBytesPerRow(cg);
- rec->fHandle = cg;
- CGContextSaveGState(cg); // balanced each time updateContext is called
- return true;
- }
- void updateHandle(Handle hndl, const SkMatrix& ctm, const SkIRect& clip) override {
- CGContextRef cg = (CGContextRef)hndl;
- CGContextRestoreGState(cg);
- CGContextSaveGState(cg);
- CGContextClipToRect(cg, CGRectMake(clip.x(), clip.y(), clip.width(), clip.height()));
- CGContextConcatCTM(cg, matrix_to_transform(cg, ctm));
- }
- };
- #define MyPort CGGraphicsPort
- #define MyAllocator Allocator_CG
- #elif defined(SK_BUILD_FOR_WIN)
- #include "src/core/SkLeanWindows.h"
- static RECT toRECT(const SkIRect& r) {
- return { r.left(), r.top(), r.right(), r.bottom() };
- }
- class GDIGraphicsPort : public GraphicsPort {
- public:
- GDIGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
- void drawRect(const SkRect& r, SkColor c) override {
- HDC hdc = (HDC)fCanvas->accessTopRasterHandle();
- COLORREF cr = RGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));// SkEndian_Swap32(c) >> 8;
- RECT rounded = toRECT(r.round());
- FillRect(hdc, &rounded, CreateSolidBrush(cr));
- // Assuming GDI wrote zeros for alpha, this will or-in 0xFF for alpha
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kDstATop);
- fCanvas->drawRect(r, paint);
- }
- };
- // We use this static factory function instead of the regular constructor so
- // that we can create the pixel data before calling the constructor. This is
- // required so that we can call the base class' constructor with the pixel
- // data.
- static bool Create(int width, int height, bool is_opaque, SkRasterHandleAllocator::Rec* rec) {
- BITMAPINFOHEADER hdr;
- memset(&hdr, 0, sizeof(hdr));
- hdr.biSize = sizeof(BITMAPINFOHEADER);
- hdr.biWidth = width;
- hdr.biHeight = -height; // Minus means top-down bitmap.
- hdr.biPlanes = 1;
- hdr.biBitCount = 32;
- hdr.biCompression = BI_RGB; // No compression.
- hdr.biSizeImage = 0;
- hdr.biXPelsPerMeter = 1;
- hdr.biYPelsPerMeter = 1;
- void* pixels;
- HBITMAP hbitmap = CreateDIBSection(nullptr, (const BITMAPINFO*)&hdr, 0, &pixels, 0, 0);
- if (!hbitmap) {
- return false;
- }
- size_t row_bytes = width * sizeof(SkPMColor);
- sk_bzero(pixels, row_bytes * height);
- HDC hdc = CreateCompatibleDC(nullptr);
- if (!hdc) {
- DeleteObject(hbitmap);
- return false;
- }
- SetGraphicsMode(hdc, GM_ADVANCED);
- HGDIOBJ origBitmap = SelectObject(hdc, hbitmap);
- struct ReleaseContext {
- HDC hdc;
- HGDIOBJ hbitmap;
- };
- rec->fReleaseProc = [](void*, void* context) {
- ReleaseContext* ctx = static_cast<ReleaseContext*>(context);
- HBITMAP hbitmap = static_cast<HBITMAP>(SelectObject(ctx->hdc, ctx->hbitmap));
- DeleteObject(hbitmap);
- DeleteDC(ctx->hdc);
- delete ctx;
- };
- rec->fReleaseCtx = new ReleaseContext{hdc, origBitmap};
- rec->fPixels = pixels;
- rec->fRowBytes = row_bytes;
- rec->fHandle = hdc;
- return true;
- }
- /**
- * Subclass of SkRasterHandleAllocator that returns an HDC as its "handle".
- */
- class GDIAllocator : public SkRasterHandleAllocator {
- public:
- GDIAllocator() {}
- bool allocHandle(const SkImageInfo& info, Rec* rec) override {
- SkASSERT(info.colorType() == kN32_SkColorType);
- return Create(info.width(), info.height(), info.isOpaque(), rec);
- }
- void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
- HDC hdc = static_cast<HDC>(handle);
- XFORM xf;
- xf.eM11 = ctm[SkMatrix::kMScaleX];
- xf.eM21 = ctm[SkMatrix::kMSkewX];
- xf.eDx = ctm[SkMatrix::kMTransX];
- xf.eM12 = ctm[SkMatrix::kMSkewY];
- xf.eM22 = ctm[SkMatrix::kMScaleY];
- xf.eDy = ctm[SkMatrix::kMTransY];
- SetWorldTransform(hdc, &xf);
- RECT clip_bounds_RECT = toRECT(clip_bounds);
- HRGN hrgn = CreateRectRgnIndirect(&clip_bounds_RECT);
- int result = SelectClipRgn(hdc, hrgn);
- SkASSERT(result != ERROR);
- result = DeleteObject(hrgn);
- SkASSERT(result != 0);
- }
- };
- #define MyPort GDIGraphicsPort
- #define MyAllocator GDIAllocator
- #endif
- DEF_SIMPLE_GM(rasterallocator, canvas, 600, 300) {
- auto doDraw = [](GraphicsPort* port) {
- SkAutoCanvasRestore acr(port->peekCanvas(), true);
- port->drawRect({0, 0, 256, 256}, SK_ColorRED);
- port->save();
- port->translate(30, 30);
- port->drawRect({0, 0, 30, 30}, SK_ColorBLUE);
- port->drawOval({10, 10, 20, 20}, SK_ColorWHITE);
- port->restore();
- port->saveLayer({50, 50, 100, 100}, 0x80);
- port->drawRect({55, 55, 95, 95}, SK_ColorGREEN);
- port->restore();
- port->clip({150, 50, 200, 200});
- port->drawRect({0, 0, 256, 256}, 0xFFCCCCCC);
- };
- // TODO: this common code fails pic-8888 and serialize-8888
- sk_ignore_unused_variable(doDraw);
- //GraphicsPort skiaPort(canvas);
- //doDraw(&skiaPort);
- #ifdef MyAllocator
- const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
- std::unique_ptr<SkCanvas> nativeCanvas =
- SkRasterHandleAllocator::MakeCanvas(skstd::make_unique<MyAllocator>(), info);
- MyPort nativePort(nativeCanvas.get());
- doDraw(&nativePort);
- SkPixmap pm;
- nativeCanvas->peekPixels(&pm);
- SkBitmap bm;
- bm.installPixels(pm);
- canvas->drawBitmap(bm, 280, 0, nullptr);
- #endif
- }
|