blob: 8e348acdf0d7a7bb62d5e83cdbaacc4ea35f39a1 [file] [log] [blame]
scroggob7e9aee2011-03-15 15:15:15 +00001#include <X11/Xlib.h>
2#include <X11/Xatom.h>
3#include <X11/keysym.h>
4#include <GL/glx.h>
5
6#include "SkWindow.h"
7
8#include "SkBitmap.h"
scroggo08526c02011-03-22 14:03:21 +00009#include "SkCanvas.h"
scroggob7e9aee2011-03-15 15:15:15 +000010#include "SkColor.h"
11#include "SkEvent.h"
scroggo08526c02011-03-22 14:03:21 +000012#include "SkTypeface.h"
scroggob7e9aee2011-03-15 15:15:15 +000013
14SkOSWindow::SkOSWindow(void* unused)
15{
16 fUnixWindow.fDisplay = NULL;
scroggo08526c02011-03-22 14:03:21 +000017 fMouseX = fMouseY = 0;
18 fTypeface = SkTypeface::CreateFromTypeface(NULL, SkTypeface::kBold);
19 fShowZoomer = false;
20 fScale = 4;
scroggob7e9aee2011-03-15 15:15:15 +000021}
22
23SkOSWindow::~SkOSWindow()
24{
scroggo08526c02011-03-22 14:03:21 +000025 fTypeface->unref();
scroggob7e9aee2011-03-15 15:15:15 +000026}
27
28void SkOSWindow::setUnixWindow(Display* dsp, Window win, size_t screenNumber, GC gc)
29{
30 fUnixWindow.fDisplay = dsp;
31 fUnixWindow.fWin = win;
32 fUnixWindow.fOSWin = screenNumber;
33 fUnixWindow.fGc = gc;
34}
35
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000036bool SkOSWindow::attachGL()
scroggob7e9aee2011-03-15 15:15:15 +000037{
38 return false;
39}
40
41void SkOSWindow::detachGL()
42{
43
44}
45
46void SkOSWindow::presentGL()
47{
48
49}
50
scroggo08526c02011-03-22 14:03:21 +000051bool SkOSWindow::zoomIn()
52{
53 // Arbitrarily decided
54 if (fScale == 25) return false;
55 fScale++;
56 inval(NULL);
57 return true;
58}
59
60bool SkOSWindow::zoomOut()
61{
62 if (fScale == 1) return false;
63 fScale--;
64 inval(NULL);
65 return true;
66}
67
68void SkOSWindow::toggleZoomer()
69{
70 fShowZoomer = !fShowZoomer;
71 inval(NULL);
72}
73
scroggob7e9aee2011-03-15 15:15:15 +000074void SkOSWindow::onSetTitle(const char title[])
75{
76 if (!fUnixWindow.fDisplay) return;
77 XTextProperty textProp;
78 textProp.value = (unsigned char*)title;
79 textProp.format = 8;
80 textProp.nitems = strlen((char*)textProp.value);
81 textProp.encoding = XA_STRING;
82 XSetWMName(fUnixWindow.fDisplay, fUnixWindow.fWin, &textProp);
83}
84
85void SkOSWindow::onHandleInval(const SkIRect&)
86{
87 SkEvent* evt = new SkEvent("inval-imageview");
88 evt->post(getSinkID());
89}
90
91bool SkOSWindow::onEvent(const SkEvent& evt)
92{
93 if (evt.isType("inval-imageview")) {
94 update(NULL);
95 doPaint();
96 return true;
97 }
98 return INHERITED::onEvent(evt);
99}
100
scroggo08526c02011-03-22 14:03:21 +0000101static bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap)
102{
scroggob66365f2011-03-18 21:43:03 +0000103 sk_bzero(&image, sizeof(image));
104
105 int bitsPerPixel = bitmap.bytesPerPixel() * 8;
106 image.width = bitmap.width();
107 image.height = bitmap.height();
108 image.format = ZPixmap;
109 image.data = (char*) bitmap.getPixels();
110 image.byte_order = LSBFirst;
111 image.bitmap_unit = bitsPerPixel;
112 image.bitmap_bit_order = LSBFirst;
113 image.bitmap_pad = bitsPerPixel;
114 image.depth = 24;
115 image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * bitmap.bytesPerPixel();
116 image.bits_per_pixel = bitsPerPixel;
scroggo08526c02011-03-22 14:03:21 +0000117 return XInitImage(&image);
118}
119
120void SkOSWindow::updatePointer(int x, int y)
121{
122 fMouseX = x;
123 fMouseY = y;
124 inval(NULL);
125}
126
127static void drawText(SkCanvas& canvas, SkString string, SkScalar left, SkScalar top, SkPaint& paint)
128{
129 SkColor desiredColor = paint.getColor();
130 paint.setColor(SK_ColorWHITE);
131 const char* c_str = string.c_str();
132 size_t size = string.size();
133 SkRect bounds;
134 paint.measureText(c_str, size, &bounds);
135 bounds.offset(left, top);
136 SkScalar inset = SkIntToScalar(-2);
137 bounds.inset(inset, inset);
138 canvas.drawRect(bounds, paint);
139 if (desiredColor != SK_ColorBLACK) {
140 paint.setColor(SK_ColorBLACK);
141 canvas.drawText(c_str, size, left + SK_Scalar1, top + SK_Scalar1, paint);
142 }
143 paint.setColor(desiredColor);
144 canvas.drawText(c_str, size, left, top, paint);
145}
146
147void SkOSWindow::doPaint() {
148 if (!fUnixWindow.fDisplay) return;
149 // Draw the bitmap to the screen.
150 const SkBitmap& bitmap = getBitmap();
151 int width = bitmap.width();
152 int height = bitmap.height();
153
154 if (!fShowZoomer) {
155 XImage image;
156 if (!convertBitmapToXImage(image, bitmap)) return;
157
158 XPutImage(fUnixWindow.fDisplay, fUnixWindow.fWin, fUnixWindow.fGc, &image, 0, 0, 0, 0, width, height);
159 } else {
160 // Ensure the mouse position is on screen.
161 if (fMouseX >= width) fMouseX = width - 1;
162 else if (fMouseX < 0) fMouseX = 0;
163 if (fMouseY >= height) fMouseY = height - 1;
164 else if (fMouseY < 0) fMouseY = 0;
165 // zoomedBitmap will show the original bitmap, plus a zoomed in view (fat bits).
166 SkBitmap zoomedBitmap;
167 bitmap.copyTo(&zoomedBitmap, bitmap.getConfig());
168 SkCanvas canvas(zoomedBitmap);
169 // Find the size of the zoomed in view, forced to be odd, so the examined pixel is in the middle.
170 int zoomedWidth = (width >> 2) | 1;
171 int zoomedHeight = (height >> 2) | 1;
172 SkIRect src;
173 src.set(0, 0, zoomedWidth / fScale, zoomedHeight / fScale);
174 src.offset(fMouseX - (src.width()>>1), fMouseY - (src.height()>>1));
175 SkRect dest;
176 dest.set(0, 0, SkIntToScalar(zoomedWidth), SkIntToScalar(zoomedHeight));
177 dest.offset(SkIntToScalar(width - zoomedWidth), SkIntToScalar(height - zoomedHeight));
178 SkPaint paint;
179 // Clear the background behind our zoomed in view
180 paint.setColor(SK_ColorWHITE);
181 canvas.drawRect(dest, paint);
182 canvas.drawBitmapRect(bitmap, &src, dest);
183 paint.setColor(SK_ColorBLACK);
184 paint.setStyle(SkPaint::kStroke_Style);
185 // Draw a border around the pixel in the middle
186 SkRect originalPixel;
187 originalPixel.set(SkIntToScalar(fMouseX), SkIntToScalar(fMouseY), SkIntToScalar(fMouseX + 1), SkIntToScalar(fMouseY + 1));
188 SkMatrix matrix;
189 SkRect scalarSrc;
190 scalarSrc.set(src);
191 SkColor color = bitmap.getColor(fMouseX, fMouseY);
192 if (matrix.setRectToRect(scalarSrc, dest, SkMatrix::kFill_ScaleToFit)) {
193 SkRect pixel;
194 matrix.mapRect(&pixel, originalPixel);
195 // TODO Perhaps measure the values and make the outline white if it's "dark"
196 if (color == SK_ColorBLACK) {
197 paint.setColor(SK_ColorWHITE);
198 }
199 canvas.drawRect(pixel, paint);
200 }
201 paint.setColor(SK_ColorBLACK);
202 // Draw a border around the destination rectangle
203 canvas.drawRect(dest, paint);
204 paint.setStyle(SkPaint::kStrokeAndFill_Style);
205 // Identify the pixel and its color on screen
206 paint.setTypeface(fTypeface);
207 paint.setAntiAlias(true);
208 SkScalar lineHeight = paint.getFontMetrics(NULL);
209 SkString string;
210 string.appendf("(%i, %i)", fMouseX, fMouseY);
211 SkScalar left = dest.fLeft + SkIntToScalar(3);
212 SkScalar i = SK_Scalar1;
213 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
214 // Alpha
215 i += SK_Scalar1;
216 string.reset();
217 string.appendf("A: %X", SkColorGetA(color));
218 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
219 // Red
220 i += SK_Scalar1;
221 string.reset();
222 string.appendf("R: %X", SkColorGetR(color));
223 paint.setColor(SK_ColorRED);
224 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
225 // Green
226 i += SK_Scalar1;
227 string.reset();
228 string.appendf("G: %X", SkColorGetG(color));
229 paint.setColor(SK_ColorGREEN);
230 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
231 // Blue
232 i += SK_Scalar1;
233 string.reset();
234 string.appendf("B: %X", SkColorGetB(color));
235 paint.setColor(SK_ColorBLUE);
236 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
237 // Finally, put our bitmap on the screen
238 XImage zoomedImage;
239 convertBitmapToXImage(zoomedImage, zoomedBitmap);
240 XPutImage(fUnixWindow.fDisplay, fUnixWindow.fWin, fUnixWindow.fGc, &zoomedImage, 0, 0, 0, 0, width, height);
241 }
scroggob7e9aee2011-03-15 15:15:15 +0000242}
243
244bool SkOSWindow::onHandleChar(SkUnichar)
245{
246 return false;
247}
248
249bool SkOSWindow::onHandleKey(SkKey key)
250{
251 return false;
252}
253
254bool SkOSWindow::onHandleKeyUp(SkKey key)
255{
256 return false;
257}