FX_BOOL CFX_QuartzDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2, FX_DWORD argb, int alphaFlag , void* iccTransform , int blend_type ) { CGBlendMode mode = GetCGBlendMode(blend_type); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, mode); } CGPoint pt = CGPointApplyAffineTransform(CGPointMake(x1, y1), _foxitDevice2User); x1 = pt.x; y1 = pt.y; pt = CGPointApplyAffineTransform(CGPointMake(x2, y2), _foxitDevice2User); x2 = pt.x; y2 = pt.y; FX_INT32 a, r, g, b; ArgbDecode(argb, a, r, g, b); CGContextSetRGBStrokeColor(_context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); CGContextMoveToPoint(_context, x1, y1); CGContextAddLineToPoint(_context, x2, y2); CGContextStrokePath(_context); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, kCGBlendModeNormal); } return TRUE; }
FX_BOOL CFX_QuartzDeviceDriver::FillRect(const FX_RECT* rect, FX_ARGB fillArgb, int alphaFlag , void* iccTransform , int blend_type ) { CGBlendMode mode = GetCGBlendMode(blend_type); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, mode); } CGRect rect_fx = CGRectMake(rect->left, rect->top, rect->Width(), rect->Height()); CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); FX_INT32 a, r, g, b; ArgbDecode(fillArgb, a, r, g, b); CGContextSetRGBFillColor(_context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); CGContextFillRect(_context, rect_usr); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, kCGBlendModeNormal); } return TRUE; }
static void quartzPrepareLine (GraphicsScreen me) { CGContextSetLineJoin (my d_macGraphicsContext, kCGLineJoinRound); if (my duringXor) { CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeDifference); CGContextSetAllowsAntialiasing (my d_macGraphicsContext, false); CGContextSetRGBStrokeColor (my d_macGraphicsContext, 1.0, 1.0, 1.0, 1.0); } else { CGContextSetRGBStrokeColor (my d_macGraphicsContext, my d_macColour.red / 65536.0, my d_macColour.green / 65536.0, my d_macColour.blue / 65536.0, 1.0); } double lineWidth_pixels = LINE_WIDTH_IN_PIXELS (me); CGContextSetLineWidth (my d_macGraphicsContext, lineWidth_pixels); CGFloat lengths [4]; if (my lineType == Graphics_DOTTED) lengths [0] = my resolution > 192 ? my resolution / 100.0 : 2, lengths [1] = my resolution > 192 ? my resolution / 75.0 + lineWidth_pixels : 2; if (my lineType == Graphics_DASHED) lengths [0] = my resolution > 192 ? my resolution / 25 : 6, lengths [1] = my resolution > 192 ? my resolution / 50.0 + lineWidth_pixels : 2; if (my lineType == Graphics_DASHED_DOTTED) lengths [0] = my resolution > 192 ? my resolution / 25 : 6, lengths [1] = my resolution > 192 ? my resolution / 50.0 + lineWidth_pixels : 2; lengths [2] = my resolution > 192 ? my resolution / 100.0 : 2; lengths [3] = my resolution > 192 ? my resolution / 50.0 + lineWidth_pixels : 2; CGContextSetLineDash (my d_macGraphicsContext, 0.0, my lineType == Graphics_DRAWN ? NULL : lengths, my lineType == 0 ? 0 : my lineType == Graphics_DASHED_DOTTED ? 4 : 2); }
SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* pixels, CGImageRef image) { CGBitmapInfo cg_bitmap_info = 0; size_t bitsPerComponent = 0; switch (info.colorType()) { case kRGBA_8888_SkColorType: bitsPerComponent = 8; cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType()); break; case kBGRA_8888_SkColorType: bitsPerComponent = 8; cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType()); break; default: return false; // no other colortypes are supported (for now) } CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent, rowBytes, cs, cg_bitmap_info); CFRelease(cs); if (NULL == cg) { return false; } // use this blend mode, to avoid having to erase the pixels first, and to avoid CG performing // any blending (which could introduce errors and be slower). CGContextSetBlendMode(cg, kCGBlendModeCopy); CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image); CGContextRelease(cg); return true; }
void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { if (!m_context->isAcceleratedContext()) { m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied); return; } #if USE(IOSURFACE_CANVAS_BACKING_STORE) // Make a copy of the source to ensure the bits don't change before being drawn IntSize sourceCopySize(sourceRect.width(), sourceRect.height()); OwnPtr<ImageBuffer> sourceCopy = ImageBuffer::create(sourceCopySize, 1, ColorSpaceDeviceRGB, Unaccelerated); if (!sourceCopy) return; sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied); // Set up context for using drawImage as a direct bit copy CGContextRef destContext = context()->platformContext(); CGContextSaveGState(destContext); CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse()); wkCGContextResetClip(destContext); CGContextSetInterpolationQuality(destContext, kCGInterpolationNone); CGContextSetAlpha(destContext, 1.0); CGContextSetBlendMode(destContext, kCGBlendModeCopy); CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0); // Draw the image in CG coordinate space IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), internalSize().height() - (destPoint.y()+sourceRect.y()) - sourceRect.height()); IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize); RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage()); CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get()); CGContextRestoreGState(destContext); #endif }
DragImageRef createDragImageFromImage(Image* img, ImageOrientationDescription) { HWndDC dc(0); auto workingDC = adoptGDIObject(::CreateCompatibleDC(dc)); if (!workingDC) return 0; CGContextRef drawContext = 0; auto hbmp = allocImage(workingDC.get(), img->size(), &drawContext); if (!hbmp || !drawContext) return 0; CGImageRef srcImage = img->getCGImageRef(); CGRect rect; rect.size = img->size(); rect.origin.x = 0; rect.origin.y = -rect.size.height; static const CGFloat white [] = {1.0, 1.0, 1.0, 1.0}; CGContextScaleCTM(drawContext, 1, -1); CGContextSetFillColor(drawContext, white); CGContextFillRect(drawContext, rect); if (srcImage) { CGContextSetBlendMode(drawContext, kCGBlendModeNormal); CGContextDrawImage(drawContext, rect, srcImage); } CGContextRelease(drawContext); return hbmp.leak(); }
bool MCTileCacheCoreGraphicsCompositor_BeginLayer(void *p_context, const MCRectangle& p_clip, uint32_t p_opacity, uint32_t p_ink) { MCTileCacheCoreGraphicsCompositorContext *self; self = (MCTileCacheCoreGraphicsCompositorContext *)p_context; CGContextSaveGState(self -> cgcontext); // MW-2012-09-18: [[ Bug 10202 ]] If the ink is no-op then ensure nothing happens. if (p_ink == GXnoop) CGContextClipToRect(self -> cgcontext, CGRectZero); else { CGContextClipToRect(self -> cgcontext, CGRectMake(p_clip . x, self -> viewport_height - (p_clip . y + p_clip . height), p_clip . width, p_clip . height)); CGContextSetAlpha(self -> cgcontext, p_opacity / 255.0); CGBlendMode t_blend_mode; switch(p_ink) { case GXblendMultiply: t_blend_mode = kCGBlendModeMultiply; break; case GXblendScreen: t_blend_mode = kCGBlendModeScreen; break; case GXblendOverlay: t_blend_mode = kCGBlendModeOverlay; break; case GXblendDarken: t_blend_mode = kCGBlendModeDarken; break; case GXblendLighten: t_blend_mode = kCGBlendModeLighten; break; case GXblendDodge: t_blend_mode = kCGBlendModeColorDodge; break; case GXblendBurn: t_blend_mode = kCGBlendModeColorBurn; break; case GXblendSoftLight: t_blend_mode = kCGBlendModeSoftLight; break; case GXblendHardLight: t_blend_mode = kCGBlendModeHardLight; break; case GXblendDifference: t_blend_mode = kCGBlendModeDifference; break; case GXblendExclusion: t_blend_mode = kCGBlendModeExclusion; break; default: t_blend_mode = kCGBlendModeNormal; break; } CGContextSetBlendMode(self -> cgcontext, t_blend_mode); } return true; }
void drawWithColorBlendMode(CGContextRef context, CFURLRef url) { // A pleasant green color. float green[4] = { 0.584, 0.871, 0.318, 1.0 }; CGRect insetRect, pdfRect; // Create a CGPDFDocument object from the URL. CGPDFDocumentRef pdfDoc = CGPDFDocumentCreateWithURL(url); if(pdfDoc == NULL){ fprintf(stderr, "Couldn't create CGPDFDocument from URL!\n"); return; } // Obtain the media box for page 1 of the PDF document. pdfRect = CGPDFDocumentGetMediaBox(pdfDoc, 1); // Set the origin of the rectangle to (0,0). pdfRect.origin.x = pdfRect.origin.y = 0; // Graphic 1, the left portion of the figure. CGContextTranslateCTM(context, 20, 10 + CGRectGetHeight(pdfRect)/2); // Draw the PDF document. CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1); // Set the fill color space to that returned by getTheCalibratedRGBColorSpace. CGContextSetFillColorSpace(context, getTheCalibratedRGBColorSpace()); // Set the fill color to green. CGContextSetFillColor(context, green); // Graphic 2, the top-right portion of the figure. CGContextTranslateCTM(context, CGRectGetWidth(pdfRect) + 10, CGRectGetHeight(pdfRect)/2 + 10); // Draw the PDF document again. CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1); // Make a fill rectangle that is the same size as the PDF document // but inset each side by 80 units in x and 20 units in y. insetRect = CGRectInset(pdfRect, 80, 20); // Fill the rectangle with green. Because the fill color is opaque and // the blend mode is Normal, this obscures the drawing underneath. CGContextFillRect(context, insetRect); // Graphic 3, the bottom-right portion of the figure. CGContextTranslateCTM(context, 0, -(10 + CGRectGetHeight(pdfRect))); // Draw the PDF document again. CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1); // Set the blend mode to kCGBlendModeColor which will // colorize the destination with subsequent drawing. CGContextSetBlendMode(context, kCGBlendModeColor); // Draw the rectangle on top of the PDF document. The portion of the // background that is covered by the rectangle is colorized // with the fill color. CGContextFillRect(context, insetRect); // Release the CGPDFDocumentRef the code created. CGPDFDocumentRelease(pdfDoc); }
FX_BOOL CFX_QuartzDeviceDriver::DrawPath(const CFX_PathData* pathData, const CFX_AffineMatrix* matrix, const CFX_GraphStateData* graphState, FX_DWORD fillArgb, FX_DWORD strokeArgb, int fillMode, int alpha_flag, void* pIccTransform, int blend_type ) { SaveState(); CGBlendMode mode = GetCGBlendMode(blend_type); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, mode); } CGAffineTransform m = CGAffineTransformIdentity; if (matrix) { m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(), matrix->GetE(), matrix->GetF()); } m = CGAffineTransformConcat(m, _foxitDevice2User); CGContextConcatCTM(_context, m); int pathMode = 0; if (graphState && strokeArgb) { CGContextSetMiterLimit(_context, graphState->m_MiterLimit); FX_FLOAT lineWidth = getLineWidth(graphState, m); setStrokeInfo(graphState, strokeArgb, lineWidth); pathMode |= 4; } if (fillMode && fillArgb) { setFillInfo(fillArgb); if ((fillMode & 3) == FXFILL_WINDING) { pathMode |= 1; } else if ((fillMode & 3) == FXFILL_ALTERNATE) { pathMode |= 2; } } setPathToContext(pathData); if (fillMode & FXFILL_FULLCOVER) { CGContextSetShouldAntialias(_context, false); } if (pathMode == 4) { CGContextStrokePath(_context); } else if (pathMode == 1) { CGContextFillPath(_context); } else if (pathMode == 2) { CGContextEOFillPath(_context); } else if (pathMode == 5) { CGContextDrawPath(_context, kCGPathFillStroke); } else if (pathMode == 6) { CGContextDrawPath(_context, kCGPathEOFillStroke); } RestoreState(FALSE); return TRUE; }
void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode) { if (paintingDisabled()) return; CGBlendMode target = kCGBlendModeNormal; switch (mode) { case CompositeClear: target = kCGBlendModeClear; break; case CompositeCopy: target = kCGBlendModeCopy; break; case CompositeSourceOver: //kCGBlendModeNormal break; case CompositeSourceIn: target = kCGBlendModeSourceIn; break; case CompositeSourceOut: target = kCGBlendModeSourceOut; break; case CompositeSourceAtop: target = kCGBlendModeSourceAtop; break; case CompositeDestinationOver: target = kCGBlendModeDestinationOver; break; case CompositeDestinationIn: target = kCGBlendModeDestinationIn; break; case CompositeDestinationOut: target = kCGBlendModeDestinationOut; break; case CompositeDestinationAtop: target = kCGBlendModeDestinationAtop; break; case CompositeXOR: target = kCGBlendModeXOR; break; case CompositePlusDarker: target = kCGBlendModePlusDarker; break; case CompositeHighlight: // currently unsupported break; case CompositePlusLighter: target = kCGBlendModePlusLighter; break; } CGContextSetBlendMode(platformContext(), target); }
static void resolveColorSpace(const SkBitmap& bitmap, CGColorSpaceRef colorSpace) { int width = bitmap.width(); int height = bitmap.height(); CGImageRef srcImage = SkCreateCGImageRefWithColorspace(bitmap, colorSpace); SkAutoLockPixels lock(bitmap); void* pixels = bitmap.getPixels(); RetainPtr<CGContextRef> cgBitmap(AdoptCF, CGBitmapContextCreate(pixels, width, height, 8, width * 4, deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst)); if (!cgBitmap) return; CGContextSetBlendMode(cgBitmap.get(), kCGBlendModeCopy); CGRect bounds = { {0, 0}, {width, height} }; CGContextDrawImage(cgBitmap.get(), bounds, srcImage); }
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem) { if (!context().isAcceleratedContext()) { IntRect scaledSourceRect = sourceRect; IntSize scaledSourceSize = sourceSize; if (coordinateSystem == LogicalCoordinateSystem) { scaledSourceRect.scale(m_resolutionScale); scaledSourceSize.scale(m_resolutionScale); } m_data.putData(source, scaledSourceSize, scaledSourceRect, destPoint, internalSize(), false, multiplied == Unmultiplied, 1); return; } #if USE(IOSURFACE_CANVAS_BACKING_STORE) // Make a copy of the source to ensure the bits don't change before being drawn IntSize sourceCopySize(sourceRect.width(), sourceRect.height()); // FIXME (149431): Should this ImageBuffer be unconditionally unaccelerated? Making it match the context seems to break putData(). std::unique_ptr<ImageBuffer> sourceCopy = ImageBuffer::create(sourceCopySize, Unaccelerated, 1, ColorSpaceDeviceRGB); if (!sourceCopy) return; sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context().isAcceleratedContext(), multiplied == Unmultiplied, 1); // Set up context for using drawImage as a direct bit copy CGContextRef destContext = context().platformContext(); CGContextSaveGState(destContext); if (coordinateSystem == LogicalCoordinateSystem) CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse()); else CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse()); CGContextResetClip(destContext); CGContextSetInterpolationQuality(destContext, kCGInterpolationNone); CGContextSetAlpha(destContext, 1.0); CGContextSetBlendMode(destContext, kCGBlendModeCopy); CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0); // Draw the image in CG coordinate space FloatSize scaledDestSize = scaleSizeToUserSpace(coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize(), m_data.backingStoreSize, internalSize()); IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), scaledDestSize.height() - (destPoint.y() + sourceRect.y()) - sourceRect.height()); IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize); CGContextClipToRect(destContext, destRectInCGCoords); RetainPtr<CGImageRef> sourceCopyImage = sourceCopy->copyNativeImage(); FloatRect backingStoreInDestRect = FloatRect(FloatPoint(destPointInCGCoords.x(), destPointInCGCoords.y() + sourceCopySize.height() - (int)CGImageGetHeight(sourceCopyImage.get())), FloatSize(CGImageGetWidth(sourceCopyImage.get()), CGImageGetHeight(sourceCopyImage.get()))); CGContextDrawImage(destContext, backingStoreInDestRect, sourceCopyImage.get()); CGContextRestoreGState(destContext); #endif }
PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const { RetainPtr<CGImageRef> image; if (m_resolutionScale == 1) image = copyNativeImage(copyBehavior); else { image.adoptCF(copyNativeImage(DontCopyBackingStore)); RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(context.get(), kCGBlendModeCopy); CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get()); image = CGBitmapContextCreateImage(context.get()); } if (!image) return 0; return BitmapImage::create(image.get()); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); if (context().isAcceleratedContext()) flushContext(); RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType); ASSERT(uti); RefPtr<Uint8ClampedArray> premultipliedData; RetainPtr<CGImageRef> image; if (CFEqual(uti.get(), jpegUTI())) { // JPEGs don't have an alpha channel, so we have to manually composite on top of black. premultipliedData = getPremultipliedImageData(IntRect(IntPoint(0, 0), logicalSize())); if (!premultipliedData) return "data:,"; RetainPtr<CGDataProviderRef> dataProvider; dataProvider = adoptCF(CGDataProviderCreateWithData(0, premultipliedData->data(), 4 * logicalSize().width() * logicalSize().height(), 0)); if (!dataProvider) return "data:,"; image = adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); } else if (m_resolutionScale == 1) { image = copyNativeImage(CopyBackingStore); image = createCroppedImageIfNecessary(image.get(), internalSize()); } else { image = copyNativeImage(DontCopyBackingStore); RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(context.get(), kCGBlendModeCopy); CGContextClipToRect(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height())); FloatSize imageSizeInUserSpace = scaleSizeToUserSpace(logicalSize(), m_data.backingStoreSize, internalSize()); CGContextDrawImage(context.get(), CGRectMake(0, 0, imageSizeInUserSpace.width(), imageSizeInUserSpace.height()), image.get()); image = adoptCF(CGBitmapContextCreateImage(context.get())); } return CGImageToDataURL(image.get(), mimeType, quality); }
RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior scaleBehavior) const { RetainPtr<CGImageRef> image; if (m_resolutionScale == 1 || scaleBehavior == Unscaled) { image = copyNativeImage(copyBehavior); image = createCroppedImageIfNecessary(image.get(), internalSize()); } else { image = copyNativeImage(DontCopyBackingStore); RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(context.get(), kCGBlendModeCopy); CGContextClipToRect(context.get(), FloatRect(FloatPoint::zero(), logicalSize())); FloatSize imageSizeInUserSpace = scaleSizeToUserSpace(logicalSize(), m_data.backingStoreSize, internalSize()); CGContextDrawImage(context.get(), FloatRect(FloatPoint::zero(), imageSizeInUserSpace), image.get()); image = adoptCF(CGBitmapContextCreateImage(context.get())); } if (!image) return nullptr; return BitmapImage::create(image.get()); }
void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context) { if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) return; int rowBytes = imageWidth * 4; RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0)); RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(imageWidth, imageHeight, 8, 32, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); // CSS styling may cause the canvas's content to be resized on // the page. Go back to the Canvas to figure out the correct // width and height to draw. CGRect rect = CGRectMake(0, 0, canvasWidth, canvasHeight); // We want to completely overwrite the previous frame's // rendering results. CGContextSaveGState(context); CGContextSetBlendMode(context, kCGBlendModeCopy); CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextDrawImage(context, rect, cgImage.get()); CGContextRestoreGState(context); }
DragImageRef createDragImageFromImage(Image* img) { HBITMAP hbmp = 0; HDC dc = GetDC(0); HDC workingDC = CreateCompatibleDC(dc); CGContextRef drawContext = 0; if (!workingDC) goto exit; hbmp = allocImage(workingDC, img->size(), &drawContext); if (!hbmp) goto exit; if (!drawContext) { ::DeleteObject(hbmp); hbmp = 0; } CGImageRef srcImage = img->getCGImageRef(); CGRect rect; rect.size = img->size(); rect.origin.x = 0; rect.origin.y = -rect.size.height; static const CGFloat white [] = {1.0, 1.0, 1.0, 1.0}; CGContextScaleCTM(drawContext, 1, -1); CGContextSetFillColor(drawContext, white); CGContextFillRect(drawContext, rect); CGContextSetBlendMode(drawContext, kCGBlendModeNormal); CGContextDrawImage(drawContext, rect, srcImage); CGContextRelease(drawContext); exit: if (workingDC) DeleteDC(workingDC); ReleaseDC(0, dc); return hbmp; }
void ImageBufferData::putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = (destPoint.x() + sourceRect.x()) * resolutionScale; ASSERT(destx >= 0); ASSERT(destx < size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = (destPoint.x() + sourceRect.maxX()) * resolutionScale; ASSERT(endx <= size.width()); int width = sourceRect.width(); int destw = endx - destx; int originy = sourceRect.y(); int desty = (destPoint.y() + sourceRect.y()) * resolutionScale; ASSERT(desty >= 0); ASSERT(desty < size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = (destPoint.y() + sourceRect.maxY()) * resolutionScale; ASSERT(endy <= size.height()); int height = sourceRect.height(); int desth = endy - desty; if (width <= 0 || height <= 0) return; unsigned srcBytesPerRow = 4 * sourceSize.width(); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; unsigned destBytesPerRow; unsigned char* destRows; if (!accelerateRendering) { destBytesPerRow = 4 * size.width(); destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) if (haveVImageRoundingErrorFix() && unmultiplied) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = desth; dst.width = destw; dst.rowBytes = destBytesPerRow; dst.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The premultiplying will be done in-place. src = dst; } vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return; } #endif if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. if (!unmultiplied) return; srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, 0, 0); destBytesPerRow = IOSurfaceGetBytesPerRow(surface); destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = desth; dest.width = destw; dest.rowBytes = destBytesPerRow; dest.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying and channel-swapping will be done in-place. if (unmultiplied) { srcRows = destRows; width = destw; height = desth; srcBytesPerRow = destBytesPerRow; } else src = dest; } if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline); } else { // Swap pixel channels from RGBA to BGRA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (b * alpha + 254) / 255; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = alpha; } } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, 0, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } }
static void quartzPrepareFill (GraphicsScreen me) { CGContextSetAlpha (my d_macGraphicsContext, 1.0); CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal); CGContextSetRGBFillColor (my d_macGraphicsContext, my d_macColour.red / 65536.0, my d_macColour.green / 65536.0, my d_macColour.blue / 65536.0, 1.0); }
void QuartzWindow::set_copy() { CGContextSetBlendMode(myContext, kCGBlendModeNormal); }
void QuartzWindow::set_xor() { CGContextSetBlendMode(myContext, kCGBlendModeDifference); }
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight) { if (URIUtils::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } #if defined(__APPLE__) && defined(__arm__) XFILE::CFile file; UInt8 *imageBuff = NULL; int64_t imageBuffSize = 0; //open path and read data to buffer //this handles advancedsettings.xml pathsubstitution //and resulting networking if (file.Open(texturePath, 0)) { imageBuffSize =file.GetLength(); imageBuff = new UInt8[imageBuffSize]; imageBuffSize = file.Read(imageBuff, imageBuffSize); file.Close(); } else { CLog::Log(LOGERROR, "Texture manager unable to open file %s", texturePath.c_str()); return false; } if (imageBuffSize <= 0) { CLog::Log(LOGERROR, "Texture manager read texture file failed."); delete [] imageBuff; return false; } // create the image from buffer; CGImageSourceRef imageSource; // create a CFDataRef using CFDataCreateWithBytesNoCopy and kCFAllocatorNull for deallocator. // this allows us to do a nocopy reference and we handle the free of imageBuff CFDataRef cfdata = CFDataCreateWithBytesNoCopy(NULL, imageBuff, imageBuffSize, kCFAllocatorNull); imageSource = CGImageSourceCreateWithData(cfdata, NULL); if (imageSource == nil) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", CSpecialProtocol::TranslatePath(texturePath).c_str()); CFRelease(cfdata); delete [] imageBuff; return false; } CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); int rotate = 0; if (autoRotate) { // get the orientation of the image for displaying it correctly CFDictionaryRef imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(imageSource,0, NULL); if (imagePropertiesDictionary != nil) { CFNumberRef orientation = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyOrientation); if (orientation != nil) { int value = 0; CFNumberGetValue(orientation, kCFNumberIntType, &value); if (value) rotate = value - 1; } CFRelease(imagePropertiesDictionary); } } CFRelease(imageSource); unsigned int width = CGImageGetWidth(image); unsigned int height = CGImageGetHeight(image); m_hasAlpha = (CGImageGetAlphaInfo(image) != kCGImageAlphaNone); if (originalWidth) *originalWidth = width; if (originalHeight) *originalHeight = height; // check texture size limits and limit to screen size - preserving aspectratio of image if ( width > g_Windowing.GetMaxTextureSize() || height > g_Windowing.GetMaxTextureSize() ) { float aspect; if ( width > height ) { aspect = (float)width / (float)height; width = g_Windowing.GetWidth(); height = (float)width / (float)aspect; } else { aspect = (float)height / (float)width; height = g_Windowing.GetHeight(); width = (float)height / (float)aspect; } CLog::Log(LOGDEBUG, "Texture manager texture clamp:new texture size: %i x %i", width, height); } // use RGBA to skip swizzling Allocate(width, height, XB_FMT_RGBA8); m_orientation = rotate; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // hw convert jmpeg to RGBA CGContextRef context = CGBitmapContextCreate(m_pixels, width, height, 8, GetPitch(), colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); // Flip so that it isn't upside-down //CGContextTranslateCTM(context, 0, height); //CGContextScaleCTM(context, 1.0f, -1.0f); #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 CGContextClearRect(context, CGRectMake(0, 0, width, height)); #else #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 // (just a way of checking whether we're running in 10.5 or later) if (CGContextDrawLinearGradient == 0) CGContextClearRect(context, CGRectMake(0, 0, width, height)); else #endif CGContextSetBlendMode(context, kCGBlendModeCopy); #endif //CGContextSetBlendMode(context, kCGBlendModeCopy); CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); CGContextRelease(context); CGImageRelease(image); CFRelease(cfdata); delete [] imageBuff; #else DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } m_hasAlpha = NULL != image.alpha; Allocate(image.width, image.height, XB_FMT_A8R8G8B8); if (autoRotate && image.exifInfo.Orientation) m_orientation = image.exifInfo.Orientation - 1; if (originalWidth) *originalWidth = image.originalwidth; if (originalHeight) *originalHeight = image.originalheight; unsigned int dstPitch = GetPitch(); unsigned int srcPitch = ((image.width + 1)* 3 / 4) * 4; // bitmap row length is aligned to 4 bytes unsigned char *dst = m_pixels; unsigned char *src = image.texture + (m_imageHeight - 1) * srcPitch; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2 += 4, src2 += 3) { dst2[0] = src2[0]; dst2[1] = src2[1]; dst2[2] = src2[2]; dst2[3] = 0xff; } src -= srcPitch; dst += dstPitch; } if(image.alpha) { dst = m_pixels + 3; src = image.alpha + (m_imageHeight - 1) * m_imageWidth; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2+=4, src2++) *dst2 = *src2; src -= m_imageWidth; dst += dstPitch; } } dll.ReleaseImage(&image); #endif ClampToEdge(); return true; }
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar) { if (paintingDisabled()) return; // These are the same for misspelling or bad grammar const int patternHeight = 3; // 3 rows ASSERT(cMisspellingLineThickness == patternHeight); const int patternWidth = 4; // 4 pixels ASSERT(patternWidth == cMisspellingLinePatternWidth); // Make sure to draw only complete dots. // NOTE: Code here used to shift the underline to the left and increase the width // to make sure everything gets underlined, but that results in drawing out of // bounds (e.g. when at the edge of a view) and could make it appear that the // space between adjacent misspelled words was underlined. // allow slightly more considering that the pattern ends with a transparent pixel int widthMod = width % patternWidth; if (patternWidth - widthMod > cMisspellingLinePatternGapWidth) width -= widthMod; // Draw the underline CGContextRef context = platformContext(); CGContextSaveGState(context); const Color& patternColor = grammar ? grammarPatternColor() : spellingPatternColor(); setCGStrokeColor(context, patternColor); wkSetPatternPhaseInUserSpace(context, point); CGContextSetBlendMode(context, kCGBlendModeNormal); // 3 rows, each offset by half a pixel for blending purposes const CGPoint upperPoints [] = {{point.x(), point.y() + patternHeight - 2.5 }, {point.x() + width, point.y() + patternHeight - 2.5}}; const CGPoint middlePoints [] = {{point.x(), point.y() + patternHeight - 1.5 }, {point.x() + width, point.y() + patternHeight - 1.5}}; const CGPoint lowerPoints [] = {{point.x(), point.y() + patternHeight - 0.5 }, {point.x() + width, point.y() + patternHeight - 0.5 }}; // Dash lengths for the top and bottom of the error underline are the same. // These are magic. static const float edge_dash_lengths[] = {2.0f, 2.0f}; static const float middle_dash_lengths[] = {2.76f, 1.24f}; static const float edge_offset = -(edge_dash_lengths[1] - 1.0f) / 2.0f; static const float middle_offset = -(middle_dash_lengths[1] - 1.0f) / 2.0f; // Line opacities. Once again, these are magic. const float upperOpacity = 0.33f; const float middleOpacity = 0.75f; const float lowerOpacity = 0.88f; //Top line CGContextSetLineDash(context, edge_offset, edge_dash_lengths, sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0])); CGContextSetAlpha(context, upperOpacity); CGContextStrokeLineSegments(context, upperPoints, 2); // Middle line CGContextSetLineDash(context, middle_offset, middle_dash_lengths, sizeof(middle_dash_lengths) / sizeof(middle_dash_lengths[0])); CGContextSetAlpha(context, middleOpacity); CGContextStrokeLineSegments(context, middlePoints, 2); // Bottom line CGContextSetLineDash(context, edge_offset, edge_dash_lengths, sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0])); CGContextSetAlpha(context, lowerOpacity); CGContextStrokeLineSegments(context, lowerPoints, 2); CGContextRestoreGState(context); }
static void quartzRevertLine (GraphicsScreen me) { if (my duringXor) { CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal); CGContextSetAllowsAntialiasing (my d_macGraphicsContext, true); } }
FX_BOOL CFX_QuartzDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, const FX_RECT* srcRect, int dest_left, int dest_top, int blendType, int alphaFlag , void* iccTransform ) { SaveState(); CGFloat src_left, src_top, src_width, src_height; if (srcRect) { src_left = srcRect->left; src_top = srcRect->top; src_width = srcRect->Width(); src_height = srcRect->Height(); } else { src_left = src_top = 0; src_width = pBitmap->GetWidth(); src_height = pBitmap->GetHeight(); } CGAffineTransform ctm = CGContextGetCTM(_context); CGFloat scale_x = FXSYS_fabs(ctm.a); CGFloat scale_y = FXSYS_fabs(ctm.d); src_left /= scale_x; src_top /= scale_y; src_width /= scale_x; src_height /= scale_y; CGRect rect_fx = CGRectMake(dest_left, dest_top, src_width, src_height); CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); CGContextBeginPath(_context); CGContextAddRect(_context, rect_usr); CGContextClip(_context); rect_usr.size = CGSizeMake(pBitmap->GetWidth() / scale_x, pBitmap->GetHeight() / scale_y); rect_usr = CGRectOffset(rect_usr, -src_left, -src_top); CG_SetImageTransform(dest_left, dest_top, src_width, src_height, &rect_usr); CFX_DIBitmap* pBitmap1 = NULL; if (pBitmap->IsAlphaMask()) { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, pBitmap1->GetBuffer(), pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, pBitmapProvider, NULL, true, kCGRenderingIntentDefault); CGContextClipToMask(_context, rect_usr, pImage); CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, FXARGB_A(argb) / 255.f); CGContextFillRect(_context, rect_usr); CGImageRelease(pImage); CGColorSpaceRelease(pColorSpace); CGDataProviderRelease(pBitmapProvider); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; } if (pBitmap->GetBPP() < 32) { pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); } else { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } if (pBitmap1->HasAlpha()) { if (pBitmap1 == pBitmap) { pBitmap1 = pBitmap->Clone(); if (!pBitmap1) { RestoreState(FALSE); return FALSE; } } for (int row = 0; row < pBitmap1->GetHeight(); row ++) { FX_LPBYTE pScanline = (FX_LPBYTE)pBitmap1->GetScanline(row); for (int col = 0; col < pBitmap1->GetWidth(); col ++) { pScanline[0] = (FX_BYTE)(pScanline[0] * pScanline[3] / 255.f + .5f); pScanline[1] = (FX_BYTE)(pScanline[1] * pScanline[3] / 255.f + .5f); pScanline[2] = (FX_BYTE)(pScanline[2] * pScanline[3] / 255.f + .5f); pScanline += 4; } } } CGContextRef ctx = createContextWithBitmap(pBitmap1); CGImageRef image = CGBitmapContextCreateImage(ctx); int blend_mode = blendType; if (FXDIB_BLEND_HARDLIGHT == blendType) { blend_mode = kCGBlendModeSoftLight; } else if (FXDIB_BLEND_SOFTLIGHT == blendType) { blend_mode = kCGBlendModeHardLight; } else if (blendType >= FXDIB_BLEND_NONSEPARABLE && blendType <= FXDIB_BLEND_LUMINOSITY) { blend_mode = blendType - 9; } else if (blendType > FXDIB_BLEND_LUMINOSITY || blendType < 0) { blend_mode = kCGBlendModeNormal; } CGContextSetBlendMode(_context, (CGBlendMode)blend_mode); CGContextDrawImage(_context, rect_usr, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; }
PassRefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const { float area = 4.0f * rect.width() * rect.height(); if (area > static_cast<float>(std::numeric_limits<int>::max())) return 0; RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); unsigned char* data = result->data(); int endx = ceilf(rect.maxX() * resolutionScale); int endy = ceilf(rect.maxY() * resolutionScale); if (rect.x() < 0 || rect.y() < 0 || endx > size.width() || endy > size.height()) result->zeroFill(); int originx = rect.x(); int destx = 0; int destw = rect.width(); if (originx < 0) { destw += originx; destx = -originx; originx = 0; } destw = min<int>(destw, ceilf(size.width() / resolutionScale) - originx); originx *= resolutionScale; if (endx > size.width()) endx = size.width(); int width = endx - originx; int originy = rect.y(); int desty = 0; int desth = rect.height(); if (originy < 0) { desth += originy; desty = -originy; originy = 0; } desth = min<int>(desth, ceilf(size.height() / resolutionScale) - originy); originy *= resolutionScale; if (endy > size.height()) endy = size.height(); int height = endy - originy; if (width <= 0 || height <= 0) return result.release(); unsigned destBytesPerRow = 4 * rect.width(); unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; unsigned srcBytesPerRow; unsigned char* srcRows; if (!accelerateRendering) { srcBytesPerRow = 4 * size.width(); srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) if (unmultiplied && haveVImageRoundingErrorFix()) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = desth; dst.width = destw; dst.rowBytes = destBytesPerRow; dst.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying will be done in-place. src = dst; } vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return result.release(); } #endif if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. if (!unmultiplied) return result.release(); srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width * 4; x += 4) reinterpret_cast<uint32_t*>(destRows + x)[0] = reinterpret_cast<uint32_t*>(srcRows + x)[0]; srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0); srcBytesPerRow = IOSurfaceGetBytesPerRow(surface); srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = desth; dest.width = destw; dest.rowBytes = destBytesPerRow; dest.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying and channel-swapping will be done in-place. if (unmultiplied) { srcRows = destRows; width = destw; height = desth; srcBytesPerRow = destBytesPerRow; } else src = dest; } if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline); } else { // Swap pixel channels from BGRA to RGBA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (b * 255) / alpha; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = srcRows[basex + 3]; } } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = srcRows[basex + 3]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } return result.release(); }
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte, long ix1, long ix2, long x1DC, long x2DC, long iy1, long iy2, long y1DC, long y2DC, double minimum, double maximum, long clipx1, long clipx2, long clipy1, long clipy2, int interpolate) { /*long t=clock();*/ long nx = ix2 - ix1 + 1; /* The number of cells along the horizontal axis. */ long ny = iy2 - iy1 + 1; /* The number of cells along the vertical axis. */ double dx = (double) (x2DC - x1DC) / (double) nx; /* Horizontal pixels per cell. Positive. */ double dy = (double) (y2DC - y1DC) / (double) ny; /* Vertical pixels per cell. Negative. */ double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale; if (x2DC <= x1DC || y1DC <= y2DC) return; trace ("scale %f", scale); /* Clip by the intersection of the world window and the outline of the cells. */ //Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2); if (clipx1 < x1DC) clipx1 = x1DC; if (clipx2 > x2DC) clipx2 = x2DC; if (clipy1 > y1DC) clipy1 = y1DC; if (clipy2 < y2DC) clipy2 = y2DC; /* * The first decision is whether we are going to use the standard rectangle drawing * (cellArray only), or whether we are going to write into a bitmap. * The standard drawing is best for small numbers of cells, * provided that some cells are larger than a pixel. */ if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) { try { /*unsigned int cellWidth = (unsigned int) dx + 1;*/ unsigned int cellHeight = (unsigned int) (- (int) dy) + 1; long ix, iy; #if cairo cairo_pattern_t *grey [256]; for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) { double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0); grey [igrey] = cairo_pattern_create_rgb (v, v, v); } #elif win static HBRUSH greyBrush [256]; RECT rect; if (! greyBrush [0]) for (int igrey = 0; igrey <= 255; igrey ++) greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey)); // once #elif mac GraphicsQuartz_initDraw (me); CGContextSetAlpha (my d_macGraphicsContext, 1.0); CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal); #endif autoNUMvector <long> lefts (ix1, ix2 + 1); for (ix = ix1; ix <= ix2 + 1; ix ++) lefts [ix] = x1DC + (long) ((ix - ix1) * dx); for (iy = iy1; iy <= iy2; iy ++) { long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight; if (top > clipy1 || bottom < clipy2) continue; if (top < clipy2) top = clipy2; if (bottom > clipy1) bottom = clipy1; #if win rect. bottom = bottom; rect. top = top; #endif for (ix = ix1; ix <= ix2; ix ++) { long left = lefts [ix], right = lefts [ix + 1]; if (right < clipx1 || left > clipx2) continue; if (left < clipx1) left = clipx1; if (right > clipx2) right = clipx2; if (z_rgbt) { #if cairo // NYI #elif win // NYI #elif mac double red = z_rgbt [iy] [ix]. red; double green = z_rgbt [iy] [ix]. green; double blue = z_rgbt [iy] [ix]. blue; double transparency = z_rgbt [iy] [ix]. transparency; red = ( red <= 0.0 ? 0.0 : red >= 1.0 ? 1.0 : red ); green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green ); blue = ( blue <= 0.0 ? 0.0 : blue >= 1.0 ? 1.0 : blue ); CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } else { #if cairo long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]); cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top); cairo_fill (my d_cairoGraphicsContext); #elif win long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); rect. left = left; rect. right = right; FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]); #elif mac double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0; CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } } } #if cairo for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) cairo_pattern_destroy (grey [igrey]); #elif mac CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0); GraphicsQuartz_exitDraw (me); #endif } catch (MelderError) { } } else { long xDC, yDC; long undersampling = 1; /* * Prepare for off-screen bitmap drawing. */ #if cairo long arrayWidth = clipx2 - clipx1; long arrayHeight = clipy1 - clipy2; trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight); cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight); unsigned char *bits = cairo_image_surface_get_data (sfc); int scanLineLength = cairo_image_surface_get_stride (sfc); unsigned char grey [256]; trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey)); for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++) grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1)); #elif win long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2; int igrey; /* * Create a device-independent bitmap, 32 bits deep. */ struct { BITMAPINFOHEADER header; } bitmapInfo; long scanLineLength = bitmapWidth * 4; // for 24 bits: (bitmapWidth * 3 + 3) & ~3L; HBITMAP bitmap; unsigned char *bits; // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection () bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER); bitmapInfo. header.biWidth = bitmapWidth; // scanLineLength; bitmapInfo. header.biHeight = bitmapHeight; bitmapInfo. header.biPlanes = 1; bitmapInfo. header.biBitCount = 32; bitmapInfo. header.biCompression = 0; bitmapInfo. header.biSizeImage = 0; bitmapInfo. header.biXPelsPerMeter = 0; bitmapInfo. header.biYPelsPerMeter = 0; bitmapInfo. header.biClrUsed = 0; bitmapInfo. header.biClrImportant = 0; bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, (VOID **) & bits, NULL, 0); #elif mac long bytesPerRow = (clipx2 - clipx1) * 4; Melder_assert (bytesPerRow > 0); long numberOfRows = clipy1 - clipy2; Melder_assert (numberOfRows > 0); unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows); #endif /* * Draw into the bitmap. */ #if cairo #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif win #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif mac #define ROW_START_ADDRESS (imageData + (clipy1 - 1 - yDC) * bytesPerRow) #define PUT_PIXEL \ if (my colourScale == kGraphics_colourScale_GREY) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \ if (value < 0.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ } else if (value < 64.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = (int) (value * 3 + 63.999); \ *pixelAddress ++ = 0; \ } else if (value < 128.0) { \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = 255; \ *pixelAddress ++ = 0; \ } else if (value < 192.0) { \ *pixelAddress ++ = 255; \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = 0; \ } else if (value < 256.0) { \ *pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } else { \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } \ } #else #define ROW_START_ADDRESS NULL #define PUT_PIXEL #endif if (interpolate) { try { autoNUMvector <long> ileft (clipx1, clipx2); autoNUMvector <long> iright (clipx1, clipx2); autoNUMvector <double> rightWeight (clipx1, clipx2); autoNUMvector <double> leftWeight (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC); ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1; rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC]; if (ileft [xDC] < ix1) ileft [xDC] = ix1; if (iright [xDC] > ix2) iright [xDC] = ix2; } for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC); long itop = ceil (iy_real), ibottom = itop - 1; double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight; unsigned char *pixelAddress = ROW_START_ADDRESS; if (itop > iy2) itop = iy2; if (ibottom < iy1) ibottom = iy1; if (z_float) { double *ztop = z_float [itop], *zbottom = z_float [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } else if (z_rgbt) { double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double red = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. red + bottomWeight * zbottom [ileft [xDC]]. red); double green = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. green + bottomWeight * zbottom [ileft [xDC]]. green); double blue = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. blue + bottomWeight * zbottom [ileft [xDC]]. blue); double transparency = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. transparency + bottomWeight * zbottom [ileft [xDC]]. transparency); if (red < 0.0) red = 0.0; else if (red > 1.0) red = 1.0; if (green < 0.0) green = 0.0; else if (green > 1.0) green = 1.0; if (blue < 0.0) blue = 0.0; else if (blue > 1.0) blue = 1.0; if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0; #if win *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = 0; #elif mac *pixelAddress ++ = red * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = transparency * 255.0; #elif cairo *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = transparency * 255.0; #endif } } else { unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } else { try { autoNUMvector <long> ix (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC)); for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC)); unsigned char *pixelAddress = ROW_START_ADDRESS; Melder_assert (iy >= iy1 && iy <= iy2); if (z_float) { double *ziy = z_float [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } else { unsigned char *ziy = z_byte [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } /* * Copy the bitmap to the screen. */ #if cairo cairo_matrix_t clip_trans; cairo_matrix_init_identity (& clip_trans); cairo_matrix_scale (& clip_trans, 1, -1); // we painted in the reverse y-direction cairo_matrix_translate (& clip_trans, - clipx1, - clipy1); cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc); trace ("bitmap pattern %p", bitmap_pattern); if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) { Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status)); } else { cairo_pattern_set_matrix (bitmap_pattern, & clip_trans); cairo_save (my d_cairoGraphicsContext); cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern); cairo_paint (my d_cairoGraphicsContext); cairo_restore (my d_cairoGraphicsContext); } cairo_pattern_destroy (bitmap_pattern); #elif win SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS); //StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, // bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY); #elif mac CGImageRef image; static CGColorSpaceRef colourSpace = NULL; if (colourSpace == NULL) { colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); // used to be kCGColorSpaceUserRGB Melder_assert (colourSpace != NULL); } if (1) { CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL, imageData, bytesPerRow * numberOfRows, _mac_releaseDataCallback // we need this because we cannot release the image data immediately after drawing, // because in PDF files the imageData has to stay available through EndPage ); Melder_assert (dataProvider != NULL); image = CGImageCreate (clipx2 - clipx1, numberOfRows, 8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault); CGDataProviderRelease (dataProvider); } else if (0) { Melder_assert (CGBitmapContextCreate != NULL); CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100, 8, 800, colourSpace, 0); Melder_assert (bitmaptest != NULL); CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows, 8, bytesPerRow, colourSpace, kCGImageAlphaLast); Melder_assert (bitmap != NULL); image = CGBitmapContextCreateImage (bitmap); // release bitmap? } Melder_assert (image != NULL); GraphicsQuartz_initDraw (me); CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image); GraphicsQuartz_exitDraw (me); //CGColorSpaceRelease (colourSpace); CGImageRelease (image); #endif /* * Clean up. */ #if cairo cairo_surface_destroy (sfc); #elif win DeleteBitmap (bitmap); #endif }
void CGContextSetBlendMode_wrap(CGContext *con, int j) { CGContextSetBlendMode(con, CGBlendMode(j)); }