static inline bool createMaskAndSwapContextForTextGradient(
    GraphicsContext*& context, GraphicsContext*& savedContext,
    OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object)
{
    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
    IntRect maskRect = enclosingIntRect(object->absoluteTransform().mapRect(maskBBox));

    IntSize maskSize(maskRect.width(), maskRect.height());
    clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);

    auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskSize, false);

    if (!maskImage.get())
        return false;

    GraphicsContext* maskImageContext = maskImage->context();

    maskImageContext->save();
    maskImageContext->translate(-maskRect.x(), -maskRect.y());
    maskImageContext->concatCTM(object->absoluteTransform());

    imageBuffer.set(maskImage.release());
    savedContext = context;

    context = maskImageContext;

    return true;
}
static inline void clipToTextMask(GraphicsContext* context,
    OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object,
    const SVGPaintServerGradient* gradientServer)
{
    FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);

    // Fixup transformations to be able to clip to mask
    TransformationMatrix transform = object->absoluteTransform();
    FloatRect textBoundary = transform.mapRect(maskBBox);

    IntSize maskSize(lroundf(textBoundary.width()), lroundf(textBoundary.height()));
    clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);
    textBoundary.setSize(textBoundary.size().shrunkTo(maskSize));

    // Clip current context to mask image (gradient)
    context->concatCTM(transform.inverse());
    context->clipToImageBuffer(textBoundary, imageBuffer.get());
    context->concatCTM(transform);

    if (gradientServer->boundingBoxMode()) {
        context->translate(maskBBox.x(), maskBBox.y());
        context->scale(FloatSize(maskBBox.width(), maskBBox.height()));
    }
    context->concatCTM(gradientServer->gradientTransform());
}
예제 #3
0
void CGdiBlitMasked::BaseTest(const TRect &aRect, TInt)
	{
// needs re-writing to emulate tiling of the source rect
	if (!aRect.Intersects(TRect(BaseWin->Size())))
		return;
	TSize size(aRect.Size());
	TSize bitSize=iBitmap->SizeInPixels();
	if (size.iWidth>bitSize.iWidth)
		size.iWidth=bitSize.iWidth;
	if (size.iHeight>bitSize.iHeight)
		size.iHeight=bitSize.iHeight;
//
// Set up the scratch mask as a black and white bitmap containing the mask to blit
// The mask pattern is replicated all over the scratchmask bitmap
//
	iScratchMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	iScratchMaskGc->SetPenStyle(CGraphicsContext::ENullPen);
	iScratchMaskGc->SetBrushColor(TRgb(0,0,0));
	iScratchMaskGc->DrawRect(TRect(iScratchMask->SizeInPixels()));
	iScratchMaskGc->SetPenColor(TRgb(255,255,255));
	iScratchMaskGc->SetPenStyle(CGraphicsContext::ESolidPen);
	TSize maskSize(iCurrMask->SizeInPixels());
	TPoint pos;
	TRgb *rgbBuf=(TRgb *)User::AllocL(maskSize.iWidth*sizeof(TRgb));		//Doesn't do any harm if it leaves
	for(pos.iY=0;pos.iY<maskSize.iHeight;pos.iY++)
		{
		TPtr8 ptr((TUint8 *)rgbBuf,maskSize.iWidth*sizeof(TRgb));
		iCurrMask->GetScanLine(ptr, pos, maskSize.iWidth, ERgb);
		for(TInt index=0;index<maskSize.iWidth;index++)
			{
			iScratchMaskGc->SetPenColor(rgbBuf[index]);
//			if ((isLow && !iLowCutOff) || (!isLow && iLowCutOff))
				iScratchMaskGc->Plot(TPoint(index,pos.iY));
			}
		}
	User::Free(rgbBuf);

	for(pos.iY=0;pos.iY<size.iHeight;pos.iY+=maskSize.iHeight)
		for(pos.iX=0;pos.iX<size.iWidth;pos.iX+=maskSize.iWidth)
			iScratchMaskGc->CopyRect(pos, TRect(maskSize));
//
// Blit this to the screen in ANDNOT mode to clear all the pixels we want the mask blit to draw to
//
	iGdi->SetDrawMode(CGraphicsContext::EDrawModeANDNOT);
	iGdi->BitBlt(aRect.iTl, iScratchMask, TRect(size));
//
// Copy the test bitmap to the scratch bitmap then use the scratch mask to clear all the bits
// that should masked out of the draw to the screen
//
	iScratchGc->SetDrawMode(CGraphicsContext::EDrawModePEN);
	iScratchGc->BitBlt(TPoint(0,0), iBitmap);
	iScratchGc->SetDrawMode(CGraphicsContext::EDrawModeAND);
	iScratchGc->BitBlt(TPoint(0,0), iScratchMask);
//
// Now copy the scratch bitmap to the screen in OR mode to get the final result
//
	iGdi->SetDrawMode(CGraphicsContext::EDrawModeOR);
	iGdi->BitBlt(aRect.iTl, iScratch, TRect(size));
	}