openclonk/src/graphics/C4FacetEx.cpp

226 lines
6.3 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2004, 2008 Matthes Bender
* Copyright (c) 2002, 2006, 2008 Sven Eberhardt
* Copyright (c) 2006-2009 Günther Brammer
* Copyright (c) 2009 Nicolas Hake
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* A facet that can hold its own surface and also target coordinates */
#include <C4Include.h>
#include <C4FacetEx.h>
#include <C4Random.h>
#include <C4Rect.h>
#include <C4Group.h>
void C4TargetFacet::Set(C4Surface * nsfc, int nx, int ny, int nwdt, int nhgt, float ntx, float nty, float Zoom)
{
C4Facet::Set(nsfc, nx, ny, nwdt, nhgt);
TargetX = ntx; TargetY = nty; this->Zoom = Zoom;
}
void C4TargetFacet::Set(C4Surface * nsfc, const C4Rect & r, float ntx, float nty, float Zoom)
{
Set(nsfc, r.x, r.y, r.Wdt, r.Hgt, ntx, nty, Zoom);
}
void C4TargetFacet::SetRect(C4TargetRect &rSrc)
{
X=rSrc.x; Y=rSrc.y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; TargetX=rSrc.tx; TargetY=rSrc.ty;
}
void C4TargetFacet::DrawLineDw(int iX1, int iY1, int iX2, int iY2, uint32_t col1, uint32_t col2)
{
if (!pDraw || !Surface || !Wdt || !Hgt) return;
// Scroll position
float gX1 = float(iX1)-TargetX;
float gY1 = float(iY1)-TargetY;
float gX2 = float(iX2)-TargetX;
float gY2 = float(iY2)-TargetY;
// No clipping is done here, because clipping will be done by gfx wrapper anyway
// Draw line
pDraw->DrawLineDw(Surface,gX1+X,gY1+Y,gX2+X,gY2+Y,col1);
pDraw->DrawPix(Surface,gX1+X,gY1+Y,col2);
}
// ------------------------
// C4FacetSurface
bool C4FacetSurface::Create(int iWdt, int iHgt, int iWdt2, int iHgt2)
{
Clear();
// Create surface
Face.Default();
if (!Face.Create(iWdt,iHgt)) return false;
// Set facet
if (iWdt2==C4FCT_Full) iWdt2=Face.Wdt; if (iWdt2==C4FCT_Height) iWdt2=Face.Hgt; if (iWdt2==C4FCT_Width) iWdt2=Face.Wdt;
if (iHgt2==C4FCT_Full) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Height) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Width) iHgt2=Face.Wdt;
Set(&Face,0,0,iWdt2,iHgt2);
return true;
}
bool C4FacetSurface::CreateClrByOwner(C4Surface *pBySurface)
{
Clear();
// create surface
if (!Face.CreateColorByOwner(pBySurface)) return false;
// set facet
Set(&Face,0,0,Face.Wdt,Face.Hgt);
// success
return true;
}
bool C4FacetSurface::EnsureSize(int iMinWdt, int iMinHgt)
{
// safety
if (!Surface) return false;
// check size
int iWdt=Face.Wdt,iHgt=Face.Hgt;
if (iWdt>=iMinWdt && iHgt>=iMinHgt) return true;
// create temp surface
C4Surface *sfcDup=new C4Surface(iWdt,iHgt);
if (!sfcDup) return false;
if (!pDraw->BlitSurface(&Face,sfcDup,0,0,false))
{ delete sfcDup; return false; }
// calc needed size
int iDstWdt=Surface->Wdt,iDstHgt=iHgt;
while (iDstWdt<iMinWdt) iDstWdt+=iWdt;
while (iDstHgt<iMinHgt) iDstHgt+=iHgt;
// recreate this one
if (!Face.Create(iDstWdt, iDstHgt)) { delete sfcDup; Clear(); return false; }
// blit tiled into it
bool fSuccess=pDraw->BlitSurfaceTile(sfcDup, &Face, 0, 0, iDstWdt, iDstHgt, 0, 0, false);
// del temp surface
delete sfcDup;
// done
return fSuccess;
}
/*bool C4FacetSurface::Save(C4Group &hGroup, const char *szName)
{
// Empty
if (!Wdt || !Hgt) return false;
// Full surface
if ((Wdt==Face.Wdt) && (Hgt==Face.Hgt))
{
if (!Face.Save(hGroup,szName)) return false;
}
// Surface section
else
{
C4Surface sfcFacet;
if (!sfcFacet.Create(Wdt,Hgt)) return false;
Draw(&sfcFacet,0,0);
if (!sfcFacet.Save(hGroup,szName)) return false;
}
// Success
return true;
}*/
bool C4FacetSurface::Load(C4Group &hGroup, const char *szName, int iWdt, int iHgt, bool fOwnPal, bool fNoErrIfNotFound)
{
Clear();
// Entry name
char szFilename[_MAX_FNAME+1];
SCopy(szName,szFilename,_MAX_FNAME);
char *szExt = GetExtension(szFilename);
if (!*szExt)
{
// no extension: Default to extension that is found as file in group
const char * const extensions[] = { "png", "bmp", "jpeg", "jpg", NULL };
int i = 0; const char *szExt;
while ((szExt = extensions[i++]))
{
EnforceExtension(szFilename, szExt);
if (hGroup.FindEntry(szFilename)) break;
}
}
// Load surface
if (!Face.Load(hGroup,szFilename,fOwnPal,fNoErrIfNotFound)) return false;
// Set facet
if (iWdt==C4FCT_Full) iWdt=Face.Wdt; if (iWdt==C4FCT_Height) iWdt=Face.Hgt; if (iWdt==C4FCT_Width) iWdt=Face.Wdt;
if (iHgt==C4FCT_Full) iHgt=Face.Hgt; if (iHgt==C4FCT_Height) iHgt=Face.Hgt; if (iHgt==C4FCT_Width) iHgt=Face.Wdt;
Set(&Face,0,0,iWdt,iHgt);
return true;
}
bool C4FacetSurface::CopyFromSfcMaxSize(C4Surface &srcSfc, int32_t iMaxSize, uint32_t dwColor)
{
// safety
if (!srcSfc.Wdt || !srcSfc.Hgt) return false;
Clear();
// no scale?
bool fNeedsScale = !(srcSfc.Wdt <= iMaxSize && srcSfc.Hgt <= iMaxSize);
if (!fNeedsScale && !dwColor)
{
// no change necessary; just copy then
Face.Copy(srcSfc);
}
else
{
// must scale down or colorize. Just blit.
C4Facet fctSource;
fctSource.Set(&srcSfc, 0,0,srcSfc.Wdt,srcSfc.Hgt);
int32_t iTargetWdt, iTargetHgt;
if (fNeedsScale)
{
if (fctSource.Wdt > fctSource.Hgt)
{
iTargetWdt = iMaxSize;
iTargetHgt = fctSource.Hgt * iTargetWdt / fctSource.Wdt;
}
else
{
iTargetHgt = iMaxSize;
iTargetWdt = fctSource.Wdt * iTargetHgt / fctSource.Hgt;
}
}
else
{
iTargetWdt = fctSource.Wdt;
iTargetHgt = fctSource.Hgt;
}
if (dwColor) srcSfc.SetClr(dwColor);
Create(iTargetWdt, iTargetHgt);
pDraw->Blit(&srcSfc, 0.0f,0.0f,float(fctSource.Wdt),float(fctSource.Hgt),
&Face, 0,0,iTargetWdt,iTargetHgt);
}
Set(&Face, 0,0, Face.Wdt, Face.Hgt);
return true;
}
void C4FacetSurface::Grayscale(int32_t iOffset)
{
if (!pDraw || !Surface || !Wdt || !Hgt) return;
pDraw->Grayscale(Surface, iOffset);
}
bool C4FacetSurface::EnsureOwnSurface()
{
// is it a link?
if (Surface != &Face)
{
// then recreate in same size
C4Facet fctOld = *this;
if (!Create(fctOld.Wdt, fctOld.Hgt)) return false;
fctOld.Draw(*this);
}
return true;
}