update FontCollection && Resource

This commit is contained in:
Nomango 2019-08-18 17:49:13 +08:00
parent aec069b167
commit 253548dafe
33 changed files with 838 additions and 538 deletions

View File

@ -67,6 +67,7 @@
<ClInclude Include="..\src\kiwano\platform\modules.h" /> <ClInclude Include="..\src\kiwano\platform\modules.h" />
<ClInclude Include="..\src\kiwano\renderer\Color.h" /> <ClInclude Include="..\src\kiwano\renderer\Color.h" />
<ClInclude Include="..\src\kiwano\renderer\Font.h" /> <ClInclude Include="..\src\kiwano\renderer\Font.h" />
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h" />
<ClInclude Include="..\src\kiwano\renderer\Geometry.h" /> <ClInclude Include="..\src\kiwano\renderer\Geometry.h" />
<ClInclude Include="..\src\kiwano\renderer\GifImage.h" /> <ClInclude Include="..\src\kiwano\renderer\GifImage.h" />
<ClInclude Include="..\src\kiwano\renderer\Image.h" /> <ClInclude Include="..\src\kiwano\renderer\Image.h" />
@ -127,6 +128,7 @@
<ClCompile Include="..\src\kiwano\platform\modules.cpp" /> <ClCompile Include="..\src\kiwano\platform\modules.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Color.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Color.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Font.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Font.cpp" />
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Geometry.cpp" />
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp" /> <ClCompile Include="..\src\kiwano\renderer\GifImage.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Image.cpp" />

View File

@ -303,6 +303,9 @@
<ClInclude Include="..\src\kiwano\renderer\RenderTarget.h"> <ClInclude Include="..\src\kiwano\renderer\RenderTarget.h">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h">
<Filter>renderer</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\kiwano\ui\Button.cpp"> <ClCompile Include="..\src\kiwano\ui\Button.cpp">
@ -473,5 +476,8 @@
<ClCompile Include="..\src\kiwano\renderer\RenderTarget.cpp"> <ClCompile Include="..\src\kiwano\renderer\RenderTarget.cpp">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp">
<Filter>renderer</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -34,13 +34,33 @@ namespace kiwano
ClearCache(); ClearCache();
} }
bool Player::Load(Resource const& res) size_t Player::Load(String const& file_path)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = file_path.hash();
if (sound_cache_.end() != sound_cache_.find(hash_code)) if (sound_cache_.end() != sound_cache_.find(hash_code))
return true; return true;
SoundPtr sound = new (std::nothrow) Sound(); SoundPtr sound = new (std::nothrow) Sound;
if (sound)
{
if (sound->Load(file_path))
{
sound->SetVolume(volume_);
sound_cache_.insert(std::make_pair(hash_code, sound));
return true;
}
}
return false;
}
size_t Player::Load(Resource const& res)
{
size_t hash_code = res.GetId();
if (sound_cache_.end() != sound_cache_.find(hash_code))
return true;
SoundPtr sound = new (std::nothrow) Sound;
if (sound) if (sound)
{ {
@ -54,42 +74,39 @@ namespace kiwano
return false; return false;
} }
void Player::Play(Resource const& res, int loop_count) void Player::Play(size_t id, int loop_count)
{ {
if (Load(res)) auto iter = sound_cache_.find(id);
{ if (sound_cache_.end() != iter)
size_t hash_code = res.GetHashCode(); iter->second->Play(loop_count);
if (sound_cache_.end() != sound_cache_.find(hash_code))
sound_cache_[hash_code]->Play(loop_count);
}
} }
void Player::Pause(Resource const& res) void Player::Pause(size_t id)
{ {
size_t hash_code = res.GetHashCode(); auto iter = sound_cache_.find(id);
if (sound_cache_.end() != sound_cache_.find(hash_code)) if (sound_cache_.end() != iter)
sound_cache_[hash_code]->Pause(); iter->second->Pause();
} }
void Player::Resume(Resource const& res) void Player::Resume(size_t id)
{ {
size_t hash_code = res.GetHashCode(); auto iter = sound_cache_.find(id);
if (sound_cache_.end() != sound_cache_.find(hash_code)) if (sound_cache_.end() != iter)
sound_cache_[hash_code]->Resume(); iter->second->Resume();
} }
void Player::Stop(Resource const& res) void Player::Stop(size_t id)
{ {
size_t hash_code = res.GetHashCode(); auto iter = sound_cache_.find(id);
if (sound_cache_.end() != sound_cache_.find(hash_code)) if (sound_cache_.end() != iter)
sound_cache_[hash_code]->Stop(); iter->second->Stop();
} }
bool Player::IsPlaying(Resource const& res) bool Player::IsPlaying(size_t id)
{ {
size_t hash_code = res.GetHashCode(); auto iter = sound_cache_.find(id);
if (sound_cache_.end() != sound_cache_.find(hash_code)) if (sound_cache_.end() != iter)
return sound_cache_[hash_code]->IsPlaying(); return iter->second->IsPlaying();
return false; return false;
} }

View File

@ -33,42 +33,45 @@ namespace kiwano
class KGE_API Player class KGE_API Player
: protected ObjectBase : protected ObjectBase
{ {
using MusicMap = Map<size_t, SoundPtr>;
public: public:
Player(); Player();
~Player(); ~Player();
// 속潼稜있栗都 // 加载本地音频文件, 返回该资源标识符
bool Load( size_t Load(
String const& file_path
);
// 加载音乐资源, 返回该资源标识符
size_t Load(
Resource const& res /* 稜있栗都 */ Resource const& res /* 稜있栗都 */
); );
// 꺄렴稜있 // 꺄렴稜있
void Play( void Play(
Resource const& res, /* 稜있栗都 */ size_t id, /* 标识符 */
int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */ int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */
); );
// 董界稜있 // 董界稜있
void Pause( void Pause(
Resource const& res /* 稜있栗都 */ size_t id /* 标识符 */
); );
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
void Resume( void Resume(
Resource const& res /* 稜있栗都 */ size_t id /* 标识符 */
); );
// 界岺稜있 // 界岺稜있
void Stop( void Stop(
Resource const& res /* 稜있栗都 */ size_t id /* 标识符 */
); );
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
bool IsPlaying( bool IsPlaying(
Resource const& res /* 稜있栗都 */ size_t id /* 标识符 */
); );
// 삿혤稜좆 // 삿혤稜좆
@ -92,8 +95,10 @@ namespace kiwano
void ClearCache(); void ClearCache();
protected: protected:
float volume_; float volume_;
MusicMap sound_cache_;
using MusicMap = Map<size_t, SoundPtr>;
MusicMap sound_cache_;
}; };
} }
} }

View File

@ -49,6 +49,46 @@ namespace kiwano
Close(); Close();
} }
bool Sound::Load(String const& file_path)
{
if (opened_)
{
Close();
}
#if defined(KGE_DEBUG)
if (!FileUtil::ExistsFile(file_path))
{
KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str());
return false;
}
#endif
Transcoder transcoder;
HRESULT hr = transcoder.LoadMediaFile(file_path, &wave_data_, &size_);
if (FAILED(hr))
{
KGE_ERROR_LOG(L"Load media file failed with HRESULT of %08X", hr);
return false;
}
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr))
{
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
opened_ = true;
return true;
}
bool Sound::Load(Resource const& res) bool Sound::Load(Resource const& res)
{ {
if (opened_) if (opened_)
@ -56,28 +96,12 @@ namespace kiwano
Close(); Close();
} }
HRESULT hr = S_OK;
Transcoder transcoder; Transcoder transcoder;
HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
if (res.IsFileType())
{
#if defined(KGE_DEBUG)
if (!FileUtil::ExistsFile(res.GetFileName()))
{
KGE_WARNING_LOG(L"Media file '%s' not found", res.GetFileName().c_str());
return false;
}
#endif
hr = transcoder.LoadMediaFile(res.GetFileName(), &wave_data_, &size_);
}
else
{
hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
}
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_ERROR_LOG(L"Load media file failed with HRESULT of %08X", hr); KGE_ERROR_LOG(L"Load media resource failed with HRESULT of %08X", hr);
return false; return false;
} }

