int setterraincolor(CGContextRef context, BoloTerrainTypes tile) { switch (tile) { case kWallTile: /* wall */ CGContextSetFillColorWithColor(context, myGetBrownColor()); return 0; case kRiverTile: /* river */ CGContextSetFillColorWithColor(context, myGetCyanColor()); return 0; case kSwampTile: /* swamp */ case kMinedSwampTile: /* mined swamp */ CGContextSetFillColorWithColor(context, myGetDarkCyanColor()); return 0; case kCraterTile: /* crater */ case kMinedCraterTile: /* mined crater */ CGContextSetFillColorWithColor(context, myGetDarkBrownColor()); return 0; case kRoadTile: /* road */ case kMinedRoadTile: /* mined road */ CGContextSetFillColorWithColor(context, myGetBlackColor()); return 0; case kForestTile: /* forest */ case kMinedForestTile: /* mined forest */ CGContextSetFillColorWithColor(context, myGetDarkGreenColor()); return 0; case kRubbleTile: /* rubble */ case kMinedRubbleTile: /* mined rubble */ CGContextSetFillColorWithColor(context, myGetVeryLightBrownColor()); return 0; case kGrassTile: /* grass */ case kMinedGrassTile: /* mined grass */ CGContextSetFillColorWithColor(context, myGetGreenColor()); return 0; case kDamagedWallTile: /* damaged wall */ CGContextSetFillColorWithColor(context, myGetLightBrownColor()); return 0; case kBoatTile: /* river w/boat */ CGContextSetFillColorWithColor(context, myGetDarkBlueColor()); return 0; default: return -1; } }
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) { // load the actual file CFDataRef fileData = nil; CFDictionaryRef propertyDictionary = nil; SInt32 errorCode; if (CFURLCreateDataAndPropertiesFromResource(NULL, url, &fileData, &propertyDictionary, nil, &errorCode)) { CFIndex dataLength = CFDataGetLength(fileData); UInt8 *bytes = (UInt8 *)CFDataGetBytePtr(fileData); long pages = dataLength / ONE_LCD_FRAME_BYTESIZE; CGSize lcdSize = CGSizeMake(LCD_FRAME_PIXEL_WIDTH, LCD_FRAME_PIXEL_HEIGHT * pages); CGContextRef cgContext = QLThumbnailRequestCreateContext(thumbnail, lcdSize, true, NULL); if(cgContext) { CGColorRef lcdForegroundColor = CGColorCreateGenericRGB(0.467, 0.522, 0.047, 1.000); CGColorRef lcdBackgroundColor = CGColorCreateGenericRGB(0.227, 0.192, 0.000, 1.000); CGContextSetFillColorWithColor(cgContext, lcdBackgroundColor); CGContextFillRect(cgContext, CGRectMake(0,0,lcdSize.width,lcdSize.height)); CGPoint origin = CGPointMake(0,0); while (pages-- > 0) { CGContextSetFillColorWithColor(cgContext, lcdForegroundColor); // CGContextFillRect(cgContext, CGRectMake(origin.x,origin.y,10,10)); for (int y=0;y<9;y++) { for (int x=0; x < LCD_FRAME_PIXEL_WIDTH; x++) { UInt8 byte = bytes[y*LCD_FRAME_PIXEL_WIDTH + (LCD_FRAME_PIXEL_WIDTH - x - 1)]; if (byte > 0) { UInt8 byteMask = 1; for (int littleY = 0; littleY < 8; littleY++) { if ((byte & (byteMask << littleY))) { CGContextFillRect(cgContext, CGRectMake(origin.x + x,origin.y + y*8 + littleY,1,1)); } } } } } origin.y += 68; bytes += ONE_LCD_FRAME_BYTESIZE; } // When we are done with our drawing code QLPreviewRequestFlushContext() is called to flush the context QLThumbnailRequestFlushContext(thumbnail, cgContext); } CFRelease(cgContext); CFRelease(fileData); CFRelease(propertyDictionary); } return noErr; }
void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor) { char text[16]; // that's a lot of repaints snprintf(text, sizeof(text), "%d", repaintCount); CGRect indicatorBox = platformCALayer->bounds(); indicatorBox.size.width = 12 + 10 * strlen(text); indicatorBox.size.height = 27; CGContextSaveGState(context); CGContextSetAlpha(context, 0.5f); CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0); if (customBackgroundColor) CGContextSetFillColorWithColor(context, customBackgroundColor); else CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1); CGContextFillRect(context, indicatorBox); if (platformCALayer->acceleratesDrawing()) CGContextSetRGBFillColor(context, 1, 0, 0, 1); else CGContextSetRGBFillColor(context, 1, 1, 1, 1); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1, -1)); CGContextSelectFont(context, "Helvetica", 22, kCGEncodingMacRoman); CGContextShowTextAtPoint(context, indicatorBox.origin.x + 5, indicatorBox.origin.y + 22, text, strlen(text)); #pragma clang diagnostic pop CGContextEndTransparencyLayer(context); CGContextRestoreGState(context); }
static CGLayerRef createCGLayerForDrawing(CGContextRef c) { CGRect rect = { 0, 0, 50, 50 }; CGSize layerSize; CGLayerRef layer; // Make the layer the size of the rectangle that // this code draws into the layer. layerSize.width = rect.size.width; layerSize.height = rect.size.height; // Create the layer to draw into. layer = CGLayerCreateWithContext(c, layerSize, NULL); if(layer == NULL) return NULL; // Get the context corresponding to the layer. Note // that this is a 'Get' function so the code must // not release the context. CGContextRef layerContext = CGLayerGetContext(layer); if(layerContext == NULL){ CGLayerRelease(layer); return NULL; } // Set the fill color to opaque black. CGContextSetFillColorWithColor(layerContext, getRGBOpaqueBlackColor()); // Draw the content into the layer. CGContextFillRect(layerContext, rect); // Now the layer has the contents needed. return layer; }
void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor) { char text[16]; // that's a lot of repaints snprintf(text, sizeof(text), "%d", repaintCount); CGRect indicatorBox = platformCALayer->bounds(); CGContextSaveGState(context); indicatorBox.size.width = 12 + 10 * strlen(text); indicatorBox.size.height = 27; CGContextSetAlpha(context, 0.5f); CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0); if (customBackgroundColor) CGContextSetFillColorWithColor(context, customBackgroundColor); else CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1); CGContextFillRect(context, indicatorBox); if (platformCALayer->acceleratesDrawing()) CGContextSetRGBFillColor(context, 1, 0, 0, 1); else CGContextSetRGBFillColor(context, 1, 1, 1, 1); platformCALayer->drawTextAtPoint(context, indicatorBox.origin.x + 5, indicatorBox.origin.y + 22, CGSizeMake(1, -1), 22, text, strlen(text)); CGContextEndTransparencyLayer(context); CGContextRestoreGState(context); }
CGContextRef createRGBBitmapContext(size_t width, size_t height, Boolean wantDisplayColorSpace, Boolean needsTransparentBitmap) { /* This routine allocates data for a pixel array that contains width*height pixels where each pixel is 4 bytes. The format is 8-bit ARGB or XRGB, depending on whether needsTransparentBitmap is true. In order to get the recommended pixel alignment, the bytesPerRow is rounded up to the nearest multiple of BEST_BYTE_ALIGNMENT bytes. */ CGContextRef context; size_t bytesPerRow; unsigned char *rasterData; // Minimum bytes per row is 4 bytes per sample * number of samples. bytesPerRow = width*4; // Round to nearest multiple of BEST_BYTE_ALIGNMENT. bytesPerRow = COMPUTE_BEST_BYTES_PER_ROW(bytesPerRow); // Allocate the data for the raster. The total amount of data is bytesPerRow // times the number of rows. The function 'calloc' is used so that the // memory is initialized to 0. rasterData = calloc(1, bytesPerRow * height); if(rasterData == NULL){ fprintf(stderr, "Couldn't allocate the needed amount of memory!\n"); return NULL; } // The wantDisplayColorSpace argument passed to the function determines // whether or not to use the display color space or the generic calibrated // RGB color space. The needsTransparentBitmap argument determines whether // create a context that records alpha or not. context = CGBitmapContextCreate(rasterData, width, height, 8, bytesPerRow, (wantDisplayColorSpace ? getTheDisplayColorSpace(): getTheCalibratedRGBColorSpace()) , (needsTransparentBitmap ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst)); if(context == NULL){ // If the context couldn't be created, release the raster memory. free(rasterData); fprintf(stderr, "Couldn't create the context!\n"); return NULL; } // Either clear the rect or paint with opaque white, depending on // the needs of the caller. if(needsTransparentBitmap){ // Clear the context bits so they are transparent. CGContextClearRect(context, CGRectMake(0, 0, width, height)); }else{ // Since the drawing destination is opaque, first paint // the context bits to white. CGContextSaveGState(context); CGContextSetFillColorWithColor(context, getRGBOpaqueWhiteColor()); CGContextFillRect(context, CGRectMake(0, 0, width, height)); CGContextRestoreGState(context); } return context; }
void JBGFillTriangle(CGContextRef ctx, CGPoint point_a, CGPoint point_b, CGPoint point_c, CGColorRef color) { CGContextBeginPath(ctx); CGPoint points[] = {point_a, point_b, point_c}; CGContextAddLines(ctx, points, sizeof(points) / sizeof(points[0])); CGContextClosePath(ctx); CGContextSetFillColorWithColor(ctx, color); CGContextFillPath(ctx); }
//----------------------------------------------------------------------------- void CGDrawContext::setFillColor (const CColor& color) { if (currentState.fillColor == color) return; if (cgContext) CGContextSetFillColorWithColor (cgContext, getCGColor (color)); CDrawContext::setFillColor (color); }
void drawRect(const SkRect& r, SkColor c) override { CGContextRef cg = (CGContextRef)fCanvas->accessTopRasterHandle(); CGColorRef color = CGColorCreateGenericRGB(SkColorGetR(c)/255.f, SkColorGetG(c)/255.f, SkColorGetB(c)/255.f, SkColorGetA(c)/255.f); CGContextSetFillColorWithColor(cg, color); CGContextFillRect(cg, CGRectMake(r.x(), r.y(), r.width(), r.height())); }
void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor) { char text[16]; // that's a lot of repaints snprintf(text, sizeof(text), "%d", repaintCount); FloatRect indicatorBox = platformCALayer->bounds();\ indicatorBox.setLocation( { 1, 1 } ); indicatorBox.setSize(FloatSize(12 + 10 * strlen(text), 27)); CGContextStateSaver stateSaver(context); CGContextSetAlpha(context, 0.5f); CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0); if (customBackgroundColor) CGContextSetFillColorWithColor(context, customBackgroundColor); else CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1); if (platformCALayer->isOpaque()) CGContextFillRect(context, indicatorBox); else { Path boundsPath; boundsPath.moveTo(indicatorBox.maxXMinYCorner()); boundsPath.addLineTo(indicatorBox.maxXMaxYCorner()); boundsPath.addLineTo(indicatorBox.minXMaxYCorner()); const float cornerChunk = 8; boundsPath.addLineTo(FloatPoint(indicatorBox.x(), indicatorBox.y() + cornerChunk)); boundsPath.addLineTo(FloatPoint(indicatorBox.x() + cornerChunk, indicatorBox.y())); boundsPath.closeSubpath(); CGContextAddPath(context, boundsPath.platformPath()); CGContextFillPath(context); } if (platformCALayer->owner()->isUsingDisplayListDrawing(platformCALayer)) { CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.65); CGContextSetLineWidth(context, 2); CGContextStrokeRect(context, indicatorBox); } if (platformCALayer->acceleratesDrawing()) CGContextSetRGBFillColor(context, 1, 0, 0, 1); else CGContextSetRGBFillColor(context, 1, 1, 1, 1); platformCALayer->drawTextAtPoint(context, indicatorBox.x() + 5, indicatorBox.y() + 22, CGSizeMake(1, -1), 22, text, strlen(text)); CGContextEndTransparencyLayer(context); }
void drawWithColorRefs(CGContextRef context) { static CGColorRef opaqueRedColor = NULL, opaqueBlueColor = NULL, transparentBlueColor = NULL; // Initialize the CGColorRefs if necessary if(opaqueRedColor == NULL){ // Initialize the color array to an opaque red // in the generic calibrated RGB color space. float color[4] = { 0.663, 0.0, 0.031, 1.0 }; CGColorSpaceRef theColorSpace = getTheCalibratedRGBColorSpace(); // Create a CGColorRef for opaque red. opaqueRedColor = CGColorCreate(theColorSpace, color); // Make the color array correspond to an opaque blue color. color[0] = 0.482; color[1] = 0.62; color[2] = 0.871; // Create another CGColorRef for opaque blue. opaqueBlueColor = CGColorCreate(theColorSpace, color); // Create a new CGColorRef from the opaqueBlue CGColorRef // but with a different alpha value. transparentBlueColor = CGColorCreateCopyWithAlpha(opaqueBlueColor, 0.5); if(!(opaqueRedColor && opaqueBlueColor && transparentBlueColor)){ fprintf(stderr, "Couldn't create one of the CGColorRefs!!!\n"); return; } } // Set the fill color to the opaque red CGColor object. CGContextSetFillColorWithColor(context, opaqueRedColor); // Set the stroke color to the opaque blue CGColor object. CGContextSetStrokeColorWithColor(context, opaqueBlueColor); CGContextSetLineWidth(context, 8.); // Draw the first rectangle. CGContextBeginPath(context); CGContextAddRect(context, CGRectMake(20., 20., 100., 100.)); CGContextDrawPath(context, kCGPathFillStroke); // Set the stroke color to be that of the transparent blue // CGColor object. CGContextSetStrokeColorWithColor(context, transparentBlueColor); // Draw a second rectangle to the right of the first one. CGContextBeginPath(context); CGContextAddRect(context, CGRectMake(140., 20., 100., 100.)); CGContextDrawPath(context, kCGPathFillStroke); }
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) { if (!nativeImageForCurrentFrame()) return; ASSERT(patternTransform.isInvertible()); if (!patternTransform.isInvertible()) // Avoid a hang under CGContextDrawTiledImage on release builds. return; CGContextRef context = ctxt->platformContext(); ctxt->save(); CGContextClipToRect(context, destRect); ctxt->setCompositeOperation(op); CGContextTranslateCTM(context, destRect.x(), destRect.y() + destRect.height()); CGContextScaleCTM(context, 1, -1); // Compute the scaled tile size. float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d()); // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being // the origin). float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out. float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight); CGImageRef tileImage = nativeImageForCurrentFrame(); float h = CGImageGetHeight(tileImage); RetainPtr<CGImageRef> subImage; if (tileRect.size() == size()) subImage = tileImage; else { // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen // because sub-images are only used for border-image, which only renders when the image is fully decoded. ASSERT(h == height()); subImage.adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect)); } // Adjust the color space. subImage = imageWithColorSpace(subImage.get(), styleColorSpace); #ifndef BUILDING_ON_TIGER // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that // its buffer is the same size as the overall image. Because a partially decoded CGImageRef with a smaller width or height than the // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case. // FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well. // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors. Snow Leopard is ok. float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a()); float w = CGImageGetWidth(tileImage); #ifdef BUILDING_ON_LEOPARD if (w == size().width() && h == size().height() && scaledTileWidth == tileRect.width() && scaledTileHeight == tileRect.height()) #else if (w == size().width() && h == size().height()) #endif CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get()); else { #endif // On Leopard, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image. // On Tiger this code runs all the time. This code is suboptimal because the pattern does not reference the image directly, and the // pattern is destroyed before exiting the function. This means any decoding the pattern does doesn't end up cached anywhere, so we // redecode every time we paint. static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL }; CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY); matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context)); // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top. matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h); RetainPtr<CGPatternRef> pattern(AdoptCF, CGPatternCreate(subImage.get(), CGRectMake(0, 0, tileRect.width(), tileRect.height()), matrix, tileRect.width(), tileRect.height(), kCGPatternTilingConstantSpacing, true, &patternCallbacks)); if (!pattern) { ctxt->restore(); return; } RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0)); CGFloat alpha = 1; RetainPtr<CGColorRef> color(AdoptCF, CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha)); CGContextSetFillColorSpace(context, patternSpace.get()); // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy). wkSetPatternBaseCTM(context, CGAffineTransformIdentity); CGContextSetPatternPhase(context, CGSizeZero); CGContextSetFillColorWithColor(context, color.get()); CGContextFillRect(context, CGContextGetClipBoundingBox(context)); #ifndef BUILDING_ON_TIGER } #endif ctxt->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
bool FBVLC_Mac::onCoreGraphicsDraw(FB::CoreGraphicsDraw *evt, FB::PluginWindowMacCG*) { boost::lock_guard<boost::mutex> lock( m_frameGuard ); FB::Rect bounds(evt->bounds); //FB::Rect clip(evt->clip); short width = bounds.right - bounds.left, height = bounds.bottom - bounds.top; CGContextRef cgContext(evt->context); CGContextSaveGState(cgContext); CGContextTranslateCTM(cgContext, 0.0, height); CGContextScaleCTM(cgContext, 1.0, -1.0); CGColorSpaceRef cSpace = CGColorSpaceCreateDeviceRGB(); CGContextSetFillColorSpace(cgContext, cSpace); CGColorRef bgColor = CGColorCreate(cSpace, m_bgComponents); CGContextSetFillColorWithColor(cgContext, bgColor); if ( 0 != m_media_width && 0 != m_media_height ) { CGRect imgRect = { { (width - m_media_width) / 2, (height - m_media_height) / 2 }, { m_media_width, m_media_height } }; const std::vector<char>& fb = vlc::vmem::frame_buf(); CGContextRef frameBmpCtx = CGBitmapContextCreate( (void*)&fb[0], m_media_width, m_media_height, 8, m_media_width * vlc::DEF_PIXEL_BYTES, cSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little ); CGImageRef frameImage = CGBitmapContextCreateImage( frameBmpCtx ); CGContextDrawImage( cgContext, imgRect, frameImage ); CGImageRelease( frameImage ); CGContextRelease( frameBmpCtx ); if( m_media_width < width ) { CGRect bgLeft = { { 0, 0 }, { imgRect.origin.x, height } }; CGContextFillRect(cgContext, bgLeft); CGRect bgRight = { { imgRect.origin.x + imgRect.size.width, 0 }, { width - (imgRect.origin.x + imgRect.size.width), height } }; CGContextFillRect(cgContext, bgRight); } else if( m_media_height < height ){ CGRect bgTop = { { 0, 0 }, { width, imgRect.origin.y } }; CGContextFillRect(cgContext, bgTop); CGRect bgBottom = { { 0, imgRect.origin.y + imgRect.size.height }, { width, height - (imgRect.origin.y + imgRect.size.height) } }; CGContextFillRect(cgContext, bgBottom); } } else { CGRect cgBounds = { { 0, 0 }, { width, height } }; CGContextFillRect(cgContext, cgBounds); } CGColorRelease(bgColor); CGColorSpaceRelease(cSpace); CGContextRestoreGState(cgContext); return true; // This is handled }
void QuartzWindow::set_color(int c) { CGContextSetFillColorWithColor( myContext, (CGColorRef)c ); CGContextSetStrokeColorWithColor( myContext, (CGColorRef)c ); }
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); }
static void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace) { CGContextSetFillColorWithColor(context, cachedCGColor(color, colorSpace)); }
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (!nativeImageForCurrentFrame()) return; if (!patternTransform.isInvertible()) return; CGContextRef context = ctxt->platformContext(); GraphicsContextStateSaver stateSaver(*ctxt); CGContextClipToRect(context, destRect); ctxt->setCompositeOperation(op, blendMode); CGContextTranslateCTM(context, destRect.x(), destRect.y() + destRect.height()); CGContextScaleCTM(context, 1, -1); // Compute the scaled tile size. float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d()); // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being // the origin). float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out. float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight); CGImageRef tileImage = nativeImageForCurrentFrame(); float h = CGImageGetHeight(tileImage); RetainPtr<CGImageRef> subImage; if (tileRect.size() == size()) subImage = tileImage; else { // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen // because sub-images are only used for border-image, which only renders when the image is fully decoded. ASSERT(h == height()); subImage = adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect)); } // Adjust the color space. subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace); // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that // its buffer is the same size as the overall image. Because a partially decoded CGImageRef with a smaller width or height than the // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case. // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors. Snow Leopard is ok. float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a()); float w = CGImageGetWidth(tileImage); if (w == size().width() && h == size().height() && !spaceSize().width() && !spaceSize().height()) CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get()); else { // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image. static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, patternReleaseCallback }; CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY); matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context)); // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top. matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h); #if PLATFORM(IOS) matrix = CGAffineTransformScale(matrix, 1, -1); matrix = CGAffineTransformTranslate(matrix, 0, -h); #endif CGImageRef platformImage = CGImageRetain(subImage.get()); RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(platformImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()), matrix, tileRect.width() + spaceSize().width() * (1 / narrowPrecisionToFloat(patternTransform.a())), tileRect.height() + spaceSize().height() * (1 / narrowPrecisionToFloat(patternTransform.d())), kCGPatternTilingConstantSpacing, true, &patternCallbacks)); if (!pattern) return; RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0)); CGFloat alpha = 1; RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha)); CGContextSetFillColorSpace(context, patternSpace.get()); // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy). wkSetBaseCTM(context, CGAffineTransformIdentity); CGContextSetPatternPhase(context, CGSizeZero); CGContextSetFillColorWithColor(context, color.get()); CGContextFillRect(context, CGContextGetClipBoundingBox(context)); } stateSaver.restore(); if (imageObserver()) imageObserver()->didDraw(this); }