optimize: manage COM resources with intrusive::SmartPointer

refactoring: loads dll modules in constructors
This commit is contained in:
Haibo 2018-11-17 17:15:32 +08:00 committed by Nomango
parent 4498a3dd8b
commit b98e958213
49 changed files with 741 additions and 788 deletions

View File

@ -58,7 +58,7 @@ namespace easy2d
if (actions_.IsEmpty()) if (actions_.IsEmpty())
return; return;
for (auto& action = actions_.First(); action; action = action->NextItem()) for (auto action = actions_.First(); action; action = action->NextItem())
{ {
action->Resume(); action->Resume();
} }
@ -69,7 +69,7 @@ namespace easy2d
if (actions_.IsEmpty()) if (actions_.IsEmpty())
return; return;
for (auto& action = actions_.First(); action; action = action->NextItem()) for (auto action = actions_.First(); action; action = action->NextItem())
{ {
action->Pause(); action->Pause();
} }
@ -80,7 +80,7 @@ namespace easy2d
if (actions_.IsEmpty()) if (actions_.IsEmpty())
return; return;
for (auto& action = actions_.First(); action; action = action->NextItem()) for (auto action = actions_.First(); action; action = action->NextItem())
{ {
action->Stop(); action->Stop();
} }

View File

@ -18,20 +18,17 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include "base.hpp"
#include "Canvas.h" #include "Canvas.h"
#include "render.h" #include "render.h"
#include "logs.h" #include "logs.h"
namespace easy2d namespace easy2d
{ {
/////////////////////////////////////////////////////// //-------------------------------------------------------
/////////////////////////////////////////////////////// // CanvasBrush
// FIXME!!! //-------------------------------------------------------
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
Canvas::Canvas(float width, float height) CanvasBrush::CanvasBrush()
: render_target_(nullptr) : render_target_(nullptr)
, fill_brush_(nullptr) , fill_brush_(nullptr)
, line_brush_(nullptr) , line_brush_(nullptr)
@ -39,94 +36,76 @@ namespace easy2d
, stroke_width_(1.0f) , stroke_width_(1.0f)
, stroke_(StrokeStyle::Miter) , stroke_(StrokeStyle::Miter)
{ {
// render_target_ = render::D2D.HwndRenderTarget; auto graphics = devices::Graphics::Instance();
render_target_->AddRef(); render_target_ = graphics->GetRenderTarget();
ThrowIfFailed( ThrowIfFailed(
render_target_->CreateSolidColorBrush( graphics->CreateSolidColorBrush(fill_brush_)
D2D1::ColorF(D2D1::ColorF::White),
&fill_brush_
)
); );
ThrowIfFailed( ThrowIfFailed(
render_target_->CreateSolidColorBrush( graphics->CreateSolidColorBrush(line_brush_)
D2D1::ColorF(D2D1::ColorF::White),
&line_brush_
)
); );
this->SetClipEnabled(true);
this->SetWidth(width);
this->SetHeight(height);
this->SetStrokeStyle(stroke_); this->SetStrokeStyle(stroke_);
} }
Canvas::~Canvas() CanvasBrush::~CanvasBrush()
{ {
SafeRelease(stroke_style_);
SafeRelease(line_brush_);
SafeRelease(fill_brush_);
SafeRelease(render_target_);
} }
void Canvas::SetLineColor(const Color & color) void CanvasBrush::SetLineColor(Color const& color)
{ {
line_brush_->SetColor(D2D_COLOR_F(color)); line_brush_->SetColor(D2D_COLOR_F(color));
} }
void Canvas::SetFillColor(const Color & color) void CanvasBrush::SetFillColor(Color const& color)
{ {
fill_brush_->SetColor(D2D_COLOR_F(color)); fill_brush_->SetColor(D2D_COLOR_F(color));
} }
void Canvas::SetStrokeWidth(float width) void CanvasBrush::SetStrokeWidth(float width)
{ {
stroke_width_ = std::max(width, 0.f); stroke_width_ = std::max(width, 0.f);
} }
void Canvas::SetStrokeStyle(StrokeStyle stroke) void CanvasBrush::SetStrokeStyle(StrokeStyle stroke)
{ {
SafeRelease(stroke_style_);
stroke_style_ = devices::Graphics::Instance()->GetStrokeStyle(stroke); stroke_style_ = devices::Graphics::Instance()->GetStrokeStyle(stroke);
if (stroke_style_)
stroke_style_->AddRef();
} }
Color Canvas::GetLineColor() const Color CanvasBrush::GetLineColor() const
{ {
return line_brush_->GetColor(); return line_brush_->GetColor();
} }
Color Canvas::GetFillColor() const Color CanvasBrush::GetFillColor() const
{ {
return fill_brush_->GetColor(); return fill_brush_->GetColor();
} }
float Canvas::GetStrokeWidth() const float CanvasBrush::GetStrokeWidth() const
{ {
return stroke_width_; return stroke_width_;
} }
StrokeStyle Canvas::GetStrokeStyle() const StrokeStyle CanvasBrush::GetStrokeStyle() const
{ {
return stroke_; return stroke_;
} }
void Canvas::DrawLine(const Point & begin, const Point & end) void CanvasBrush::DrawLine(const Point & begin, const Point & end)
{ {
render_target_->DrawLine( render_target_->DrawLine(
D2D1::Point2F(begin.x, begin.y), D2D1::Point2F(begin.x, begin.y),
D2D1::Point2F(end.x, end.y), D2D1::Point2F(end.x, end.y),
line_brush_, line_brush_.Get(),
stroke_width_, stroke_width_,
stroke_style_ stroke_style_.Get()
); );
} }
void Canvas::DrawCircle(const Point & center, float radius) void CanvasBrush::DrawCircle(const Point & center, float radius)
{ {
render_target_->DrawEllipse( render_target_->DrawEllipse(
D2D1::Ellipse( D2D1::Ellipse(
@ -137,13 +116,13 @@ namespace easy2d
radius, radius,
radius radius
), ),
line_brush_, line_brush_.Get(),
stroke_width_, stroke_width_,
stroke_style_ stroke_style_.Get()
); );
} }
void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) void CanvasBrush::DrawEllipse(const Point & center, float radius_x, float radius_y)
{ {
render_target_->DrawEllipse( render_target_->DrawEllipse(
D2D1::Ellipse( D2D1::Ellipse(
@ -154,13 +133,13 @@ namespace easy2d
radius_x, radius_x,
radius_y radius_y
), ),
line_brush_, line_brush_.Get(),
stroke_width_, stroke_width_,
stroke_style_ stroke_style_.Get()
); );
} }
void Canvas::DrawRect(const Rect & rect) void CanvasBrush::DrawRect(const Rect & rect)
{ {
render_target_->DrawRectangle( render_target_->DrawRectangle(
D2D1::RectF( D2D1::RectF(
@ -169,13 +148,13 @@ namespace easy2d
rect.origin.x + rect.size.width, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height rect.origin.y + rect.size.height
), ),
line_brush_, line_brush_.Get(),
stroke_width_, stroke_width_,
stroke_style_ stroke_style_.Get()
); );
} }
void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) void CanvasBrush::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y)
{ {
render_target_->DrawRoundedRectangle( render_target_->DrawRoundedRectangle(
D2D1::RoundedRect( D2D1::RoundedRect(
@ -188,13 +167,13 @@ namespace easy2d
radius_x, radius_x,
radius_y radius_y
), ),
line_brush_, line_brush_.Get(),
stroke_width_, stroke_width_,
stroke_style_ stroke_style_.Get()
); );
} }
void Canvas::FillCircle(const Point & center, float radius) void CanvasBrush::FillCircle(const Point & center, float radius)
{ {
render_target_->FillEllipse( render_target_->FillEllipse(
D2D1::Ellipse( D2D1::Ellipse(
@ -205,11 +184,11 @@ namespace easy2d
radius, radius,
radius radius
), ),
fill_brush_ fill_brush_.Get()
); );
} }
void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) void CanvasBrush::FillEllipse(const Point & center, float radius_x, float radius_y)
{ {
render_target_->FillEllipse( render_target_->FillEllipse(
D2D1::Ellipse( D2D1::Ellipse(
@ -220,11 +199,11 @@ namespace easy2d
radius_x, radius_x,
radius_y radius_y
), ),
fill_brush_ fill_brush_.Get()
); );
} }
void Canvas::FillRect(const Rect & rect) void CanvasBrush::FillRect(const Rect & rect)
{ {
render_target_->FillRectangle( render_target_->FillRectangle(
D2D1::RectF( D2D1::RectF(
@ -233,11 +212,11 @@ namespace easy2d
rect.origin.x + rect.size.width, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height rect.origin.y + rect.size.height
), ),
fill_brush_ fill_brush_.Get()
); );
} }
void Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) void CanvasBrush::FillRoundedRect(const Rect & rect, float radius_x, float radius_y)
{ {
render_target_->FillRoundedRectangle( render_target_->FillRoundedRectangle(
D2D1::RoundedRect( D2D1::RoundedRect(
@ -250,7 +229,40 @@ namespace easy2d
radius_x, radius_x,
radius_y radius_y
), ),
fill_brush_ fill_brush_.Get()
); );
} }
//-------------------------------------------------------
// Canvas
//-------------------------------------------------------
Canvas::Canvas()
{
}
Canvas::Canvas(float width, float height)
{
this->SetClipEnabled(true);
this->SetWidth(width);
this->SetHeight(height);
}
Canvas::~Canvas()
{
}
void Canvas::SetBrush(spCanvasBrush const & brush)
{
brush_ = brush;
}
void Canvas::OnDraw()
{
if (!brush_)
brush_ = new CanvasBrush;
OnDraw(*brush_);
}
} }

View File

@ -20,55 +20,21 @@
#pragma once #pragma once
#include "Node.h" #include "Node.h"
#include <d2d1.h>
namespace easy2d namespace easy2d
{ {
// ť­˛ź E2D_DECLARE_SMART_PTR(CanvasBrush);
class Canvas
: public Node // ť­ąĘ
class CanvasBrush
: public RefCounter
{ {
E2D_DISABLE_COPY(Canvas); E2D_DISABLE_COPY(CanvasBrush);
public: public:
Canvas( CanvasBrush();
float width,
float height
);
virtual ~Canvas(); virtual ~CanvasBrush();
// ÉčÖĂĎßĚőŃŐÉŤ
void SetLineColor(
const Color& color
);
// ÉčÖĂĚîłäŃŐÉŤ
void SetFillColor(
const Color& color
);
// ÉčÖĂĎßĚőżíśČ
void SetStrokeWidth(
float width
);
// ÉčÖĂĎßĚőĎཝŃůĘ˝
void SetStrokeStyle(
StrokeStyle stroke
);
// ťńČĄĎßĚőŃŐÉŤ
Color GetLineColor() const;
// ťńČĄĚîłäŃŐÉŤ
Color GetFillColor() const;
// ťńČĄĎßĚőżíśČ
float GetStrokeWidth() const;
// ťńČĄĎßĚőĎཝŃůĘ˝
StrokeStyle GetStrokeStyle() const;
// »­Ö±Ïß // »­Ö±Ïß
void DrawLine( void DrawLine(
@ -126,12 +92,74 @@ namespace easy2d
float radius_y float radius_y
); );
// ÉčÖĂĎßĚőŃŐÉŤ
void SetLineColor(
const Color& color
);
// ÉčÖĂĚîłäŃŐÉŤ
void SetFillColor(
const Color& color
);
// ÉčÖĂĎßĚőżíśČ
void SetStrokeWidth(
float width
);
// ÉčÖĂĎßĚőĎཝŃůĘ˝
void SetStrokeStyle(
StrokeStyle stroke
);
// ťńČĄĎßĚőŃŐÉŤ
Color GetLineColor() const;
// ťńČĄĚîłäŃŐÉŤ
Color GetFillColor() const;
// ťńČĄĎßĚőżíśČ
float GetStrokeWidth() const;
// ťńČĄĎßĚőĎཝŃůĘ˝
StrokeStyle GetStrokeStyle() const;
protected: protected:
float stroke_width_; float stroke_width_;
StrokeStyle stroke_; StrokeStyle stroke_;
ID2D1RenderTarget* render_target_; cpRenderTarget render_target_;
ID2D1SolidColorBrush* fill_brush_; cpSolidColorBrush fill_brush_;
ID2D1SolidColorBrush* line_brush_; cpSolidColorBrush line_brush_;
ID2D1StrokeStyle* stroke_style_; cpStrokeStyle stroke_style_;
};
// ť­˛ź
class Canvas
: public Node
{
E2D_DISABLE_COPY(Canvas);
public:
Canvas();
Canvas(
float width,
float height
);
virtual ~Canvas();
virtual void OnDraw(CanvasBrush& brush) = 0;
// ÉčÖĂť­Ë˘
void SetBrush(
spCanvasBrush const& brush
);
virtual void OnDraw() override;
private:
spCanvasBrush brush_;
}; };
} }

View File

