Exemplo n.º 1
0
static HCURSOR CreateCompatibleCursor(FTexture *cursorpic)
{
	int picwidth = cursorpic->GetWidth();
	int picheight = cursorpic->GetHeight();

	// Create bitmap masks for the cursor from the texture.
	HDC dc = GetDC(NULL);
	if (dc == NULL)
	{
		return nullptr;
	}
	HDC and_mask_dc = CreateCompatibleDC(dc);
	HDC xor_mask_dc = CreateCompatibleDC(dc);
	HBITMAP and_mask = CreateCompatibleBitmap(dc, 32, 32);
	HBITMAP xor_mask = CreateCompatibleBitmap(dc, 32, 32);
	ReleaseDC(NULL, dc);

	SelectObject(and_mask_dc, and_mask);
	SelectObject(xor_mask_dc, xor_mask);

	// Initialize with an invisible cursor.
	SelectObject(and_mask_dc, GetStockObject(WHITE_PEN));
	SelectObject(and_mask_dc, GetStockObject(WHITE_BRUSH));
	Rectangle(and_mask_dc, 0, 0, 32, 32);
	SelectObject(xor_mask_dc, GetStockObject(BLACK_PEN));
	SelectObject(xor_mask_dc, GetStockObject(BLACK_BRUSH));
	Rectangle(xor_mask_dc, 0, 0, 32, 32);

	FBitmap bmp;
	const uint8_t *pixels;

	bmp.Create(picwidth, picheight);
	cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
	pixels = bmp.GetPixels();

	// Copy color data from the source texture to the cursor bitmaps.
	for (int y = 0; y < picheight; ++y)
	{
		for (int x = 0; x < picwidth; ++x)
		{
			const uint8_t *bgra = &pixels[x*4 + y*bmp.GetPitch()];
			if (bgra[3] != 0)
			{
				SetPixelV(and_mask_dc, x, y, RGB(0,0,0));
				SetPixelV(xor_mask_dc, x, y, RGB(bgra[2], bgra[1], bgra[0]));
			}
		}
	}
	DeleteDC(and_mask_dc);
	DeleteDC(xor_mask_dc);

	// Create the cursor from the bitmaps.
	return CreateBitmapCursor(cursorpic->LeftOffset, cursorpic->TopOffset, and_mask, xor_mask);
}
Exemplo n.º 2
0
int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
	int retv = -1;

	if (bRedirect)
	{ // Redirect straight to the real texture's routine.
		return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf);
	}

	if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE)))
	{ // We are doing some sort of fancy stuff to the destination bitmap, so composite to
	  // a temporary bitmap, and copy that.
		FBitmap tbmp;
		if (tbmp.Create(Width, Height))
		{
			retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0));
			bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height,
				4, tbmp.GetPitch(), rotate, CF_BGRA, inf);
		}
		return retv;
	}

	// When compositing a multipatch texture with multipatch parts,
	// drawing must be restricted to the actual area which is covered by this texture.
	FClipRect saved_cr = bmp->GetClipRect();
	bmp->IntersectClipRect(x, y, Width, Height);

	if (inf != NULL && inf->op == OP_OVERWRITE)
	{
		bmp->Zero();
	}

	for(int i = 0; i < NumParts; i++)
	{
		int ret = -1;
		FCopyInfo info;

		if (Parts[i].Texture->bHasCanvas) continue;	// cannot use camera textures as patch.

		memset (&info, 0, sizeof(info));
		info.alpha = Parts[i].Alpha;
		info.invalpha = BLENDUNIT - info.alpha;
		info.op = ECopyOp(Parts[i].op);
		PalEntry b = Parts[i].Blend;
		if (b.a == 0 && b != BLEND_NONE)
		{
			info.blend = EBlend(b.d);
		}
		else if (b.a != 0)
		{
			if (b.a == 255)
			{
				info.blendcolor[0] = b.r * BLENDUNIT / 255;
				info.blendcolor[1] = b.g * BLENDUNIT / 255;
				info.blendcolor[2] = b.b * BLENDUNIT / 255;
				info.blend = BLEND_MODULATE;
			}
			else
			{
				blend_t blendalpha = b.a * BLENDUNIT / 255;
				info.blendcolor[0] = b.r * blendalpha;
				info.blendcolor[1] = b.g * blendalpha;
				info.blendcolor[2] = b.b * blendalpha;
				info.blendcolor[3] = FRACUNIT - blendalpha;
				info.blend = BLEND_OVERLAY;
			}
		}

		if (Parts[i].Translation != NULL)
		{ // Using a translation forces downconversion to the base palette
			ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation->Palette, &info);
		}
		else
		{
			ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info);
		}
		// treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done.
		if (ret == -1) retv = ret;
		else if (retv != -1 && ret > retv) retv = ret;
	}
	// Restore previous clipping rectangle.
	bmp->SetClipRect(saved_cr);
	return retv;
}