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\renderer\Color.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\GifImage.h" />
<ClInclude Include="..\src\kiwano\renderer\Image.h" />
@ -127,6 +128,7 @@
<ClCompile Include="..\src\kiwano\platform\modules.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Color.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\GifImage.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" />

View File

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

View File

@ -34,13 +34,33 @@ namespace kiwano
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))
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)
{
@ -54,42 +74,39 @@ namespace kiwano
return false;
}
void Player::Play(Resource const& res, int loop_count)
void Player::Play(size_t id, int loop_count)
{
if (Load(res))
{
size_t hash_code = res.GetHashCode();
if (sound_cache_.end() != sound_cache_.find(hash_code))
sound_cache_[hash_code]->Play(loop_count);
}
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Play(loop_count);
}
void Player::Pause(Resource const& res)
void Player::Pause(size_t id)
{
size_t hash_code = res.GetHashCode();
if (sound_cache_.end() != sound_cache_.find(hash_code))
sound_cache_[hash_code]->Pause();
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Pause();
}
void Player::Resume(Resource const& res)
void Player::Resume(size_t id)
{
size_t hash_code = res.GetHashCode();
if (sound_cache_.end() != sound_cache_.find(hash_code))
sound_cache_[hash_code]->Resume();
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Resume();
}
void Player::Stop(Resource const& res)
void Player::Stop(size_t id)
{
size_t hash_code = res.GetHashCode();
if (sound_cache_.end() != sound_cache_.find(hash_code))
sound_cache_[hash_code]->Stop();
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Stop();
}
bool Player::IsPlaying(Resource const& res)
bool Player::IsPlaying(size_t id)
{
size_t hash_code = res.GetHashCode();
if (sound_cache_.end() != sound_cache_.find(hash_code))
return sound_cache_[hash_code]->IsPlaying();
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
return iter->second->IsPlaying();
return false;
}

View File

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

View File

@ -49,6 +49,46 @@ namespace kiwano
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)
{
if (opened_)
@ -56,28 +96,12 @@ namespace kiwano
Close();
}
HRESULT hr = S_OK;
Transcoder transcoder;
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_);
}
HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
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;
}

View File

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

View File

@ -83,13 +83,12 @@ namespace kiwano
ComPtr<IMFByteStream> byte_stream;
ComPtr<IMFSourceReader> reader;
LPVOID buffer;
DWORD buffer_size;
if (!res.Load(buffer, buffer_size)) { return E_FAIL; }
Resource::Data data = res.GetData();
if (!data) { return E_FAIL; }
stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream(
static_cast<const BYTE*>(buffer),
static_cast<UINT>(buffer_size)
static_cast<const BYTE*>(data.buffer),
static_cast<UINT>(data.size)
);
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)
{
Load(res);
}
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)
{
Image image = ImageCache::GetInstance()->AddImage(res);
Image image = ImageCache::GetInstance()->AddOrGetImage(res);
if (image.IsValid())
{
SetImage(image);

View File

@ -30,6 +30,10 @@ namespace kiwano
public:
Frame();
explicit Frame(
String const& file_path
);
explicit Frame(
Resource const& res
);
@ -38,6 +42,10 @@ namespace kiwano
Image const& image
);
bool Load(
String const& file_path
);
bool Load(
Resource const& res
);
@ -47,6 +55,11 @@ namespace kiwano
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
);
// ÉèÖÃλͼ
void SetImage(
Image const& image
);
// »ñÈ¡¿í¶È
float GetWidth() const { return crop_rect_.size.x; }
@ -65,9 +78,6 @@ namespace kiwano
// »ñȡλͼ
inline Image const& GetImage() const { return image_; }
// ÉèÖÃλͼ
void SetImage(Image const& image);
protected:
Image image_;
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()
{
Load(res);
}
GifSprite::GifSprite(GifImagePtr image)
GifSprite::GifSprite(GifImage 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);
}
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;
@ -62,8 +73,8 @@ namespace kiwano
disposal_type_ = DisposalType::None;
SetSize(
static_cast<float>(image_->GetWidthInPixels()),
static_cast<float>(image_->GetHeightInPixels())
static_cast<float>(image_.GetWidthInPixels()),
static_cast<float>(image_.GetHeightInPixels())
);
if (!frame_rt_.IsValid())
@ -71,7 +82,7 @@ namespace kiwano
Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
}
if (image_->GetFramesCount() > 0)
if (image_.GetFramesCount() > 0)
{
ComposeNextFrame();
}
@ -94,7 +105,7 @@ namespace kiwano
{
Actor::Update(dt);
if (image_ && animating_)
if (image_.IsValid() && animating_)
{
frame_elapsed_ += dt;
if (frame_delay_ <= frame_elapsed_)
@ -124,7 +135,7 @@ namespace kiwano
OverlayNextFrame();
} while (frame_delay_.IsZero() && !IsLastFrame());
animating_ = (!EndOfAnimation() && image_->GetFramesCount() > 1);
animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1);
}
}
@ -157,7 +168,7 @@ namespace kiwano
{
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))
{
@ -174,7 +185,7 @@ namespace kiwano
if (next_index_ == 0)
{
// ÖØÐ»æÖƱ³¾°
frame_rt_.Clear(image_->GetBackgroundColor());
frame_rt_.Clear(image_.GetBackgroundColor());
loop_count_++;
}
@ -192,7 +203,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
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_.PushClipRect(frame_rect_);
frame_rt_.Clear(image_->GetBackgroundColor());
frame_rt_.Clear(image_.GetBackgroundColor());
frame_rt_.PopClipRect();
return frame_rt_.EndDraw();

View File

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

View File

@ -24,18 +24,26 @@
namespace kiwano
{
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)
: frame_(nullptr)
{
Load(res);
}
Sprite::Sprite(Resource const& res, const Rect& crop_rect)
: frame_(nullptr)
{
Load(res);
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)
{
FramePtr frame = new (std::nothrow) Frame;

View File

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

View File

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

View File

@ -26,64 +26,43 @@ namespace kiwano
{
// 资源
//
// 资源可以是文件类型,也可以是保存在 exe 中的二进制资源
// 资源是保存在 exe 中的二进制数据
// 例如, 一份音频资源的类型为 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
//
class KGE_API Resource
{
enum class Type { File, Binary };
public:
Resource(
LPCWSTR file_name /* 文件路径 */
);
// 二进制数据
struct Data
{
void* buffer;
UINT32 size;
Resource(
String const& file_name /* 文件路径 */
);
inline Data() : buffer(nullptr), size(0) {}
inline operator bool() const { return buffer && size; }
};
Resource();
Resource(
UINT id, /* 资源名称 */
LPCWSTR type /* 资源类型 */
);
Resource(
Resource const& rhs
);
// 获取二进制数据
Resource::Data GetData() const;
virtual ~Resource();
inline UINT GetId() const { return id_; }
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_; }
inline LPCWSTR GetType() const { return type_; }
private:
Type type_;
union
{
struct
{
String* file_name_;
};
struct
{
UINT bin_id_;
LPCWSTR bin_type_;
};
};
UINT id_;
LPCWSTR type_;
mutable Resource::Data data_;
};
}

View File

@ -19,34 +19,9 @@
// THE SOFTWARE.
#include "Font.h"
#include "Renderer.h"
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)
: family(family)
, size(size)