View File

@ -37,12 +37,21 @@ namespace kiwano
public: public:
Sound(); Sound();
Sound(
String const& file_path /* 本地音频文件 */
);
Sound( Sound(
Resource const& res /* 稜있栗都 */ Resource const& res /* 稜있栗都 */
); );
virtual ~Sound(); virtual ~Sound();
// 打开本地音频文件
bool Load(
String const& file_path
);
// 댔역稜있栗都 // 댔역稜있栗都
bool Load( bool Load(
Resource const& res /* 稜있栗都 */ Resource const& res /* 稜있栗都 */

View File

@ -83,13 +83,12 @@ namespace kiwano
ComPtr<IMFByteStream> byte_stream; ComPtr<IMFByteStream> byte_stream;
ComPtr<IMFSourceReader> reader; ComPtr<IMFSourceReader> reader;
LPVOID buffer; Resource::Data data = res.GetData();
DWORD buffer_size; if (!data) { return E_FAIL; }
if (!res.Load(buffer, buffer_size)) { return E_FAIL; }
stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream( stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream(
static_cast<const BYTE*>(buffer), static_cast<const BYTE*>(data.buffer),
static_cast<UINT>(buffer_size) static_cast<UINT>(data.size)
); );
if (stream == nullptr) if (stream == nullptr)

View File

@ -27,19 +27,35 @@ namespace kiwano
{ {
} }
Frame::Frame(String const& file_path)
{
Load(file_path);
}
Frame::Frame(Resource const& res) Frame::Frame(Resource const& res)
{ {
Load(res); Load(res);
} }
Frame::Frame(Image const& image) Frame::Frame(Image const& image)
: image_(image)
{ {
SetImage(image);
}
bool Frame::Load(String const& file_path)
{
Image image = ImageCache::GetInstance()->AddOrGetImage(file_path);
if (image.IsValid())
{
SetImage(image);
return true;
}
return false;
} }
bool Frame::Load(Resource const& res) bool Frame::Load(Resource const& res)
{ {
Image image = ImageCache::GetInstance()->AddImage(res); Image image = ImageCache::GetInstance()->AddOrGetImage(res);
if (image.IsValid()) if (image.IsValid())
{ {
SetImage(image); SetImage(image);

View File

@ -30,6 +30,10 @@ namespace kiwano
public: public:
Frame(); Frame();
explicit Frame(
String const& file_path
);
explicit Frame( explicit Frame(
Resource const& res Resource const& res
); );
@ -38,6 +42,10 @@ namespace kiwano
Image const& image Image const& image
); );
bool Load(
String const& file_path
);
bool Load( bool Load(
Resource const& res Resource const& res
); );
@ -47,6 +55,11 @@ namespace kiwano
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */ Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
// ÉèÖÃλͼ
void SetImage(
Image const& image
);
// »ñÈ¡¿í¶È // »ñÈ¡¿í¶È
float GetWidth() const { return crop_rect_.size.x; } float GetWidth() const { return crop_rect_.size.x; }
@ -65,9 +78,6 @@ namespace kiwano
// »ñȡλͼ // »ñȡλͼ
inline Image const& GetImage() const { return image_; } inline Image const& GetImage() const { return image_; }
// ÉèÖÃλͼ
void SetImage(Image const& image);
protected: protected:
Image image_; Image image_;
Rect crop_rect_; Rect crop_rect_;

View File

@ -34,26 +34,37 @@ namespace kiwano
{ {
} }
GifSprite::GifSprite(String const& file_path)
{
Load(file_path);
}
GifSprite::GifSprite(Resource const& res) GifSprite::GifSprite(Resource const& res)
: GifSprite() : GifSprite()
{ {
Load(res); Load(res);
} }
GifSprite::GifSprite(GifImagePtr image) GifSprite::GifSprite(GifImage image)
{ {
Load(image); Load(image);
} }
bool GifSprite::Load(Resource const& res) bool GifSprite::Load(String const& file_path)
{ {
GifImagePtr image = ImageCache::GetInstance()->AddGifImage(res); GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(file_path);
return Load(image); return Load(image);
} }
bool GifSprite::Load(GifImagePtr image) bool GifSprite::Load(Resource const& res)
{ {
if (image && image_ != image) GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(res);
return Load(image);
}
bool GifSprite::Load(GifImage image)
{
if (image.IsValid())
{ {
image_ = image; image_ = image;
@ -62,8 +73,8 @@ namespace kiwano
disposal_type_ = DisposalType::None; disposal_type_ = DisposalType::None;
SetSize( SetSize(
static_cast<float>(image_->GetWidthInPixels()), static_cast<float>(image_.GetWidthInPixels()),
static_cast<float>(image_->GetHeightInPixels()) static_cast<float>(image_.GetHeightInPixels())
); );
if (!frame_rt_.IsValid()) if (!frame_rt_.IsValid())
@ -71,7 +82,7 @@ namespace kiwano
Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_); Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
} }
if (image_->GetFramesCount() > 0) if (image_.GetFramesCount() > 0)
{ {
ComposeNextFrame(); ComposeNextFrame();
} }
@ -94,7 +105,7 @@ namespace kiwano
{ {
Actor::Update(dt); Actor::Update(dt);
if (image_ && animating_) if (image_.IsValid() && animating_)
{ {
frame_elapsed_ += dt; frame_elapsed_ += dt;
if (frame_delay_ <= frame_elapsed_) if (frame_delay_ <= frame_elapsed_)
@ -124,7 +135,7 @@ namespace kiwano
OverlayNextFrame(); OverlayNextFrame();
} while (frame_delay_.IsZero() && !IsLastFrame()); } while (frame_delay_.IsZero() && !IsLastFrame());
animating_ = (!EndOfAnimation() && image_->GetFramesCount() > 1); animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1);
} }
} }
@ -157,7 +168,7 @@ namespace kiwano
{ {
Image raw_image; Image raw_image;
HRESULT hr = image_->GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_); HRESULT hr = image_.GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -174,7 +185,7 @@ namespace kiwano
if (next_index_ == 0) if (next_index_ == 0)
{ {
// ÖØÐ»æÖƱ³¾° // ÖØÐ»æÖƱ³¾°
frame_rt_.Clear(image_->GetBackgroundColor()); frame_rt_.Clear(image_.GetBackgroundColor());
loop_count_++; loop_count_++;
} }
@ -192,7 +203,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
frame_ = frame_to_render; frame_ = frame_to_render;
next_index_ = (++next_index_) % image_->GetFramesCount(); next_index_ = (++next_index_) % image_.GetFramesCount();
} }
} }
@ -266,7 +277,7 @@ namespace kiwano
frame_rt_.BeginDraw(); frame_rt_.BeginDraw();
frame_rt_.PushClipRect(frame_rect_); frame_rt_.PushClipRect(frame_rect_);
frame_rt_.Clear(image_->GetBackgroundColor()); frame_rt_.Clear(image_.GetBackgroundColor());
frame_rt_.PopClipRect(); frame_rt_.PopClipRect();
return frame_rt_.EndDraw(); return frame_rt_.EndDraw();

View File

