Beispiel #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);
}
Beispiel #2
0
int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion)
{
	int retv = -1;

	if (conversion == noremap0)
	{
		if (bTextual || !UseGamePalette()) conversion = normal;
	}

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

		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;
			}
		}

		auto trans = Parts[i].Translation ? Parts[i].Translation->Palette : nullptr;
		FBitmap Pixels = Parts[i].Image->GetCachedBitmap(trans, conversion, &ret);
		bmp->Blit(Parts[i].OriginX, Parts[i].OriginY, Pixels, Pixels.GetWidth(), Pixels.GetHeight(), 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;
	}
	return retv;
}
Beispiel #3
0
unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck, bool createexpanded, bool alphatrans)
{
	unsigned char * buffer;
	int W, H;
	int isTransparent = -1;


	// Textures that are already scaled in the texture lump will not get replaced
	// by hires textures
	if (gl_texture_usehires && hirescheck != NULL && !alphatrans)
	{
		buffer = LoadHiresTexture (hirescheck, &w, &h);
		if (buffer)
		{
			return buffer;
		}
	}

	int exx = bExpandFlag && createexpanded;

	W = w = tex->GetWidth() + 2 * exx;
	H = h = tex->GetHeight() + 2 * exx;


	buffer=new unsigned char[W*(H+1)*4];
	memset(buffer, 0, W * (H+1) * 4);

	FGLBitmap bmp(buffer, W*4, W, H);
	bmp.SetTranslationInfo(translation, alphatrans);

	if (tex->bComplex)
	{
		FBitmap imgCreate;

		// The texture contains special processing so it must be composited using the
		// base bitmap class and then be converted as a whole.
		if (imgCreate.Create(W, H))
		{
			memset(imgCreate.GetPixels(), 0, W * H * 4);
			int trans = tex->CopyTrueColorPixels(&imgCreate, exx, exx);
			bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), W, H, 4, W * 4, 0, CF_BGRA);
			tex->CheckTrans(buffer, W*H, trans);
			isTransparent = tex->gl_info.mIsTransparent;
			if (bIsTransparent == -1) bIsTransparent = isTransparent;
		}
	}
	else if (translation<=0)
	{
		int trans = tex->CopyTrueColorPixels(&bmp, exx, exx);
		tex->CheckTrans(buffer, W*H, trans);
		isTransparent = tex->gl_info.mIsTransparent;
		if (bIsTransparent == -1) bIsTransparent = isTransparent;
	}
	else
	{
		// When using translations everything must be mapped to the base palette.
		// Since FTexture's method is doing exactly that by calling GetPixels let's use that here
		// to do all the dirty work for us. ;)
		tex->FTexture::CopyTrueColorPixels(&bmp, exx, exx);
		isTransparent = 0;
		// This is not conclusive for setting the texture's transparency info.
	}

	// if we just want the texture for some checks there's no need for upsampling.
	if (!createexpanded) return buffer;

	// [BB] The hqnx upsampling (not the scaleN one) destroys partial transparency, don't upsamle textures using it.
	// [BB] Potentially upsample the buffer.
	return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, !!isTransparent);
}
Beispiel #4
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;
}
Beispiel #5
0
TArray<uint8_t> FMultiPatchTexture::CreatePalettedPixels(int conversion)
{
	int numpix = Width * Height;
	uint8_t blendwork[256];
	bool buildrgb = bComplex;

	TArray<uint8_t> Pixels(numpix, true);
	memset (Pixels.Data(), 0, numpix);

	if (conversion == luminance)
	{
		// For alpha textures, downconversion to the palette would lose too much precision if not all patches use the palette.
		buildrgb = !UseGamePalette();
	}
	else
	{
		// For regular textures we can use paletted compositing if all patches are just being copied because they all can create a paletted buffer.
		if (!buildrgb) for (int i = 0; i < NumParts; ++i)
		{
			if (Parts[i].op != OP_COPY)
			{
				buildrgb = true;
			}
		}
	}
	if (conversion == noremap0)
	{
		// sky remapping will only happen if
		// - the texture was defined through a TEXTUREx lump (this implies only trivial copies)
		// - all patches use the base palette.
		// All other cases would not be able to properly deal with this special case.
		// For textual definitions this hack isn't necessary.
		if (bTextual || !UseGamePalette()) conversion = normal;
	}

	if (!buildrgb)
	{	
		for (int i = 0; i < NumParts; ++i)
		{
			uint8_t *trans = Parts[i].Translation? Parts[i].Translation->Remap : nullptr;
			{
				if (Parts[i].Blend != 0)
				{
					trans = GetBlendMap(Parts[i].Blend, blendwork);
				}
				CopyToBlock (Pixels.Data(), Width, Height, Parts[i].Image, Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, conversion);
			}
		}
	}
	else
	{
		// In case there are translucent patches let's do the composition in
		// True color to keep as much precision as possible before downconverting to the palette.
		FBitmap PixelsIn;
		PixelsIn.Create(Width, Height);
		CopyPixels(&PixelsIn, normal);
		for(int y = 0; y < Height; y++)
		{
			uint8_t *in = PixelsIn.GetPixels() + Width * y * 4;
			uint8_t *out = Pixels.Data() + y;
			for (int x = 0; x < Width; x++)
			{
				if (*out == 0 && in[3] != 0)
				{
					*out = ImageHelpers::RGBToPalette(conversion == luminance, in[2], in[1], in[0]);
				}
				out += Height;
				in += 4;
			}
		}
	}
	return Pixels;
}
Beispiel #6
0
unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck, bool createexpanded, bool alphatrans)
{
	unsigned char * buffer;
	int W, H;
	int isTransparent = -1;


	// Textures that are already scaled in the texture lump will not get replaced
	// by hires textures
	if (gl_texture_usehires && hirescheck != NULL && !alphatrans)
	{
		buffer = LoadHiresTexture (hirescheck, &w, &h);
		if (buffer)
		{
			return buffer;
		}
	}

	int exx = bExpandFlag && createexpanded;

	W = w = tex->GetWidth() + 2 * exx;
	H = h = tex->GetHeight() + 2 * exx;


	buffer=new unsigned char[W*(H+1)*4];
	memset(buffer, 0, W * (H+1) * 4);

	FBitmap bmp(buffer, W*4, W, H);

	if (translation <= 0)
	{
		// Q: Is this special treatment still needed? Needs to be checked.
		if (tex->bComplex)
		{
			FBitmap imgCreate;

			// The texture contains special processing so it must be fully composited before being converted as a whole.
			if (imgCreate.Create(W, H))
			{
				memset(imgCreate.GetPixels(), 0, W * H * 4);
				int trans = tex->CopyTrueColorPixels(&imgCreate, exx, exx);
				bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), W, H, 4, W * 4, 0, CF_BGRA);
				tex->CheckTrans(buffer, W*H, trans);
				isTransparent = tex->gl_info.mIsTransparent;
				if (bIsTransparent == -1) bIsTransparent = isTransparent;
			}
		}
		else
		{
			int trans = tex->CopyTrueColorPixels(&bmp, exx, exx);
			tex->CheckTrans(buffer, W*H, trans);
			isTransparent = tex->gl_info.mIsTransparent;
			if (bIsTransparent == -1) bIsTransparent = isTransparent;
		}
	}
	else
	{
#ifdef __MOBILE__
        if( alphatrans )
        {
            //tex->CopyTrueColorRedToAlpha(&bmp, exx, exx);#
            tex->CopyTrueColorPixels(&bmp, exx, exx);
            uint32_t* pix = ( uint32_t *)bmp.GetPixels();
            uint32_t w = bmp.GetWidth();
            uint32_t h = bmp.GetHeight();
            uint32_t pit = bmp.GetPitch();
            LOGI("%d  %d  %d",w,h,pit);
            for(int y = 0; y < h; y++ )
            {
                for(int x = 0; x < w; x++ )
                {
                    uint32_t p = *pix;
                    p = (p & 0x00FFFFFF) | ((p & 0x00FF0000) << 8); // Copy red to alpha channel
                    *pix = p;
                    pix++;
                }
            }
            isTransparent = 0;
        }
        else
#endif
        {
		    // When using translations everything must be mapped to the base palette.
		    // so use CopyTrueColorTranslated
		    tex->CopyTrueColorTranslated(&bmp, exx, exx, 0, GLTranslationPalette::GetPalette(translation));
		    isTransparent = 0;
		    // This is not conclusive for setting the texture's transparency info.
		}
	}

	// if we just want the texture for some checks there's no need for upsampling.
	if (!createexpanded) return buffer;

	// [BB] The hqnx upsampling (not the scaleN one) destroys partial transparency, don't upsamle textures using it.
	// [BB] Potentially upsample the buffer.
	return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, !!isTransparent);
}