View File

@ -19,10 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/core.h"
#include "../base/Resource.h"
#include "win32/ComPtr.hpp"
#include <dwrite.h>
#include "FontCollection.h"
namespace kiwano
{
@ -40,28 +37,6 @@ namespace kiwano
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
{

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()
{
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)
{
Renderer::GetInstance()->CreateGifImage(*this, res);

View File

@ -24,15 +24,17 @@
namespace kiwano
{
// GIF ͼÏñ
KGE_DECLARE_SMART_PTR(GifImage);
class KGE_API GifImage
: public ObjectBase
{
public:
GifImage();
GifImage(String const& file_path);
GifImage(Resource const& res);
bool Load(String const& file_path);
bool Load(Resource const& res);
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)
{
Load(res);
}
Image::Image(ComPtr<ID2D1Bitmap> const & bitmap)
: Image()
{
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)
{
Renderer::GetInstance()->CreateImage(*this, res);

View File

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

View File

@ -24,6 +24,32 @@
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()
{
@ -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();
auto iter = image_cache_.find(hash_code);
if (iter != image_cache_.end())
{
return iter->second;
return CreateOrGetCache<Image>(image_cache_, file_path, file_path.hash());
}
Image image;
if (image.Load(res))
Image ImageCache::AddOrGetImage(Resource const& res)
{
image_cache_.insert(std::make_pair(hash_code, image));
return CreateOrGetCache<Image>(image_cache_, res, res.GetId());
}
return image;
GifImage ImageCache::AddOrGetGifImage(String const& file_path)
{
return CreateOrGetCache<GifImage>(gif_image_cache_, file_path, file_path.hash());
}
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)
{
size_t hash_code = res.GetHashCode();
auto iter = image_cache_.find(hash_code);
if (iter != image_cache_.end())
{
image_cache_.erase(iter);
}
RemoveCache(image_cache_, res.GetId());
}
GifImagePtr ImageCache::AddGifImage(Resource const& res)
void ImageCache::RemoveGifImage(String const& file_path)
{
size_t hash_code = res.GetHashCode();
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;
RemoveCache(gif_image_cache_, file_path.hash());
}
void ImageCache::RemoveGifImage(Resource const& res)
{
size_t hash_code = res.GetHashCode();
auto iter = gif_image_cache_.find(hash_code);
if (iter != gif_image_cache_.end())
{
gif_image_cache_.erase(iter);
}
RemoveCache(gif_image_cache_, res.GetId());
}
void ImageCache::Clear()

View File

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

View File

@ -232,6 +232,31 @@ namespace kiwano
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)
{
HRESULT hr = S_OK;
@ -240,20 +265,16 @@ namespace kiwano
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
ComPtr<ID2D1Bitmap> bitmap;
if (res.IsFileType())
{
hr = d2d_res_->CreateBitmapFromFile(bitmap, res.GetFileName());
}
else
{
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
}
if (SUCCEEDED(hr))
{
image.SetBitmap(bitmap);
}
}
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)
{
HRESULT hr = S_OK;
@ -269,62 +327,39 @@ namespace kiwano
hr = E_UNEXPECTED;
}
ComPtr<IWICBitmapDecoder> decoder;
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;
}
Resource::Data res_data = res.GetData();
hr = res_data ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
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;
ComPtr<IWICStream> stream;
if (SUCCEEDED(hr))
{
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
}
if (SUCCEEDED(hr))
{
hr = stream->InitializeFromMemory(
static_cast<WICInProcPointer>(buffer),
buffer_size
static_cast<WICInProcPointer>(res_data.buffer),
res_data.size
);
}
if (SUCCEEDED(hr))
{
ComPtr<IWICBitmapDecoder> decoder;
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
stream.get(),
nullptr,
WICDecodeMetadataCacheOnLoad,
&decoder
);
}
}
if (SUCCEEDED(hr))
{
image.SetDecoder(decoder);
}
}
}
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;
if (!d2d_res_)
@ -340,38 +375,79 @@ namespace kiwano
hr = E_UNEXPECTED;
}
ComPtr<IDWriteFontCollection> font_collection;
if (res.IsFileType())
if (SUCCEEDED(hr))
{
String file_path = res.GetFileName();
if (!FileUtil::ExistsFile(file_path.c_str()))
for (const auto& file_path : file_paths)
{
if (!FileUtil::ExistsFile(file_path))
{
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))
{
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))
{

View File

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

View File

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

View File

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

View File

@ -46,12 +46,11 @@ namespace kiwano
if (file_handle == INVALID_HANDLE_VALUE)
return false;
LPVOID buffer;
DWORD buffer_size;
if (res.Load(buffer, buffer_size))
Resource::Data data = res.GetData();
if (data)
{
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);
return true;

View File

@ -173,12 +173,12 @@ namespace kiwano
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;
if (ptr)
{
if (ptr->Load(res))
if (ptr->Load(file_path))
{
return AddFrame(id, ptr);
}
@ -196,43 +196,20 @@ namespace kiwano
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 (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())
if (files.empty())
return 0;
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;
if (ptr)
{
if (ptr->Load(image))
if (ptr->Load(file))
{
image_arr.push_back(ptr);
}
@ -247,22 +224,13 @@ namespace kiwano
return 0;
}
size_t ResourceCache::AddFrameSequence(String const& id, Vector<FramePtr> const& images)
{
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)
size_t ResourceCache::AddFrameSequence(String const & id, String const& file_path, int cols, int rows)
{
if (cols <= 0 || rows <= 0)
return 0;
FramePtr raw = new (std::nothrow) Frame;
if (!raw || !raw->Load(image))
if (!raw || !raw->Load(file_path))
return false;
float raw_width = raw->GetWidth();
@ -290,29 +258,6 @@ namespace kiwano
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)
{
if (frames)
@ -338,11 +283,6 @@ namespace kiwano
return Get<Frame>(id);
}
GifImagePtr ResourceCache::GetGifImage(String const& id) const
{
return Get<GifImage>(id);
}
FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const
{
return Get<FrameSequence>(id);
@ -376,23 +316,17 @@ namespace kiwano
if (file)
{
// Gif image
if (type && (*type) == L"gif")
{
return loader->AddGifImage(*id, Resource(gdata->path + (*file)));
}
if (!(*file).empty())
{
if (rows || cols)
{
// 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
{
// 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);
}
}
return !!loader->AddFrameSequence(*id, frames);
FrameSequencePtr frame_seq = new FrameSequence(frames);
return !!loader->AddFrameSequence(*id, frame_seq);
}
return false;
}

View File

@ -46,31 +46,18 @@ namespace kiwano
// 从 XML 文档对象加载资源信息
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);
// Ìí¼Ó 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<FramePtr> const& frames);
size_t AddFrameSequence(String const& id, Vector<String> const& files);
// 添加序列帧
// 按行列数裁剪图片
size_t AddFrameSequence(String const& id, Resource const& frame, 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, String const& file_path, int cols, int rows = 1);
// 添加序列帧
size_t AddFrameSequence(String const& id, FrameSequencePtr frames);
@ -78,12 +65,9 @@ namespace kiwano
// 添加对象
bool AddObjectBase(String const& id, ObjectBasePtr obj);
// »ñȡͼƬ×ÊÔ´
// »ñȡ֡ͼÏñ
FramePtr GetFrame(String const& id) const;
// »ñÈ¡ GIF ͼƬ×ÊÔ´
GifImagePtr GetGifImage(String const& id) const;
// 获取序列帧
FrameSequencePtr GetFrameSequence(String const& id) const;