@ -31,14 +31,14 @@ namespace easy2d
{ {
} }
Image::Image(Resource& res) Image::Image(Resource const& res)
: bitmap_(nullptr) : bitmap_(nullptr)
, crop_rect_() , crop_rect_()
{ {
this->Load(res); this->Load(res);
} }
Image::Image(Resource& res, const Rect& crop_rect) Image::Image(Resource const& res, Rect const& crop_rect)
: bitmap_(nullptr) : bitmap_(nullptr)
, crop_rect_() , crop_rect_()
{ {
@ -46,14 +46,14 @@ namespace easy2d
this->Crop(crop_rect); this->Crop(crop_rect);
} }
Image::Image(const String & file_name) Image::Image(String const& file_name)
: bitmap_(nullptr) : bitmap_(nullptr)
, crop_rect_() , crop_rect_()
{ {
this->Load(file_name); this->Load(file_name);
} }
Image::Image(const String & file_name, const Rect & crop_rect) Image::Image(String const& file_name, const Rect & crop_rect)
: bitmap_(nullptr) : bitmap_(nullptr)
, crop_rect_() , crop_rect_()
{ {
@ -63,23 +63,24 @@ namespace easy2d
Image::~Image() Image::~Image()
{ {
SafeRelease(bitmap_);
} }
bool Image::Load(Resource& res) bool Image::Load(Resource const& res)
{ {
ID2D1Bitmap* bitmap; HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(bitmap_, res);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(res, &bitmap);
if (FAILED(hr)) if (FAILED(hr))
{ {
logs::Errorln(hr, "Load Image from resource failed!"); logs::Errorln(hr, "Load Image from resource failed!");
return false; return false;
} }
this->SetBitmap(bitmap);
crop_rect_.origin.x = crop_rect_.origin.y = 0;
crop_rect_.size.width = bitmap_->GetSize().width;
crop_rect_.size.height = bitmap_->GetSize().height;
return true; return true;
} }
bool Image::Load(const String & file_name) bool Image::Load(String const& file_name)
{ {
File image_file; File image_file;
if (!image_file.Open(file_name)) if (!image_file.Open(file_name))
@ -92,18 +93,20 @@ namespace easy2d
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径 // 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
String image_file_path = image_file.GetPath(); String image_file_path = image_file.GetPath();
ID2D1Bitmap* bitmap; HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(bitmap_, image_file_path);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(image_file_path, &bitmap);
if (FAILED(hr)) if (FAILED(hr))
{ {
logs::Errorln(hr, "Load Image from file failed!"); logs::Errorln(hr, "Load Image from file failed!");
return false; return false;
} }
this->SetBitmap(bitmap);
crop_rect_.origin.x = crop_rect_.origin.y = 0;
crop_rect_.size.width = bitmap_->GetSize().width;
crop_rect_.size.height = bitmap_->GetSize().height;
return true; return true;
} }
void Image::Crop(const Rect& crop_rect) void Image::Crop(Rect const& crop_rect)
{ {
if (bitmap_) if (bitmap_)
{ {
@ -179,31 +182,13 @@ namespace easy2d
return crop_rect_.origin; return crop_rect_.origin;
} }
const Rect & Image::GetCropRect() const Rect const& Image::GetCropRect() const
{ {
return crop_rect_; return crop_rect_;
} }
ID2D1Bitmap * Image::GetBitmap() const cpBitmap const& Image::GetBitmap() const
{ {
return bitmap_; return bitmap_;
} }
void Image::SetBitmap(ID2D1Bitmap * bitmap)
{
if (bitmap_ == bitmap)
return;
SafeRelease(bitmap_);
if (bitmap)
{
bitmap->AddRef();
bitmap_ = bitmap;
crop_rect_.origin.x = crop_rect_.origin.y = 0;
crop_rect_.size.width = bitmap_->GetSize().width;
crop_rect_.size.height = bitmap_->GetSize().height;
}
}
} }

View File

@ -34,38 +34,38 @@ namespace easy2d
Image(); Image();
explicit Image( explicit Image(
Resource& res Resource const& res
); );
explicit Image( explicit Image(
Resource& res, Resource const& res,
const Rect& crop_rect /* 裁剪矩形 */ Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
explicit Image( explicit Image(
const String& file_name String const& file_name
); );
explicit Image( explicit Image(
const String& file_name, String const& file_name,
const Rect& crop_rect /* 裁剪矩形 */ Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
virtual ~Image(); virtual ~Image();
// 加载图片资源 // 加载图片资源
bool Load( bool Load(
Resource& res Resource const& res
); );
// 加载图片资源 // 加载图片资源
bool Load( bool Load(
const String& file_name String const& file_name
); );
// 将图片裁剪为矩形 // 将图片裁剪为矩形
void Crop( void Crop(
const Rect& crop_rect /* 裁剪矩形 */ Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
); );
// 获取宽度 // 获取宽度
@ -96,19 +96,12 @@ namespace easy2d
Point GetCropPos() const; Point GetCropPos() const;
// 获取裁剪矩形 // 获取裁剪矩形
const Rect& GetCropRect() const; Rect const& GetCropRect() const;
// 获取 ID2D1Bitmap 对象 cpBitmap const& GetBitmap() const;
ID2D1Bitmap * GetBitmap() const;
private: protected:
// 设置 Bitmap
void SetBitmap(
ID2D1Bitmap * bitmap
);
private:
Rect crop_rect_; Rect crop_rect_;
ID2D1Bitmap* bitmap_; cpBitmap bitmap_;
}; };
} }

View File

@ -36,7 +36,7 @@ namespace easy2d
{ {
} }
Music::Music(const String& file_path) Music::Music(String const& file_path)
: opened_(false) : opened_(false)
, playing_(false) , playing_(false)
, wave_data_(nullptr) , wave_data_(nullptr)
@ -46,7 +46,7 @@ namespace easy2d
Load(file_path); Load(file_path);
} }
Music::Music(Resource& res) Music::Music(Resource const& res)
: opened_(false) : opened_(false)
, playing_(false) , playing_(false)
, wave_data_(nullptr) , wave_data_(nullptr)
@ -61,7 +61,7 @@ namespace easy2d
Close(); Close();
} }
bool Music::Load(const String & file_path) bool Music::Load(String const& file_path)
{ {
if (opened_) if (opened_)
{ {
@ -87,7 +87,7 @@ namespace easy2d
return false; return false;
} }
hr = devices::Audio::Instance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); hr = devices::Audio::Instance()->CreateVoice(voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr)) if (FAILED(hr))
{ {
if (wave_data_) if (wave_data_)
@ -103,7 +103,7 @@ namespace easy2d
return true; return true;
} }
bool Music::Load(Resource& res) bool Music::Load(Resource const& res)
{ {
if (opened_) if (opened_)
{ {
@ -119,7 +119,7 @@ namespace easy2d
return false; return false;
} }
hr = devices::Audio::Instance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); hr = devices::Audio::Instance()->CreateVoice(voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr)) if (FAILED(hr))
{ {
if (wave_data_) if (wave_data_)

View File

@ -22,7 +22,6 @@
#include "base.hpp" #include "base.hpp"
#include "audio.h" #include "audio.h"
#include "Resource.h" #include "Resource.h"
#include <xaudio2.h>
namespace easy2d namespace easy2d
{ {
@ -36,23 +35,23 @@ namespace easy2d
Music(); Music();
Music( Music(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
Music( Music(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
virtual ~Music(); virtual ~Music();
// 打开音乐文件 // 打开音乐文件
bool Load( bool Load(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 打开音乐资源 // 打开音乐资源
bool Load( bool Load(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 播放 // 播放

View File

@ -46,7 +46,6 @@ namespace easy2d
, clip_enabled_(false) , clip_enabled_(false)
, dirty_sort_(false) , dirty_sort_(false)
, dirty_transform_(false) , dirty_transform_(false)
, border_(nullptr)
, order_(0) , order_(0)
, transform_() , transform_()
, display_opacity_(1.f) , display_opacity_(1.f)
@ -62,7 +61,6 @@ namespace easy2d
Node::~Node() Node::~Node()
{ {
SafeRelease(border_);
} }
void Node::Visit() void Node::Visit()
@ -172,7 +170,7 @@ namespace easy2d
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.f, 1.5f); devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.f, 1.5f);
} }
for (auto& child = children_.First(); child; child = child->NextItem()) for (auto child = children_.First(); child; child = child->NextItem())
{ {
child->DrawBorder(); child->DrawBorder();
} }
@ -198,12 +196,11 @@ namespace easy2d
} }
// ÖØÐ¹¹ÔìÂÖÀª // ÖØÐ¹¹ÔìÂÖÀª
SafeRelease(border_);
ThrowIfFailed( ThrowIfFailed(
devices::Graphics::Instance()->CreateRectGeometry(final_matrix_, transform_.size, &border_) devices::Graphics::Instance()->CreateRectGeometry(border_, final_matrix_, transform_.size)
); );
for (auto& child = children_.First(); child; child = child->NextItem()) for (auto child = children_.First(); child; child = child->NextItem())
{ {
child->dirty_transform_ = true; child->dirty_transform_ = true;
} }
@ -214,7 +211,7 @@ namespace easy2d
if (visible_) if (visible_)
{ {
spNode prev; spNode prev;
for (auto& child = children_.Last(); child; child = prev) for (auto child = children_.Last(); child; child = prev)
{ {
prev = child->PrevItem(); prev = child->PrevItem();
handled = child->Dispatch(e, handled); handled = child->Dispatch(e, handled);
@ -233,7 +230,7 @@ namespace easy2d
if (visible_) if (visible_)
{ {
spNode prev; spNode prev;
for (auto& child = children_.Last(); child; child = prev) for (auto child = children_.Last(); child; child = prev)
{ {
prev = child->PrevItem(); prev = child->PrevItem();
handled = child->Dispatch(e, handled); handled = child->Dispatch(e, handled);
@ -253,7 +250,7 @@ namespace easy2d
{ {
display_opacity_ = real_opacity_ * parent_->display_opacity_; display_opacity_ = real_opacity_ * parent_->display_opacity_;
} }
for (auto& child = children_.First(); child; child = child->NextItem()) for (auto child = children_.First(); child; child = child->NextItem())
{ {
child->UpdateOpacity(); child->UpdateOpacity();
} }
@ -264,7 +261,7 @@ namespace easy2d
return visible_; return visible_;
} }
const String& Node::GetName() const String const& Node::GetName() const
{ {
return name_; return name_;
} }
@ -531,7 +528,7 @@ namespace easy2d
clip_enabled_ = enabled; clip_enabled_ = enabled;
} }
void Node::SetBorderColor(const Color & color) void Node::SetBorderColor(Color const& color)
{ {
border_color_ = color; border_color_ = color;
} }
@ -579,7 +576,7 @@ namespace easy2d
return Rect(Point{}, transform_.size); return Rect(Point{}, transform_.size);
} }
Node::Nodes Node::GetChildren(const String& name) const Node::Nodes Node::GetChildren(String const& name) const
{ {
Nodes children; Nodes children;
size_t hash_code = std::hash<String>{}(name); size_t hash_code = std::hash<String>{}(name);
@ -594,7 +591,7 @@ namespace easy2d
return children; return children;
} }
spNode Node::GetChild(const String& name) const spNode Node::GetChild(String const& name) const
{ {
size_t hash_code = std::hash<String>{}(name); size_t hash_code = std::hash<String>{}(name);
@ -639,7 +636,7 @@ namespace easy2d
return false; return false;
} }
void Node::RemoveChildren(const String& child_name) void Node::RemoveChildren(String const& child_name)
{ {
if (children_.IsEmpty()) if (children_.IsEmpty())
{ {
@ -648,7 +645,7 @@ namespace easy2d
size_t hash_code = std::hash<String>{}(child_name); size_t hash_code = std::hash<String>{}(child_name);
spNode next; spNode next;
for (auto& child = children_.First(); child; child = next) for (auto child = children_.First(); child; child = next)
{ {
next = child->NextItem(); next = child->NextItem();
@ -693,7 +690,7 @@ namespace easy2d
D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN; D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN;
ThrowIfFailed( ThrowIfFailed(
border_->CompareWithGeometry( border_->CompareWithGeometry(
node->border_, node->border_.Get(),
D2D1::Matrix3x2F::Identity(), D2D1::Matrix3x2F::Identity(),
&relation &relation
) )
@ -707,7 +704,7 @@ namespace easy2d
visible_ = val; visible_ = val;
} }
void Node::SetName(const String& name) void Node::SetName(String const& name)
{ {
if (name_ != name) if (name_ != name)
{ {

View File

@ -64,7 +64,7 @@ namespace easy2d
bool IsVisible() const; bool IsVisible() const;
// 获取节点名称 // 获取节点名称
const String& GetName() const; String const& GetName() const;
// 获取节点名称的 Hash 值 // 获取节点名称的 Hash 值
size_t GetHashName() const; size_t GetHashName() const;
@ -133,7 +133,7 @@ namespace easy2d
// 设置节点名称 // 设置节点名称
void SetName( void SetName(
const String& name String const& name
); );
// 设置节点横坐标 // 设置节点横坐标
@ -310,12 +310,12 @@ namespace easy2d
// 获取所有名称相同的子节点 // 获取所有名称相同的子节点
Nodes GetChildren( Nodes GetChildren(
const String& name String const& name
) const; ) const;
// 获取名称相同的子节点 // 获取名称相同的子节点
spNode GetChild( spNode GetChild(
const String& name String const& name
) const; ) const;
// 获取全部子节点 // 获取全部子节点
@ -328,7 +328,7 @@ namespace easy2d
// 移除所有名称相同的子节点 // 移除所有名称相同的子节点
void RemoveChildren( void RemoveChildren(
const String& child_name String const& child_name
); );
// 移除所有节点 // 移除所有节点
@ -378,7 +378,7 @@ namespace easy2d
Node* parent_; Node* parent_;
Color border_color_; Color border_color_;
Children children_; Children children_;
ID2D1Geometry* border_; cpGeometry border_;
Transform transform_; Transform transform_;
math::Matrix initial_matrix_; math::Matrix initial_matrix_;
math::Matrix final_matrix_; math::Matrix final_matrix_;

View File

@ -33,12 +33,12 @@ namespace easy2d
virtual ~RefCounter() {} virtual ~RefCounter() {}
// 增加引用计数 // 增加引用计数
inline void Retain() { ::InterlockedIncrement(&ref_count_); } inline void Retain() { ++ref_count_; }
// 减少引用计数 // 减少引用计数
inline void Release() inline void Release()
{ {
if (::InterlockedDecrement(&ref_count_) <= 0) if (--ref_count_ <= 0)
delete this; delete this;
} }

View File

@ -35,26 +35,26 @@ namespace easy2d
Load(image); Load(image);
} }
Sprite::Sprite(Resource& res) Sprite::Sprite(Resource const& res)
: image_(nullptr) : image_(nullptr)
{ {
Load(res); Load(res);
} }
Sprite::Sprite(Resource& res, const Rect& crop_rect) Sprite::Sprite(Resource const& res, const Rect& crop_rect)
: image_(nullptr) : image_(nullptr)
{ {
Load(res); Load(res);
Crop(crop_rect); Crop(crop_rect);
} }
Sprite::Sprite(const String & file_name) Sprite::Sprite(String const& file_name)
: image_(nullptr) : image_(nullptr)
{ {
Load(file_name); Load(file_name);
} }
Sprite::Sprite(const String & file_name, const Rect & crop_rect) Sprite::Sprite(String const& file_name, const Rect & crop_rect)
: image_(nullptr) : image_(nullptr)
{ {
Load(file_name); Load(file_name);
@ -77,7 +77,7 @@ namespace easy2d
return false; return false;
} }
bool Sprite::Load(Resource& res) bool Sprite::Load(Resource const& res)
{ {
if (!image_) if (!image_)
{ {
@ -95,7 +95,7 @@ namespace easy2d
return false; return false;
} }
bool Sprite::Load(const String & file_name) bool Sprite::Load(String const& file_name)
{ {
if (!image_) if (!image_)
{ {

View File

@ -38,20 +38,20 @@ namespace easy2d
); );
explicit Sprite( explicit Sprite(
Resource& res Resource const& res
); );
explicit Sprite( explicit Sprite(
Resource& res, Resource const& res,
const Rect& crop_rect /* 裁剪矩形 */ const Rect& crop_rect /* 裁剪矩形 */
); );
explicit Sprite( explicit Sprite(
const String& file_name String const& file_name
); );
explicit Sprite( explicit Sprite(
const String& file_name, String const& file_name,
const Rect& crop_rect /* 裁剪矩形 */ const Rect& crop_rect /* 裁剪矩形 */
); );
@ -59,12 +59,12 @@ namespace easy2d
// 加载图片文件 // 加载图片文件
bool Load( bool Load(
Resource& res Resource const& res
); );
// 加载图片文件 // 加载图片文件
bool Load( bool Load(
const String& file_name String const& file_name
); );
// 加载图片 // 加载图片

View File

@ -22,12 +22,12 @@
namespace easy2d namespace easy2d
{ {
Task::Task(const Callback & func, const String & name) Task::Task(const Callback & func, String const& name)
: Task(func, Duration{}, -1, name) : Task(func, Duration{}, -1, name)
{ {
} }
Task::Task(Callback const& func, Duration const& delay, int times, const String & name) Task::Task(Callback const& func, Duration const& delay, int times, String const& name)
: running_(true) : running_(true)
, stopped_(false) , stopped_(false)
, run_times_(0) , run_times_(0)
@ -92,7 +92,7 @@ namespace easy2d
return running_; return running_;
} }
const String& Task::GetName() const String const& Task::GetName() const
{ {
return name_; return name_;
} }

View File

@ -41,14 +41,14 @@ namespace easy2d
public: public:
explicit Task( explicit Task(
const Callback& func, /* 执行函数 */ const Callback& func, /* 执行函数 */
const String& name = L"" /* ÈÎÎñÃû³Æ */ String const& name = L"" /* ÈÎÎñÃû³Æ */
); );
explicit Task( explicit Task(
Callback const& func, /* 执行函数 */ Callback const& func, /* 执行函数 */
Duration const& delay, /* 时间间隔(秒) */ Duration const& delay, /* 时间间隔(秒) */
int times = -1, /* 执行次数(设 -1 为永久执行) */ int times = -1, /* 执行次数(设 -1 为永久执行) */
const String& name = L"" /* ÈÎÎñÃû³Æ */ String const& name = L"" /* ÈÎÎñÃû³Æ */
); );
// 启动任务 // 启动任务
@ -61,7 +61,7 @@ namespace easy2d
bool IsRunning() const; bool IsRunning() const;
// 获取任务名称 // 获取任务名称
const String& GetName() const; String const& GetName() const;
protected: protected:
void Update(Duration const& dt); void Update(Duration const& dt);

View File

@ -52,9 +52,9 @@ namespace easy2d
} }
} }
void TaskManager::StopTasks(const String& name) void TaskManager::StopTasks(String const& name)
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
if (task->GetName() == name) if (task->GetName() == name)
{ {
@ -63,9 +63,9 @@ namespace easy2d
} }
} }
void TaskManager::StartTasks(const String& name) void TaskManager::StartTasks(String const& name)
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
if (task->GetName() == name) if (task->GetName() == name)
{ {
@ -74,9 +74,9 @@ namespace easy2d
} }
} }
void TaskManager::RemoveTasks(const String& name) void TaskManager::RemoveTasks(String const& name)
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
if (task->GetName() == name) if (task->GetName() == name)
{ {
@ -87,7 +87,7 @@ namespace easy2d
void TaskManager::StopAllTasks() void TaskManager::StopAllTasks()
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
task->Stop(); task->Stop();
} }
@ -95,7 +95,7 @@ namespace easy2d
void TaskManager::StartAllTasks() void TaskManager::StartAllTasks()
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
task->Start(); task->Start();
} }
@ -103,7 +103,7 @@ namespace easy2d
void TaskManager::RemoveAllTasks() void TaskManager::RemoveAllTasks()
{ {
for (auto& task = tasks_.First(); task; task = task->NextItem()) for (auto task = tasks_.First(); task; task = task->NextItem())
{ {
task->stopped_ = true; task->stopped_ = true;
} }

View File

@ -35,17 +35,17 @@ namespace easy2d
// 启动任务 // 启动任务
void StartTasks( void StartTasks(
const String& task_name String const& task_name
); );
// 停止任务 // 停止任务
void StopTasks( void StopTasks(
const String& task_name String const& task_name
); );
// 移除任务 // 移除任务
void RemoveTasks( void RemoveTasks(
const String& task_name String const& task_name
); );
// 启动所有任务 // 启动所有任务

View File

@ -44,44 +44,38 @@ namespace easy2d
Text::Text() Text::Text()
: font_(text_default_font) : font_(text_default_font)
, style_(text_default_style) , style_(text_default_style)
, text_layout_(nullptr)
, text_format_(nullptr)
, dirty_layout_(false) , dirty_layout_(false)
{ {
} }
Text::Text(const String & text) Text::Text(String const& text)
: Text(text, text_default_font, text_default_style) : Text(text, text_default_font, text_default_style)
{ {
} }
Text::Text(const String & text, const Font & font) Text::Text(String const& text, const Font & font)
: Text(text, font, text_default_style) : Text(text, font, text_default_style)
{ {
} }
Text::Text(const String & text, const TextStyle & style) Text::Text(String const& text, const TextStyle & style)
: Text(text, text_default_font, style) : Text(text, text_default_font, style)
{ {
} }
Text::Text(const String & text, const Font & font, const TextStyle & style) Text::Text(String const& text, const Font & font, const TextStyle & style)
: font_(font) : font_(font)
, style_(style) , style_(style)
, text_(text) , text_(text)
, text_layout_(nullptr)
, text_format_(nullptr)
, dirty_layout_(true) , dirty_layout_(true)
{ {
} }
Text::~Text() Text::~Text()
{ {
SafeRelease(text_format_);
SafeRelease(text_layout_);
} }
const String& Text::GetText() const String const& Text::GetText() const
{ {
return text_; return text_;
} }
@ -96,7 +90,7 @@ namespace easy2d
return style_; return style_;
} }
const String& Text::GetFontFamily() const String const& Text::GetFontFamily() const
{ {
return font_.family; return font_.family;
} }
@ -171,7 +165,7 @@ namespace easy2d
return style_.outline; return style_.outline;
} }
void Text::SetText(const String& text) void Text::SetText(String const& text)
{ {
text_ = text; text_ = text;
dirty_layout_ = true; dirty_layout_ = true;
@ -189,7 +183,7 @@ namespace easy2d
dirty_layout_ = true; dirty_layout_ = true;
} }
void Text::SetFontFamily(const String& family) void Text::SetFontFamily(String const& family)
{ {
if (font_.family != family) if (font_.family != family)
{ {
@ -332,8 +326,8 @@ namespace easy2d
if (!dirty_layout_) if (!dirty_layout_)
return; return;
SafeRelease(text_format_); text_format_ = nullptr;
SafeRelease(text_layout_); text_layout_ = nullptr;
if (text_.empty()) if (text_.empty())
return; return;
@ -342,7 +336,7 @@ namespace easy2d
ThrowIfFailed( ThrowIfFailed(
graphics->CreateTextFormat( graphics->CreateTextFormat(
&text_format_, text_format_,
font_ font_
) )
); );
@ -366,7 +360,7 @@ namespace easy2d
{ {
ThrowIfFailed( ThrowIfFailed(
graphics->CreateTextLayout( graphics->CreateTextLayout(
&text_layout_, text_layout_,
text_, text_,
text_format_, text_format_,
style_.wrap_width style_.wrap_width
@ -381,7 +375,7 @@ namespace easy2d
{ {
ThrowIfFailed( ThrowIfFailed(
graphics->CreateTextLayout( graphics->CreateTextLayout(
&text_layout_, text_layout_,
text_, text_,
text_format_, text_format_,
0 0
@ -392,10 +386,9 @@ namespace easy2d
text_layout_->GetMetrics(&metrics); text_layout_->GetMetrics(&metrics);
this->SetSize(metrics.width, metrics.height); this->SetSize(metrics.width, metrics.height);
SafeRelease(text_layout_);
ThrowIfFailed( ThrowIfFailed(
graphics->CreateTextLayout( graphics->CreateTextLayout(
&text_layout_, text_layout_,
text_, text_,
text_format_, text_format_,
metrics.width metrics.width

View File

@ -35,21 +35,21 @@ namespace easy2d
Text(); Text();
explicit Text( explicit Text(
const String& text /* 文字内容 */ String const& text /* 文字内容 */
); );
explicit Text( explicit Text(
const String& text, /* 文字内容 */ String const& text, /* 文字内容 */
const Font& font /* 字体 */ const Font& font /* 字体 */
); );
explicit Text( explicit Text(
const String& text, /* 文字内容 */ String const& text, /* 文字内容 */
const TextStyle& style /* 文本样式 */ const TextStyle& style /* 文本样式 */
); );
explicit Text( explicit Text(
const String& text, /* 文字内容 */ String const& text, /* 文字内容 */
const Font& font, /* 字体 */ const Font& font, /* 字体 */
const TextStyle& style /* 文本样式 */ const TextStyle& style /* 文本样式 */
); );
@ -57,7 +57,7 @@ namespace easy2d
virtual ~Text(); virtual ~Text();
// 获取文本 // 获取文本
const String& GetText() const; String const& GetText() const;
// 获取字体 // 获取字体
const Font& GetFont() const; const Font& GetFont() const;
@ -66,7 +66,7 @@ namespace easy2d
const TextStyle& GetStyle() const; const TextStyle& GetStyle() const;
// 获取字体族 // 获取字体族
const String& GetFontFamily() const; String const& GetFontFamily() const;
// 获取当前字号 // 获取当前字号
float GetFontSize() const; float GetFontSize() const;
@ -106,7 +106,7 @@ namespace easy2d
// 设置文本 // 设置文本
void SetText( void SetText(
const String& text String const& text
); );
// 设置文本样式 // 设置文本样式
@ -121,7 +121,7 @@ namespace easy2d
// 设置字体族 // 设置字体族
void SetFontFamily( void SetFontFamily(
const String& family String const& family
); );
// 设置字号(默认值为 22 // 设置字号(默认值为 22
@ -217,7 +217,7 @@ namespace easy2d
Font font_; Font font_;
TextStyle style_; TextStyle style_;
bool dirty_layout_; bool dirty_layout_;
IDWriteTextFormat* text_format_; cpTextFormat text_format_;
IDWriteTextLayout* text_layout_; cpTextLayout text_layout_;
}; };
} }

View File

@ -65,15 +65,15 @@ namespace easy2d
STDMETHODIMP_(void) ITextRenderer::SetTextStyle( STDMETHODIMP_(void) ITextRenderer::SetTextStyle(
CONST D2D1_COLOR_F &fillColor, CONST D2D1_COLOR_F &fillColor,
BOOL outline, BOOL outline,
CONST D2D1_COLOR_F &outline_color, CONST D2D1_COLOR_F &outlineColor,
FLOAT outline_width, FLOAT outlineWidth,
D2D1_LINE_JOIN outlineJoin) ID2D1StrokeStyle* outlineJoin)
{ {
sFillColor_ = fillColor; sFillColor_ = fillColor;
bShowOutline_ = outline; bShowOutline_ = outline;
sOutlineColor_ = outline_color; sOutlineColor_ = outlineColor;
fOutlineWidth = 2 * outline_width; fOutlineWidth = 2 * outlineWidth;
pCurrStrokeStyle_ = devices::Graphics::Instance()->GetStrokeStyle(StrokeStyle(outlineJoin)); pCurrStrokeStyle_ = outlineJoin;
} }
STDMETHODIMP ITextRenderer::DrawGlyphRun( STDMETHODIMP ITextRenderer::DrawGlyphRun(

View File

@ -19,9 +19,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include "macros.h" #include "d2dres.hpp"
#include <d2d1.h>
#include <dwrite.h>
namespace easy2d namespace easy2d
{ {
@ -39,9 +37,9 @@ namespace easy2d
STDMETHOD_(void, SetTextStyle)( STDMETHOD_(void, SetTextStyle)(
CONST D2D1_COLOR_F &fillColor, CONST D2D1_COLOR_F &fillColor,
BOOL outline, BOOL outline,
CONST D2D1_COLOR_F &outline_color, CONST D2D1_COLOR_F &outlineColor,
FLOAT outline_width, FLOAT outlineWidth,
D2D1_LINE_JOIN outlineJoin ID2D1StrokeStyle* outlineJoin
); );
STDMETHOD(DrawGlyphRun)( STDMETHOD(DrawGlyphRun)(
@ -124,3 +122,5 @@ namespace easy2d
ID2D1StrokeStyle* pCurrStrokeStyle_; ID2D1StrokeStyle* pCurrStrokeStyle_;
}; };
} }
E2D_DECLARE_D2D_SMART_PTR(easy2d::ITextRenderer, spTextRenderer);

View File

@ -48,8 +48,6 @@ namespace easy2d
Transition::~Transition() Transition::~Transition()
{ {
SafeRelease(out_layer_);
SafeRelease(in_layer_);
} }
bool Transition::IsDone() bool Transition::IsDone()
@ -68,14 +66,14 @@ namespace easy2d
if (in_scene_) if (in_scene_)
{ {
ThrowIfFailed( ThrowIfFailed(
devices::Graphics::Instance()->CreateLayer(&in_layer_) devices::Graphics::Instance()->CreateLayer(in_layer_)
); );
} }
if (out_scene_) if (out_scene_)
{ {
ThrowIfFailed( ThrowIfFailed(
devices::Graphics::Instance()->CreateLayer(&out_layer_) devices::Graphics::Instance()->CreateLayer(out_layer_)
); );
} }

View File

@ -63,8 +63,8 @@ namespace easy2d
Size window_size_; Size window_size_;
spScene out_scene_; spScene out_scene_;
spScene in_scene_; spScene in_scene_;
ID2D1Layer* out_layer_; cpLayer out_layer_;
ID2D1Layer* in_layer_; cpLayer in_layer_;
LayerProperties out_layer_prop_; LayerProperties out_layer_prop_;
LayerProperties in_layer_prop_; LayerProperties in_layer_prop_;
}; };

View File

@ -166,7 +166,6 @@ namespace easy2d
, mastering_voice_(nullptr) , mastering_voice_(nullptr)
, initialized(false) , initialized(false)
{ {
modules::Init();
} }
AudioDevice::~AudioDevice() AudioDevice::~AudioDevice()
@ -183,9 +182,7 @@ namespace easy2d
SafeRelease(x_audio2_); SafeRelease(x_audio2_);
modules::MediaFoundation.MFShutdown(); modules::MediaFoundation().MFShutdown();
modules::Destroy();
} }
void AudioDevice::Init(bool debug) void AudioDevice::Init(bool debug)
@ -196,11 +193,11 @@ namespace easy2d
E2D_LOG("Initing audio device"); E2D_LOG("Initing audio device");
ThrowIfFailed( ThrowIfFailed(
modules::MediaFoundation.MFStartup(MF_VERSION, MFSTARTUP_FULL) modules::MediaFoundation().MFStartup(MF_VERSION, MFSTARTUP_FULL)
); );
ThrowIfFailed( ThrowIfFailed(
modules::XAudio2.XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR) modules::XAudio2().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR)
); );
ThrowIfFailed( ThrowIfFailed(
@ -210,33 +207,23 @@ namespace easy2d
initialized = true; initialized = true;
} }
HRESULT AudioDevice::CreateVoice(Voice* voice, WAVEFORMATEX * wfx) HRESULT AudioDevice::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx)
{ {
HRESULT hr; HRESULT hr;
IXAudio2SourceVoice* source_voice; IXAudio2SourceVoice* source_voice;
if (!voice)
return E_POINTER;
hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
voice->SetSourceVoice(source_voice); voice.SetSourceVoice(source_voice);
voice_cache_.push_back(voice); voice_cache_.insert(&voice);
} }
return hr; return hr;
} }
void AudioDevice::DeleteVoice(Voice * voice) void AudioDevice::DeleteVoice(Voice* voice)
{ {
for (auto iter = voice_cache_.begin(); iter != voice_cache_.end(); ++iter) voice_cache_.erase(voice);
{
if (*iter == voice)
{
voice_cache_.erase(iter);
break;
}
}
} }
void AudioDevice::ClearVoiceCache() void AudioDevice::ClearVoiceCache()

View File

@ -90,8 +90,8 @@ namespace easy2d
void Close(); void Close();
HRESULT CreateVoice( HRESULT CreateVoice(
Voice* voice, Voice& voice,
WAVEFORMATEX * wfx const WAVEFORMATEX* wfx
); );
void DeleteVoice( void DeleteVoice(
@ -109,7 +109,7 @@ namespace easy2d
bool initialized; bool initialized;
IXAudio2* x_audio2_; IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_; IXAudio2MasteringVoice* mastering_voice_;
std::list<Voice*> voice_cache_; std::set<Voice*> voice_cache_;
}; };
E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio); E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio);

View File

@ -22,7 +22,7 @@
#include "BaseTypes.hpp" #include "BaseTypes.hpp"
#include "RefCounter.hpp" #include "RefCounter.hpp"
#include "intrusive/SmartPointer.hpp" #include "intrusive/SmartPointer.hpp"
#include "d2dres.hpp"
#ifndef E2D_DECLARE_SMART_PTR #ifndef E2D_DECLARE_SMART_PTR
#define E2D_DECLARE_SMART_PTR(class_name)\ #define E2D_DECLARE_SMART_PTR(class_name)\
@ -37,7 +37,6 @@
} }
#endif #endif
namespace easy2d namespace easy2d
{ {
E2D_DECLARE_SMART_PTR(Image); E2D_DECLARE_SMART_PTR(Image);
@ -80,14 +79,4 @@ namespace easy2d
E2D_DECLARE_NS_SMART_PTR(ui, Button); E2D_DECLARE_NS_SMART_PTR(ui, Button);
E2D_DECLARE_NS_SMART_PTR(ui, Menu); E2D_DECLARE_NS_SMART_PTR(ui, Menu);
template<class Interface>
inline void SafeRelease(Interface*& p)
{
if (p != nullptr)
{
p->Release();
p = nullptr;
}
}
} }

65
core/base/d2dres.hpp Normal file
View File

@ -0,0 +1,65 @@
// Copyright (c) 2016-2018 Easy2D - 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 "macros.h"
#include "intrusive/SmartPointer.hpp"
#include <d2d1.h>
#include <dwrite.h>
#ifndef E2D_DECLARE_D2D_SMART_PTR
#define E2D_DECLARE_D2D_SMART_PTR(class_name, sp_name)\
using sp_name = ::easy2d::intrusive::SmartPointer< class_name >
#endif
namespace easy2d
{
E2D_DECLARE_D2D_SMART_PTR(ID2D1Factory, cpFactory);
E2D_DECLARE_D2D_SMART_PTR(IWICImagingFactory, cpImagingFactory);
E2D_DECLARE_D2D_SMART_PTR(IDWriteFactory, cpWriteFactory);
E2D_DECLARE_D2D_SMART_PTR(ID2D1SolidColorBrush, cpSolidColorBrush);
E2D_DECLARE_D2D_SMART_PTR(ID2D1HwndRenderTarget, cpRenderTarget);
E2D_DECLARE_D2D_SMART_PTR(ID2D1StrokeStyle, cpStrokeStyle);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Layer, cpLayer);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Bitmap, cpBitmap);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Geometry, cpGeometry);
E2D_DECLARE_D2D_SMART_PTR(IDWriteTextFormat, cpTextFormat);
E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, cpTextLayout);
inline void IntrusivePtrAddRef(IUnknown* ptr)
{
if (ptr) { ptr->AddRef(); }
}
inline void IntrusivePtrRelease(IUnknown* ptr)
{
if (ptr) { ptr->Release(); }
}
inline void SafeRelease(IUnknown* ptr)
{
if (ptr != nullptr)
{
ptr->Release();
}
}
}

View File

@ -19,8 +19,17 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include "../macros.h"
#include <utility> #include <utility>
#ifndef E2D_INTRUSIVE_PTR_ASSERT
# ifdef E2D_DEBUG
# define E2D_INTRUSIVE_PTR_ASSERT(expr, msg) do { if (!(expr)) throw std::runtime_error(msg); } while(0);
# else
# define E2D_INTRUSIVE_PTR_ASSERT __noop
# endif
#endif
namespace easy2d namespace easy2d
{ {
namespace intrusive namespace intrusive
@ -33,65 +42,74 @@ namespace easy2d
public: public:
using Type = T; using Type = T;
SmartPointer() {} SmartPointer() E2D_NOEXCEPT {}
SmartPointer(nullptr_t) {} SmartPointer(nullptr_t) E2D_NOEXCEPT {}
SmartPointer(Type* p) : ptr_(p) SmartPointer(Type* p) E2D_NOEXCEPT : ptr_(p)
{ {
IntrusivePtrAddRef(ptr_); IntrusivePtrAddRef(ptr_);
} }
SmartPointer(const SmartPointer& other) : ptr_(other.ptr_) SmartPointer(const SmartPointer& other) E2D_NOEXCEPT : ptr_(other.ptr_)
{ {
IntrusivePtrAddRef(ptr_); IntrusivePtrAddRef(ptr_);
} }
template <typename U> template <typename U>
SmartPointer(const SmartPointer<U>& other) : ptr_(other.Get()) SmartPointer(const SmartPointer<U>& other) E2D_NOEXCEPT : ptr_(other.Get())
{ {
IntrusivePtrAddRef(ptr_); IntrusivePtrAddRef(ptr_);
} }
SmartPointer(SmartPointer&& other) SmartPointer(SmartPointer&& other) E2D_NOEXCEPT
{ {
ptr_ = other.ptr_; ptr_ = other.ptr_;
other.ptr_ = nullptr; other.ptr_ = nullptr;
} }
~SmartPointer() ~SmartPointer() E2D_NOEXCEPT
{ {
IntrusivePtrRelease(ptr_); IntrusivePtrRelease(ptr_);
} }
inline Type* Get() const { return ptr_; } inline Type* Get() const E2D_NOEXCEPT { return ptr_; }
inline void Swap(SmartPointer& other) inline void Swap(SmartPointer& other) E2D_NOEXCEPT
{ {
std::swap(ptr_, other.ptr_); std::swap(ptr_, other.ptr_);
} }
inline Type* operator ->() const inline Type* operator ->() const
{ {
E2D_INTRUSIVE_PTR_ASSERT(ptr_ != nullptr, "Invalid pointer");
return ptr_; return ptr_;
} }
inline Type& operator *() const inline Type& operator *() const
{ {
E2D_INTRUSIVE_PTR_ASSERT(ptr_ != nullptr, "Invalid pointer");
return *ptr_; return *ptr_;
} }
inline operator bool() const { return ptr_ != nullptr; } inline Type** operator &()
inline bool operator !() const { return ptr_ == 0; }
inline SmartPointer& operator =(const SmartPointer& other)
{ {
E2D_INTRUSIVE_PTR_ASSERT(ptr_ == nullptr, "Memory leak");
return &ptr_;
}
inline operator bool() const E2D_NOEXCEPT { return ptr_ != nullptr; }
inline bool operator !() const E2D_NOEXCEPT { return ptr_ == 0; }
inline SmartPointer& operator =(const SmartPointer& other) E2D_NOEXCEPT
{
if (other.ptr_ != ptr_)
SmartPointer(other).Swap(*this); SmartPointer(other).Swap(*this);
return *this; return *this;
} }
inline SmartPointer& operator =(SmartPointer&& other) inline SmartPointer& operator =(SmartPointer&& other) E2D_NOEXCEPT
{ {
IntrusivePtrRelease(ptr_); IntrusivePtrRelease(ptr_);
ptr_ = other.ptr_; ptr_ = other.ptr_;
@ -99,88 +117,90 @@ namespace easy2d
return *this; return *this;
} }
inline SmartPointer& operator =(Type* p) inline SmartPointer& operator =(Type* p) E2D_NOEXCEPT
{ {
if (p != ptr_)
SmartPointer(p).Swap(*this); SmartPointer(p).Swap(*this);
return *this; return *this;
} }
inline SmartPointer& operator =(nullptr_t) inline SmartPointer& operator =(nullptr_t) E2D_NOEXCEPT
{ {
if (nullptr != ptr_)
SmartPointer{}.Swap(*this); SmartPointer{}.Swap(*this);
return *this; return *this;
} }
}; };
template<class T, class U> template<class T, class U>
inline bool operator==(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) inline bool operator==(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) E2D_NOEXCEPT
{ {
return lhs.Get() == rhs.Get(); return lhs.Get() == rhs.Get();
} }
template<class T, class U> template<class T, class U>
inline bool operator!=(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) inline bool operator!=(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) E2D_NOEXCEPT
{ {
return lhs.Get() != rhs.Get(); return lhs.Get() != rhs.Get();
} }
template<class T, class U> template<class T, class U>
inline bool operator<(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) inline bool operator<(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs) E2D_NOEXCEPT
{ {
return lhs.Get() < rhs.Get(); return lhs.Get() < rhs.Get();
} }
template<class T> template<class T>
inline bool operator==(SmartPointer<T> const& lhs, T* rhs) inline bool operator==(SmartPointer<T> const& lhs, T* rhs) E2D_NOEXCEPT
{ {
return lhs.Get() == rhs; return lhs.Get() == rhs;
} }
template<class T> template<class T>
inline bool operator!=(SmartPointer<T> const& lhs, T* rhs) inline bool operator!=(SmartPointer<T> const& lhs, T* rhs) E2D_NOEXCEPT
{ {
return lhs.Get() != rhs; return lhs.Get() != rhs;
} }
template<class T> template<class T>
inline bool operator==(T* lhs, SmartPointer<T> const& rhs) inline bool operator==(T* lhs, SmartPointer<T> const& rhs) E2D_NOEXCEPT
{ {
return lhs == rhs.Get(); return lhs == rhs.Get();
} }
template<class T> template<class T>
inline bool operator!=(T* lhs, SmartPointer<T> const& rhs) inline bool operator!=(T* lhs, SmartPointer<T> const& rhs) E2D_NOEXCEPT
{ {
return lhs != rhs.Get(); return lhs != rhs.Get();
} }
template<class T> template<class T>
inline bool operator==(SmartPointer<T> const& lhs, nullptr_t) inline bool operator==(SmartPointer<T> const& lhs, nullptr_t) E2D_NOEXCEPT
{ {
return !static_cast<bool>(lhs); return !static_cast<bool>(lhs);
} }
template<class T> template<class T>
inline bool operator!=(SmartPointer<T> const& lhs, nullptr_t) inline bool operator!=(SmartPointer<T> const& lhs, nullptr_t) E2D_NOEXCEPT
{ {
return static_cast<bool>(lhs); return static_cast<bool>(lhs);
} }
template<class T> template<class T>
inline bool operator==(nullptr_t, SmartPointer<T> const& rhs) inline bool operator==(nullptr_t, SmartPointer<T> const& rhs) E2D_NOEXCEPT
{ {
return !static_cast<bool>(rhs); return !static_cast<bool>(rhs);
} }
template<class T> template<class T>
inline bool operator!=(nullptr_t, SmartPointer<T> const& rhs) inline bool operator!=(nullptr_t, SmartPointer<T> const& rhs) E2D_NOEXCEPT
{ {
return static_cast<bool>(rhs); return static_cast<bool>(rhs);
} }
} }
template<class T> template<class T>
inline intrusive::SmartPointer<T> make_intrusive(T* ptr) inline intrusive::SmartPointer<T> make_intrusive(T* ptr) E2D_NOEXCEPT
{ {
return intrusive::SmartPointer<T>(ptr); return intrusive::SmartPointer<T>(ptr);
} }
@ -188,7 +208,7 @@ namespace easy2d
// template class cannot specialize std::swap, // template class cannot specialize std::swap,
// so implement a swap function in easy2d namespace // so implement a swap function in easy2d namespace
template<class T> template<class T>
inline void swap(intrusive::SmartPointer<T>& lhs, intrusive::SmartPointer<T>& rhs) inline void swap(intrusive::SmartPointer<T>& lhs, intrusive::SmartPointer<T>& rhs) E2D_NOEXCEPT
{ {
lhs.Swap(rhs); lhs.Swap(rhs);
} }

View File

@ -25,28 +25,47 @@ namespace easy2d
{ {
namespace modules namespace modules
{ {
namespace Shlwapi::Shlwapi()
{ {
int initialize_count = 0; shlwapi = LoadLibraryW(L"shlwapi.dll");
if (shlwapi)
inline void SafeFreeLibrary(HMODULE instance)
{ {
if (instance) PathFileExistsW = (PFN_PathFileExistsW)
FreeLibrary(instance); GetProcAddress(shlwapi, "PathFileExistsW");
}
else
{
E2D_LOG("load shlapi.dll failed");
} }
} }
Module_XAudio2 XAudio2; DirectX::DirectX()
Module_MediaFoundation MediaFoundation;
void Init()
{ {
initialize_count++; d2d = LoadLibraryW(L"d2d1.dll");
if (initialize_count > 1) if (d2d)
return; {
D2D1CreateFactory = (PFN_D2D1CreateFactory)
GetProcAddress(d2d, "D2D1CreateFactory");
}
else
{
E2D_LOG("load d2d.dll failed");
}
E2D_LOG("Initing modules"); dwrite = LoadLibraryW(L"dwrite.dll");
if (dwrite)
{
DWriteCreateFactory = (PFN_DWriteCreateFactory)
GetProcAddress(dwrite, "DWriteCreateFactory");
}
else
{
E2D_LOG("load dwrite.dll failed");
}
}
XAudio2::XAudio2()
{
const auto xaudio2_dll_names = const auto xaudio2_dll_names =
{ {
L"xaudio2_9.dll", L"xaudio2_9.dll",
@ -56,56 +75,59 @@ namespace easy2d
for (const auto& name : xaudio2_dll_names) for (const auto& name : xaudio2_dll_names)
{ {
XAudio2.instance = LoadLibraryW(name); xaudio2 = LoadLibraryW(name);
if (XAudio2.instance) if (xaudio2)
{ {
XAudio2.XAudio2Create = (PFN_XAudio2Create) XAudio2Create = (PFN_XAudio2Create)
GetProcAddress(XAudio2.instance, "XAudio2Create"); GetProcAddress(xaudio2, "XAudio2Create");
break; break;
} }
} }
MediaFoundation.mfplat = LoadLibraryW(L"Mfplat.dll"); if (!xaudio2)
if (MediaFoundation.mfplat)
{ {
MediaFoundation.MFStartup = (PFN_MFStartup) E2D_LOG("load xaudio2.dll failed");
GetProcAddress(MediaFoundation.mfplat, "MFStartup");
MediaFoundation.MFShutdown = (PFN_MFShutdown)
GetProcAddress(MediaFoundation.mfplat, "MFShutdown");
MediaFoundation.MFCreateMediaType = (PFN_MFCreateMediaType)
GetProcAddress(MediaFoundation.mfplat, "MFCreateMediaType");
MediaFoundation.MFCreateWaveFormatExFromMFMediaType = (PFN_MFCreateWaveFormatExFromMFMediaType)
GetProcAddress(MediaFoundation.mfplat, "MFCreateWaveFormatExFromMFMediaType");
MediaFoundation.MFCreateMFByteStreamOnStream = (PFN_MFCreateMFByteStreamOnStream)
GetProcAddress(MediaFoundation.mfplat, "MFCreateMFByteStreamOnStream");
}
MediaFoundation.mfreadwrite = LoadLibraryW(L"Mfreadwrite.dll");
if (MediaFoundation.mfreadwrite)
{
MediaFoundation.MFCreateSourceReaderFromURL = (PFN_MFCreateSourceReaderFromURL)
GetProcAddress(MediaFoundation.mfreadwrite, "MFCreateSourceReaderFromURL");
MediaFoundation.MFCreateSourceReaderFromByteStream = (PFN_MFCreateSourceReaderFromByteStream)
GetProcAddress(MediaFoundation.mfreadwrite, "MFCreateSourceReaderFromByteStream");
} }
} }
void Destroy() MediaFoundation::MediaFoundation()
{ {
initialize_count--; mfplat = LoadLibraryW(L"Mfplat.dll");
if (initialize_count > 0) if (mfplat)
return; {
MFStartup = (PFN_MFStartup)
GetProcAddress(mfplat, "MFStartup");
E2D_LOG("Destroying modules"); MFShutdown = (PFN_MFShutdown)
GetProcAddress(mfplat, "MFShutdown");
SafeFreeLibrary(XAudio2.instance); MFCreateMediaType = (PFN_MFCreateMediaType)
SafeFreeLibrary(MediaFoundation.mfplat); GetProcAddress(mfplat, "MFCreateMediaType");
SafeFreeLibrary(MediaFoundation.mfreadwrite);
MFCreateWaveFormatExFromMFMediaType = (PFN_MFCreateWaveFormatExFromMFMediaType)
GetProcAddress(mfplat, "MFCreateWaveFormatExFromMFMediaType");
MFCreateMFByteStreamOnStream = (PFN_MFCreateMFByteStreamOnStream)
GetProcAddress(mfplat, "MFCreateMFByteStreamOnStream");
}
else
{
E2D_LOG("load Mfplat.dll failed");
}
mfreadwrite = LoadLibraryW(L"Mfreadwrite.dll");
if (mfreadwrite)
{
MFCreateSourceReaderFromURL = (PFN_MFCreateSourceReaderFromURL)
GetProcAddress(mfreadwrite, "MFCreateSourceReaderFromURL");
MFCreateSourceReaderFromByteStream = (PFN_MFCreateSourceReaderFromByteStream)
GetProcAddress(mfreadwrite, "MFCreateSourceReaderFromByteStream");
}
else
{
E2D_LOG("load Mfreadwrite.dll failed");
}
} }
} }
} }

View File

@ -20,6 +20,8 @@
#pragma once #pragma once
#include "macros.h" #include "macros.h"
#include <d2d1.h>
#include <dwrite.h>
#include <xaudio2.h> #include <xaudio2.h>
#include <mfapi.h> #include <mfapi.h>
#include <mfidl.h> #include <mfidl.h>
@ -29,24 +31,55 @@ namespace easy2d
{ {
namespace modules namespace modules
{ {
// modules can be initialized multiple times, class Shlwapi
// but it needs to be destroyed every time {
void Init(); HMODULE shlwapi;
void Destroy(); // Shlwapi functions
typedef BOOL(WINAPI *PFN_PathFileExistsW)(LPCWSTR);
public:
Shlwapi();
PFN_PathFileExistsW PathFileExistsW;
};
class DirectX
{
HMODULE d2d;
HMODULE dwrite;
// DirectX functions
typedef HRESULT(WINAPI *PFN_D2D1CreateFactory)(D2D1_FACTORY_TYPE, const IID&, const D2D1_FACTORY_OPTIONS*, void **);
typedef HRESULT(WINAPI *PFN_DWriteCreateFactory)(DWRITE_FACTORY_TYPE, const IID&, IUnknown **);
public:
DirectX();
PFN_D2D1CreateFactory D2D1CreateFactory;
PFN_DWriteCreateFactory DWriteCreateFactory;
};
class XAudio2
{
HMODULE xaudio2;
// XAudio2 functions // XAudio2 functions
typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
struct Module_XAudio2 public:
{ XAudio2();
HMODULE instance;
PFN_XAudio2Create XAudio2Create; PFN_XAudio2Create XAudio2Create;
}; };
extern Module_XAudio2 XAudio2;
class MediaFoundation
{
HMODULE mfplat;
HMODULE mfreadwrite;
// MediaFoundation functions // MediaFoundation functions
typedef HRESULT(WINAPI *PFN_MFStartup)(ULONG, DWORD); typedef HRESULT(WINAPI *PFN_MFStartup)(ULONG, DWORD);
@ -57,10 +90,8 @@ namespace easy2d
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**); typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
typedef HRESULT(WINAPI *PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**); typedef HRESULT(WINAPI *PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
struct Module_MediaFoundation public:
{ MediaFoundation();
HMODULE mfplat;
HMODULE mfreadwrite;
PFN_MFStartup MFStartup; PFN_MFStartup MFStartup;
PFN_MFShutdown MFShutdown; PFN_MFShutdown MFShutdown;
@ -70,7 +101,5 @@ namespace easy2d
PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream; PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream; PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
}; };
extern Module_MediaFoundation MediaFoundation;
} }
} }

View File

@ -25,9 +25,6 @@
#include "modules.h" #include "modules.h"
#include "Image.h" #include "Image.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
namespace easy2d namespace easy2d
{ {
namespace devices namespace devices
@ -51,8 +48,6 @@ namespace easy2d
, initialized(false) , initialized(false)
{ {
ZeroMemory(&d2d, sizeof(D2DResources)); ZeroMemory(&d2d, sizeof(D2DResources));
modules::Init();
} }
GraphicsDevice::~GraphicsDevice() GraphicsDevice::~GraphicsDevice()
@ -60,23 +55,6 @@ namespace easy2d
E2D_LOG("Destroying graphics device"); E2D_LOG("Destroying graphics device");
ClearImageCache(); ClearImageCache();
SafeRelease(fps_text_format_);
SafeRelease(fps_text_layout_);
SafeRelease(d2d.text_renderer);
SafeRelease(d2d.solid_brush);
SafeRelease(d2d.render_target);
SafeRelease(d2d.miter_stroke_style);
SafeRelease(d2d.bevel_stroke_style);
SafeRelease(d2d.round_stroke_style);
SafeRelease(d2d.imaging_factory);
SafeRelease(d2d.write_factory);
SafeRelease(d2d.factory);
modules::Destroy();
} }
void GraphicsDevice::Init(HWND hwnd, bool debug) void GraphicsDevice::Init(HWND hwnd, bool debug)
@ -88,7 +66,7 @@ namespace easy2d
D2D1_FACTORY_OPTIONS options{ debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE }; D2D1_FACTORY_OPTIONS options{ debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE };
ThrowIfFailed( ThrowIfFailed(
D2D1CreateFactory( modules::DirectX().D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED, D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory), __uuidof(ID2D1Factory),
&options, &options,
@ -107,7 +85,7 @@ namespace easy2d
); );
ThrowIfFailed( ThrowIfFailed(
DWriteCreateFactory( modules::DirectX().DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED, DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory), __uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&d2d.write_factory) reinterpret_cast<IUnknown**>(&d2d.write_factory)
@ -134,7 +112,6 @@ namespace easy2d
); );
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
ThrowIfFailed( ThrowIfFailed(
d2d.factory->CreateStrokeStyle( d2d.factory->CreateStrokeStyle(
stroke_style, stroke_style,
@ -145,7 +122,6 @@ namespace easy2d
); );
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
ThrowIfFailed( ThrowIfFailed(
d2d.factory->CreateStrokeStyle( d2d.factory->CreateStrokeStyle(
stroke_style, stroke_style,
@ -178,11 +154,11 @@ namespace easy2d
// 并在下一次调用时重建资源 // 并在下一次调用时重建资源
hr = S_OK; hr = S_OK;
SafeRelease(fps_text_format_); fps_text_format_ = nullptr;
SafeRelease(fps_text_layout_); fps_text_layout_ = nullptr;
SafeRelease(d2d.text_renderer); d2d.text_renderer = nullptr;
SafeRelease(d2d.solid_brush); d2d.solid_brush = nullptr;
SafeRelease(d2d.render_target); d2d.render_target = nullptr;
} }
ThrowIfFailed(hr); ThrowIfFailed(hr);
@ -190,20 +166,13 @@ namespace easy2d
void GraphicsDevice::ClearImageCache() void GraphicsDevice::ClearImageCache()
{ {
if (bitmap_cache_.empty())
return;
for (const auto& bitmap : bitmap_cache_)
{
bitmap.second->Release();
}
bitmap_cache_.clear(); bitmap_cache_.clear();
} }
HRESULT GraphicsDevice::CreateRectGeometry( HRESULT GraphicsDevice::CreateRectGeometry(
cpGeometry& geometry,
const math::Matrix& matrix, const math::Matrix& matrix,
const Size& size, const Size& size
ID2D1Geometry** geometry
) const ) const
{ {
if (!d2d.factory) if (!d2d.factory)
@ -230,18 +199,20 @@ namespace easy2d
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
*geometry = transformed; geometry = transformed;
} }
SafeRelease(rectangle); SafeRelease(rectangle);
SafeRelease(transformed);
return hr; return hr;
} }
HRESULT GraphicsDevice::CreateTextFormat(IDWriteTextFormat ** text_format, const Font & font) const HRESULT GraphicsDevice::CreateTextFormat(cpTextFormat& text_format, Font const& font) const
{ {
if (!d2d.write_factory) if (!d2d.write_factory)
return E_UNEXPECTED; return E_UNEXPECTED;
text_format = nullptr;
return d2d.write_factory->CreateTextFormat( return d2d.write_factory->CreateTextFormat(
font.family.c_str(), font.family.c_str(),
nullptr, nullptr,
@ -250,37 +221,52 @@ namespace easy2d
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
font.size, font.size,
L"", L"",
text_format &text_format
); );;
} }
HRESULT GraphicsDevice::CreateTextLayout(IDWriteTextLayout ** text_layout, const String & text, IDWriteTextFormat * text_format, float wrap_width) const HRESULT GraphicsDevice::CreateTextLayout(cpTextLayout& text_layout, String const& text, cpTextFormat const& text_format, float wrap_width) const
{ {
if (!d2d.write_factory) if (!d2d.write_factory)
return E_UNEXPECTED; return E_UNEXPECTED;
text_layout = nullptr;
UINT32 length = static_cast<UINT32>(text.length()); UINT32 length = static_cast<UINT32>(text.length());
return d2d.write_factory->CreateTextLayout( return d2d.write_factory->CreateTextLayout(
text.c_str(), text.c_str(),
length, length,
text_format, text_format.Get(),
wrap_width, wrap_width,
0, 0,
text_layout &text_layout
); );
} }
HRESULT GraphicsDevice::CreateLayer(ID2D1Layer ** layer) HRESULT GraphicsDevice::CreateLayer(cpLayer& layer)
{ {
if (!d2d.render_target) if (!d2d.render_target)
return E_UNEXPECTED; return E_UNEXPECTED;
return d2d.render_target->CreateLayer(layer); layer = nullptr;
return d2d.render_target->CreateLayer(&layer);
}
HRESULT GraphicsDevice::CreateSolidColorBrush(cpSolidColorBrush & brush) const
{
if (!d2d.render_target)
return E_UNEXPECTED;
brush = nullptr;
return d2d.render_target->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&brush
);
} }
HRESULT GraphicsDevice::DrawGeometry( HRESULT GraphicsDevice::DrawGeometry(
ID2D1Geometry * geometry, cpGeometry const& geometry,
const Color & border_color, Color const& border_color,
float opacity, float opacity,
float stroke_width, float stroke_width,
StrokeStyle stroke StrokeStyle stroke
@ -293,30 +279,34 @@ namespace easy2d
d2d.solid_brush->SetColor(border_color); d2d.solid_brush->SetColor(border_color);
d2d.solid_brush->SetOpacity(opacity); d2d.solid_brush->SetOpacity(opacity);
d2d.render_target->DrawGeometry( d2d.render_target->DrawGeometry(
geometry, geometry.Get(),
d2d.solid_brush, d2d.solid_brush.Get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke) GetStrokeStyle(stroke).Get()
); );
return S_OK; return S_OK;
} }
ID2D1StrokeStyle * GraphicsDevice::GetStrokeStyle(StrokeStyle stroke) const cpStrokeStyle const& GraphicsDevice::GetStrokeStyle(StrokeStyle stroke) const
{ {
ID2D1StrokeStyle * stroke_style = nullptr;
switch (stroke) switch (stroke)
{ {
case StrokeStyle::Miter: case StrokeStyle::Miter:
stroke_style = d2d.miter_stroke_style; return d2d.miter_stroke_style;
break; break;
case StrokeStyle::Bevel: case StrokeStyle::Bevel:
stroke_style = d2d.bevel_stroke_style; return d2d.bevel_stroke_style;
break; break;
case StrokeStyle::Round: case StrokeStyle::Round:
stroke_style = d2d.round_stroke_style; return d2d.round_stroke_style;
break; break;
} }
return stroke_style; return d2d.miter_stroke_style;
}
cpRenderTarget const & GraphicsDevice::GetRenderTarget() const
{
return d2d.render_target;
} }
HRESULT GraphicsDevice::DrawImage( HRESULT GraphicsDevice::DrawImage(
@ -330,7 +320,7 @@ namespace easy2d
return E_UNEXPECTED; return E_UNEXPECTED;
d2d.render_target->DrawBitmap( d2d.render_target->DrawBitmap(
image->GetBitmap(), image->GetBitmap().Get(),
dest_rect, dest_rect,
opacity, opacity,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
@ -339,12 +329,12 @@ namespace easy2d
return S_OK; return S_OK;
} }
HRESULT GraphicsDevice::DrawTextLayout(IDWriteTextLayout * text_layout) HRESULT GraphicsDevice::DrawTextLayout(cpTextLayout const& text_layout)
{ {
if (!d2d.text_renderer) if (!d2d.text_renderer)
return E_UNEXPECTED; return E_UNEXPECTED;
return text_layout->Draw(nullptr, d2d.text_renderer, 0, 0); return text_layout->Draw(nullptr, d2d.text_renderer.Get(), 0, 0);
} }
HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size) HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size)
@ -369,7 +359,7 @@ namespace easy2d
return S_OK; return S_OK;
} }
HRESULT GraphicsDevice::PushLayer(ID2D1Layer * layer, LayerProperties properties) HRESULT GraphicsDevice::PushLayer(cpLayer const& layer, LayerProperties const& properties)
{ {
if (!d2d.render_target || if (!d2d.render_target ||
!d2d.solid_brush) !d2d.solid_brush)
@ -382,10 +372,10 @@ namespace easy2d
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(), D2D1::Matrix3x2F::Identity(),
properties.opacity, properties.opacity,
d2d.solid_brush, d2d.solid_brush.Get(),
D2D1_LAYER_OPTIONS_NONE D2D1_LAYER_OPTIONS_NONE
), ),
layer layer.Get()
); );
return S_OK; return S_OK;
} }
@ -399,7 +389,7 @@ namespace easy2d
return S_OK; return S_OK;
} }
HRESULT GraphicsDevice::CreateBitmapFromFile(const String & file_path, ID2D1Bitmap ** bitmap) HRESULT GraphicsDevice::CreateBitmapFromFile(cpBitmap& bitmap, String const& file_path)
{ {
if (d2d.imaging_factory == nullptr || if (d2d.imaging_factory == nullptr ||
d2d.render_target == nullptr) d2d.render_target == nullptr)
@ -407,15 +397,10 @@ namespace easy2d
return E_UNEXPECTED; return E_UNEXPECTED;
} }
if (bitmap == nullptr)
{
return E_POINTER;
}
size_t hash_code = std::hash<String>{}(file_path); size_t hash_code = std::hash<String>{}(file_path);
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{ {
*bitmap = bitmap_cache_[hash_code]; bitmap = bitmap_cache_[hash_code];
return S_OK; return S_OK;
} }
@ -461,19 +446,19 @@ namespace easy2d
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// 从 WIC 位图创建一个 Direct2D 位图 // 从 WIC 位图创建一个 Direct2D 位图
bitmap = nullptr;
hr = d2d.render_target->CreateBitmapFromWicBitmap( hr = d2d.render_target->CreateBitmapFromWicBitmap(
converter, converter,
nullptr, nullptr,
bitmap &bitmap
); );
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
} }
// 释放相关资源
SafeRelease(decoder); SafeRelease(decoder);
SafeRelease(source); SafeRelease(source);
SafeRelease(stream); SafeRelease(stream);
@ -482,7 +467,7 @@ namespace easy2d
return hr; return hr;
} }
HRESULT GraphicsDevice::CreateBitmapFromResource(Resource & res, ID2D1Bitmap ** bitmap) HRESULT GraphicsDevice::CreateBitmapFromResource(cpBitmap& bitmap, Resource const& res)
{ {
if (d2d.imaging_factory == nullptr || if (d2d.imaging_factory == nullptr ||
d2d.render_target == nullptr) d2d.render_target == nullptr)
@ -490,15 +475,10 @@ namespace easy2d
return E_UNEXPECTED; return E_UNEXPECTED;
} }
if (bitmap == nullptr)
{
return E_POINTER;
}
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{ {
*bitmap = bitmap_cache_[hash_code]; bitmap = bitmap_cache_[hash_code];
return S_OK; return S_OK;
} }
@ -571,16 +551,15 @@ namespace easy2d
hr = d2d.render_target->CreateBitmapFromWicBitmap( hr = d2d.render_target->CreateBitmapFromWicBitmap(
converter, converter,
nullptr, nullptr,
bitmap &bitmap
); );
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
} }
// 释放相关资源
SafeRelease(decoder); SafeRelease(decoder);
SafeRelease(source); SafeRelease(source);
SafeRelease(stream); SafeRelease(stream);
@ -617,9 +596,9 @@ namespace easy2d
} }
HRESULT GraphicsDevice::SetTextStyle( HRESULT GraphicsDevice::SetTextStyle(
const Color & color, Color const& color,
bool has_outline, bool has_outline,
const Color & outline_color, Color const& outline_color,
float outline_width, float outline_width,
StrokeStyle outline_stroke StrokeStyle outline_stroke
) )
@ -632,7 +611,7 @@ namespace easy2d
has_outline, has_outline,
outline_color, outline_color,
outline_width, outline_width,
static_cast<D2D1_LINE_JOIN>(outline_stroke) GetStrokeStyle(outline_stroke).Get()
); );
return S_OK; return S_OK;
} }
@ -652,23 +631,10 @@ namespace easy2d
if (!fps_text_format_) if (!fps_text_format_)
{ {
ThrowIfFailed( ThrowIfFailed(
d2d.write_factory->CreateTextFormat( CreateTextFormat(fps_text_format_, Font{ L"", 20 })
L"",
nullptr,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
20,
L"",
&fps_text_format_
)
); );
ThrowIfFailed( fps_text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
fps_text_format_->SetWordWrapping(
DWRITE_WORD_WRAPPING_NO_WRAP
)
);
} }
++render_times_; ++render_times_;
@ -680,17 +646,8 @@ namespace easy2d
last_render_time_ = time::Now(); last_render_time_ = time::Now();
render_times_ = 0; render_times_ = 0;
SafeRelease(fps_text_layout_);
ThrowIfFailed( ThrowIfFailed(
d2d.write_factory->CreateTextLayout( CreateTextLayout(fps_text_layout_, fps_text, fps_text_format_, 0)
fps_text,
static_cast<UINT32>(len),
fps_text_format_,
0,
0,
&fps_text_layout_
)
); );
} }
@ -703,10 +660,10 @@ namespace easy2d
TRUE, TRUE,
D2D1::ColorF(D2D1::ColorF::Black, 0.4f), D2D1::ColorF(D2D1::ColorF::Black, 0.4f),
1.5f, 1.5f,
D2D1_LINE_JOIN_ROUND d2d.round_stroke_style.Get()
); );
fps_text_layout_->Draw(nullptr, d2d.text_renderer, 10, 0); fps_text_layout_->Draw(nullptr, d2d.text_renderer.Get(), 10, 0);
} }
} }
@ -751,9 +708,9 @@ namespace easy2d
ThrowIfFailed( ThrowIfFailed(
ITextRenderer::Create( ITextRenderer::Create(
&d2d.text_renderer, &d2d.text_renderer,
d2d.factory, d2d.factory.Get(),
d2d.render_target, d2d.render_target.Get(),
d2d.solid_brush d2d.solid_brush.Get()
) )
); );
} }

