void GiCanvasIos::endPaint(bool draw) { if (m_draw->getContext()) { if (draw && m_draw->_buffctx && m_draw->_context) { CGContextRef context = m_draw->_context; CGImageRef image = CGBitmapContextCreateImage(m_draw->_buffctx); CGRect rect = CGRectMake(0, 0, m_draw->width(), m_draw->height()); // 逻辑宽高点数 if (image) { CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height()); CGContextConcatCTM(context, af); // 图像是朝上的,上下文坐标系朝下,上下颠倒显示 CGInterpolationQuality old = CGContextGetInterpolationQuality(context); CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextDrawImage(context, rect, image); CGContextSetInterpolationQuality(context, old); CGContextConcatCTM(context, CGAffineTransformInvert(af)); // 恢复成坐标系朝下 CGImageRelease(image); } } if (m_draw->_buffctx) { CGContextRelease(m_draw->_buffctx); m_draw->_buffctx = NULL; } m_draw->_context = NULL; if (owner()) owner()->_endPaint(); } }
bool GiCanvasIos::drawCachedBitmap2(const GiCanvas* p, float x, float y, bool secondBmp) { bool ret = false; if (p && p->getCanvasType() == getCanvasType()) { GiCanvasIos* gs = (GiCanvasIos*)p; int index = secondBmp ? 1 : 0; CGImageRef image = gs->m_draw->_cacheserr[index] ? NULL : gs->m_draw->_caches[index]; CGContextRef context = m_draw->getContext(); if (context && image) { CGRect rect = CGRectMake(x, y, m_draw->width(), m_draw->height()); CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height()); CGContextConcatCTM(context, af); CGInterpolationQuality oldQuality = CGContextGetInterpolationQuality(context); CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextDrawImage(context, rect, image); CGContextSetInterpolationQuality(context, oldQuality); CGContextConcatCTM(context, CGAffineTransformInvert(af)); ret = true; } } return ret; }
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 }
void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) { if (paintingDisabled()) return; CGInterpolationQuality quality = kCGInterpolationDefault; switch (mode) { case InterpolationDefault: quality = kCGInterpolationDefault; break; case InterpolationNone: quality = kCGInterpolationNone; break; case InterpolationLow: quality = kCGInterpolationLow; break; // Fall through to InterpolationHigh if kCGInterpolationMedium is not usable. case InterpolationMedium: #if USE(CG_INTERPOLATION_MEDIUM) quality = kCGInterpolationMedium; break; #endif case InterpolationHigh: quality = kCGInterpolationHigh; break; } CGContextSetInterpolationQuality(platformContext(), quality); }
/* draw image to frame */ static void icvDrawImage( CvWindow* window ) { Assert( window != 0 ); if( window->imageRef == 0 ) return; CGContextRef myContext; CvTrackbar* t; CGRect rect; Rect portrect; int width = window->imageWidth; int height = window->imageHeight; GetWindowPortBounds(window->window, &portrect); if( window->flags & CV_WINDOW_AUTOSIZE ) { CGPoint origin = {0,0}; CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight}; rect.origin = origin; rect.size = size; } else { CGPoint origin = {0, portrect.bottom - height - window->trackbarheight}; CGSize size = {width, height}; rect.origin = origin; rect.size = size; } /* To be sybnchronous we are using this, better would be to susbcribe to the draw event and process whenever requested, we might save SOME CPU cycles*/ SetPortWindowPort (window->window); QDBeginCGContext (GetWindowPort (window->window), &myContext); CGContextSetInterpolationQuality (myContext, kCGInterpolationLow); CGContextDrawImage(myContext,rect,window->imageRef); CGContextFlush(myContext);// 4 QDEndCGContext (GetWindowPort(window->window), &myContext);// 5 }
DRAW_TEST_F(CGContext, DrawAnImageWithInterpolationQualityAndAlpha, UIKitMimicTest<>) { auto drawingConfig = DrawingTestConfig::Get(); woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("png1.9.png")) }; woc::unique_cf<CGImageRef> image{ _CGImageCreateFromPNGFile(testFilename.get()) }; ASSERT_NE(image, nullptr); CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); CGContextSetAlpha(context, 0.25); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); CGContextDrawImage(context, bounds, image.get()); }
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 }
bool GiCanvasIos::drawCachedBitmap(float x, float y, bool secondBmp) { int index = secondBmp ? 1 : 0; CGImageRef image = m_draw->_cacheserr[index] ? NULL : m_draw->_caches[index]; CGContextRef context = m_draw->getContext(); bool ret = false; if (context && image) { CGRect rect = CGRectMake(x, y, m_draw->width(), m_draw->height()); CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height()); CGContextConcatCTM(context, af); // 图像是朝上的,上下文坐标系朝下,上下颠倒显示 CGInterpolationQuality oldQuality = CGContextGetInterpolationQuality(context); CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextDrawImage(context, rect, image); CGContextSetInterpolationQuality(context, oldQuality); CGContextConcatCTM(context, CGAffineTransformInvert(af)); // 恢复成坐标系朝下 ret = true; } return ret; }
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); }
bool GCPVideoRenderer::OnWindowRefresh(FB::RefreshEvent* pEvt) { FB::CoreGraphicsDraw* pCgDrawEvt(static_cast<FB::CoreGraphicsDraw*>(pEvt)); CGContextRef pContext = pCgDrawEvt->context; boost::mutex::scoped_lock winLock(m_winMutex); const int stride = m_width*4; const int frameBufferSize = m_height*stride; static SInt32 osMajorVersion = 0; static SInt32 osMinorVersion = 0; static CGInterpolationQuality interpolationMode = kCGInterpolationNone; if(0 == osMajorVersion || 0 == osMinorVersion) { if(noErr != Gestalt(gestaltSystemVersionMajor, &osMajorVersion)) { osMajorVersion = 10; } if(noErr != Gestalt(gestaltSystemVersionMinor, &osMinorVersion)) { osMinorVersion = 6; } if(10 <= osMajorVersion && 7 <= osMinorVersion) { interpolationMode = kCGInterpolationDefault; } } if(NULL == pContext || NULL == m_pFrameBuffer.get()) { return false; } int winWidth = pCgDrawEvt->bounds.right - pCgDrawEvt->bounds.left; int winHeight = pCgDrawEvt->bounds.bottom - pCgDrawEvt->bounds.top; if(winWidth<=1 || winHeight<=1) return false; CGContextSaveGState(pContext); CGContextSetShouldAntialias(pContext, true); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGImageRef cgImage = CGImageCreate(m_width, m_height, 8, 32, stride, colorSpace, kCGImageAlphaNoneSkipLast, CGDataProviderCreateWithData(NULL, m_pFrameBuffer.get(), frameBufferSize, NULL), NULL, false, kCGRenderingIntentDefault); if(NULL == cgImage) { CGColorSpaceRelease(colorSpace); CGContextRestoreGState(pContext); return false; } CGContextSetInterpolationQuality(pContext, interpolationMode); CGContextTranslateCTM(pContext, 0, winHeight); CGContextScaleCTM(pContext, 1, -1); CGContextDrawImage(pContext, CGRectMake(0, 0, winWidth, winHeight), cgImage); CGImageRelease(cgImage); CGColorSpaceRelease(colorSpace); CGContextRestoreGState(pContext); return true; }
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF16 ch) const { // We use some static data here to avoid re allocating the same variable in a loop. // this func is primarily called by GFont::loadCharInfo(), Rect imageRect; CGContextRef imageCtx; U32 bitmapDataSize; ATSUTextMeasurement tbefore, tafter, tascent, tdescent; OSStatus err; // 16 bit character buffer for the ATUSI calls. // -- hey... could we cache this at the class level, set style and loc *once*, // then just write to this buffer and clear the layout cache, to speed up drawing? static UniChar chUniChar[1]; chUniChar[0] = ch; // Declare and clear out the CharInfo that will be returned. static PlatformFont::CharInfo c; dMemset(&c, 0, sizeof(c)); // prep values for GFont::addBitmap() c.bitmapIndex = 0; c.xOffset = 0; c.yOffset = 0; // put the text in the layout. // we've hardcoded a string length of 1 here, but this could work for longer strings... (hint hint) // note: ATSUSetTextPointerLocation() also clears the previous cached layout information. ATSUSetTextPointerLocation( mLayout, chUniChar, 0, 1, 1); ATSUSetRunStyle( mLayout, mStyle, 0,1); // get the typographic bounds. this tells us how characters are placed relative to other characters. ATSUGetUnjustifiedBounds( mLayout, 0, 1, &tbefore, &tafter, &tascent, &tdescent); c.xIncrement = FixedToInt(tafter); // find out how big of a bitmap we'll need. // as a bonus, we also get the origin where we should draw, encoded in the Rect. ATSUMeasureTextImage( mLayout, 0, 1, 0, 0, &imageRect); U32 xFudge = 2; U32 yFudge = 1; c.width = imageRect.right - imageRect.left + xFudge; // add 2 because small fonts don't always have enough room c.height = imageRect.bottom - imageRect.top + yFudge; c.xOrigin = imageRect.left; // dist x0 -> center line c.yOrigin = -imageRect.top; // dist y0 -> base line // kick out early if the character is undrawable if( c.width == xFudge || c.height == yFudge) return c; // allocate a greyscale bitmap and clear it. bitmapDataSize = c.width * c.height; c.bitmapData = new U8[bitmapDataSize]; dMemset(c.bitmapData,0x00,bitmapDataSize); // get a graphics context on the bitmap imageCtx = CGBitmapContextCreate( c.bitmapData, c.width, c.height, 8, c.width, mColorSpace, kCGImageAlphaNone); if(!imageCtx) { Con::errorf("Error: failed to create a graphics context on the CharInfo bitmap! Drawing a blank block."); c.xIncrement = c.width; dMemset(c.bitmapData,0x0F,bitmapDataSize); return c; } // Turn off antialiasing for monospaced console fonts. yes, this is cheating. if(mSize < 12 && ( dStrstr(mName,"Monaco")!=NULL || dStrstr(mName,"Courier")!=NULL )) CGContextSetShouldAntialias(imageCtx, false); // Set up drawing options for the context. // Since we're not going straight to the screen, we need to adjust accordingly CGContextSetShouldSmoothFonts(imageCtx, false); CGContextSetRenderingIntent(imageCtx, kCGRenderingIntentAbsoluteColorimetric); CGContextSetInterpolationQuality( imageCtx, kCGInterpolationNone); CGContextSetGrayFillColor( imageCtx, 1.0, 1.0); CGContextSetTextDrawingMode( imageCtx, kCGTextFill); // tell ATSUI to substitute fonts as needed for missing glyphs ATSUSetTransientFontMatching(mLayout, true); // set up three parrallel arrays for setting up attributes. // this is how most options in ATSUI are set, by passing arrays of options. ATSUAttributeTag theTags[] = { kATSUCGContextTag }; ByteCount theSizes[] = { sizeof(CGContextRef) }; ATSUAttributeValuePtr theValues[] = { &imageCtx }; // bind the layout to the context. ATSUSetLayoutControls( mLayout, 1, theTags, theSizes, theValues ); // Draw the character! int yoff = c.height < 3 ? 1 : 0; // kludge for 1 pixel high characters, such as '-' and '_' int xoff = 1; err = ATSUDrawText( mLayout, 0, 1, IntToFixed(-imageRect.left + xoff), IntToFixed(imageRect.bottom + yoff ) ); CGContextRelease(imageCtx); if(err != noErr) { Con::errorf("Error: could not draw the character! Drawing a blank box."); dMemset(c.bitmapData,0x0F,bitmapDataSize); } #if TORQUE_DEBUG // Con::printf("Font Metrics: Rect = %2i %2i %2i %2i Char= %C, 0x%x Size= %i, Baseline= %i, Height= %i",imageRect.top, imageRect.bottom, imageRect.left, imageRect.right,ch,ch, mSize,mBaseline, mHeight); // Con::printf("Font Bounds: left= %2i right= %2i Char= %C, 0x%x Size= %i",FixedToInt(tbefore), FixedToInt(tafter), ch,ch, mSize); #endif return c; }
/* read image file */ int BIReadFile( const char *fileName, BIFileType fileType, BIPadMode padMode, unsigned padSize, BIImageInfo *imageInfo, /* RETURNED */ unsigned char **bitmap) /* mallocd and RETURNED; caller must free */ { CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (unsigned char*)fileName, strlen(fileName), FALSE); if(fileURL == NULL) { fprintf(stderr, "***BIReadFile: Error on CFURLCreateFromFileSystemRepresentation\n"); return -1; } CFStringRef keys[1] = {kCGImageSourceTypeIdentifierHint}; CFStringRef values[1] = {BIGetUTI(fileURL, fileType)}; if(values[0] == NULL) { return -1; } CFDictionaryRef optionsDict = NULL; CGImageSourceRef imageSourceRef = NULL; CGImageRef imageRef = NULL; CGColorSpaceRef rgbColorSpaceRef = NULL; CGContextRef bitmapContextRef = NULL; CGBitmapInfo bitmapInfo = 0; CGImageAlphaInfo alpha; unsigned bytesPerPixel = 4; optionsDict = CFDictionaryCreate( kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); /* subsequent errors to errOut: */ int ourRtn = 0; /* source file --> CGImageRef */ imageSourceRef = CGImageSourceCreateWithURL(fileURL, optionsDict); if(imageSourceRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateWithURL\n"); ourRtn = 1; goto errOut; } CFRELEASE(fileURL); imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, optionsDict ); if(imageRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateImageAtIndex\n"); ourRtn = 1; goto errOut; } imageInfo->imageWidth = CGImageGetWidth(imageRef); imageInfo->imageHeight = CGImageGetHeight(imageRef); imageInfo->bitsPerComponent = CGImageGetBitsPerComponent(imageRef); imageInfo->bitsPerPixel = CGImageGetBitsPerPixel(imageRef); if(imageInfo->bitsPerPixel == 8) { /* the image is gray */ rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); imageInfo->bytesPerRow = imageInfo->imageWidth; alpha = kCGImageAlphaNone; bitmapInfo = CGImageGetBitmapInfo(imageRef); bytesPerPixel = 1; } else { rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB(); imageInfo->bytesPerRow = imageInfo->imageWidth * 4; alpha = kCGImageAlphaPremultipliedLast; bitmapInfo = kCGBitmapByteOrder32Big | alpha; } if(rgbColorSpaceRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGColorSpaceCreateWithName\n"); ourRtn = 1; goto errOut; } /* optionally pad */ imageInfo->effectHeight = imageInfo->imageHeight; if(padMode != PM_None) { if(padSize == 0) { fprintf(stderr, "***Pad size of 0 invalid\n"); ourRtn = 1; goto errOut; } unsigned padSizeBytes = padSize; if(padMode == PM_Pixels) { padSizeBytes *= bytesPerPixel; } imageInfo->bytesPerRow = ROUND_TO(imageInfo->bytesPerRow, padSizeBytes); /* also round up row count */ imageInfo->effectHeight = ROUND_TO(imageInfo->imageHeight, padSize); } *bitmap = (unsigned char *)malloc(imageInfo->bytesPerRow * imageInfo->effectHeight); bitmapContextRef = CGBitmapContextCreate(*bitmap, imageInfo->imageWidth, imageInfo->imageHeight, imageInfo->bitsPerComponent, imageInfo->bytesPerRow, rgbColorSpaceRef, bitmapInfo); if(bitmapContextRef == NULL) { fprintf(stderr, "***BIReadFile: Error creating CGBitmapContext\n"); ourRtn = 1; goto errOut; } /* enable high quality interpolation */ CGContextSetInterpolationQuality(bitmapContextRef, kCGInterpolationHigh); /* Draw into the context */ CGContextDrawImage(bitmapContextRef, CGRectMake(0, 0, imageInfo->imageWidth, imageInfo->imageHeight), imageRef); errOut: CFRELEASE(optionsDict); CFRELEASE(imageSourceRef); CFRELEASE(imageRef); CFRELEASE(rgbColorSpaceRef); CFRELEASE(bitmapContextRef); if(ourRtn) { if(*bitmap) { free(*bitmap); *bitmap = NULL; } } return ourRtn; }
FX_BOOL CFX_QuartzDeviceDriver::StretchDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, int dest_left, int dest_top, int dest_width, int dest_height, const FX_RECT* clipRect, FX_DWORD flags, int alphaFlag , void* iccTransform , int blend_type) { SaveState(); if (clipRect) { CGContextBeginPath(_context); CGRect rect_clip = CGRectMake(clipRect->left, clipRect->top, clipRect->Width(), clipRect->Height()); rect_clip = CGRectApplyAffineTransform(rect_clip, _foxitDevice2User); CGContextAddRect(_context, rect_clip); CGContextClip(_context); } CGRect rect = CGRectMake(dest_left, dest_top, dest_width, dest_height); rect = CGRectApplyAffineTransform(rect, _foxitDevice2User); if (FXDIB_BICUBIC_INTERPOL == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationHigh); } else if (FXDIB_DOWNSAMPLE == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationNone); } else { CGContextSetInterpolationQuality(_context, kCGInterpolationMedium); } CG_SetImageTransform(dest_left, dest_top, dest_width, dest_height); 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, 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); 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); CGContextDrawImage(_context, rect, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; }
void CGContextSetInterpolationQuality_wrap(CGContext *con, int j) { CGContextSetInterpolationQuality(con, CGInterpolationQuality(j)); }