Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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
}
Ejemplo n.º 13
0
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());
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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());
}
Ejemplo n.º 16
0
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);
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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)
    }
}
Ejemplo n.º 19
0
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);
}
Ejemplo n.º 20
0
void QuartzWindow::set_copy()  { CGContextSetBlendMode(myContext, kCGBlendModeNormal);  }
Ejemplo n.º 21
0
void QuartzWindow::set_xor()   { CGContextSetBlendMode(myContext, kCGBlendModeDifference);  }
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
static void quartzRevertLine (GraphicsScreen me) {
    if (my duringXor) {
        CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal);
        CGContextSetAllowsAntialiasing (my d_macGraphicsContext, true);
    }
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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();
}
Ejemplo n.º 27
0
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
	}
Ejemplo n.º 28
0
void CGContextSetBlendMode_wrap(CGContext *con, int j) {
  CGContextSetBlendMode(con, CGBlendMode(j));
}