--- /dev/null
+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation. //
+// //
+// This program is distributed in the hope that it will be useful, but //
+// WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
+// General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+// //
+// Written by and Copyright (C) Francois Fleuret //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports //
+///////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+
+#include "simple_window.h"
+
+using namespace std;
+
+int main() {
+ SimpleWindow window("Mandelbrot", 600, 600);
+ int n;
+ int depth = 100;
+
+ const int width = window.get_width();
+ const int height = window.get_height();
+
+ window.map();
+
+ for(int i = 0; i < width; i++)
+ for(int j = 0; j < height; j++) {
+ double cr = -2.0 + 3.0 * (double(i)/double(width));
+ double ci = -1.5 + 3.0 * (double(j)/double(height));
+ double zr = 0, zi = 0;
+ for(n = 0; (n < depth) && (zr*zr + zi*zi < 100); n++) {
+ double t = zr*zr -zi*zi + cr;
+ zi = 2*zr*zi + ci;
+ zr = t;
+ }
+
+ float a = float(n)/float(depth);
+
+ if(a < 0.5) window.color(0, 0, a*2);
+ else window.color((a-0.5)*2, (a-0.5)*2, 1.0);
+
+ window.draw_point(i, j);
+ }
+
+ window.show();
+
+ cout << "Press [ENTER] to close the window.\n";
+
+ cin.get();
+}
--- /dev/null
+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation. //
+// //
+// This program is distributed in the hope that it will be useful, but //
+// WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
+// General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+// //
+// Written by and Copyright (C) Francois Fleuret //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports //
+///////////////////////////////////////////////////////////////////////////
+
+#include "simple_window.h"
+
+SimpleWindow::SimpleWindow(const char *name, int w, int h) {
+
+ width = w; height = h;
+
+ dpy = XOpenDisplay(0);
+
+ if (dpy) {
+
+ Visual *v = XDefaultVisual(dpy, DefaultScreen(dpy));
+
+ blue_mask = v->blue_mask;
+ green_mask = v->green_mask;
+ red_mask = v->red_mask;
+
+ if(blue_mask == 0 || green_mask == 0 || red_mask == 0) {
+ std::cerr << "Can not deal with the colors on that display.\n";
+ }
+
+ // We compute how many bits we have for each component, and
+ // compute the corresponding mask
+ red_shift = 1;
+ while(!(red_mask & 1)) {
+ red_mask = red_mask >> 1;
+ red_shift = red_shift << 1;
+ }
+
+ green_shift = 1;
+ while(!(green_mask & 1)) {
+ green_mask = green_mask >> 1;
+ green_shift = green_shift << 1;
+ }
+
+ blue_shift = 1;
+ while(!(blue_mask & 1)) {
+ blue_mask = blue_mask >> 1;
+ blue_shift = blue_shift << 1;
+ }
+
+ gc = DefaultGC(dpy, DefaultScreen(dpy));
+
+ XSetWindowAttributes xswa;
+
+ pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ width, height, DisplayPlanes(dpy, DefaultScreen(dpy)));
+
+ xswa.background_pixmap = pixmap;
+ xswa.event_mask = NoEventMask;
+ xswa.backing_store = Always;
+
+ window = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, width, height,
+ 0, 0, InputOutput, CopyFromParent,
+ CWBackPixmap | CWEventMask | CWBackingStore,
+ &xswa);
+
+ XSizeHints size_hints;
+ size_hints.flags = PMinSize | PMaxSize;
+ size_hints.min_width = width;
+ size_hints.min_height = height;
+ size_hints.max_width = width;
+ size_hints.max_height = height;
+ XSetNormalHints(dpy, window, &size_hints);
+
+ XStoreName(dpy, window, name);
+
+ XSetState(dpy, gc, 0, 0, GXcopy, AllPlanes);
+ XFillRectangle(dpy, pixmap, gc, 0, 0, width, height);
+ XFlush(dpy);
+ } else abort();
+}
+
+SimpleWindow::~SimpleWindow() {
+ XUnmapWindow(dpy, window);
+ XDestroyWindow(dpy, window);
+ XCloseDisplay(dpy);
+}
+
+int SimpleWindow::get_width() {
+ return width;
+}
+
+int SimpleWindow::get_height() {
+ return height;
+}
+
+void SimpleWindow::map() {
+ XMapWindow(dpy, window);
+ XFlush(dpy);
+}
+
+void SimpleWindow::unmap() {
+ XUnmapWindow(dpy, window);
+ XFlush(dpy);
+}
+
+void SimpleWindow::color(float red, float green, float blue) {
+ // We work under the assumption that the bits come in the
+ // red/green/blue order with the corresponding masks
+ XSetState(dpy, gc,
+ ((unsigned int) ( red * red_mask)) * red_shift
+ + ((unsigned int) (green * green_mask)) * green_shift
+ + ((unsigned int) ( blue * blue_mask)) * blue_shift,
+ 0, GXcopy, AllPlanes);
+}
+
+void SimpleWindow::draw_point(int x, int y) {
+ XDrawPoint(dpy, pixmap, gc, x, y);
+}
+
+void SimpleWindow::draw_line(int x1, int y1, int x2, int y2) {
+ XDrawLine(dpy, pixmap, gc, x1, y1, x2, y2);
+}
+
+void SimpleWindow::draw_circle(int x, int y, int r) {
+ XDrawArc(dpy, pixmap, gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
+}
+
+void SimpleWindow::draw_text(char *s, int x, int y) {
+ XDrawString(dpy, pixmap, gc, x, y, s, strlen(s));
+}
+
+void SimpleWindow::fill_rectangle(int x, int y, int w, int h) {
+ XFillRectangle(dpy, pixmap, gc, x, y, w, h);
+}
+
+void SimpleWindow::show() {
+ XCopyArea(dpy, pixmap, window, gc, 0, 0, width, height, 0, 0);
+ XFlush(dpy);
+}
+
+void SimpleWindow::fill() {
+ XFillRectangle(dpy, pixmap, gc, 0, 0, width, height);
+}
--- /dev/null
+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation. //
+// //
+// This program is distributed in the hope that it will be useful, but //
+// WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
+// General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+// //
+// Written by and Copyright (C) Francois Fleuret //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports //
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef SIMPLE_WINDOW_H
+#define SIMPLE_WINDOW_H
+
+#include <iostream>
+#include <cmath>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+#include <X11/cursorfont.h>
+
+class SimpleWindow {
+ Display *dpy;
+ Window window;
+ Pixmap pixmap;
+ GC gc;
+
+protected:
+ int red_mask, green_mask, blue_mask;
+ int red_shift, green_shift, blue_shift;
+ int width, height;
+
+public:
+ SimpleWindow(const char *name, int w, int h);
+ virtual ~SimpleWindow();
+
+ virtual int get_width();
+ virtual int get_height();
+
+ virtual void map();
+ virtual void unmap();
+ virtual void color(float red, float green, float blue);
+ virtual void draw_point(int x, int y);
+ virtual void draw_line(int x1, int y1, int x2, int y2);
+ virtual void draw_circle(int x, int y, int r);
+ virtual void draw_text(char *s, int x, int y);
+ virtual void fill_rectangle(int x, int y, int w, int h);
+ virtual void show();
+ virtual void fill();
+};
+
+#endif