1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* A facet that can hold its own surface and also target coordinates */
19 
20 #include "C4Include.h"
21 #include "graphics/C4FacetEx.h"
22 #include "graphics/C4Draw.h"
23 
24 #include "lib/C4Rect.h"
25 #include "c4group/C4Group.h"
26 
Set(C4Surface * nsfc,float nx,float ny,float nwdt,float nhgt,float ntx,float nty,float Zoom)27 void C4TargetFacet::Set(C4Surface * nsfc, float nx, float ny, float nwdt, float nhgt, float ntx, float nty, float Zoom)
28 {
29 	Set(nsfc, nx, ny, nwdt, nhgt, ntx, nty, Zoom, ntx, nty);
30 }
31 
Set(C4Surface * nsfc,float nx,float ny,float nwdt,float nhgt,float ntx,float nty,float Zoom,float prx,float pry)32 void C4TargetFacet::Set(C4Surface * nsfc, float nx, float ny, float nwdt, float nhgt, float ntx, float nty, float Zoom, float prx, float pry)
33 {
34 	C4Facet::Set(nsfc, nx, ny, nwdt, nhgt);
35 	TargetX = ntx; TargetY = nty; this->Zoom = Zoom;
36 	ParRefX = prx; ParRefY = pry;
37 }
38 
Set(C4Surface * nsfc,const C4Rect & r,float ntx,float nty,float Zoom)39 void C4TargetFacet::Set(C4Surface * nsfc, const C4Rect & r, float ntx, float nty, float Zoom)
40 {
41 	Set(nsfc, r.x, r.y, r.Wdt, r.Hgt, ntx, nty, Zoom);
42 }
43 
SetRect(C4TargetRect & rSrc)44 void C4TargetFacet::SetRect(C4TargetRect &rSrc)
45 {
46 	X=rSrc.x; Y=rSrc.y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt;
47 	TargetX=rSrc.tx; TargetY=rSrc.ty;
48 	ParRefX=rSrc.tx; TargetY=rSrc.ty;
49 }
50 
51 // ------------------------
52 // C4FacetSurface
53 
Create(int iWdt,int iHgt,int iWdt2,int iHgt2)54 bool C4FacetSurface::Create(int iWdt, int iHgt, int iWdt2, int iHgt2)
55 {
56 	Clear();
57 	// Create surface
58 	Face.Default();
59 	if (!Face.Create(iWdt,iHgt)) return false;
60 	// Set facet
61 	if (iWdt2==C4FCT_Full) iWdt2=Face.Wdt; if (iWdt2==C4FCT_Height) iWdt2=Face.Hgt; if (iWdt2==C4FCT_Width) iWdt2=Face.Wdt;
62 	if (iHgt2==C4FCT_Full) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Height) iHgt2=Face.Hgt; if (iHgt2==C4FCT_Width) iHgt2=Face.Wdt;
63 	Set(&Face,0,0,iWdt2,iHgt2);
64 	return true;
65 }
66 
CreateClrByOwner(C4Surface * pBySurface)67 bool C4FacetSurface::CreateClrByOwner(C4Surface *pBySurface)
68 {
69 	Clear();
70 	// create surface
71 	if (!Face.CreateColorByOwner(pBySurface)) return false;
72 	// set facet
73 	Set(&Face,0,0,Face.Wdt,Face.Hgt);
74 	// success
75 	return true;
76 }
77 
Load(C4Group & hGroup,const char * szName,int iWdt,int iHgt,bool fNoErrIfNotFound,int iFlags)78 bool C4FacetSurface::Load(C4Group &hGroup, const char *szName, int iWdt, int iHgt, bool fNoErrIfNotFound, int iFlags)
79 {
80 	Clear();
81 	// Entry name
82 	char szFilename[_MAX_FNAME+1];
83 	SCopy(szName,szFilename,_MAX_FNAME);
84 	char *szExt = GetExtension(szFilename);
85 	if (!*szExt)
86 	{
87 		// no extension: Default to extension that is found as file in group
88 		const char * const extensions[] = { "png", "bmp", "jpeg", "jpg", nullptr };
89 		int i = 0; const char *szExt;
90 		while ((szExt = extensions[i++]))
91 		{
92 			EnforceExtension(szFilename, szExt);
93 			if (hGroup.FindEntry(szFilename)) break;
94 		}
95 	}
96 	// Load surface
97 	if (!Face.Load(hGroup,szFilename,false,fNoErrIfNotFound, iFlags)) return false;
98 	// Set facet
99 	if (iWdt==C4FCT_Full) iWdt=Face.Wdt; if (iWdt==C4FCT_Height) iWdt=Face.Hgt; if (iWdt==C4FCT_Width) iWdt=Face.Wdt;
100 	if (iHgt==C4FCT_Full) iHgt=Face.Hgt; if (iHgt==C4FCT_Height) iHgt=Face.Hgt; if (iHgt==C4FCT_Width) iHgt=Face.Wdt;
101 	Set(&Face,0,0,iWdt,iHgt);
102 	return true;
103 }
104 
CopyFromSfcMaxSize(C4Surface & srcSfc,int32_t iMaxSize,uint32_t dwColor)105 bool C4FacetSurface::CopyFromSfcMaxSize(C4Surface &srcSfc, int32_t iMaxSize, uint32_t dwColor)
106 {
107 	// safety
108 	if (!srcSfc.Wdt || !srcSfc.Hgt) return false;
109 	Clear();
110 	// no scale?
111 	bool fNeedsScale = !(srcSfc.Wdt <= iMaxSize && srcSfc.Hgt <= iMaxSize);
112 	if (!fNeedsScale && !dwColor)
113 	{
114 		// no change necessary; just copy then
115 		Face.Copy(srcSfc);
116 	}
117 	else
118 	{
119 		// must scale down or colorize. Just blit.
120 		C4Facet fctSource;
121 		fctSource.Set(&srcSfc, 0,0,srcSfc.Wdt,srcSfc.Hgt);
122 		int32_t iTargetWdt, iTargetHgt;
123 		if (fNeedsScale)
124 		{
125 			if (fctSource.Wdt > fctSource.Hgt)
126 			{
127 				iTargetWdt = iMaxSize;
128 				iTargetHgt = fctSource.Hgt * iTargetWdt / fctSource.Wdt;
129 			}
130 			else
131 			{
132 				iTargetHgt = iMaxSize;
133 				iTargetWdt = fctSource.Wdt * iTargetHgt / fctSource.Hgt;
134 			}
135 		}
136 		else
137 		{
138 			iTargetWdt = fctSource.Wdt;
139 			iTargetHgt = fctSource.Hgt;
140 		}
141 		if (dwColor) srcSfc.SetClr(dwColor);
142 		Create(iTargetWdt, iTargetHgt);
143 		pDraw->Blit(&srcSfc, 0.0f,0.0f,float(fctSource.Wdt),float(fctSource.Hgt),
144 		              &Face, 0,0,iTargetWdt,iTargetHgt);
145 	}
146 	Set(&Face, 0,0, Face.Wdt, Face.Hgt);
147 	return true;
148 }
149 
Grayscale(int32_t iOffset)150 void C4FacetSurface::Grayscale(int32_t iOffset)
151 {
152 	if (!pDraw || !Surface || !Wdt || !Hgt) return;
153 	pDraw->Grayscale(Surface, iOffset);
154 }
155 
EnsureOwnSurface()156 bool C4FacetSurface::EnsureOwnSurface()
157 {
158 	// is it a link?
159 	if (Surface != &Face)
160 	{
161 		// then recreate in same size
162 		C4Facet fctOld = *this;
163 		if (!Create(fctOld.Wdt, fctOld.Hgt)) return false;
164 		fctOld.Draw(*this);
165 	}
166 	return true;
167 }
168 
169