@ -37,12 +37,20 @@ namespace kiwano
GifSprite(); GifSprite();
GifSprite(
String const& file_path
);
GifSprite( GifSprite(
Resource const& res Resource const& res
); );
GifSprite( GifSprite(
GifImagePtr image GifImage image
);
bool Load(
String const& file_path
); );
bool Load( bool Load(
@ -50,7 +58,7 @@ namespace kiwano
); );
bool Load( bool Load(
GifImagePtr image GifImage image
); );
// 设置 GIF 动画循环次数 // 设置 GIF 动画循环次数
@ -100,7 +108,7 @@ namespace kiwano
DisposalType disposal_type_; DisposalType disposal_type_;
LoopDoneCallback loop_cb_; LoopDoneCallback loop_cb_;
DoneCallback done_cb_; DoneCallback done_cb_;
GifImagePtr image_; GifImage image_;
Image frame_; Image frame_;
Rect frame_rect_; Rect frame_rect_;
Image saved_frame_; Image saved_frame_;

View File

@ -24,18 +24,26 @@
namespace kiwano namespace kiwano
{ {
Sprite::Sprite() Sprite::Sprite()
: frame_(nullptr)
{ {
} }
Sprite::Sprite(String const& file_path)
{
Load(file_path);
}
Sprite::Sprite(String const& file_path, Rect const& crop_rect)
{
Load(file_path);
SetCropRect(crop_rect);
}
Sprite::Sprite(Resource const& res) Sprite::Sprite(Resource const& res)
: frame_(nullptr)
{ {
Load(res); Load(res);
} }
Sprite::Sprite(Resource const& res, const Rect& crop_rect) Sprite::Sprite(Resource const& res, const Rect& crop_rect)
: frame_(nullptr)
{ {
Load(res); Load(res);
SetCropRect(crop_rect); SetCropRect(crop_rect);
@ -51,6 +59,17 @@ namespace kiwano
{ {
} }
bool Sprite::Load(String const& file_path)
{
FramePtr frame = new (std::nothrow) Frame;
if (frame->Load(file_path))
{
SetFrame(frame);
return true;
}
return false;
}
bool Sprite::Load(Resource const& res) bool Sprite::Load(Resource const& res)
{ {
FramePtr frame = new (std::nothrow) Frame; FramePtr frame = new (std::nothrow) Frame;

View File

@ -32,10 +32,19 @@ namespace kiwano
Sprite(); Sprite();
explicit Sprite( explicit Sprite(
Resource const& res String const& file_path
);
Sprite(
String const& file_path,
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
explicit Sprite( explicit Sprite(
Resource const& res
);
Sprite(
Resource const& res, Resource const& res,
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */ Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
@ -46,6 +55,11 @@ namespace kiwano
virtual ~Sprite(); virtual ~Sprite();
// ¼ÓÔØÍ¼Ïñ
bool Load(
String const& file_path
);
// ¼ÓÔØÍ¼Ïñ×ÊÔ´ // ¼ÓÔØÍ¼Ïñ×ÊÔ´
bool Load( bool Load(
Resource const& res Resource const& res

View File

@ -21,114 +21,63 @@
#include "Resource.h" #include "Resource.h"
#include "../base/Logger.h" #include "../base/Logger.h"
#include <iostream>
namespace kiwano namespace kiwano
{ {
Resource::Resource(LPCWSTR file_name) Resource::Resource()
: type_(Type::File) : id_(0)
, bin_id_(0) , type_(nullptr)
, bin_type_(nullptr)
{ {
if (file_name)
file_name_ = new (std::nothrow) String(file_name);
}
Resource::Resource(String const& file_name)
: type_(Type::File)
, bin_id_(0)
, bin_type_(nullptr)
{
if (!file_name.empty())
file_name_ = new (std::nothrow) String(file_name);
} }
Resource::Resource(UINT id, LPCWSTR type) Resource::Resource(UINT id, LPCWSTR type)
: type_(Type::Binary) : id_(id)
, bin_id_(id) , type_(type)
, bin_type_(type)
{ {
} }
Resource::Resource(Resource const & rhs) Resource::Data Resource::GetData() const
{ {
operator=(rhs); do
}
Resource::~Resource()
{
if (IsFileType() && file_name_)
delete file_name_;
}
size_t Resource::GetHashCode() const
{
return (type_ == Type::File) ? GetFileName().hash() : static_cast<size_t>(bin_id_);
}
Resource & Resource::operator=(Resource const & rhs)
{
if (&rhs != this)
{ {
if (IsFileType() && file_name_) if (data_.buffer && data_.size)
{ {
delete file_name_; break;
file_name_ = nullptr;
} }
type_ = rhs.type_; HRSRC res_info = FindResourceW(nullptr, MAKEINTRESOURCE(id_), type_);
if (IsFileType()) if (res_info == nullptr)
{ {
if (rhs.file_name_) KGE_ERROR_LOG(L"FindResource failed");
{ break;
file_name_ = new (std::nothrow) String(*rhs.file_name_);
}
} }
else
HGLOBAL res_data = LoadResource(nullptr, res_info);
if (res_data == nullptr)
{ {
bin_id_ = rhs.bin_id_; KGE_ERROR_LOG(L"LoadResource failed");
bin_type_ = rhs.bin_type_; break;
} }
}
return *this;
}
bool Resource::Load(LPVOID& buffer, DWORD& buffer_size) const DWORD size = SizeofResource(nullptr, res_info);
{ if (size == 0)
if (type_ != Type::Binary) {
{ KGE_ERROR_LOG(L"SizeofResource failed");
KGE_ERROR_LOG(L"Only binary resource can be loaded"); break;
return false; }
}
HGLOBAL res_data; LPVOID buffer = LockResource(res_data);
HRSRC res_info; if (buffer == nullptr)
{
KGE_ERROR_LOG(L"LockResource failed");
break;
}
res_info = FindResourceW(nullptr, MAKEINTRESOURCE(bin_id_), bin_type_); data_.buffer = static_cast<void*>(buffer);
if (res_info == nullptr) data_.size = static_cast<UINT32>(size);
{ } while (0);
KGE_ERROR_LOG(L"FindResource failed");
return false;
}
res_data = LoadResource(nullptr, res_info); return data_;
if (res_data == nullptr)
{
KGE_ERROR_LOG(L"LoadResource failed");
return false;
}
buffer_size = SizeofResource(nullptr, res_info);
if (buffer_size == 0)
{
KGE_ERROR_LOG(L"SizeofResource failed");
return false;
}
buffer = LockResource(res_data);
if (buffer == nullptr)
{
KGE_ERROR_LOG(L"LockResource failed");
return false;
}
return true;
} }
} }

View File

@ -26,64 +26,43 @@ namespace kiwano
{ {
// 资源 // 资源
// //
// 资源可以是文件类型,也可以是保存在 exe 中的二进制资源 // 资源是保存在 exe 中的二进制数据
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1, // 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1,
// 那么可以这样指定该资源: Resource res(IDR_WAVE_1, L"WAVE"); // 那么可以这样指定该资源: Resource(IDR_WAVE_1, L"WAVE");
// //
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources // 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
// //
class KGE_API Resource class KGE_API Resource
{ {
enum class Type { File, Binary };
public: public:
Resource( // 二进制数据
LPCWSTR file_name /* 文件路径 */ struct Data
); {
void* buffer;
UINT32 size;
inline Data() : buffer(nullptr), size(0) {}
inline operator bool() const { return buffer && size; }
};
Resource();
Resource( Resource(
String const& file_name /* 文件路径 */ UINT id, /* 资源名称 */
LPCWSTR type /* 资源类型 */
); );
Resource( // 获取二进制数据
UINT id, /* 资源名称 */ Resource::Data GetData() const;
LPCWSTR type /* 资源类型 */
);
Resource( inline UINT GetId() const { return id_; }
Resource const& rhs
);
virtual ~Resource(); inline LPCWSTR GetType() const { return type_; }
bool Load(LPVOID& buffer, DWORD& buffer_size) const;
size_t GetHashCode() const;
Resource& operator= (Resource const& rhs);
inline bool IsFileType() const { return type_ == Type::File; }
inline String GetFileName() const { return file_name_ ? (*file_name_) : L""; }
inline UINT GetResourceId() const { return bin_id_; }
inline LPCWSTR GetResourceType() const { return bin_type_; }
private: private:
Type type_; UINT id_;
union LPCWSTR type_;
{ mutable Resource::Data data_;
struct
{
String* file_name_;
};
struct
{
UINT bin_id_;
LPCWSTR bin_type_;
};
};
}; };
} }

View File

@ -19,34 +19,9 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "Font.h" #include "Font.h"
#include "Renderer.h"
namespace kiwano namespace kiwano
{ {
//
// FontCollection
//
FontCollection::FontCollection()
{
}
FontCollection::FontCollection(Resource const& res)
{
Load(res);
}
bool FontCollection::Load(Resource const& res)
{
Renderer::GetInstance()->CreateFontFromResource(*this, res);
return false;
}
//
// Font
//
Font::Font(const String& family, float size, unsigned int weight, bool italic, FontCollection collection) Font::Font(const String& family, float size, unsigned int weight, bool italic, FontCollection collection)
: family(family) : family(family)
, size(size) , size(size)

View File

@ -19,10 +19,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include "../core/core.h" #include "FontCollection.h"
#include "../base/Resource.h"
#include "win32/ComPtr.hpp"
#include <dwrite.h>
namespace kiwano namespace kiwano
{ {
@ -40,28 +37,6 @@ namespace kiwano
ExtraBlack = 950 ExtraBlack = 950
}; };
// ×ÖÌ弯
class FontCollection
{
public:
FontCollection();
FontCollection(Resource const& res);
// ´Ó×ÊÔ´¼ÓÔØ×ÖÌ弯
bool Load(Resource const& res);
public:
inline ComPtr<IDWriteFontCollection> GetFontCollection() const { return collection_; }
inline void SetFontCollection(ComPtr<IDWriteFontCollection> collection) { collection_ = collection; }
protected:
ComPtr<IDWriteFontCollection> collection_;
};
// ×ÖÌå // ×ÖÌå
class Font class Font
{ {

View File

@ -0,0 +1,73 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "FontCollection.h"
#include "Renderer.h"
namespace kiwano
{
FontCollection::FontCollection()
{
}
FontCollection::FontCollection(String const& file)
{
Load(file);
}
FontCollection::FontCollection(Vector<String> const& files)
{
Load(files);
}
FontCollection::FontCollection(Resource const& res)
{
Load(res);
}
FontCollection::FontCollection(Vector<Resource> const& res_arr)
{
Load(res_arr);
}
bool FontCollection::Load(String const& file)
{
Renderer::GetInstance()->CreateFontCollection(*this, { file });
return false;
}
bool FontCollection::Load(Vector<String> const& files)
{
Renderer::GetInstance()->CreateFontCollection(*this, files);
return false;
}
bool FontCollection::Load(Resource const& res)
{
Renderer::GetInstance()->CreateFontCollection(*this, { res });
return false;
}
bool FontCollection::Load(Vector<Resource> const& res_arr)
{
Renderer::GetInstance()->CreateFontCollection(*this, res_arr);
return false;
}
}

View File

@ -0,0 +1,62 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "../base/Resource.h"
#include "win32/ComPtr.hpp"
#include <dwrite.h>
namespace kiwano
{
// 字体集
class FontCollection
{
public:
FontCollection();
FontCollection(String const& file);
FontCollection(Vector<String> const& files);
FontCollection(Resource const& res);
FontCollection(Vector<Resource> const& res_arr);
// 从本地文件加载字体
bool Load(String const& file);
// 从多个本地文件加载字体
bool Load(Vector<String> const& files);
// 从资源加载字体
bool Load(Resource const& res);
// 从多个资源加载字体
bool Load(Vector<Resource> const& res_arr);
public:
inline ComPtr<IDWriteFontCollection> GetFontCollection() const { return collection_; }
inline void SetFontCollection(ComPtr<IDWriteFontCollection> collection) { collection_ = collection; }
protected:
ComPtr<IDWriteFontCollection> collection_;
};
}

View File

@ -32,12 +32,33 @@ namespace kiwano
{ {
} }
GifImage::GifImage(String const& file_path)
{
Load(file_path);
}
GifImage::GifImage(Resource const& res) GifImage::GifImage(Resource const& res)
: GifImage() : GifImage()
{ {
Load(res); Load(res);
} }
bool GifImage::Load(String const& file_path)
{
Renderer::GetInstance()->CreateGifImage(*this, file_path);
if (IsValid())
{
if (FAILED(GetGlobalMetadata()))
{
SetDecoder(nullptr);
return false;
}
return true;
}
return false;
}
bool GifImage::Load(Resource const& res) bool GifImage::Load(Resource const& res)
{ {
Renderer::GetInstance()->CreateGifImage(*this, res); Renderer::GetInstance()->CreateGifImage(*this, res);

View File

@ -24,15 +24,17 @@
namespace kiwano namespace kiwano
{ {
// GIF ͼÏñ // GIF ͼÏñ
KGE_DECLARE_SMART_PTR(GifImage);
class KGE_API GifImage class KGE_API GifImage
: public ObjectBase
{ {
public: public:
GifImage(); GifImage();
GifImage(String const& file_path);
GifImage(Resource const& res); GifImage(Resource const& res);
bool Load(String const& file_path);
bool Load(Resource const& res); bool Load(Resource const& res);
bool IsValid() const; bool IsValid() const;

View File

@ -28,13 +28,17 @@ namespace kiwano
{ {
} }
Image::Image(String const& file_path)
{
Load(file_path);
}
Image::Image(Resource const& res) Image::Image(Resource const& res)
{ {
Load(res); Load(res);
} }
Image::Image(ComPtr<ID2D1Bitmap> const & bitmap) Image::Image(ComPtr<ID2D1Bitmap> const & bitmap)
: Image()
{ {
SetBitmap(bitmap); SetBitmap(bitmap);
} }
@ -43,6 +47,12 @@ namespace kiwano
{ {
} }
bool Image::Load(String const& file_path)
{
Renderer::GetInstance()->CreateImage(*this, file_path);
return IsValid();
}
bool Image::Load(Resource const& res) bool Image::Load(Resource const& res)
{ {
Renderer::GetInstance()->CreateImage(*this, res); Renderer::GetInstance()->CreateImage(*this, res);

View File

@ -29,6 +29,10 @@ namespace kiwano
public: public:
Image(); Image();
explicit Image(
String const& file_path
);
explicit Image( explicit Image(
Resource const& res Resource const& res
); );
@ -39,6 +43,11 @@ namespace kiwano
virtual ~Image(); virtual ~Image();
// 加载本地文件
bool Load(
String const& file_path
);
// ¼ÓÔØ×ÊÔ´ // ¼ÓÔØ×ÊÔ´
bool Load( bool Load(
Resource const& res Resource const& res

View File

@ -24,6 +24,32 @@
namespace kiwano namespace kiwano
{ {
template <typename _Ty, typename _PathTy, typename _CacheTy>
_Ty CreateOrGetCache(_CacheTy& cache, _PathTy const& path, size_t hash)
{
auto iter = cache.find(hash);
if (iter != cache.end())
{
return iter->second;
}
_Ty image;
if (image.Load(path))
{
cache.insert(std::make_pair(hash, image));
}
return image;
}
template <typename _CacheTy>
void RemoveCache(_CacheTy& cache, size_t hash)
{
auto iter = cache.find(hash);
if (iter != cache.end())
{
cache.erase(iter);
}
}
ImageCache::ImageCache() ImageCache::ImageCache()
{ {
@ -33,62 +59,44 @@ namespace kiwano
{ {
} }
Image ImageCache::AddImage(Resource const& res) Image ImageCache::AddOrGetImage(String const& file_path)
{ {
size_t hash_code = res.GetHashCode(); return CreateOrGetCache<Image>(image_cache_, file_path, file_path.hash());
}
auto iter = image_cache_.find(hash_code); Image ImageCache::AddOrGetImage(Resource const& res)
if (iter != image_cache_.end()) {
{ return CreateOrGetCache<Image>(image_cache_, res, res.GetId());
return iter->second; }
}
Image image; GifImage ImageCache::AddOrGetGifImage(String const& file_path)
if (image.Load(res)) {
{ return CreateOrGetCache<GifImage>(gif_image_cache_, file_path, file_path.hash());
image_cache_.insert(std::make_pair(hash_code, image)); }
}
return image; GifImage ImageCache::AddOrGetGifImage(Resource const& res)
{
return CreateOrGetCache<GifImage>(gif_image_cache_, res, res.GetId());
}
void ImageCache::RemoveImage(String const& file_path)
{
RemoveCache(image_cache_, file_path.hash());
} }
void ImageCache::RemoveImage(Resource const& res) void ImageCache::RemoveImage(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); RemoveCache(image_cache_, res.GetId());
auto iter = image_cache_.find(hash_code);
if (iter != image_cache_.end())
{
image_cache_.erase(iter);
}
} }
GifImagePtr ImageCache::AddGifImage(Resource const& res) void ImageCache::RemoveGifImage(String const& file_path)
{ {
size_t hash_code = res.GetHashCode(); RemoveCache(gif_image_cache_, file_path.hash());
auto iter = gif_image_cache_.find(hash_code);
if (iter != gif_image_cache_.end())
{
return iter->second;
}
GifImagePtr ptr = new GifImage;
if (ptr->Load(res))
{
gif_image_cache_.insert(std::make_pair(hash_code, ptr));
}
return ptr;
} }
void ImageCache::RemoveGifImage(Resource const& res) void ImageCache::RemoveGifImage(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); RemoveCache(gif_image_cache_, res.GetId());
auto iter = gif_image_cache_.find(hash_code);
if (iter != gif_image_cache_.end())
{
gif_image_cache_.erase(iter);
}
} }
void ImageCache::Clear() void ImageCache::Clear()

View File

@ -30,12 +30,14 @@ namespace kiwano
KGE_DECLARE_SINGLETON(ImageCache); KGE_DECLARE_SINGLETON(ImageCache);
public: public:
Image AddImage(Resource const& res); Image AddOrGetImage(String const& file_path);
Image AddOrGetImage(Resource const& res);
GifImage AddOrGetGifImage(String const& file_path);
GifImage AddOrGetGifImage(Resource const& res);
void RemoveImage(String const& file_path);
void RemoveImage(Resource const& res); void RemoveImage(Resource const& res);
void RemoveGifImage(String const& file_path);
GifImagePtr AddGifImage(Resource const& res);
void RemoveGifImage(Resource const& res); void RemoveGifImage(Resource const& res);
void Clear(); void Clear();
@ -49,7 +51,7 @@ namespace kiwano
using ImageMap = UnorderedMap<size_t, Image>; using ImageMap = UnorderedMap<size_t, Image>;
ImageMap image_cache_; ImageMap image_cache_;
using GifImageMap = UnorderedMap<size_t, GifImagePtr>; using GifImageMap = UnorderedMap<size_t, GifImage>;
GifImageMap gif_image_cache_; GifImageMap gif_image_cache_;
}; };
} }

View File

@ -232,6 +232,31 @@ namespace kiwano
return hr; return hr;
} }
void Renderer::CreateImage(Image& image, String const& file_path)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
ComPtr<ID2D1Bitmap> bitmap;
hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path);
if (SUCCEEDED(hr))
{
image.SetBitmap(bitmap);
}
}
if (FAILED(hr))
{
KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
}
}
void Renderer::CreateImage(Image& image, Resource const& res) void Renderer::CreateImage(Image& image, Resource const& res)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -240,19 +265,15 @@ namespace kiwano
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
ComPtr<ID2D1Bitmap> bitmap;
if (res.IsFileType())
{
hr = d2d_res_->CreateBitmapFromFile(bitmap, res.GetFileName());
}
else
{
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
image.SetBitmap(bitmap); ComPtr<ID2D1Bitmap> bitmap;
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
if (SUCCEEDED(hr))
{
image.SetBitmap(bitmap);
}
} }
if (FAILED(hr)) if (FAILED(hr))
@ -261,6 +282,43 @@ namespace kiwano
} }
} }
void Renderer::CreateGifImage(GifImage& image, String const& file_path)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
if (!FileUtil::ExistsFile(file_path))
{
KGE_WARNING_LOG(L"Gif image file '%s' not found!", file_path.c_str());
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
ComPtr<IWICBitmapDecoder> decoder;
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
file_path.c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&decoder
);
if (SUCCEEDED(hr))
{
image.SetDecoder(decoder);
}
}
if (FAILED(hr))
{
KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
}
}
void Renderer::CreateGifImage(GifImage& image, Resource const& res) void Renderer::CreateGifImage(GifImage& image, Resource const& res)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -269,61 +327,38 @@ namespace kiwano
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
ComPtr<IWICBitmapDecoder> decoder; Resource::Data res_data = res.GetData();
if (res.IsFileType())
{
if (!FileUtil::ExistsFile(res.GetFileName().c_str()))
{
KGE_WARNING_LOG(L"Gif image file '%s' not found!", res.GetFileName().c_str());
hr = E_FAIL;
}
if (SUCCEEDED(hr)) hr = res_data ? S_OK : E_FAIL;
{
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
res.GetFileName().c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&decoder
);
}
}
else
{
LPVOID buffer;
DWORD buffer_size;
HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
ComPtr<IWICStream> stream; ComPtr<IWICStream> stream;
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
if (SUCCEEDED(hr))
{
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = stream->InitializeFromMemory( hr = stream->InitializeFromMemory(
static_cast<WICInProcPointer>(buffer), static_cast<WICInProcPointer>(res_data.buffer),
buffer_size res_data.size
); );
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
ComPtr<IWICBitmapDecoder> decoder;
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream( hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
stream.get(), stream.get(),
nullptr, nullptr,
WICDecodeMetadataCacheOnLoad, WICDecodeMetadataCacheOnLoad,
&decoder &decoder
); );
}
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
image.SetDecoder(decoder); image.SetDecoder(decoder);
}
}
} }
if (FAILED(hr)) if (FAILED(hr))
@ -332,7 +367,7 @@ namespace kiwano
} }
} }
void Renderer::CreateFontFromResource(FontCollection& collection, Resource const& res) void Renderer::CreateFontCollection(FontCollection& collection, Vector<String> const& file_paths)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!d2d_res_) if (!d2d_res_)
@ -340,37 +375,78 @@ namespace kiwano
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
ComPtr<IDWriteFontCollection> font_collection; if (SUCCEEDED(hr))
if (res.IsFileType())
{ {
String file_path = res.GetFileName(); for (const auto& file_path : file_paths)
if (!FileUtil::ExistsFile(file_path.c_str()))
{ {
KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str()); if (!FileUtil::ExistsFile(file_path))
hr = E_FAIL; {
KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str());
hr = E_FAIL;
}
} }
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
font_collection_loader_.get(),
reinterpret_cast<const void*>(&file_path),
sizeof(file_path),
&font_collection
);
}
else
{
UINT id = res.GetResourceId();
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
res_font_collection_loader_.get(),
reinterpret_cast<const void*>(&id),
sizeof(id),
&font_collection
);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
collection.SetFontCollection(font_collection); LPVOID collection_key = nullptr;
UINT32 collection_key_size = 0;
hr = font_collection_loader_->AddFilePaths(file_paths, &collection_key, &collection_key_size);
if (SUCCEEDED(hr))
{
ComPtr<IDWriteFontCollection> font_collection;
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
font_collection_loader_.get(),
collection_key,
collection_key_size,
&font_collection
);
if (SUCCEEDED(hr))
{
collection.SetFontCollection(font_collection);
}
}
}
if (FAILED(hr))
{
KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr);
}
}
void Renderer::CreateFontCollection(FontCollection& collection, Vector<Resource> const& res_arr)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
LPVOID collection_key = nullptr;
UINT32 collection_key_size = 0;
hr = res_font_collection_loader_->AddResources(res_arr, &collection_key, &collection_key_size);
if (SUCCEEDED(hr))
{
ComPtr<IDWriteFontCollection> font_collection;
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
res_font_collection_loader_.get(),
collection_key,
collection_key_size,
&font_collection
);
if (SUCCEEDED(hr))
{
collection.SetFontCollection(font_collection);
}
}
} }
if (FAILED(hr)) if (FAILED(hr))

