mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	prescaled image support
This commit is contained in:
		| @@ -55,6 +55,58 @@ std::shared_ptr<CDefFile> RenderHandler::getAnimationFile(const AnimationPath & | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| std::optional<ResourcePath> RenderHandler::getPath(ResourcePath path) | ||||
| { | ||||
| 	if(CResourceHandler::get()->existsResource(path)) | ||||
| 		return path; | ||||
| 	if(path.getType() == EResType::IMAGE) | ||||
| 	{ | ||||
| 		auto p = ImagePath::builtin(path.getName()); | ||||
| 		if(CResourceHandler::get()->existsResource(p.addPrefix("DATA/"))) | ||||
| 			return std::optional<ResourcePath>(p.addPrefix("DATA/")); | ||||
| 		if(CResourceHandler::get()->existsResource(p.addPrefix("SPRITES/"))) | ||||
| 			return std::optional<ResourcePath>(p.addPrefix("SPRITES/")); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		auto p = AnimationPath::builtin(path.getName()); | ||||
| 		auto pJson = p.toType<EResType::JSON>(); | ||||
| 		if(CResourceHandler::get()->existsResource(p.addPrefix("SPRITES/"))) | ||||
| 			return std::optional<ResourcePath>(p.addPrefix("SPRITES/")); | ||||
| 		if(CResourceHandler::get()->existsResource(pJson)) | ||||
| 			return std::optional<ResourcePath>(p); | ||||
| 		if(CResourceHandler::get()->existsResource(pJson.addPrefix("SPRITES/"))) | ||||
| 			return std::optional<ResourcePath>(p.addPrefix("SPRITES/")); | ||||
| 	} | ||||
|  | ||||
| 	return std::nullopt; | ||||
| } | ||||
|  | ||||
| std::pair<ResourcePath, int> RenderHandler::getScalePath(ResourcePath p) | ||||
| { | ||||
| 	auto path = p; | ||||
| 	auto name = p.getName(); | ||||
| 	int scaleFactor = 1; | ||||
| 	if(getScalingFactor() > 1) | ||||
| 	{ | ||||
| 		std::vector<int> factorsToCheck = {getScalingFactor(), 4, 3, 2}; | ||||
| 		for(auto factorToCheck : factorsToCheck) | ||||
| 		{ | ||||
| 			ResourcePath scaledPath = ImagePath::builtin(name + "$" + std::to_string(factorToCheck)); | ||||
| 			if(p.getType() != EResType::IMAGE) | ||||
| 				scaledPath = AnimationPath::builtin(name + "$" + std::to_string(factorToCheck)); | ||||
| 			if(getPath(scaledPath)) | ||||
| 			{ | ||||
| 				path = scaledPath; | ||||
| 				scaleFactor = factorToCheck; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return std::pair<ResourcePath, int>(path, scaleFactor); | ||||
| }; | ||||
|  | ||||
| void RenderHandler::initFromJson(AnimationLayoutMap & source, const JsonNode & config) | ||||
| { | ||||
| 	std::string basepath; | ||||
| @@ -177,13 +229,13 @@ std::shared_ptr<ISharedImage> RenderHandler::loadImageFromFileUncached(const Ima | ||||
| 	if (locator.image) | ||||
| 	{ | ||||
| 		// TODO: create EmptySharedImage class that will be instantiated if image does not exists or fails to load | ||||
| 		return std::make_shared<SDLImageShared>(*locator.image); | ||||
| 		return std::make_shared<SDLImageShared>(*locator.image, locator.preScaledFactor); | ||||
| 	} | ||||
|  | ||||
| 	if (locator.defFile) | ||||
| 	{ | ||||
| 		auto defFile = getAnimationFile(*locator.defFile); | ||||
| 		return std::make_shared<SDLImageShared>(defFile.get(), locator.defFrame, locator.defGroup); | ||||
| 		return std::make_shared<SDLImageShared>(defFile.get(), locator.defFrame, locator.defGroup, locator.preScaledFactor); | ||||
| 	} | ||||
|  | ||||
| 	throw std::runtime_error("Invalid image locator received!"); | ||||
| @@ -247,7 +299,7 @@ std::shared_ptr<ISharedImage> RenderHandler::scaleImage(const ImageLocator & loc | ||||
| 	if (locator.layer == EImageLayer::ALL && locator.playerColored != PlayerColor::CANNOT_DETERMINE) | ||||
| 		handle->playerColored(locator.playerColored); | ||||
|  | ||||
| 	handle->scaleInteger(locator.scalingFactor); | ||||
| 	handle->scaleInteger(locator.scalingFactor);	 | ||||
|  | ||||
| 	// TODO: try to optimize image size (possibly even before scaling?) - trim image borders if they are completely transparent | ||||
| 	auto result = handle->getSharedImage(); | ||||
| @@ -284,13 +336,17 @@ std::shared_ptr<IImage> RenderHandler::loadImage(const ImageLocator & locator, E | ||||
|  | ||||
| std::shared_ptr<IImage> RenderHandler::loadImage(const AnimationPath & path, int frame, int group, EImageBlitMode mode) | ||||
| { | ||||
| 	ImageLocator locator = getLocatorForAnimationFrame(path, frame, group); | ||||
| 	auto tmp = getScalePath(path); | ||||
| 	ImageLocator locator = getLocatorForAnimationFrame(AnimationPath::builtin(tmp.first.getName()), frame, group); | ||||
| 	locator.preScaledFactor = tmp.second; | ||||
| 	return loadImage(locator, mode); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<IImage> RenderHandler::loadImage(const ImagePath & path, EImageBlitMode mode) | ||||
| { | ||||
| 	ImageLocator locator(path); | ||||
| 	auto tmp = getScalePath(path); | ||||
| 	ImageLocator locator(ImagePath::builtin(tmp.first.getName())); | ||||
| 	locator.preScaledFactor = tmp.second; | ||||
| 	return loadImage(locator, mode); | ||||
| } | ||||
|  | ||||
| @@ -301,7 +357,14 @@ std::shared_ptr<IImage> RenderHandler::createImage(SDL_Surface * source) | ||||
|  | ||||
| std::shared_ptr<CAnimation> RenderHandler::loadAnimation(const AnimationPath & path, EImageBlitMode mode) | ||||
| { | ||||
| 	return std::make_shared<CAnimation>(path, getAnimationLayout(path), mode); | ||||
| 	auto tmp = getScalePath(path); | ||||
| 	auto animPath = AnimationPath::builtin(tmp.first.getName()); | ||||
| 	auto layout = getAnimationLayout(animPath); | ||||
| 	for(auto & g : layout) | ||||
| 		for(auto & i : g.second) | ||||
| 			i.preScaledFactor = tmp.second; | ||||
|  | ||||
| 	return std::make_shared<CAnimation>(animPath, layout, mode); | ||||
| } | ||||
|  | ||||
| void RenderHandler::addImageListEntries(const EntityService * service) | ||||
|   | ||||
| @@ -29,6 +29,8 @@ class RenderHandler : public IRenderHandler | ||||
| 	std::map<EFonts, std::shared_ptr<const IFont>> fonts; | ||||
|  | ||||
| 	std::shared_ptr<CDefFile> getAnimationFile(const AnimationPath & path); | ||||
| 	std::optional<ResourcePath> getPath(ResourcePath path); | ||||
| 	std::pair<ResourcePath, int> getScalePath(ResourcePath p); | ||||
| 	AnimationLayoutMap & getAnimationLayout(const AnimationPath & path); | ||||
| 	void initFromJson(AnimationLayoutMap & layout, const JsonNode & config); | ||||
|  | ||||
|   | ||||
| @@ -89,11 +89,12 @@ int IImage::height() const | ||||
| 	return dimensions().y; | ||||
| } | ||||
|  | ||||
| SDLImageShared::SDLImageShared(const CDefFile * data, size_t frame, size_t group) | ||||
| SDLImageShared::SDLImageShared(const CDefFile * data, size_t frame, size_t group, int scaleFactor) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| 	originalPalette(nullptr) | ||||
| 	originalPalette(nullptr), | ||||
| 	scaleFactor(scaleFactor) | ||||
| { | ||||
| 	SDLImageLoader loader(this); | ||||
| 	data->loadFrame(frame, group, loader); | ||||
| @@ -105,7 +106,8 @@ SDLImageShared::SDLImageShared(SDL_Surface * from) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| 	originalPalette(nullptr) | ||||
| 	originalPalette(nullptr), | ||||
| 	scaleFactor(1) | ||||
| { | ||||
| 	surf = from; | ||||
| 	if (surf == nullptr) | ||||
| @@ -118,11 +120,12 @@ SDLImageShared::SDLImageShared(SDL_Surface * from) | ||||
| 	fullSize.y = surf->h; | ||||
| } | ||||
|  | ||||
| SDLImageShared::SDLImageShared(const ImagePath & filename) | ||||
| SDLImageShared::SDLImageShared(const ImagePath & filename, int scaleFactor) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| 	originalPalette(nullptr) | ||||
| 	originalPalette(nullptr), | ||||
| 	scaleFactor(scaleFactor) | ||||
| { | ||||
| 	surf = BitmapHandler::loadBitmap(filename); | ||||
|  | ||||
| @@ -274,7 +277,13 @@ std::shared_ptr<ISharedImage> SDLImageShared::scaleInteger(int factor, SDL_Palet | ||||
| 	if (palette && surf && surf->format->palette) | ||||
| 		SDL_SetSurfacePalette(surf, palette); | ||||
|  | ||||
| 	SDL_Surface * scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, factor, EScalingAlgorithm::XBRZ); | ||||
| 	SDL_Surface * scaled = nullptr; | ||||
| 	if(scaleFactor == factor) | ||||
| 		scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, 1, EScalingAlgorithm::NEAREST); // keep size | ||||
| 	else if(scaleFactor == 1) | ||||
| 		scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, factor, EScalingAlgorithm::XBRZ); | ||||
| 	else | ||||
| 		scaled = CSDL_Ext::scaleSurface(surf, (surf->w / scaleFactor) * factor, (surf->h / scaleFactor) * factor); | ||||
|  | ||||
| 	auto ret = std::make_shared<SDLImageShared>(scaled); | ||||
|  | ||||
| @@ -296,8 +305,8 @@ std::shared_ptr<ISharedImage> SDLImageShared::scaleInteger(int factor, SDL_Palet | ||||
|  | ||||
| std::shared_ptr<ISharedImage> SDLImageShared::scaleTo(const Point & size, SDL_Palette * palette) const | ||||
| { | ||||
| 	float scaleX = float(size.x) / dimensions().x; | ||||
| 	float scaleY = float(size.y) / dimensions().y; | ||||
| 	float scaleX = float(size.x) / fullSize.x; | ||||
| 	float scaleY = float(size.y) / fullSize.y; | ||||
|  | ||||
| 	if (palette && surf->format->palette) | ||||
| 		SDL_SetSurfacePalette(surf, palette); | ||||
| @@ -355,7 +364,7 @@ bool SDLImageShared::isTransparent(const Point & coords) const | ||||
|  | ||||
| Point SDLImageShared::dimensions() const | ||||
| { | ||||
| 	return fullSize; | ||||
| 	return fullSize / scaleFactor; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<IImage> SDLImageShared::createImageReference(EImageBlitMode mode) | ||||
|   | ||||
| @@ -35,6 +35,9 @@ class SDLImageShared final : public ISharedImage, public std::enable_shared_from | ||||
| 	//total size including borders | ||||
| 	Point fullSize; | ||||
|  | ||||
| 	//pre scaled image | ||||
| 	int scaleFactor; | ||||
|  | ||||
| 	// Keep the original palette, in order to do color switching operation | ||||
| 	void savePalette(); | ||||
|  | ||||
| @@ -42,9 +45,9 @@ class SDLImageShared final : public ISharedImage, public std::enable_shared_from | ||||
|  | ||||
| public: | ||||
| 	//Load image from def file | ||||
| 	SDLImageShared(const CDefFile *data, size_t frame, size_t group=0); | ||||
| 	SDLImageShared(const CDefFile *data, size_t frame, size_t group=0, int scaleFactor=1); | ||||
| 	//Load from bitmap file | ||||
| 	SDLImageShared(const ImagePath & filename); | ||||
| 	SDLImageShared(const ImagePath & filename, int scaleFactor=1); | ||||
| 	//Create using existing surface, extraRef will increase refcount on SDL_Surface | ||||
| 	SDLImageShared(SDL_Surface * from); | ||||
| 	~SDLImageShared(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user