View File

@ -34,15 +34,15 @@ namespace easy2d
{ {
struct D2DResources struct D2DResources
{ {
ID2D1Factory* factory; cpFactory factory;
IWICImagingFactory* imaging_factory; cpImagingFactory imaging_factory;
IDWriteFactory* write_factory; cpWriteFactory write_factory;
ITextRenderer* text_renderer; spTextRenderer text_renderer;
ID2D1SolidColorBrush* solid_brush; cpSolidColorBrush solid_brush;
ID2D1HwndRenderTarget* render_target; cpRenderTarget render_target;
ID2D1StrokeStyle* miter_stroke_style; cpStrokeStyle miter_stroke_style;
ID2D1StrokeStyle* bevel_stroke_style; cpStrokeStyle bevel_stroke_style;
ID2D1StrokeStyle* round_stroke_style; cpStrokeStyle round_stroke_style;
}; };
@ -72,31 +72,37 @@ namespace easy2d
void CreateDeviceResources(HWND hwnd); void CreateDeviceResources(HWND hwnd);
HRESULT CreateRectGeometry( HRESULT CreateRectGeometry(
cpGeometry& geometry,
const math::Matrix& matrix, const math::Matrix& matrix,
const Size& size, const Size& size
ID2D1Geometry** geometry
) const; ) const;
HRESULT CreateTextFormat( HRESULT CreateTextFormat(
IDWriteTextFormat** text_format, cpTextFormat& text_format,
const Font& font Font const& font
) const; ) const;
HRESULT CreateTextLayout( HRESULT CreateTextLayout(
IDWriteTextLayout** text_layout, cpTextLayout& text_layout,
const String& text, String const& text,
IDWriteTextFormat* text_format, cpTextFormat const& text_format,
float wrap_width float wrap_width
) const; ) const;
HRESULT CreateLayer( HRESULT CreateLayer(
ID2D1Layer** layer cpLayer& layer
); );
ID2D1StrokeStyle* GetStrokeStyle( HRESULT CreateSolidColorBrush(
cpSolidColorBrush& brush
) const;
cpStrokeStyle const& GetStrokeStyle(
StrokeStyle stroke StrokeStyle stroke
) const; ) const;
cpRenderTarget const& GetRenderTarget() const;
HRESULT SetTransform( HRESULT SetTransform(
const math::Matrix& matrix const math::Matrix& matrix
); );
@ -114,7 +120,7 @@ namespace easy2d
); );
HRESULT DrawGeometry( HRESULT DrawGeometry(
ID2D1Geometry* geometry, cpGeometry const& geometry,
const Color& border_color, const Color& border_color,
float opacity, float opacity,
float stroke_width, float stroke_width,
@ -129,7 +135,7 @@ namespace easy2d
); );
HRESULT DrawTextLayout( HRESULT DrawTextLayout(
IDWriteTextLayout* text_layout cpTextLayout const& text_layout
); );
HRESULT PushClip( HRESULT PushClip(
@ -140,20 +146,20 @@ namespace easy2d
HRESULT PopClip(); HRESULT PopClip();
HRESULT PushLayer( HRESULT PushLayer(
ID2D1Layer* layer, cpLayer const& layer,
LayerProperties properties LayerProperties const& properties
); );
HRESULT PopLayer(); HRESULT PopLayer();
HRESULT CreateBitmapFromFile( HRESULT CreateBitmapFromFile(
const String& file_path, cpBitmap& bitmap,
ID2D1Bitmap** bitmap String const& file_path
); );
HRESULT CreateBitmapFromResource( HRESULT CreateBitmapFromResource(
Resource& res, cpBitmap& bitmap,
ID2D1Bitmap** bitmap Resource const& res
); );
HRESULT Resize( HRESULT Resize(
@ -172,9 +178,9 @@ namespace easy2d
bool initialized; bool initialized;
D2DResources d2d; D2DResources d2d;
D2D1_COLOR_F clear_color_; D2D1_COLOR_F clear_color_;
IDWriteTextFormat* fps_text_format_; cpTextFormat fps_text_format_;
IDWriteTextLayout* fps_text_layout_; cpTextLayout fps_text_layout_;
std::map<size_t, ID2D1Bitmap*> bitmap_cache_; std::map<size_t, cpBitmap> bitmap_cache_;
}; };
E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics); E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics);

