1 // SHE library
2 // Copyright (C) 2016-2017  David Capello
3 //
4 // This file is released under the terms of the MIT license.
5 // Read LICENSE.txt for more information.
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "she/skia/skia_window_x11.h"
12 
13 #include "gfx/size.h"
14 #include "she/event.h"
15 #include "she/event_queue.h"
16 #include "she/skia/skia_display.h"
17 #include "she/skia/skia_surface.h"
18 #include "she/x11/x11.h"
19 
20 #include "SkBitmap.h"
21 
22 namespace she {
23 
24 namespace {
25 
convert_skia_bitmap_to_ximage(const SkBitmap & bitmap,XImage & image)26 bool convert_skia_bitmap_to_ximage(const SkBitmap& bitmap, XImage& image)
27 {
28   memset(&image, 0, sizeof(image));
29   int bpp = 8*bitmap.bytesPerPixel();
30   image.width = bitmap.width();
31   image.height = bitmap.height();
32   image.format = ZPixmap;
33   image.data = (char*)bitmap.getPixels();
34   image.byte_order = LSBFirst;
35   image.bitmap_unit = bpp;
36   image.bitmap_bit_order = LSBFirst;
37   image.bitmap_pad = bpp;
38   image.depth = 24;
39   image.bytes_per_line = bitmap.rowBytes() - 4*bitmap.width();
40   image.bits_per_pixel = bpp;
41 
42   bool result = XInitImage(&image);
43 
44   return result;
45 }
46 
47 } // anonymous namespace
48 
SkiaWindow(EventQueue * queue,SkiaDisplay * display,int width,int height,int scale)49 SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display,
50                        int width, int height, int scale)
51   : X11Window(X11::instance()->display(), width, height, scale)
52   , m_queue(queue)
53   , m_display(display)
54 {
55 }
56 
~SkiaWindow()57 SkiaWindow::~SkiaWindow()
58 {
59 }
60 
setVisible(bool visible)61 void SkiaWindow::setVisible(bool visible)
62 {
63 }
64 
maximize()65 void SkiaWindow::maximize()
66 {
67 }
68 
isMaximized() const69 bool SkiaWindow::isMaximized() const
70 {
71   return false;
72 }
73 
isMinimized() const74 bool SkiaWindow::isMinimized() const
75 {
76   return false;
77 }
78 
queueEvent(Event & ev)79 void SkiaWindow::queueEvent(Event& ev)
80 {
81   ev.setDisplay(m_display);
82   m_queue->queueEvent(ev);
83 }
84 
paintGC(const gfx::Rect & rc)85 void SkiaWindow::paintGC(const gfx::Rect& rc)
86 {
87   SkiaSurface* surface = static_cast<SkiaSurface*>(m_display->getSurface());
88   const SkBitmap& bitmap = surface->bitmap();
89 
90   int scale = this->scale();
91   if (scale == 1) {
92     XImage image;
93     if (convert_skia_bitmap_to_ximage(bitmap, image)) {
94       XPutImage(
95         x11display(), handle(), gc(), &image,
96         rc.x, rc.y,
97         rc.x, rc.y,
98         rc.w, rc.h);
99     }
100   }
101   else {
102     SkBitmap scaled;
103     if (scaled.tryAllocPixels(
104           SkImageInfo::Make(rc.w, rc.h,
105                             bitmap.info().colorType(),
106                             bitmap.info().alphaType()))) {
107       SkPaint paint;
108       paint.setBlendMode(SkBlendMode::kSrc);
109 
110       SkCanvas canvas(scaled);
111       SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(rc.x/scale, rc.y/scale, rc.w/scale, rc.h/scale));
112       SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, rc.w, rc.h));
113       canvas.drawBitmapRect(bitmap, srcRect, dstRect, &paint,
114                             SkCanvas::kStrict_SrcRectConstraint);
115 
116       XImage image;
117       if (convert_skia_bitmap_to_ximage(scaled, image)) {
118         XPutImage(
119           x11display(), handle(), gc(), &image,
120           0, 0,
121           rc.x, rc.y,
122           rc.w, rc.h);
123       }
124     }
125   }
126 }
127 
resizeDisplay(const gfx::Size & sz)128 void SkiaWindow::resizeDisplay(const gfx::Size& sz)
129 {
130   m_display->resize(sz);
131   updateWindow(gfx::Rect(sz / scale()));
132 }
133 
134 } // namespace she
135