View File

@ -58,19 +58,34 @@ namespace kiwano
); );
public: public:
void CreateImage(
Image& image,
String const& file_path
);
void CreateImage( void CreateImage(
Image& image, Image& image,
Resource const& res Resource const& res
); );
void CreateGifImage(
GifImage& image,
String const& file_path
);
void CreateGifImage( void CreateGifImage(
GifImage& image, GifImage& image,
Resource const& res Resource const& res
); );
void CreateFontFromResource( void CreateFontCollection(
FontCollection& collection, FontCollection& collection,
Resource const& res Vector<String> const& file_paths
);
void CreateFontCollection(
FontCollection& collection,
Vector<Resource> const& res_arr
); );
void CreateTextFormat( void CreateTextFormat(

View File

@ -392,9 +392,8 @@ namespace kiwano
ComPtr<ID2D1Bitmap> bitmap_tmp; ComPtr<ID2D1Bitmap> bitmap_tmp;
// ¼ÓÔØ×ÊÔ´ // ¼ÓÔØ×ÊÔ´
LPVOID buffer; Resource::Data res_data = res.GetData();
DWORD buffer_size; HRESULT hr = res_data ? S_OK : E_FAIL;
HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -404,8 +403,8 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = stream->InitializeFromMemory( hr = stream->InitializeFromMemory(
static_cast<WICInProcPointer>(buffer), static_cast<WICInProcPointer>(res_data.buffer),
buffer_size res_data.size
); );
} }