View File

@ -140,7 +140,7 @@ namespace easy2d
return String(); return String();
} }
void WindowImpl::SetTitle(const String& title) void WindowImpl::SetTitle(String const& title)
{ {
if (handle) if (handle)
::SetWindowText(handle, title.c_str()); ::SetWindowText(handle, title.c_str());

View File

@ -45,7 +45,7 @@ namespace easy2d
String GetTitle() const; String GetTitle() const;
// 设置标题 // 设置标题
void SetTitle(const String& title); void SetTitle(String const& title);
// 获取窗口大小 // 获取窗口大小
Size GetSize() const; Size GetSize() const;

View File

@ -23,7 +23,7 @@
namespace easy2d namespace easy2d
{ {
Data::Data(const String & key, const String & field) Data::Data(String const& key, String const& field)
: key_(key) : key_(key)
, field_(field) , field_(field)
, data_path_(Path::GetDataPath()) , data_path_(Path::GetDataPath())
@ -88,7 +88,7 @@ namespace easy2d
return ret == TRUE; return ret == TRUE;
} }
bool Data::SaveString(const String& val) bool Data::SaveString(String const& val)
{ {
BOOL ret = ::WritePrivateProfileStringW( BOOL ret = ::WritePrivateProfileStringW(
field_.c_str(), field_.c_str(),

View File

@ -28,8 +28,8 @@ namespace easy2d
{ {
public: public:
Data( Data(
const String& key, /* ¼üÖµ */ String const& key, /* ¼üÖµ */
const String& field = L"Defalut" /* ×Ö¶ÎÃû³Æ */ String const& field = L"Defalut" /* ×Ö¶ÎÃû³Æ */
); );
// 该数据是否存在 // 该数据是否存在
@ -57,7 +57,7 @@ namespace easy2d
// 保存 String 类型的值 // 保存 String 类型的值
bool SaveString( bool SaveString(
const String& val String const& val
); );
// 获取 int 类型的值 // 获取 int 类型的值
@ -78,6 +78,6 @@ namespace easy2d
protected: protected:
String key_; String key_;
String field_; String field_;
const String& data_path_; String const& data_path_;
}; };
} }

View File

@ -19,11 +19,8 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "File.h" #include "File.h"
#include "../base/modules.h"
#include <cwctype> #include <cwctype>
#include <shobjidl.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
namespace easy2d namespace easy2d
{ {
@ -34,7 +31,7 @@ namespace easy2d
{ {
} }
File::File(const String & file_name) File::File(String const& file_name)
: file_path_(file_name) : file_path_(file_name)
{ {
this->Open(file_name); this->Open(file_name);
@ -44,14 +41,14 @@ namespace easy2d
{ {
} }
bool File::Open(const String & file_name) bool File::Open(String const& file_name)
{ {
if (file_name.empty()) if (file_name.empty())
return false; return false;
auto FindFile = [](const String & path) -> bool auto FindFile = [](String const& path) -> bool
{ {
if (::PathFileExists(path.c_str())) if (modules::Shlwapi().PathFileExistsW(path.c_str()))
return true; return true;
return false; return false;
}; };
@ -75,12 +72,12 @@ namespace easy2d
bool File::Exists() const bool File::Exists() const
{ {
if (::PathFileExists(file_path_.c_str())) if (modules::Shlwapi().PathFileExistsW(file_path_.c_str()))
return true; return true;
return false; return false;
} }
const String& File::GetPath() const String const& File::GetPath() const
{ {
return file_path_; return file_path_;
} }
@ -88,14 +85,10 @@ namespace easy2d
String File::GetExtension() const String File::GetExtension() const
{ {
String file_ext; String file_ext;
// 找到文件名中的最后一个 '.' 的位置
size_t pos = file_path_.find_last_of(L'.'); size_t pos = file_path_.find_last_of(L'.');
// 判断 pos 是否是有效位置
if (pos != String::npos) if (pos != String::npos)
{ {
// 截取扩展名
file_ext = file_path_.substr(pos); file_ext = file_path_.substr(pos);
// 转换为小写字母
std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower); std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower);
} }
return file_ext; return file_ext;
@ -108,7 +101,7 @@ namespace easy2d
return false; return false;
} }
File File::Extract(Resource& res, const String& dest_file_name) File File::Extract(Resource& res, String const& dest_file_name)
{ {
File file; File file;
HANDLE file_handle = ::CreateFile( HANDLE file_handle = ::CreateFile(
@ -143,7 +136,7 @@ namespace easy2d
return file; return file;
} }
void File::AddSearchPath(const String & path) void File::AddSearchPath(String const& path)
{ {
String tmp = path; String tmp = path;
size_t pos = 0; size_t pos = 0;
@ -163,136 +156,4 @@ namespace easy2d
search_paths_.push_front(tmp); search_paths_.push_front(tmp);
} }
} }
File File::ShowOpenDialog(const String & title, const String & filter)
{
String file_path;
HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog *file_open;
hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&file_open));
if (SUCCEEDED(hr))
{
if (!title.empty())
{
file_open->SetTitle(title.c_str());
}
if (!filter.empty())
{
COMDLG_FILTERSPEC spec[] =
{
{ L"", filter.c_str() }
};
file_open->SetFileTypes(1, spec);
}
else
{
COMDLG_FILTERSPEC spec[] =
{
{ L"所有文件", L"*.*" }
};
file_open->SetFileTypes(1, spec);
}
hr = file_open->Show(nullptr);
if (SUCCEEDED(hr))
{
IShellItem *item;
hr = file_open->GetResult(&item);
if (SUCCEEDED(hr))
{
PWSTR str_file_path;
hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path);
if (SUCCEEDED(hr))
{
file_path = str_file_path;
::CoTaskMemFree(str_file_path);
}
item->Release();
}
}
file_open->Release();
}
::CoUninitialize();
}
return File(file_path);
}
File File::ShowSaveDialog(const String & title, const String& def_file, const String & def_ext)
{
String file_path;
HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileSaveDialog *file_save;
hr = ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL,
IID_IFileSaveDialog, reinterpret_cast<void**>(&file_save));
if (SUCCEEDED(hr))
{
if (!title.empty())
{
file_save->SetTitle(title.c_str());
}
if (!def_file.empty())
{
file_save->SetFileName(def_file.c_str());
}
if (!def_ext.empty())
{
file_save->SetDefaultExtension(def_ext.c_str());
String ext = L"*." + def_ext;
COMDLG_FILTERSPEC spec[] =
{
{ L"", ext.c_str() }
};
file_save->SetFileTypes(1, spec);
}
else
{
COMDLG_FILTERSPEC spec[] =
{
{ L"所有文件", L"*.*" }
};
file_save->SetFileTypes(1, spec);
}
hr = file_save->Show(nullptr);
if (SUCCEEDED(hr))
{
IShellItem *item;
hr = file_save->GetResult(&item);
if (SUCCEEDED(hr))
{
PWSTR str_file_path;
hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path);
if (SUCCEEDED(hr))
{
file_path = str_file_path;
::CoTaskMemFree(str_file_path);
}
item->Release();
}
}
file_save->Release();
}
::CoUninitialize();
}
return File(file_path);
}
} }

