void GraphicsContext::rotate(float angle) { if (paintingDisabled()) return; CGContextRotateCTM(platformContext(), angle); m_data->rotate(angle); }
static double Quartz_StrWidth(char *str, R_GE_gcontext *gc, NewDevDesc *dd) { QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific; CGPoint position; CGContextSaveGState( GetContext(xd) ); CGContextTranslateCTM( GetContext(xd), 0, 0 ); CGContextScaleCTM( GetContext(xd), -1, 1); CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416); CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible ); Quartz_SetFont(gc->fontfamily, gc->fontface, gc->cex, gc->ps, dd); CGContextShowTextAtPoint( GetContext(xd), 0, 0, str, strlen(str) ); position = CGContextGetTextPosition( GetContext(xd) ); CGContextRestoreGState( GetContext(xd) ); return(position.x); }
void GraphicsContext::rotate(float angle) { if (paintingDisabled()) return; CGContextRotateCTM(platformContext(), angle); m_data->rotate(angle); m_data->m_userToDeviceTransformKnownToBeIdentity = false; }
//----------------------------------------------------------------------------- static void addOvalToPath (CGContextRef c, CPoint center, CGFloat a, CGFloat b, CGFloat start_angle, CGFloat end_angle) { CGContextSaveGState (c); CGContextTranslateCTM (c, center.x, center.y); CGContextScaleCTM (c, a, b); CGContextRotateCTM (c, radians (-90.f)); CGContextMoveToPoint (c, cos (radians (start_angle)), sin (radians (start_angle))); CGContextAddArc(c, 0, 0, 1, radians (start_angle), radians (end_angle), 1); CGContextRestoreGState(c); }
DISABLED_DRAW_TEST_F(CGContext, ShadowWithRotatedCTM, WhiteBackgroundTest) { CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); CGContextSetLineWidth(context, 5); CGContextSetShadow(context, CGSize{ 10.f, 10.f }, 1.0); CGPoint center = _CGRectGetCenter(bounds); CGRect rect = _CGRectCenteredOnPoint({ 150, 150 }, center); CGPoint rectCenter = _CGRectGetCenter(rect); CGContextTranslateCTM(context, rectCenter.x, rectCenter.y); CGContextRotateCTM(context, 15.f * M_PI / 180.f); CGContextTranslateCTM(context, -rectCenter.x, -rectCenter.y); CGContextStrokeRect(context, rect); }
/* Draw the source PDF document into the context and then draw the stamp PDF document on top of it. When drawing the stamp on top, place it along the diagonal from the lower left corner to the upper right corner and center its media rect to the center of that diagonal. */ void StampWithPDFDocument(CGContextRef context, CGPDFDocumentRef sourcePDFDoc, CGPDFDocumentRef stampFileDoc, CGRect stampMediaRect) { CGRect pageRect; float angle; size_t i, numPages = CGPDFDocumentGetNumberOfPages(sourcePDFDoc); // Loop over document pages and stamp each one appropriately. for(i = 1 ; i <= numPages ; i++) { // Use the page rectangle of each page from the source to compute // the destination media box for each page and the location of // the stamp. CGRect pageRect = CGPDFDocumentGetMediaBox(sourcePDFDoc, i); CGContextBeginPage(context, &pageRect); CGContextSaveGState(context); // Clip to the media box of the page. CGContextClipToRect(context, pageRect); // First draw the content of the source document. CGContextDrawPDFDocument(context, pageRect, sourcePDFDoc, i); // Translate to center of destination rect, that is the center of // the media box of content to draw on top of. CGContextTranslateCTM(context, pageRect.size.width/2, pageRect.size.height/2); // Compute angle of the diagonal across the destination page. angle = atan(pageRect.size.height/pageRect.size.width); // Rotate by an amount so that drawn content goes along a diagonal // axis across the page. CGContextRotateCTM(context, angle); // Move the origin so that the media box of the PDF to stamp // is centered around center point of destination. CGContextTranslateCTM(context, -stampMediaRect.size.width/2, -stampMediaRect.size.height/2); // Now draw the document to stamp with on top of original content. CGContextDrawPDFDocument(context, stampMediaRect, stampFileDoc, 1); CGContextRestoreGState(context); CGContextEndPage(context); } }
void PDFDocumentImage::adjustCTM(GraphicsContext* context) const { // rotate the crop box and calculate bounding box float sina = sinf(-m_rotation); float cosa = cosf(-m_rotation); float width = m_cropBox.width(); float height = m_cropBox.height(); // calculate rotated x and y edges of the corp box. if they're negative, it means part of the image has // been rotated outside of the bounds and we need to shift over the image so it lies inside the bounds again CGPoint rx = CGPointMake(width * cosa, width * sina); CGPoint ry = CGPointMake(-height * sina, height * cosa); // adjust so we are at the crop box origin const CGFloat zero = 0; CGContextTranslateCTM(context->platformContext(), floorf(-min(zero, min(rx.x, ry.x))), floorf(-min(zero, min(rx.y, ry.y)))); // rotate -ve to remove rotation CGContextRotateCTM(context->platformContext(), -m_rotation); // shift so we are completely within media box CGContextTranslateCTM(context->platformContext(), m_mediaBox.x() - m_cropBox.x(), m_mediaBox.y() - m_cropBox.y()); }
static void quartzgen_begin_page(GVJ_t *job) { CGRect bounds = CGRectMake(0.0, 0.0, job->width, job->height); if (!job->context) { switch (job->device.id) { case FORMAT_PDF: { /* create the auxiliary info for PDF content, author and title */ CFStringRef auxiliaryKeys[] = { kCGPDFContextCreator, kCGPDFContextTitle }; CFStringRef auxiliaryValues[] = { CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s %s"), job->common->info[0], job->common->info[1]), job->obj->type == ROOTGRAPH_OBJTYPE ? CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)job->obj->u.g->name, strlen(job->obj->u.g->name), kCFStringEncodingUTF8, false, kCFAllocatorNull) : CFSTR("") }; CFDictionaryRef auxiliaryInfo = CFDictionaryCreate( kCFAllocatorDefault, (const void **)&auxiliaryKeys, (const void **)&auxiliaryValues, sizeof(auxiliaryValues)/sizeof(auxiliaryValues[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); /* create a PDF for drawing into */ CGDataConsumerRef data_consumer = CGDataConsumerCreate(job, &device_data_consumer_callbacks); job->context = CGPDFContextCreate(data_consumer, &bounds, auxiliaryInfo); /* clean up */ CGDataConsumerRelease(data_consumer); CFRelease(auxiliaryInfo); int i; for (i = 0; i < sizeof(auxiliaryValues)/sizeof(auxiliaryValues[0]); ++i) CFRelease(auxiliaryValues[i]); } break; default: /* bitmap formats */ { size_t bytes_per_row = (job->width * BYTES_PER_PIXEL + BYTE_ALIGN) & ~BYTE_ALIGN; void* buffer = NULL; #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 /* iPhoneOS has no swap files for memory, so if we're short of memory we need to make our own temp scratch file to back it */ size_t buffer_size = job->height * bytes_per_row; mach_msg_type_number_t vm_info_size = HOST_VM_INFO_COUNT; vm_statistics_data_t vm_info; if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &vm_info_size) != KERN_SUCCESS || buffer_size * 2 > vm_info.free_count * vm_page_size) { FILE* temp_file = tmpfile(); if (temp_file) { int temp_file_descriptor = fileno(temp_file); if (temp_file_descriptor >= 0 && ftruncate(temp_file_descriptor, buffer_size) == 0) { buffer = mmap( NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, temp_file_descriptor, 0); if (buffer == (void*)-1) buffer = NULL; } fclose(temp_file); } } if (!buffer) buffer = mmap( NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_ANON| MAP_SHARED, -1, 0); #endif /* create a true color bitmap for drawing into */ CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); job->context = CGBitmapContextCreate( buffer, /* data: MacOSX lets system allocate, iPhoneOS use manual memory mapping */ job->width, /* width in pixels */ job->height, /* height in pixels */ BITS_PER_COMPONENT, /* bits per component */ bytes_per_row, /* bytes per row: align to 16 byte boundary */ color_space, /* color space: device RGB */ kCGImageAlphaPremultipliedFirst /* bitmap info: premul ARGB has best support in OS X */ ); job->imagedata = CGBitmapContextGetData((CGContextRef)job->context); /* clean up */ CGColorSpaceRelease(color_space); } break; } } /* start the page (if this is a paged context) and graphics state */ CGContextRef context = (CGContextRef)job->context; CGContextBeginPage(context, &bounds); CGContextSaveGState(context); CGContextSetMiterLimit(context, 1.0); CGContextSetLineJoin(context, kCGLineJoinRound); /* set up the context transformation */ CGContextScaleCTM(context, job->scale.x, job->scale.y); CGContextRotateCTM(context, -job->rotation * M_PI / 180.0); CGContextTranslateCTM(context, job->translation.x, job->translation.y); }
void doClippedEllipse(CGContextRef context) { CGPoint theCenterPoint = { 120., 120. }; CGSize theEllipseSize = { 100., 200. }; float dash[1] = { 2 }; static CGColorRef opaqueBrownColor = NULL, opaqueOrangeColor = NULL; // Initialize the CGColorRefs if necessary. if(opaqueBrownColor == NULL){ // The initial value of the color array is an // opaque brown in an RGB color space. float color[4] = { 0.325, 0.208, 0.157, 1.0 }; CGColorSpaceRef theColorSpace = getTheCalibratedRGBColorSpace(); // Create a CGColorRef for opaque brown. opaqueBrownColor = CGColorCreate(theColorSpace, color); // Make the color array correspond to an opaque orange. color[0] = 0.965 ; color[1] = 0.584; color[2] = 0.059; // Create another CGColorRef for opaque orange. opaqueOrangeColor = CGColorCreate(theColorSpace, color); } // Draw two ellipses centered about the same point, one // rotated 45 degrees from the other. CGContextSaveGState(context); // Ellipse 1 createEllipsePath(context, theCenterPoint, theEllipseSize); CGContextSetFillColorWithColor(context, opaqueBrownColor); CGContextFillPath(context); // Translate and rotate about the center point of the ellipse. CGContextTranslateCTM(context, theCenterPoint.x, theCenterPoint.y); // Rotate by 45 degrees. CGContextRotateCTM(context, DEGREES_TO_RADIANS(45)); // Ellipse 2 // CGPointZero is a pre-defined Quartz point corresponding to // the coordinate (0,0). createEllipsePath(context, CGPointZero, theEllipseSize); CGContextSetFillColorWithColor(context, opaqueOrangeColor); CGContextFillPath(context); CGContextRestoreGState(context); CGContextTranslateCTM(context, 170., 0.); // Now use the first ellipse as a clipping area prior to // painting the second ellipse. CGContextSaveGState(context); // Ellipse 3 createEllipsePath(context, theCenterPoint, theEllipseSize); CGContextSetStrokeColorWithColor(context, opaqueBrownColor); CGContextSetLineDash(context, 0, dash, 1); // Stroke the path with a dash. CGContextStrokePath(context); // Ellipse 4 createEllipsePath(context, theCenterPoint, theEllipseSize); // Clip to the elliptical path. CGContextClip(context); CGContextTranslateCTM(context, theCenterPoint.x, theCenterPoint.y); // Rotate by 45 degrees. CGContextRotateCTM(context, DEGREES_TO_RADIANS(45)); // Ellipse 5 createEllipsePath(context, CGPointZero, theEllipseSize); CGContextSetFillColorWithColor(context, opaqueOrangeColor); CGContextFillPath(context); CGContextRestoreGState(context); }
/* OvalTeenDrawEventHandler : Handles the draw events for the "Ovalteen" window. Parameter DescriptionsinHandler : A reference to the current handler call chain. This is passed to your handler so that you can call CallNextEventHandler if you need to. inEvent : The event that triggered this call. inUserData : The application-specific data you passed in to InstallEventHandler. */ OSStatus OvalTeenDrawEventHandler (EventHandlerCallRef inHandler, EventRef inEvent, void* inUserData) { OSStatus status = eventNotHandledErr; CGContextRef context; CGRect bounds; double a, b; int count, k; //CallNextEventHandler in order to make sure the default handling of the inEvent // (drawing the white background) happens status = CallNextEventHandler( inHandler, inEvent ); require_noerr(status, CantCallNextEventHandler); // Get the CGContextRef status = GetEventParameter (inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof (CGContextRef), NULL, &context); require_noerr(status, CantGetEventParameter); // Get the bounding rectangle status = HIViewGetBounds ((HIViewRef) inUserData, &bounds); require_noerr(status, CantGetViewBounds); // Calculate the dimensions for an oval inside the bounding box a = 0.9 * bounds.size.width/4; b = 0.3 * bounds.size.height/2; count = 5; // Set the fill color to a partially transparent blue CGContextSetRGBFillColor(context, 0, 0, 1, 0.5); // Set the stroke color to an opaque black CGContextSetRGBStrokeColor(context, 0, 0, 0, 1); // Set the line width to be used, in user space units. CGContextSetLineWidth(context, 3); // Save the conexts state because we are going to be moving the origin and // rotating context for drawing, but we would like to restore the current // state before drawing the next image. CGContextSaveGState(context); // Move the origin to the middle of the first image (left side) to draw. CGContextTranslateCTM(context, bounds.size.width/4, bounds.size.height/2); // Draw "count" ovals, rotating the context around the newly translated origin // 1/count radians after drawing each oval for (k = 0; k < count; k++) { // Paint the oval with the fill color paintOval(context, CGRectMake(-a, -b, 2 * a, 2 * b)); // Frame the oval with the stroke color frameOval(context, CGRectMake(-a, -b, 2 * a, 2 * b)); // Rotate the context around the center of the image CGContextRotateCTM(context, pi / count); } // Restore the saved state to a known state for dawing the next image CGContextRestoreGState(context); // Calculate a bounding box for the rounded rect a = 0.9 * bounds.size.width/4; b = 0.3 * bounds.size.height/2; count = 5; // Set the fill color to a partially transparent red CGContextSetRGBFillColor(context, 1, 0, 0, 0.5); // Set the stroke color to an opaque black CGContextSetRGBStrokeColor(context, 0, 0, 0, 1); // Set the line width to be used, in user space units. CGContextSetLineWidth(context, 3); // Save the conexts state because we are going to be moving the origin and // rotating context for drawing, but we would like to restore the current // state before drawing the next image. CGContextSaveGState(context); // Move the origin to the middle of the second image (right side) to draw. CGContextTranslateCTM(context, bounds.size.width/4 + bounds.size.width/2, bounds.size.height/2); for (k = 0; k < count; k++) { // Fill then stroke the rounding rect, otherwise the fill would cover the stroke fillRoundedRect(context, CGRectMake(-a, -b, 2 * a, 2 * b), 20, 20); strokeRoundedRect(context, CGRectMake(-a, -b, 2 * a, 2 * b), 20, 20); // Rotate the context for the next rounded rect CGContextRotateCTM(context, pi / count); } CGContextRestoreGState(context); CantCallNextEventHandler: CantGetEventParameter: CantGetViewBounds: return status; }
static void Quartz_MetricInfo(int c, R_GE_gcontext *gc, double* ascent, double* descent, double* width, NewDevDesc *dd) { FMetricRec myFMetric; QuartzDesc *xd = (QuartzDesc *) dd-> deviceSpecific; char testo[2]; char *ff; CGrafPtr savedPort; Rect bounds; CGPoint position; unsigned char tmp; testo[0] = c; testo[1] = '\0'; /* fprintf(stderr,"c=%c,>%s<\n",c,testo); */ GetPort(&savedPort); SetPort(GetWindowPort(xd->window)); Quartz_SetFont(gc->fontfamily, gc->fontface, gc->cex, gc->ps, dd); if(c==0){ FontMetrics(&myFMetric); *ascent = xd->yscale *floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.ascent); *descent = xd->yscale*floor(gc->cex * gc->ps + 0.5) * FixedToFloat(myFMetric.descent); } else { CGContextSaveGState( GetContext(xd) ); CGContextTranslateCTM( GetContext(xd), 0, 0 ); CGContextScaleCTM( GetContext(xd), -1, 1); CGContextRotateCTM( GetContext(xd), -1.0 * 3.1416); CGContextSetTextDrawingMode( GetContext(xd), kCGTextInvisible ); Quartz_SetFont(gc->fontfamily, gc->fontface, gc->cex, gc->ps, dd); ff = Quartz_TranslateFontFamily(gc->fontfamily, gc->fontface, xd->family); tmp = (unsigned char)c; if( (gc->fontface == 5) || (strcmp(ff,"Symbol")==0)){ if( (tmp>31) && IsThisASymbol(tmp)) testo[0] = (char)Lat2Uni[tmp-31-1]; else Quartz_SetFont(gc->fontfamily, -1, gc->cex, gc->ps, dd); } else { if(tmp>127) testo[0] = (char)Lat2Mac[tmp-127-1]; } CGContextShowTextAtPoint( GetContext(xd), 0, 0, testo, 1 ); position = CGContextGetTextPosition( GetContext(xd) ); CGContextRestoreGState( GetContext(xd) ); QDTextBounds(1,testo,&bounds); *ascent = -bounds.top; *descent = bounds.bottom; *width = bounds.right - bounds.left; *width = position.x; } SetPort(savedPort); /* fprintf(stderr,"ascent=%f, descent=%f,width=%f\n",*ascent, *descent, *width); */ return; }
static void Quartz_Text(double x, double y, char *str, double rot, double hadj, R_GE_gcontext *gc, NewDevDesc *dd) { int len,i; char *buf=NULL; char *ff; char symbuf; unsigned char tmp; QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific; CGContextSaveGState( GetContext(xd) ); CGContextTranslateCTM( GetContext(xd), x, y ); CGContextScaleCTM( GetContext(xd) , -1, 1); CGContextRotateCTM( GetContext(xd) , (-1.0 + 2*rot/360) * 3.1416); Quartz_SetStroke( gc->col, gc->gamma, dd); CGContextSetTextDrawingMode( GetContext(xd), kCGTextFill ); Quartz_SetFill(gc->col, gc->gamma, dd); Quartz_SetFont(gc->fontfamily, gc->fontface, gc->cex, gc->ps, dd); len = strlen(str); ff = Quartz_TranslateFontFamily(gc->fontfamily, gc->fontface, xd->family); if( ((gc->fontface == 5) || (strcmp(ff,"Symbol")==0)) && (len==1) ){ tmp = (unsigned char)str[0]; if(tmp>31) symbuf = (char)Lat2Uni[tmp-31-1]; else symbuf = str[0]; if( !IsThisASymbol(tmp) ){ Quartz_SetFont(gc->fontfamily, -1, gc->cex, gc->ps, dd); symbuf = str[0]; } if(WeAreOnPanther) CGContextShowTextAtPoint( GetContext(xd), 0, 0, &symbuf, len ); else CGContextShowTextAtPoint( GetContext(xd), 0, 0, str, len ); } else { if( (buf = malloc(len)) != NULL){ if( strcmp(ff,"Symbol")==0){ for(i=0;i <len;i++){ tmp = (unsigned char)str[i]; if(tmp>31) buf[i] = (char)Lat2Uni[tmp-31-1]; else buf[i] = str[i]; } } else { for(i=0;i <len;i++){ tmp = (unsigned char)str[i]; if(tmp>127) buf[i] = (char)Lat2Mac[tmp-127-1]; else buf[i] = str[i]; } } CGContextShowTextAtPoint( GetContext(xd), 0, 0, buf, len ); free(buf); } } CGContextRestoreGState( GetContext(xd) ); }
void MyTimerProc ( EventLoopTimerRef inTimer, void *inUserData ) { WindowRef window = (WindowRef)inUserData; static int i = 0; static int j = 0; static int step = 5; GrafPtr curPort; CGContextRef context; CGrafPtr windowPort = GetWindowPort( window ); GetPort(&curPort); SetPort(windowPort); CreateCGContextForPort( windowPort, &context ); // Do our drawing in here CGContextSetGrayFillColor( context, 0.0, 1.0 ); CGContextFillRect( context, CGRectMake( 0, 0, 800, 600 ) ); CGContextSetGrayFillColor( context, 1.0, 1.0 ); CGContextSetRGBStrokeColor( context, 1.0, 0.0, 0.0, 1.0 ); CGContextSetLineWidth( context, 5.0 ); CGContextSetLineCap( context, kCGLineCapRound ); CGContextSetLineJoin( context, kCGLineJoinRound ); CGContextSetMiterLimit( context, 5 ); // Draw each of the 4 transform demos // // 1. Translate - move the origin, draw the graphic // Place the origin in the llh corner of the upper left quadrant CGContextSaveGState( context ); CGContextTranslateCTM( context, i / 2, i / 2 + 300 ); CGContextRotateCTM( context, -2.0 * 3.1416 / 8 ); drawGraphic( context, 0, 0 ); CGContextRestoreGState( context ); // 2. Rotate - move origin, do rotation, draw the graphic // Put the origin back into the llh corner of the upper right quadrant CGContextSaveGState( context ); if ( j < 1000/2 ) { // Rotate around left circle CGContextTranslateCTM( context, 500, 450 ); CGContextRotateCTM( context, -j * 3.1416 * 2.0 / 500.0 - 3.1416 ); CGContextTranslateCTM( context, -100, -20 ); drawGraphic( context, 0, 0 ); } if ( j >= 1000/2 ) { // Rotate under bottom half and over top right 1/4 CGContextTranslateCTM( context, 700, 450 ); CGContextRotateCTM( context, j * 3.1416 * 2.0 / 500.0 ); CGContextScaleCTM( context, 1, 1 ); CGContextTranslateCTM( context, -100, 20 ); CGContextRotateCTM( context, 3.1416 ); drawGraphic( context, 0, 0 ); } CGContextRestoreGState( context ); // 3. Scale - move origin, set scale, draw the graphic CGContextSaveGState( context ); CGContextScaleCTM( context, i * 400.0 / 500.0 / 40.0, i * 300.0 / 500.0 / 40.0 ); CGContextRotateCTM( context, -3.1416 / 4 ); drawGraphic( context, 0, 0 ); CGContextRestoreGState( context ); // 4. Show the basic graphic CGContextTranslateCTM( context, 600, 150 ); drawGraphic( context, 0, 0 ); CGContextFlush( context ); CGContextRelease( context ); SetPort ( curPort ); i += step; j += abs( step ); if ( i >= 500 ) { step = -step; } if ( i <= 0 ) { step = -step; j = 0; } }