313 lines
10 KiB
C++
313 lines
10 KiB
C++
#ifndef CImage_HPP_INCLUDED
|
|
#define CImage_HPP_INCLUDED
|
|
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (c) 2018-2021 3Dconnexion.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @file CImage.hpp
|
|
* @brief SiImage_t wrapper.
|
|
*/
|
|
|
|
// stdlib
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
// 3dxware
|
|
#include <siappcmd_types.h>
|
|
|
|
#if defined(_MSC_VER) && _MSC_VER<1800
|
|
// #pragma warning(1 : 4519) // convert error C4519 'default template arguments are only allowed on a class template' to warning
|
|
#pragma warning(disable : 4519) // disable error C4519
|
|
#if _MSC_VER < 1700
|
|
#pragma warning(disable : 4482) // warning C4482: nonstandard extension used
|
|
#endif
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Determines whether a value is an integer identifier for a resource.
|
|
/// </summary>
|
|
/// <param name="id">
|
|
/// The pointer to be tested whether it contains an integer resource identifier.
|
|
/// </param>
|
|
/// <returns>
|
|
/// true when id is an integer identifier for a resource, otherwise false when
|
|
/// it is typically a pointer to a string </returns>
|
|
__inline bool IsIntResource(const char *id) {
|
|
#ifdef _WIN32
|
|
return ((reinterpret_cast<uintptr_t>(id)) >> 16) == 0;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
namespace TDx {
|
|
/// <summary>
|
|
/// A class that represents the SiImage_t structure.
|
|
/// </summary>
|
|
class CImage {
|
|
public:
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CImage"/> class.
|
|
/// </summary>
|
|
CImage() : m_type(SiImageType_t::e_none), m_index(0) {
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CImage"/> class from a <see cref="SiImage_t"/>.
|
|
/// </summary>
|
|
/// <param name="image"></param>
|
|
explicit CImage(const SiImage_t &siImage) : m_id(siImage.id), m_type(siImage.type) {
|
|
if (siImage.size != sizeof(SiImage_t)) {
|
|
throw std::invalid_argument("Invalid SiImage_t structure.");
|
|
}
|
|
|
|
switch (m_type) {
|
|
case SiImageType_t::e_image_file:
|
|
m_source = siImage.file.file_name;
|
|
m_index = siImage.file.index;
|
|
break;
|
|
case SiImageType_t::e_resource_file:
|
|
m_source = siImage.resource.file_name;
|
|
m_resourceId = siImage.resource.id;
|
|
m_resourceType = siImage.resource.type;
|
|
m_index = siImage.resource.index;
|
|
break;
|
|
case SiImageType_t::e_image:
|
|
m_source.assign(reinterpret_cast<const char *>(siImage.image.data), siImage.image.size);
|
|
m_index = siImage.image.index;
|
|
break;
|
|
case SiImageType_t::e_none:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if USE_DECLSPEC_PROPERTY
|
|
/// <summary>
|
|
/// Gets or sets the image id.
|
|
/// </summary>
|
|
__declspec(property(get = GetId, put = PutId)) std::string Id;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the resource id.
|
|
/// </summary>
|
|
__declspec(property(get = GetResourceId, put = PutResourceId)) std::string ResourceId;
|
|
|
|
/// <summary>
|
|
/// Gets the image type.
|
|
/// </summary>
|
|
__declspec(property(get = GetType)) SiImageType_t Type;
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Sets the id of the image.
|
|
/// </summary>
|
|
/// <param name="id">A <see cref="std::string"/> representing the name or id of the image.</param>
|
|
void PutId(std::string id) {
|
|
m_id = std::move(id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the image id.
|
|
/// </summary>
|
|
/// <returns>A <see cref="std::string"/> representing the name or id of the image.</returns>
|
|
std::string GetId() const {
|
|
return m_id;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the id of the resource in the resource file.
|
|
/// </summary>
|
|
/// <param name="id">A <see cref="std::string"/> representing the name or id of the image in the
|
|
/// resource file.</param>
|
|
/// <remarks>For example for Microsoft resource libraries MAKEINTRESOURCE(216) = "#216".</remarks>
|
|
void PutResourceId(std::string id) {
|
|
m_resourceId = std::move(id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the resource id.
|
|
/// </summary>
|
|
/// <returns>A <see cref="std::string"/> representing the name or id of the image.</returns>
|
|
/// <remarks>For example for Microsoft resource libraries MAKEINTRESOURCE(216) = "#216".</remarks>
|
|
std::string GetResourceId() const {
|
|
return m_resourceId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the image type.
|
|
/// </summary>
|
|
/// <returns>One of <see cref="SiImageType_t"/>.</returns>
|
|
SiImageType_t GetType() const {
|
|
return m_type;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Assigns image data to the <see cref="CImage"/> instance.
|
|
/// </summary>
|
|
/// <param name="buffer">The image data. The image may be in any format that can be loaded by
|
|
/// Gdiplus::Bitmap::FromStream() or is in a recognizable svg format.</param>
|
|
/// <returns>true if successful, otherwise false.</returns>
|
|
/// <remarks>The <see cref="CImage"/> type is set to <see
|
|
/// cref="SiImageType_t::e_image"/>.</remarks>
|
|
bool AssignImage(std::string buffer, uint32_t index = 0) {
|
|
m_source = std::move(buffer);
|
|
m_type = e_image;
|
|
m_index = index;
|
|
m_resourceId.clear();
|
|
m_resourceType.clear();
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CImage"/> class that contains the data for an
|
|
/// image held in a resource file.
|
|
/// </summary>
|
|
/// <param name="resourceFile">The name of the resource file.</param>
|
|
/// <param name="resourceId">The name or id of the image in the resource file. i.e.
|
|
/// MAKEINTRESOURCE(216) = "#216".</param>
|
|
/// <param name="resourceType">The type of the resource in the resource file. i.e. RT_BITMAP =
|
|
/// "#2".</param>
|
|
/// <param name="index">The index in a multi-image resource.</param>
|
|
/// <param name="id">The id of the command to associate with this image.</param>
|
|
/// <returns>A <see cref="CImage"/> instance.</returns>
|
|
template <class T = CImage>
|
|
static T FromResource(const std::string &resourceFile, const char *resourceId,
|
|
const char *resourceType, uint32_t index = 0, const char *id = nullptr) {
|
|
|
|
std::string r_id;
|
|
if (resourceId != nullptr) {
|
|
if (IsIntResource(resourceId)) {
|
|
std::ostringstream stream;
|
|
stream << "#" << reinterpret_cast<uintptr_t>(resourceId);
|
|
r_id = stream.str();
|
|
} else {
|
|
r_id = resourceId;
|
|
}
|
|
}
|
|
|
|
std::string r_type;
|
|
if (resourceType != nullptr) {
|
|
if (IsIntResource(resourceType)) {
|
|
std::ostringstream stream;
|
|
stream << "#" << reinterpret_cast<uintptr_t>(resourceType);
|
|
r_type = stream.str();
|
|
} else {
|
|
r_type = resourceType;
|
|
}
|
|
}
|
|
|
|
T image(resourceFile, r_id, r_type, id != nullptr ? id : "", e_resource_file,
|
|
index);
|
|
return image;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CImage"/> class that contains the data for an
|
|
/// image in a file.
|
|
/// </summary>
|
|
/// <param name="filename">The name of the image file.</param>
|
|
/// <param name="index">The index in a multi-image file.</param>
|
|
/// <param name="id">The id of the command to associate with this image.</param>
|
|
/// <returns>A <see cref="CImage"/> instance.</returns>
|
|
template <class T = CImage>
|
|
static T FromFile(const std::string &filename, uint32_t index = 0, const char *id = nullptr) {
|
|
T image(filename, id != nullptr ? id : "", e_image_file, index);
|
|
return image;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the CImage class that contains the data for an image in a file.
|
|
/// </summary>
|
|
/// <param name="buffer">The image data. The image may be in any format that can be loaded by
|
|
/// Gdiplus::Bitmap::FromStream() or is in a recognizable svg format.</param>
|
|
/// <param name="index">The index in a multi-image file.</param>
|
|
/// <param name="id">The id of the command to associate with this image.</param>
|
|
/// <returns>A <see cref="CImage"/> instance.</returns>
|
|
template <class T = CImage>
|
|
static T FromData(const std::string &buffer, uint32_t index = 0, const char *id = nullptr) {
|
|
T image(buffer, id != nullptr ? id : "", e_image, index);
|
|
return image;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an <see cref="SiImage_t"/> view of the <see cref="CImage"/> instance.
|
|
/// </summary>
|
|
/// <returns>A <see cref="SiImage_t"/>.</returns>
|
|
operator SiImage_t() const {
|
|
SiImage_t siImage = {sizeof(SiImage_t), m_type, m_id.c_str(), {nullptr, nullptr, nullptr, 0}};
|
|
switch (m_type) {
|
|
case SiImageType_t::e_image_file:
|
|
siImage.file.file_name = m_source.c_str();
|
|
siImage.file.index = m_index;
|
|
break;
|
|
case SiImageType_t::e_resource_file:
|
|
siImage.resource.file_name = m_source.c_str();
|
|
siImage.resource.id = m_resourceId.c_str();
|
|
siImage.resource.type = m_resourceType.c_str();
|
|
siImage.resource.index = m_index;
|
|
break;
|
|
case SiImageType_t::e_image:
|
|
siImage.image.data = reinterpret_cast<const uint8_t *>(m_source.data());
|
|
siImage.image.size = m_source.size();
|
|
siImage.image.index = m_index;
|
|
break;
|
|
case SiImageType_t::e_none:
|
|
break;
|
|
default:
|
|
siImage.type = SiImageType_t::e_none;
|
|
break;
|
|
}
|
|
|
|
return siImage;
|
|
}
|
|
|
|
/// <summary>
|
|
/// checks whether the image is empty.
|
|
/// </summary>
|
|
/// <returns>true if the image contains data, otherwise false.</returns>
|
|
bool empty() const {
|
|
return m_type == SiImageType_t::e_none || (m_type == SiImageType_t::e_image && m_source.empty());
|
|
}
|
|
|
|
protected:
|
|
|
|
CImage(std::string source, std::string id, SiImageType_t type, uint32_t index = 0)
|
|
: m_source(std::move(source)), m_id(std::move(id)), m_type(type), m_index(index) {
|
|
}
|
|
|
|
CImage(std::string source, std::string resourceName, std::string resourceType, std::string id,
|
|
SiImageType_t type, uint32_t index = 0)
|
|
: m_source(std::move(source)), m_resourceId(std::move(resourceName)),
|
|
m_resourceType(std::move(resourceType)), m_id(std::move(id)), m_type(type), m_index(index) {
|
|
}
|
|
|
|
protected:
|
|
std::string m_source;
|
|
std::string m_resourceId;
|
|
std::string m_resourceType;
|
|
std::string m_id;
|
|
SiImageType_t m_type;
|
|
uint32_t m_index;
|
|
};
|
|
} // namespace TDx
|
|
#endif // CImage_HPP_INCLUDED
|