View File

@ -31,14 +31,14 @@ namespace easy2d
File(); File();
File( File(
const String& file_name String const& file_name
); );
virtual ~File(); virtual ~File();
// 打开文件 // 打开文件
bool Open( bool Open(
const String& file_name String const& file_name
); );
// 文件是否存在 // 文件是否存在
@ -48,7 +48,7 @@ namespace easy2d
bool Delete(); bool Delete();
// 获取文件路径 // 获取文件路径
const String& GetPath() const; String const& GetPath() const;
// 获取文件扩展名 // 获取文件扩展名
String GetExtension() const; String GetExtension() const;
@ -56,25 +56,25 @@ namespace easy2d
// 释放资源到临时文件目录 // 释放资源到临时文件目录
static File Extract( static File Extract(
Resource& res, /* 资源 */ Resource& res, /* 资源 */
const String& dest_file_name /* 目标文件名 */ String const& dest_file_name /* 目标文件名 */
); );
// 添加文件搜索路径 // 添加文件搜索路径
static void AddSearchPath( static void AddSearchPath(
const String& path String const& path
); );
// 弹出打开文件对话框 // 弹出打开文件对话框
static File ShowOpenDialog( static File ShowOpenDialog(
const String& title = L"打开", /* 对话框标题 */ String const& title = L"打开", /* 对话框标题 */
const String& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */ String const& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */
); );
// 弹出保存文件对话框 // 弹出保存文件对话框
static File ShowSaveDialog( static File ShowSaveDialog(
const String& title = L"保存", /* 对话框标题 */ String const& title = L"保存", /* 对话框标题 */
const String& def_file = L"", /* 默认保存的文件名 */ String const& def_file = L"", /* 默认保存的文件名 */
const String& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */ String const& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */
); );
protected: protected:

