diff --git a/x/1-4-Drawing/clipping.cpp b/x/1-4-Drawing/clipping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dca7e82a67a0fdf9cb7f69454459adec52532b20 --- /dev/null +++ b/x/1-4-Drawing/clipping.cpp @@ -0,0 +1,292 @@ +/* +CS 349 Code Examples: X Windows and XLib + + displaylist Demos Displayable class and display list + +- - - - - - - - - - - - - - - - - - - - - - + +See associated makefile for compiling instructions + +*/ + +#include <iostream> +#include <list> +#include <cstdlib> +#include <vector> +/* + * Header files for X functions + */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include <unistd.h> // needed for sleep + +using namespace std; + +/* + * Information to draw on the window. + */ +struct XInfo { + Display* display; + Window window; + GC gc; +}; + + +/* + * An abstract class representing displayable things. + */ +class Displayable { +public: + virtual void paint(XInfo& xinfo) = 0; +}; + +/* + * A text displayable + */ +class Text : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + XDrawImageString( xinfo.display, xinfo.window, xinfo.gc, + this->x, this->y, this->s.c_str(), this->s.length() ); + } + + // constructor + Text(int x, int y, string s): x(x), y(y), s(s) {} + +private: + int x; + int y; + string s; // string to show +}; + +/* + * A displayable polyline + */ +class Polyline : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + + // CLIPPING CODE HERE! + // ===================================== + + // create a clip window + XRectangle clip_rect; + + clip_rect.x = 50; + clip_rect.y = 50; + clip_rect.width = 200; + clip_rect.height = 200; + + // clips all drawings that use the same GC after this call ... + XSetClipRectangles(xinfo.display, xinfo.gc, + 0, 0, &clip_rect, 1, Unsorted); + + XDrawLines(xinfo.display, xinfo.window, xinfo.gc, + &points[0], points.size(), // vector of points + CoordModeOrigin ); // use absolute coordinates + + // turn clipping off again + XSetClipMask(xinfo.display, xinfo.gc, None); + + // ===================================== + // to here + } + + // constructor + Polyline(int x, int y) { + add_point(x, y); + } + + // add another point to the line + void add_point(int x, int y) { + XPoint p; // XPoint is a built in struct + p.x = x; + p.y = y; + points.push_back(p); + } + +private: + // need to use a vector to dynamically add points + vector < XPoint > points; // XPoint is a built in struct +}; + + + +/* + * A face displayable + */ +class Face : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + + // create a simple graphics context + GC gc = XCreateGC(xinfo.display, xinfo.window, 0, 0); + int screen = DefaultScreen( xinfo.display ); + XSetForeground(xinfo.display, gc, BlackPixel(xinfo.display, screen)); + XSetBackground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + XSetFillStyle(xinfo.display, gc, FillSolid); + XSetLineAttributes(xinfo.display, gc, + 3, // 3 is line width + LineSolid, CapButt, JoinRound); // other line options + + + // draw head + XFillArc(xinfo.display, xinfo.window, gc, + x - (d / 2), y - (d / 2), d, d, 0, 360 * 64); + + XSetForeground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + + // draw mouth either smiling or serious + if (smile) { + int dd = d / 2; + XDrawArc(xinfo.display, xinfo.window, gc, + x - (dd / 2), y - (dd / 2), dd, dd, 210 * 64, 120 * 64); + } else { + int dd = d / 3; + XDrawLine(xinfo.display, xinfo.window, gc, + x - dd, y + dd / 2, x + dd, y + dd / 2); + } + } + + // constructor + Face(int x, int y, int d, bool smile): x(x), y(y), d(d), smile(smile) {} + +private: + int x; + int y; + int d; // diameter + bool smile; // is smiling +}; + + + +/* + * Function to put out a message on error exits. + */ +void error( string str ) { + cerr << str << endl; + exit(0); +} + + +/* + * Create a window + */ +void initX(int argc, char* argv[], XInfo& xinfo) { + + + /* + * Display opening uses the DISPLAY environment variable. + * It can go wrong if DISPLAY isn't set, or you don't have permission. + */ + xinfo.display = XOpenDisplay( "" ); + if ( !xinfo.display ) { + error( "Can't open display." ); + } + + /* + * Find out some things about the display you're using. + */ + // DefaultScreen is as macro to get default screen index + int screen = DefaultScreen( xinfo.display ); + + unsigned long white, black; + white = XWhitePixel( xinfo.display, screen ); + black = XBlackPixel( xinfo.display, screen ); + + xinfo.window = XCreateSimpleWindow( + xinfo.display, // display where window appears + DefaultRootWindow( xinfo.display ), // window's parent in window tree + 10, 10, // upper left corner location + 300, 300, // size of the window + 5, // width of window's border + black, // window border colour + white ); // window background colour + + // extra window properties like a window title + XSetStandardProperties( + xinfo.display, // display containing the window + xinfo.window, // window whose properties are set + "clipping", // window's title + "CL", // icon's title + None, // pixmap for the icon + argv, argc, // applications command line args + None ); // size hints for the window + + /* + * Put the window on the screen. + */ + XMapRaised( xinfo.display, xinfo.window ); + + XFlush(xinfo.display); + + // give server time to setup + sleep(1); +} + +/* + * Function to repaint a display list + */ +void repaint( list<Displayable*> dList, XInfo& xinfo) { + list<Displayable*>::const_iterator begin = dList.begin(); + list<Displayable*>::const_iterator end = dList.end(); + + XClearWindow(xinfo.display, xinfo.window); + while ( begin != end ) { + Displayable* d = *begin; + d->paint(xinfo); + begin++; + } + XFlush(xinfo.display); +} + + +int main( int argc, char* argv[] ) { + + XInfo xinfo; + + initX(argc, argv, xinfo); + + // create a simple graphics context + GC gc = XCreateGC(xinfo.display, xinfo.window, 0, 0); + int screen = DefaultScreen( xinfo.display ); + XSetForeground(xinfo.display, gc, BlackPixel(xinfo.display, screen)); + XSetBackground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + + // load a larger font + XFontStruct * font; + font = XLoadQueryFont (xinfo.display, "12x24"); + XSetFont (xinfo.display, gc, font->fid); + + xinfo.gc = gc; + + // list of Displayables + list<Displayable*> dList; + + Polyline* polyline = new Polyline(0, 0); + for (int i = 0; i < 100; i++) { + polyline->add_point(rand() % 300, rand() % 300); + } + + // try changing the order or commenting out these lines + + dList.push_back(new Text(50, 50, "ABC")); + + dList.push_back(new Text(130, 100, "DEF")); + + dList.push_back(new Text(200, 200, "GHI")); + + dList.push_back(new Face(200, 200, 50, false)); + + dList.push_back(polyline); + + // paint everything in the display list + repaint(dList, xinfo); + + XFlush(xinfo.display); + + std::cout << "ENTER2exit"; std::cin.get(); // wait for input + XCloseDisplay(xinfo.display); + +} \ No newline at end of file diff --git a/x/1-4-Drawing/displaylist.cpp b/x/1-4-Drawing/displaylist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f63022dc302b60d9a9450a0f5049758e2d58ae75 --- /dev/null +++ b/x/1-4-Drawing/displaylist.cpp @@ -0,0 +1,273 @@ +/* +CS 349 Code Examples: X Windows and XLib + + displaylist Demos Displayable class and display list technique + +- - - - - - - - - - - - - - - - - - - - - - + +See associated makefile for compiling instructions + +*/ + +#include <iostream> +#include <list> +#include <cstdlib> +#include <vector> +/* + * Header files for X functions + */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include <unistd.h> // needed for sleep + +using namespace std; + +/* + * Information to draw on the window. + */ +struct XInfo { + Display* display; + Window window; + GC gc; +}; + + +/* + * An abstract class representing displayable things. + */ +class Displayable { +public: + virtual void paint(XInfo& xinfo) = 0; +}; + +/* + * A text displayable + */ +class Text : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + XDrawImageString( xinfo.display, xinfo.window, xinfo.gc, + this->x, this->y, this->s.c_str(), this->s.length() ); + } + + // constructor + Text(int x, int y, string s): x(x), y(y), s(s) {} + +private: + int x; + int y; + string s; // string to show +}; + +/* + * A displayable polyline + */ +class Polyline : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + // note the trick to pass a stl vector as an C array + XDrawLines(xinfo.display, xinfo.window, xinfo.gc, + &points[0], points.size(), // vector of points + CoordModeOrigin ); // use absolute coordinates + } + + // constructor + Polyline(int x, int y) { + add_point(x, y); + } + + // add another point to the line + void add_point(int x, int y) { + XPoint p; // XPoint is a built in struct + p.x = x; + p.y = y; + points.push_back(p); + } + +private: + // need to use a vector to dynamically add points + vector < XPoint > points; // XPoint is a built in struct +}; + + + +/* + * A face displayable + */ +class Face : public Displayable { +public: + virtual void paint(XInfo& xinfo) { + + // create a simple graphics context + GC gc = XCreateGC(xinfo.display, xinfo.window, 0, 0); + int screen = DefaultScreen( xinfo.display ); + XSetForeground(xinfo.display, gc, BlackPixel(xinfo.display, screen)); + XSetBackground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + XSetFillStyle(xinfo.display, gc, FillSolid); + XSetLineAttributes(xinfo.display, gc, + 3, // 3 is line width + LineSolid, CapButt, JoinRound); // other line options + + + // draw head + XFillArc(xinfo.display, xinfo.window, gc, + x - (d / 2), y - (d / 2), d, d, 0, 360 * 64); + + XSetForeground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + + // draw mouth either smiling or serious + if (smile) { + int dd = d / 2; + XDrawArc(xinfo.display, xinfo.window, gc, + x - (dd / 2), y - (dd / 2), dd, dd, 210 * 64, 120 * 64); + } else { + int dd = d / 3; + XDrawLine(xinfo.display, xinfo.window, gc, + x - dd, y + dd / 2, x + dd, y + dd / 2); + } + } + + // constructor + Face(int x, int y, int d, bool smile): x(x), y(y), d(d), smile(smile) {} + +private: + int x; + int y; + int d; // diameter + bool smile; // is smiling +}; + + + +/* + * Function to put out a message on error exits. + */ +void error( string str ) { + cerr << str << endl; + exit(0); +} + + +/* + * Create a window + */ +void initX(int argc, char* argv[], XInfo& xinfo) { + + + /* + * Display opening uses the DISPLAY environment variable. + * It can go wrong if DISPLAY isn't set, or you don't have permission. + */ + xinfo.display = XOpenDisplay( "" ); + if ( !xinfo.display ) { + error( "Can't open display." ); + } + + /* + * Find out some things about the display you're using. + */ + // DefaultScreen is as macro to get default screen index + int screen = DefaultScreen( xinfo.display ); + + unsigned long white, black; + white = XWhitePixel( xinfo.display, screen ); + black = XBlackPixel( xinfo.display, screen ); + + xinfo.window = XCreateSimpleWindow( + xinfo.display, // display where window appears + DefaultRootWindow( xinfo.display ), // window's parent in window tree + 10, 10, // upper left corner location + 300, 300, // size of the window + 5, // width of window's border + black, // window border colour + white ); // window background colour + + // extra window properties like a window title + XSetStandardProperties( + xinfo.display, // display containing the window + xinfo.window, // window whose properties are set + "displaylist", // window's title + "DL", // icon's title + None, // pixmap for the icon + argv, argc, // applications command line args + None ); // size hints for the window + + /* + * Put the window on the screen. + */ + XMapRaised( xinfo.display, xinfo.window ); + + XFlush(xinfo.display); + + // give server time to setup + sleep(1); +} + +/* + * Function to repaint a display list + */ +void repaint( list<Displayable*> dList, XInfo& xinfo) { + list<Displayable*>::const_iterator begin = dList.begin(); + list<Displayable*>::const_iterator end = dList.end(); + + XClearWindow(xinfo.display, xinfo.window); + while ( begin != end ) { + Displayable* d = *begin; + d->paint(xinfo); + begin++; + } + XFlush(xinfo.display); +} + + +int main( int argc, char* argv[] ) { + + XInfo xinfo; + + initX(argc, argv, xinfo); + + // create a simple graphics context + GC gc = XCreateGC(xinfo.display, xinfo.window, 0, 0); + int screen = DefaultScreen( xinfo.display ); + XSetForeground(xinfo.display, gc, BlackPixel(xinfo.display, screen)); + XSetBackground(xinfo.display, gc, WhitePixel(xinfo.display, screen)); + + // load a larger font + XFontStruct * font; + font = XLoadQueryFont (xinfo.display, "12x24"); + XSetFont (xinfo.display, gc, font->fid); + + xinfo.gc = gc; + + // list of Displayables + list<Displayable*> dList; + + Polyline* polyline = new Polyline(0, 0); + for (int i = 0; i < 100; i++) { + polyline->add_point(rand() % 300, rand() % 300); + } + + // try changing the order or commenting out these lines + + + dList.push_back(new Text(50, 50, "ABC")); + + dList.push_back(new Text(130, 100, "DEF")); + + dList.push_back(new Text(200, 200, "GHI")); + + dList.push_back(new Face(200, 200, 50, false)); + + dList.push_back(polyline); + + + // paint everything in the display list + repaint(dList, xinfo); + + XFlush(xinfo.display); + + std::cout << "ENTER2exit"; std::cin.get(); // wait for input + XCloseDisplay(xinfo.display); + +} \ No newline at end of file diff --git a/x/1-4-Drawing/drawing.cpp b/x/1-4-Drawing/drawing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..987d86a55b6bfde26092655cdf98fbe2725b90cf --- /dev/null +++ b/x/1-4-Drawing/drawing.cpp @@ -0,0 +1,200 @@ +/* +CS 349 Code Examples: X Windows and XLib + + drawing Demos drawing functions and graphics contexts + +- - - - - - - - - - - - - - - - - - - - - - + +See associated makefile for compiling instructions + +*/ + +#include <iostream> +#include <list> +#include <cstdlib> +#include <unistd.h> + +// Header files for X functions +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +using namespace std; + +// handy struct to save display, window, and screen +struct XInfo { + Display *display; + int screen; + Window window; +}; + +// Function to put out a message on error and exits +void error( string str ) { + cerr << str << endl; + exit(0); +} + +void drawRectanglesInCorners(XInfo &xinfo, GC gc) { + Display *display = xinfo.display; + Window win = xinfo.window; + + XWindowAttributes windowInfo; + XGetWindowAttributes(display, win, &windowInfo); + // max x and y coordinate + unsigned int maxHeight = windowInfo.height - 1; + unsigned int maxWidth = windowInfo.width - 1; + + // draw rectangles in each corner of the window + int s = 32; // rectangle size + XDrawRectangle(display, win, gc, 0, 0, s, s); // top left + XDrawRectangle(display, win, gc, 0, maxHeight - s, s, s); // bottom left + XDrawRectangle(display, win, gc, maxWidth - s, 0, s, s); // top right + XDrawRectangle(display, win, gc, maxWidth - s, maxHeight - s, s, s); // bottom right +} + +void drawStuff(XInfo &xinfo, GC gc, int x, int y) { + Display *display = xinfo.display; + Window win = xinfo.window; + + // draw two intersecting lines, one horizontal and one vertical, + // which intersect at point "x,y". + XDrawLine(display, win, gc, x, y - 30, x, y + 200); + XDrawLine(display, win, gc, x - 30, y, x + 200, y); + + // now use the XDrawArc() function to draw a circle whose diameter + // is 30 pixels, and whose center is at location 'x,y'. + XDrawArc(display, win, gc, x - (30 / 2), y - (30 / 2), 30, 30, 0, 360 * 64); + + // draw a small triangle at the top-left corner of the window. + // the triangle is made of a set of consecutive lines, whose + // end-point pixels are specified in the 'points' array. + { + XPoint points[] = { + {x + 200, y + 50}, + {x + 250, y + 80}, + {x + 200, y + 80}, + {x + 200, y + 50} + }; + int npoints = sizeof(points) / sizeof(XPoint); + + XDrawLines(display, win, gc, points, npoints, CoordModeOrigin); + } + + // draw a rectangle whose top-left corner is at 'x+120,y+50', its width is + // 50 pixels, and height is 60 pixels. + XDrawRectangle(display, win, gc, x + 120, y + 50, 50, 60); + + // draw a filled rectangle of the same size as above, to the left of the + // previous rectangle. + XFillRectangle(display, win, gc, x + 60, y + 50, 50, 60); +} + + +// Initialize X and create a window +void initX(int argc, char *argv[], XInfo &xinfo) { + + XSizeHints hints; + unsigned long white, black; + + + // Display opening uses the DISPLAY environment variable. + // It can go wrong if DISPLAY isn't set, or you don't have permission. + xinfo.display = XOpenDisplay( "" ); + if ( !xinfo.display ) { + error( "Can't open display." ); + } + + // Find out some things about the display you're using. + xinfo.screen = DefaultScreen( xinfo.display ); + + white = XWhitePixel( xinfo.display, xinfo.screen ); + black = XBlackPixel( xinfo.display, xinfo.screen ); + + hints.x = 100; + hints.y = 100; + hints.width = 600; + hints.height = 600; + hints.flags = PPosition | PSize; + + xinfo.window = XCreateSimpleWindow( + xinfo.display, // display where window appears + DefaultRootWindow( xinfo.display ), // window's parent in window tree + hints.x, hints.y, // upper left corner location + hints.width, hints.height, // size of the window + 5, // width of window's border + black, // window border colour + white ); // window background colour + + XSetStandardProperties( + xinfo.display, // display containing the window + xinfo.window, // window whose properties are set + "drawing", // window's title + "SD", // icon's title + None, // pixmap for the icon + argv, argc, // applications command line args + &hints ); // size hints for the window + + // Put the window on the screen. + XMapRaised( xinfo.display, xinfo.window ); + + XFlush(xinfo.display); + + // give server time to setup before sending drawing commands + sleep(1); +} + + + +/* + * Start executing here. + * First initialize window. + * Next loop responding to events. + * Exit forcing window manager to clean up - cheesy, but easy. + */ +int main ( int argc, char *argv[] ) { + XInfo xinfo; + + initX(argc, argv, xinfo); + + // an array of graphics contexts to demo + GC gc[3]; + + // Create 3 Graphics Contexts + int i = 0; + gc[i] = XCreateGC(xinfo.display, xinfo.window, 0, 0); + XSetForeground(xinfo.display, gc[i], BlackPixel(xinfo.display, xinfo.screen)); + XSetBackground(xinfo.display, gc[i], WhitePixel(xinfo.display, xinfo.screen)); + XSetFillStyle(xinfo.display, gc[i], FillSolid); + XSetLineAttributes(xinfo.display, gc[i], + 1, LineSolid, CapButt, JoinRound); + + i = 1; + gc[i] = XCreateGC(xinfo.display, xinfo.window, 0, 0); + XSetForeground(xinfo.display, gc[i], BlackPixel(xinfo.display, xinfo.screen)); + XSetBackground(xinfo.display, gc[i], WhitePixel(xinfo.display, xinfo.screen)); + XSetFillStyle(xinfo.display, gc[i], FillSolid); + XSetLineAttributes(xinfo.display, gc[i], + 7, LineSolid, CapRound, JoinMiter); + + i = 2; + gc[i] = XCreateGC(xinfo.display, xinfo.window, 0, 0); + XSetForeground(xinfo.display, gc[i], BlackPixel(xinfo.display, xinfo.screen)); + XSetBackground(xinfo.display, gc[i], WhitePixel(xinfo.display, xinfo.screen)); + XSetFillStyle(xinfo.display, gc[i], FillSolid); + XSetLineAttributes(xinfo.display, gc[i], + 7, LineOnOffDash, CapButt, JoinBevel); + + // make the drawing + drawRectanglesInCorners(xinfo, gc[1]); + drawStuff(xinfo, gc[0], 50, 50); + drawStuff(xinfo, gc[1], 150, 200); + drawStuff(xinfo, gc[2], 250, 350); + + // flush all pending requests to the X server. + XFlush(xinfo.display); + + // wait for user input to quit + cout << "press ENTER to exit"; + cin.get(); + + XCloseDisplay(xinfo.display); +} diff --git a/x/1-4-Drawing/drawing.min b/x/1-4-Drawing/drawing.min new file mode 100755 index 0000000000000000000000000000000000000000..50f17210e879890e38db6181cca7c3708080352c Binary files /dev/null and b/x/1-4-Drawing/drawing.min differ diff --git a/x/1-4-Drawing/drawing.min.cpp b/x/1-4-Drawing/drawing.min.cpp new file mode 100644 index 0000000000000000000000000000000000000000..255e21a0c72cc4a38564ce1d0688d0715fc573c7 --- /dev/null +++ b/x/1-4-Drawing/drawing.min.cpp @@ -0,0 +1,59 @@ +/* +CS 349 Code Examples: X Windows and XLib + + drawing.min Demos drawing and graphics context (minimal version). + +- - - - - - - - - - - - - - - - - - - - - - + +See associated makefile for compiling instructions + +*/ + +#include <cstdlib> +#include <iostream> +#include <X11/Xlib.h> + +#include <unistd.h> // needed for sleep + +Display* display; +Window window; + +int main( int argc, char* argv[] ) { + // see openwindow.min for the setup code ... + display = XOpenDisplay(""); + if (!display) exit (-1); + int screen = XDefaultScreen(display); + int w = 300; + int h = 300; + window = XCreateSimpleWindow(display, + DefaultRootWindow(display), + 10, 10, w, h, 2, + XBlackPixel(display, screen), + XWhitePixel(display, screen)); + XMapRaised(display, window); + XFlush(display); + + // give server 10ms to get set up before sending drawing commands + usleep(10 * 1000); + + + // drawing demo with graphics context here ... + GC gc = XCreateGC(display, window, 0, 0); // create a graphics context + XSetForeground(display, gc, XBlackPixel(display, screen)); + XSetBackground(display, gc, XWhitePixel(display, screen)); + XSetFillStyle(display, gc, FillSolid); + XSetLineAttributes(display, gc, + 3, // 3 is line width + LineSolid, CapButt, JoinRound); // other line options + + // draw some things + XDrawLine(display, window, gc, 10, 10, w - 10, h - 10); + XFillRectangle(display, window, gc, 50, 50, w - (2 * 50), h - (2 * 50)); + XSetForeground(display, gc, XWhitePixel(display, screen)); + XDrawLine(display, window, gc, w - 10, 10, 10, h - 10); + + XFlush(display); + + std::cout << "ENTER2exit"; std::cin.get(); // wait for input + XCloseDisplay(display); +} diff --git a/x/1-4-Drawing/makefile b/x/1-4-Drawing/makefile new file mode 100644 index 0000000000000000000000000000000000000000..4db1c15900ae8640a774804730ee0a8e6860cc4a --- /dev/null +++ b/x/1-4-Drawing/makefile @@ -0,0 +1,19 @@ +# super simple makefile +# call it using 'make NAME=name_of_code_file_without_extension' +# (assumes a .cpp extension) +NAME = "drawing.min" + +# Add $(MAC_OPT) to the compile line for macOS +# (should be ignored by Linux, set to nothing if causing problems) +MAC_OPT = -I/opt/X11/include + +all: + @echo "Compiling..." + g++ -o $(NAME) $(NAME).cpp -L/opt/X11/lib -lX11 -lstdc++ $(MAC_OPT) + +run: all + @echo "Running..." + ./$(NAME) + +clean: + -rm *o