View File

@ -37,6 +37,12 @@ namespace kiwano
{ {
} }
STDMETHOD(AddFilePaths)(
Vector<String> const& filePaths,
_Out_ LPVOID* pCollectionKey,
_Out_ UINT32* pCollectionKeySize
);
// IUnknown methods // IUnknown methods
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE AddRef();
@ -52,6 +58,10 @@ namespace kiwano
private: private:
ULONG refCount_; ULONG refCount_;
typedef Vector<String> FileCollection;
Vector<FileCollection> filePaths_;
Vector<UINT32> collectionKeys_;
}; };
HRESULT IFontCollectionLoader::Create(_Out_ IFontCollectionLoader** ppCollectionLoader) HRESULT IFontCollectionLoader::Create(_Out_ IFontCollectionLoader** ppCollectionLoader)
@ -77,6 +87,37 @@ namespace kiwano
return hr; return hr;
} }
STDMETHODIMP FontCollectionLoader::AddFilePaths(
Vector<String> const& filePaths,
_Out_ LPVOID* pCollectionKey,
_Out_ UINT32* pCollectionKeySize
)
{
if (!pCollectionKey || !pCollectionKeySize)
{
return E_INVALIDARG;
}
try
{
UINT32 collectionKey = filePaths_.size();
collectionKeys_.push_back(collectionKey);
filePaths_.push_back(filePaths);
*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back());
*pCollectionKeySize = sizeof(collectionKey);
}
catch (std::bad_alloc&)
{
return E_OUTOFMEMORY;
}
catch (...)
{
return E_FAIL;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE FontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) HRESULT STDMETHODCALLTYPE FontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
{ {
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader))
@ -115,7 +156,7 @@ namespace kiwano
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (collectionKey == NULL || collectionKeySize != sizeof(String)) if (collectionKey == NULL || collectionKeySize % sizeof(UINT32) != 0)
hr = E_INVALIDARG; hr = E_INVALIDARG;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -125,10 +166,8 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
String const* filePath = static_cast<String const*>(collectionKey); const UINT32 fileIndex = *static_cast<UINT32 const*>(collectionKey);
UINT32 const fileCount = collectionKeySize / sizeof(String); hr = pEnumerator->SetFilePaths(filePaths_[fileIndex]);
hr = pEnumerator->SetFilePaths(filePath, fileCount);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -157,8 +196,7 @@ namespace kiwano
); );
STDMETHOD(SetFilePaths)( STDMETHOD(SetFilePaths)(
String const* filePath, Vector<String> const& filePaths
UINT32 const fileCount
); );
~FontFileEnumerator() ~FontFileEnumerator()
@ -234,13 +272,12 @@ namespace kiwano
} }
STDMETHODIMP FontFileEnumerator::SetFilePaths( STDMETHODIMP FontFileEnumerator::SetFilePaths(
String const* filePath, Vector<String> const& filePaths
UINT32 const fileCount
) )
{ {
try try
{ {
filePaths_.assign(filePath, filePath + fileCount); filePaths_.assign(filePaths);
} }
catch (std::bad_alloc&) catch (std::bad_alloc&)
{ {
@ -332,6 +369,12 @@ namespace kiwano
{ {
} }
STDMETHOD(AddResources)(
Vector<Resource> const& resources,
_Out_ LPVOID* pCollectionKey,
_Out_ UINT32* pCollectionKeySize
);
// IUnknown methods // IUnknown methods
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE AddRef();
@ -348,6 +391,10 @@ namespace kiwano
private: private:
ULONG refCount_; ULONG refCount_;
IDWriteFontFileLoader* pFileLoader_; IDWriteFontFileLoader* pFileLoader_;
typedef Vector<Resource> ResourceCollection;
Vector<ResourceCollection> resources_;
Vector<UINT32> collectionKeys_;
}; };
HRESULT IResourceFontCollectionLoader::Create(_Out_ IResourceFontCollectionLoader** ppCollectionLoader, IDWriteFontFileLoader* pFileLoader) HRESULT IResourceFontCollectionLoader::Create(_Out_ IResourceFontCollectionLoader** ppCollectionLoader, IDWriteFontFileLoader* pFileLoader)
@ -373,6 +420,37 @@ namespace kiwano
return hr; return hr;
} }
STDMETHODIMP ResourceFontCollectionLoader::AddResources(
Vector<Resource> const& resources,
_Out_ LPVOID* pCollectionKey,
_Out_ UINT32* pCollectionKeySize
)
{
if (!pCollectionKey || !pCollectionKeySize)
{
return E_INVALIDARG;
}
try
{
UINT32 collectionKey = resources_.size();
collectionKeys_.push_back(collectionKey);
resources_.push_back(resources);
*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back());
*pCollectionKeySize = sizeof(collectionKey);
}
catch (std::bad_alloc&)
{
return E_OUTOFMEMORY;
}
catch (...)
{
return E_FAIL;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
{ {
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader))
@ -411,7 +489,7 @@ namespace kiwano
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (collectionKey == NULL || collectionKeySize % sizeof(UINT) != 0) if (collectionKey == NULL || collectionKeySize % sizeof(Resource*) != 0)
hr = E_INVALIDARG; hr = E_INVALIDARG;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -421,10 +499,9 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
UINT const* resourceID = static_cast<const UINT*>(collectionKey); const UINT32 resourceIndex = *static_cast<const UINT32*>(collectionKey);
UINT32 const resourceCount = collectionKeySize / sizeof(UINT);
hr = pEnumerator->SetResources(resourceID, resourceCount); hr = pEnumerator->SetResources(resources_[resourceIndex]);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -527,16 +604,16 @@ namespace kiwano
HRESULT hr = S_OK; HRESULT hr = S_OK;
// Make sure the key is the right size. // Make sure the key is the right size.
if (fontFileReferenceKeySize != sizeof(UINT)) if (fontFileReferenceKeySize != sizeof(Resource))
hr = E_INVALIDARG; hr = E_INVALIDARG;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Create the pFileStream object. // Create the pFileStream object.
IResourceFontFileStream* pFileStream = NULL; IResourceFontFileStream* pFileStream = NULL;
UINT resourceID = *static_cast<UINT const*>(fontFileReferenceKey); Resource resource = *static_cast<Resource const*>(fontFileReferenceKey);
hr = IResourceFontFileStream::Create(&pFileStream, resourceID); hr = IResourceFontFileStream::Create(&pFileStream, resource);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -566,8 +643,7 @@ namespace kiwano
); );
STDMETHOD(SetResources)( STDMETHOD(SetResources)(
UINT const* resourceID, Vector<Resource> const& resources
UINT32 const resourceCount
); );
~ResourceFontFileEnumerator() ~ResourceFontFileEnumerator()
@ -591,7 +667,7 @@ namespace kiwano
IDWriteFactory* pFactory_; IDWriteFactory* pFactory_;
IDWriteFontFile* currentFile_; IDWriteFontFile* currentFile_;
IDWriteFontFileLoader* pLoader_; IDWriteFontFileLoader* pLoader_;
Vector<UINT> resourceIDs_; Vector<Resource> resources_;
size_t nextIndex_; size_t nextIndex_;
}; };
@ -647,13 +723,12 @@ namespace kiwano
} }
STDMETHODIMP ResourceFontFileEnumerator::SetResources( STDMETHODIMP ResourceFontFileEnumerator::SetResources(
UINT const* resourceID, Vector<Resource> const& resources
UINT32 const resourceCount
) )
{ {
try try
{ {
resourceIDs_.assign(resourceID, resourceID + resourceCount); resources_.assign(resources);
} }
catch (std::bad_alloc&) catch (std::bad_alloc&)
{ {
@ -702,11 +777,11 @@ namespace kiwano
*hasCurrentFile = FALSE; *hasCurrentFile = FALSE;
DX::SafeRelease(currentFile_); DX::SafeRelease(currentFile_);
if (nextIndex_ < resourceIDs_.size()) if (nextIndex_ < resources_.size())
{ {
hr = pFactory_->CreateCustomFontFileReference( hr = pFactory_->CreateCustomFontFileReference(
&resourceIDs_[nextIndex_], &resources_[nextIndex_],
sizeof(UINT), sizeof(Resource),
pLoader_, pLoader_,
&currentFile_ &currentFile_
); );
@ -743,7 +818,7 @@ namespace kiwano
ResourceFontFileStream(); ResourceFontFileStream();
STDMETHOD(Initialize)( STDMETHOD(Initialize)(
const UINT resourceID Resource const resources
); );
// IUnknown methods // IUnknown methods
@ -782,7 +857,7 @@ namespace kiwano
DWORD resourceSize_; DWORD resourceSize_;
}; };
HRESULT IResourceFontFileStream::Create(_Out_ IResourceFontFileStream** ppStream, const UINT resourceID) HRESULT IResourceFontFileStream::Create(_Out_ IResourceFontFileStream** ppStream, const Resource resource)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -798,7 +873,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = pFileStream->Initialize(resourceID); hr = pFileStream->Initialize(resource);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -818,14 +893,16 @@ namespace kiwano
} }
STDMETHODIMP ResourceFontFileStream::Initialize( STDMETHODIMP ResourceFontFileStream::Initialize(
const UINT resourceID const Resource resource
) )
{ {
HRESULT hr = S_OK; Resource::Data data = resource.GetData();
HRESULT hr = data ? S_OK : E_FAIL;
if (!Resource{ resourceID, RT_FONT }.Load(resourcePtr_, resourceSize_)) if (SUCCEEDED(hr))
{ {
hr = E_FAIL; resourcePtr_ = data.buffer;
resourceSize_ = data.size;
} }
return hr; return hr;
} }

View File

@ -30,6 +30,12 @@ namespace kiwano
static HRESULT Create( static HRESULT Create(
_Out_ IFontCollectionLoader** ppCollectionLoader _Out_ IFontCollectionLoader** ppCollectionLoader
); );
STDMETHOD(AddFilePaths)(
Vector<String> const& filePaths,
_Out_ LPVOID * pCollectionKey,
_Out_ UINT32 * pCollectionKeySize
) PURE;
}; };
@ -43,8 +49,7 @@ namespace kiwano
); );
STDMETHOD(SetFilePaths)( STDMETHOD(SetFilePaths)(
String const* filePath, Vector<String> const& filePaths
UINT32 const fileCount
) PURE; ) PURE;
}; };
@ -57,6 +62,12 @@ namespace kiwano
_Out_ IResourceFontCollectionLoader** ppCollectionLoader, _Out_ IResourceFontCollectionLoader** ppCollectionLoader,
IDWriteFontFileLoader * pFileLoader IDWriteFontFileLoader * pFileLoader
); );
STDMETHOD(AddResources)(
Vector<Resource> const& resources,
_Out_ LPVOID * pCollectionKey,
_Out_ UINT32 * pCollectionKeySize
) PURE;
}; };
@ -81,8 +92,7 @@ namespace kiwano
); );
STDMETHOD(SetResources)( STDMETHOD(SetResources)(
UINT const* resourceID, Vector<Resource> const& resources
UINT32 const resourceCount
) PURE; ) PURE;
}; };
@ -93,7 +103,7 @@ namespace kiwano
public: public:
static HRESULT Create( static HRESULT Create(
_Out_ IResourceFontFileStream** ppStream, _Out_ IResourceFontFileStream** ppStream,
const UINT resourceID const Resource resource
); );
}; };
} }