View File

@ -28,7 +28,7 @@ namespace easy2d
namespace namespace
{ {
// 创建指定文件夹 // 创建指定文件夹
bool CreateFolder(const String & dir_path) bool CreateFolder(String const& dir_path)
{ {
if (dir_path.empty() || dir_path.size() >= MAX_PATH) if (dir_path.empty() || dir_path.size() >= MAX_PATH)
return false; return false;
@ -55,7 +55,7 @@ namespace easy2d
} }
const String& Path::GetDataPath() String const& Path::GetDataPath()
{ {
static String data_path; static String data_path;
if (data_path.empty()) if (data_path.empty())
@ -83,7 +83,7 @@ namespace easy2d
return data_path; return data_path;
} }
const String& Path::GetTemporaryPath() String const& Path::GetTemporaryPath()
{ {
static String temp_path; static String temp_path;
if (temp_path.empty()) if (temp_path.empty())
@ -110,7 +110,7 @@ namespace easy2d
return temp_path; return temp_path;
} }
const String& Path::GetLocalAppDataPath() String const& Path::GetLocalAppDataPath()
{ {
static String local_app_data_path; static String local_app_data_path;
if (local_app_data_path.empty()) if (local_app_data_path.empty())
@ -124,7 +124,7 @@ namespace easy2d
return local_app_data_path; return local_app_data_path;
} }
const String& Path::GetExeFilePath() String const& Path::GetExeFilePath()
{ {
static String exe_file_path; static String exe_file_path;
if (exe_file_path.empty()) if (exe_file_path.empty())

View File

@ -28,15 +28,15 @@ namespace easy2d
{ {
public: public:
// 获取数据的默认保存路径 // 获取数据的默认保存路径
static const String& GetDataPath(); static String const& GetDataPath();
// 获取临时文件目录 // 获取临时文件目录
static const String& GetTemporaryPath(); static String const& GetTemporaryPath();
// 获取 LocalAppData 目录 // 获取 LocalAppData 目录
static const String& GetLocalAppDataPath(); static String const& GetLocalAppDataPath();
// 获取当前程序的运行路径 // 获取当前程序的运行路径
static const String& GetExeFilePath(); static String const& GetExeFilePath();
}; };
} }

View File

@ -33,7 +33,7 @@ namespace easy2d
ClearCache(); ClearCache();
} }
bool Player::Load(const String & file_path) bool Player::Load(String const& file_path)
{ {
if (file_path.empty()) if (file_path.empty())
return false; return false;
@ -54,7 +54,7 @@ namespace easy2d
return false; return false;
} }
bool Player::Play(const String & file_path, int loop_count) bool Player::Play(String const& file_path, int loop_count)
{ {
if (file_path.empty()) if (file_path.empty())
return false; return false;
@ -70,7 +70,7 @@ namespace easy2d
return false; return false;
} }
void Player::Pause(const String & file_path) void Player::Pause(String const& file_path)
{ {
if (file_path.empty()) if (file_path.empty())
return; return;
@ -80,7 +80,7 @@ namespace easy2d
musics_cache_[hash_code]->Pause(); musics_cache_[hash_code]->Pause();
} }
void Player::Resume(const String & file_path) void Player::Resume(String const& file_path)
{ {
if (file_path.empty()) if (file_path.empty())
return; return;
@ -90,7 +90,7 @@ namespace easy2d
musics_cache_[hash_code]->Resume(); musics_cache_[hash_code]->Resume();
} }
void Player::Stop(const String & file_path) void Player::Stop(String const& file_path)
{ {
if (file_path.empty()) if (file_path.empty())
return; return;
@ -100,7 +100,7 @@ namespace easy2d
musics_cache_[hash_code]->Stop(); musics_cache_[hash_code]->Stop();
} }
bool Player::IsPlaying(const String & file_path) bool Player::IsPlaying(String const& file_path)
{ {
if (file_path.empty()) if (file_path.empty())
return false; return false;
@ -111,7 +111,7 @@ namespace easy2d
return false; return false;
} }
bool Player::Load(Resource& res) bool Player::Load(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code)) if (musics_cache_.end() != musics_cache_.find(hash_code))
@ -131,7 +131,7 @@ namespace easy2d
return false; return false;
} }
bool Player::Play(Resource& res, int loop_count) bool Player::Play(Resource const& res, int loop_count)
{ {
if (Load(res)) if (Load(res))
{ {
@ -145,28 +145,28 @@ namespace easy2d
return false; return false;
} }
void Player::Pause(Resource& res) void Player::Pause(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code)) if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Pause(); musics_cache_[hash_code]->Pause();
} }
void Player::Resume(Resource& res) void Player::Resume(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code)) if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Resume(); musics_cache_[hash_code]->Resume();
} }
void Player::Stop(Resource& res) void Player::Stop(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code)) if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Stop(); musics_cache_[hash_code]->Stop();
} }
bool Player::IsPlaying(Resource& res) bool Player::IsPlaying(Resource const& res)
{ {
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code)) if (musics_cache_.end() != musics_cache_.find(hash_code))

