#include #include #include static OSStatus DrawHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData); static void Heartbeat(EventLoopTimerRef inTimer, void *inRefCon); static CGImageRef GetCGImageFromPath(CFStringRef inPath); void JustDrawSomething(CGContextRef cg, CGRect *bounds); static void createpdf(void) { CGContextRef pdfcg; CFStringRef path; CFURLRef url; CGRect solbounds = {0, 0, 800, 800}; CGRect artbounds = {-5, -5, 810, 810}; path = CFStringCreateWithCString(NULL, "LeWitt.pdf", kCFStringEncodingUTF8); url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0); CFRelease(path); pdfcg = CGPDFContextCreateWithURL(url, &artbounds, NULL); CFRelease(url); CGContextBeginPage(pdfcg, &artbounds); JustDrawSomething(pdfcg, &solbounds); CGContextEndPage(pdfcg); CGContextRelease(pdfcg); } int main(void) { IBNibRef nibRef; WindowRef window; EventTypeSpec type; HIViewRef contentView; CreateNibReference(CFSTR("main"), &nibRef); SetMenuBarFromNib(nibRef, CFSTR("MenuBar")); CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window); HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &contentView); type.eventClass = kEventClassControl; type.eventKind = kEventControlDraw; InstallEventHandler(HIViewGetEventTarget(contentView), DrawHandler, 1, &type, contentView, NULL); // InstallEventLoopTimer(GetCurrentEventLoop(), 1.0, 1.0, Heartbeat, contentView, NULL); createpdf(); ShowWindow(window); RunApplicationEventLoop(); return 0; } #define EACH_LINE_DRAW_TIME 70 #define OPEC .02 #define WIDTH 40 #define FOUR_HOUR_SECS (4 * 60 * 60) //paint a rectangle (a line...) in the appropriate square: void paint(CGContextRef cg, int square, int draftsman) { CGRect verysparsemarker; int originX, originY, height; float red, green, blue, alpha; do { originX = rand() % 400; originY = rand() % 400; height = rand() % 400; } while ((originY + height >= 400) || (originX + WIDTH >= 400)); switch (draftsman) { case 1: red = 1; blue = 0; green = 0; alpha = OPEC; break; case 2: red = 0; blue = 1; green = 0; alpha = OPEC; break; case 3: red = 1; blue = 0; green = 1; alpha = OPEC; break; case 4: red = 0; blue = 0; green = 0; alpha = OPEC; break; } CGContextSetRGBFillColor(cg, red, green, blue, alpha); switch (square) { case 1: verysparsemarker = CGRectMake(originX, originY, WIDTH, height); break; case 2: verysparsemarker = CGRectMake(originX+400, originY, WIDTH, height); break; case 3: verysparsemarker = CGRectMake(originX, originY+400, WIDTH, height); break; case 4: verysparsemarker = CGRectMake(originX+400, originY+400, WIDTH, height); break; } CGContextFillRect(cg, verysparsemarker); } //thank you forrest for being so smart and nice: int whichSquare(int draftsman, int day){ if (day == 1) return draftsman; if (day == 2){ if (draftsman == 1) return 2; if (draftsman == 2) return 3; if (draftsman == 3) return 4; if (draftsman == 4) return 1; } if (day == 3){ if (draftsman == 1) return 3; if (draftsman == 2) return 4; if (draftsman == 3) return 1; if (draftsman == 4) return 2; } if (day == 4){ if (draftsman == 1) return 4; if (draftsman == 2) return 1; if (draftsman == 3) return 2; if (draftsman == 4) return 3; } return 0; } //setup the four squares, colorspace, etc...: void JustDrawSomething(CGContextRef cg, CGRect *bounds) { CGRect square[4]; CGRect frame; static int first_time = TRUE; if(first_time) { first_time = FALSE; srand((unsigned)time(NULL)); } CGContextSetLineWidth(cg, 1); #if 0 // to add frame frame.origin.x = bounds->origin.x - 1; frame.origin.y = bounds->origin.y - 1; frame.size.width = bounds->size.width + 2; frame.size.height = bounds->size.height + 2; CGContextAddRect(cg, frame); CGContextStrokePath(cg); #endif square[0] = CGRectMake(0, 0, 400, 400); square[1] = CGRectMake(400, 400, 400, 400); square[2] = CGRectMake(0, 400, 400, 400); square[3] = CGRectMake(400, 0, 400, 400); CGContextAddRect(cg, square[0]); CGContextAddRect(cg, square[1]); CGContextAddRect(cg, square[2]); CGContextAddRect(cg, square[3]); //CGContextStrokePath(cg); int day, sec, draftsman; int blah; // The four draftsmen work for four days. for (day = 1; day <= 4; day++) { // Every day, each draftsman will work for four hours for (sec = 1; sec <= FOUR_HOUR_SECS; sec+=EACH_LINE_DRAW_TIME) { //how long it takes to draw one line // Every second, each draftsman will make one mark. for (draftsman = 1; draftsman <= 4; draftsman++) { blah = whichSquare(draftsman, day); paint(cg, draftsman, blah); // Remember, each draftsman uses the same color throughout the entire program. // Remember, each draftsman draws on a different square each day, so for example // draftsman #1 draws in the upper left on the first day, the upper right on the // second day, the lower left on the third day and the lower right on the fourth // day (this order is just an example, you can use whatever order you'd like). // You use the 'day' variable to determine where the draftsmen should be working. // More difficult than it seems: drawing a 40 pixel line at a random angle, and // making sure it doesn't extend outside the square. // Suggestions: // Make a function for a draftsman. // Make a function that generates the endpoints of a line. // Make functions whenever you want to encapsulate some behavior or knowledge, // e.g.: // Given a draftsman (1 to 4), return the draftman's color. // Given a draftsman and a day, return the square he should be drawing in. } } } } // For extra credit, figure out how much the draftsmen are getting paid. #if 0 static void Heartbeat(EventLoopTimerRef inTimer, void *inRefCon) { theView = (HIViewRef)inUserData; } #endif static OSStatus DrawHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { HIViewRef theView; CGContextRef cg; CGRect viewBounds; theView = (HIViewRef)inUserData; GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &cg); CallNextEventHandler(inHandlerCallRef, inEvent); HIViewGetBounds(theView, &viewBounds); CGContextTranslateCTM(cg, 0, viewBounds.size.height); CGContextScaleCTM(cg, 1.0, -1.0); CGRect bounds = {0, 0, 800, 800}; JustDrawSomething(cg, &bounds); return 0; } static CGImageRef GetCGImageFromPath(CFStringRef inPath) { CGImageRef imageRef; Handle dataRef; OSType dataRefType; GraphicsImportComponent gi; ComponentResult result; dataRef = NULL; gi = 0; // create the data reference result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); if (dataRef == NULL || result != 0) exit(1); // get the graphics importer for the data ref GetGraphicsImporterForDataRefWithFlags(dataRef, dataRefType, &gi, 0); if (gi == NULL) exit(1); GraphicsImportCreateCGImage(gi, &imageRef, 0); if (imageRef == NULL) exit(1); CloseComponent(gi); DisposeHandle(dataRef); return imageRef; }