View File

@ -46,12 +46,11 @@ namespace kiwano
if (file_handle == INVALID_HANDLE_VALUE) if (file_handle == INVALID_HANDLE_VALUE)
return false; return false;
LPVOID buffer; Resource::Data data = res.GetData();
DWORD buffer_size; if (data)
if (res.Load(buffer, buffer_size))
{ {
DWORD written_bytes = 0; DWORD written_bytes = 0;
::WriteFile(file_handle, buffer, buffer_size, &written_bytes, NULL); ::WriteFile(file_handle, data.buffer, data.size, &written_bytes, NULL);
::CloseHandle(file_handle); ::CloseHandle(file_handle);
return true; return true;

View File

@ -173,12 +173,12 @@ namespace kiwano
return false; return false;
} }
bool ResourceCache::AddFrame(String const& id, Resource const& res) bool ResourceCache::AddFrame(String const& id, String const& file_path)
{ {
FramePtr ptr = new (std::nothrow) Frame; FramePtr ptr = new (std::nothrow) Frame;
if (ptr) if (ptr)
{ {
if (ptr->Load(res)) if (ptr->Load(file_path))
{ {
return AddFrame(id, ptr); return AddFrame(id, ptr);
} }
@ -196,43 +196,20 @@ namespace kiwano
return false; return false;
} }
bool ResourceCache::AddGifImage(String const& id, Resource const& res) size_t ResourceCache::AddFrameSequence(String const& id, Vector<String> const& files)
{ {
GifImagePtr ptr = new (std::nothrow) GifImage; if (files.empty())
if (ptr)
{
if (ptr->Load(res))
{
return AddGifImage(id, ptr);
}
}
return false;
}
bool ResourceCache::AddGifImage(String const& id, GifImagePtr image)
{
if (image)
{
cache_.insert(std::make_pair(id, image));
return true;
}
return false;
}
size_t ResourceCache::AddFrameSequence(String const& id, Vector<Resource> const& images)
{
if (images.empty())
return 0; return 0;
Vector<FramePtr> image_arr; Vector<FramePtr> image_arr;
image_arr.reserve(images.size()); image_arr.reserve(files.size());
for (const auto& image : images) for (const auto& file : files)
{ {
FramePtr ptr = new (std::nothrow) Frame; FramePtr ptr = new (std::nothrow) Frame;
if (ptr) if (ptr)
{ {
if (ptr->Load(image)) if (ptr->Load(file))
{ {
image_arr.push_back(ptr); image_arr.push_back(ptr);
} }
@ -247,22 +224,13 @@ namespace kiwano
return 0; return 0;
} }
size_t ResourceCache::AddFrameSequence(String const& id, Vector<FramePtr> const& images) size_t ResourceCache::AddFrameSequence(String const & id, String const& file_path, int cols, int rows)
{
if (images.empty())
return 0;
FrameSequencePtr frames = new (std::nothrow) FrameSequence(images);
return AddFrameSequence(id, frames);
}
size_t ResourceCache::AddFrameSequence(String const & id, Resource const & image, int cols, int rows)
{ {
if (cols <= 0 || rows <= 0) if (cols <= 0 || rows <= 0)
return 0; return 0;
FramePtr raw = new (std::nothrow) Frame; FramePtr raw = new (std::nothrow) Frame;
if (!raw || !raw->Load(image)) if (!raw || !raw->Load(file_path))
return false; return false;
float raw_width = raw->GetWidth(); float raw_width = raw->GetWidth();
@ -290,29 +258,6 @@ namespace kiwano
return AddFrameSequence(id, frames); return AddFrameSequence(id, frames);
} }
size_t ResourceCache::AddFrameSequence(String const & id, Resource const & image, Vector<Rect> const & crop_rects)
{
FramePtr raw = new (std::nothrow) Frame;
if (!raw || !raw->Load(image))
return 0;
Vector<FramePtr> image_arr;
image_arr.reserve(crop_rects.size());
for (const auto& rect : crop_rects)
{
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
if (ptr)
{
ptr->SetCropRect(rect);
image_arr.push_back(ptr);
}
}
FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
return AddFrameSequence(id, frames);
}
size_t ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames) size_t ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
{ {
if (frames) if (frames)
@ -338,11 +283,6 @@ namespace kiwano
return Get<Frame>(id); return Get<Frame>(id);
} }
GifImagePtr ResourceCache::GetGifImage(String const& id) const
{
return Get<GifImage>(id);
}
FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const
{ {
return Get<FrameSequence>(id); return Get<FrameSequence>(id);
@ -376,23 +316,17 @@ namespace kiwano
if (file) if (file)
{ {
// Gif image
if (type && (*type) == L"gif")
{
return loader->AddGifImage(*id, Resource(gdata->path + (*file)));
}
if (!(*file).empty()) if (!(*file).empty())
{ {
if (rows || cols) if (rows || cols)
{ {
// Frame slices // Frame slices
return !!loader->AddFrameSequence(*id, Resource(gdata->path + (*file)), std::max(cols, 1), std::max(rows, 1)); return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1));
} }
else else
{ {
// Simple image // Simple image
return loader->AddFrame(*id, Resource(gdata->path + (*file))); return loader->AddFrame(*id, gdata->path + (*file));
} }
} }
} }
@ -410,7 +344,8 @@ namespace kiwano
frames.push_back(frame); frames.push_back(frame);
} }
} }
return !!loader->AddFrameSequence(*id, frames); FrameSequencePtr frame_seq = new FrameSequence(frames);
return !!loader->AddFrameSequence(*id, frame_seq);
} }
return false; return false;
} }