View File

@ -36,64 +36,64 @@ namespace easy2d
// 渡속潼稜있栗都 // 渡속潼稜있栗都
bool Load( bool Load(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 꺄렴稜있 // 꺄렴稜있
bool Play( bool Play(
const String& file_path, /* 音乐文件路径 */ String const& file_path, /* 音乐文件路径 */
int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */ int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */
); );
// 董界稜있 // 董界稜있
void Pause( void Pause(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
void Resume( void Resume(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 界岺稜있 // 界岺稜있
void Stop( void Stop(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
bool IsPlaying( bool IsPlaying(
const String& file_path /* 音乐文件路径 */ String const& file_path /* 音乐文件路径 */
); );
// 渡속潼稜있栗都 // 渡속潼稜있栗都
bool Load( bool Load(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 꺄렴稜있 // 꺄렴稜있
bool Play( bool Play(
Resource& res, /* 音乐资源 */ Resource const& res, /* 音乐资源 */
int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */ int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */
); );
// 董界稜있 // 董界稜있
void Pause( void Pause(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
void Resume( void Resume(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 界岺稜있 // 界岺稜있
void Stop( void Stop(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
bool IsPlaying( bool IsPlaying(
Resource& res /* 音乐资源 */ Resource const& res /* 音乐资源 */
); );
// 삿혤稜좆 // 삿혤稜좆

View File

@ -40,7 +40,7 @@ namespace easy2d
} }
} }
WAVEFORMATEX* Transcoder::GetWaveFormatEx() const const WAVEFORMATEX* Transcoder::GetWaveFormatEx() const
{ {
return wave_format_; return wave_format_;
} }
@ -51,7 +51,7 @@ namespace easy2d
IMFSourceReader* reader = nullptr; IMFSourceReader* reader = nullptr;
hr = modules::MediaFoundation.MFCreateSourceReaderFromURL( hr = modules::MediaFoundation().MFCreateSourceReaderFromURL(
file_path, file_path,
nullptr, nullptr,
&reader &reader
@ -67,7 +67,7 @@ namespace easy2d
return hr; return hr;
} }
HRESULT Transcoder::LoadMediaResource(const Resource& res, BYTE** wave_data, UINT32* wave_data_size) HRESULT Transcoder::LoadMediaResource(Resource const& res, BYTE** wave_data, UINT32* wave_data_size)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -92,12 +92,12 @@ namespace easy2d
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = modules::MediaFoundation.MFCreateMFByteStreamOnStream(stream, &byte_stream); hr = modules::MediaFoundation().MFCreateMFByteStreamOnStream(stream, &byte_stream);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = modules::MediaFoundation.MFCreateSourceReaderFromByteStream( hr = modules::MediaFoundation().MFCreateSourceReaderFromByteStream(
byte_stream, byte_stream,
nullptr, nullptr,
&reader &reader
@ -124,7 +124,7 @@ namespace easy2d
IMFMediaType* partial_type = nullptr; IMFMediaType* partial_type = nullptr;
IMFMediaType* uncompressed_type = nullptr; IMFMediaType* uncompressed_type = nullptr;
hr = modules::MediaFoundation.MFCreateMediaType(&partial_type); hr = modules::MediaFoundation().MFCreateMediaType(&partial_type);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -168,7 +168,7 @@ namespace easy2d
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
UINT32 size = 0; UINT32 size = 0;
hr = modules::MediaFoundation.MFCreateWaveFormatExFromMFMediaType( hr = modules::MediaFoundation().MFCreateWaveFormatExFromMFMediaType(
uncompressed_type, uncompressed_type,
&wave_format_, &wave_format_,
&size, &size,

View File

@ -36,7 +36,7 @@ namespace easy2d
~Transcoder(); ~Transcoder();
WAVEFORMATEX* GetWaveFormatEx() const; const WAVEFORMATEX* GetWaveFormatEx() const;
HRESULT LoadMediaFile( HRESULT LoadMediaFile(
LPCWSTR file_path, LPCWSTR file_path,
@ -45,7 +45,7 @@ namespace easy2d
); );
HRESULT LoadMediaResource( HRESULT LoadMediaResource(
const Resource& res, Resource const& res,
BYTE** wave_data, BYTE** wave_data,
UINT32* wave_data_size UINT32* wave_data_size
); );

View File

@ -30,6 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" /> <ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" /> <ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" /> <ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />

View File

@ -161,6 +161,9 @@
<ClInclude Include="..\..\core\base\Size.hpp"> <ClInclude Include="..\..\core\base\Size.hpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\d2dres.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">

View File

@ -30,6 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" /> <ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" /> <ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" /> <ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />

View File

@ -161,6 +161,9 @@
<ClInclude Include="..\..\core\base\Size.hpp"> <ClInclude Include="..\..\core\base\Size.hpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\d2dres.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">

View File

@ -30,6 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" /> <ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" /> <ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" /> <ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />

View File

@ -161,6 +161,9 @@
<ClInclude Include="..\..\core\base\Size.hpp"> <ClInclude Include="..\..\core\base\Size.hpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\d2dres.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">