View File

@ -46,31 +46,18 @@ namespace kiwano
// 从 XML 文档对象加载资源信息 // 从 XML 文档对象加载资源信息
bool LoadFromXml(tinyxml2::XMLDocument* doc); bool LoadFromXml(tinyxml2::XMLDocument* doc);
// Ìí¼ÓͼƬ // Ìí¼Ó֡ͼÏñ
bool AddFrame(String const& id, Resource const& res); bool AddFrame(String const& id, String const& file_path);
// Ìí¼ÓͼƬ // Ìí¼Ó֡ͼÏñ
bool AddFrame(String const& id, FramePtr frame); bool AddFrame(String const& id, FramePtr frame);
// Ìí¼Ó GIF ͼƬ
bool AddGifImage(String const& id, Resource const& res);
// Ìí¼Ó GIF ͼƬ
bool AddGifImage(String const& id, GifImagePtr image);
// 添加序列帧 // 添加序列帧
size_t AddFrameSequence(String const& id, Vector<Resource> const& frames); size_t AddFrameSequence(String const& id, Vector<String> const& files);
// Ìí¼ÓÐòÁÐÖ¡
size_t AddFrameSequence(String const& id, Vector<FramePtr> const& frames);
// 添加序列帧 // 添加序列帧
// 按行列数裁剪图片 // 按行列数裁剪图片
size_t AddFrameSequence(String const& id, Resource const& frame, int cols, int rows = 1); size_t AddFrameSequence(String const& id, String const& file_path, int cols, int rows = 1);
// Ìí¼ÓÐòÁÐÖ¡
// °´Ö¸¶¨²Ã¼ô¾ØÐβüôͼƬ
size_t AddFrameSequence(String const& id, Resource const& frame, Vector<Rect> const& crop_rects);
// 添加序列帧 // 添加序列帧
size_t AddFrameSequence(String const& id, FrameSequencePtr frames); size_t AddFrameSequence(String const& id, FrameSequencePtr frames);
@ -78,12 +65,9 @@ namespace kiwano
// 添加对象 // 添加对象
bool AddObjectBase(String const& id, ObjectBasePtr obj); bool AddObjectBase(String const& id, ObjectBasePtr obj);
// »ñȡͼƬ×ÊÔ´ // »ñȡ֡ͼÏñ
FramePtr GetFrame(String const& id) const; FramePtr GetFrame(String const& id) const;
// »ñÈ¡ GIF ͼƬ×ÊÔ´
GifImagePtr GetGifImage(String const& id) const;
// 获取序列帧 // 获取序列帧
FrameSequencePtr GetFrameSequence(String const& id) const; FrameSequencePtr GetFrameSequence(String const& id) const;