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

View File

@ -18,20 +18,17 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "base.hpp"
#include "Canvas.h"
#include "render.h"
#include "logs.h"
namespace easy2d
{
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// FIXME!!!
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
//-------------------------------------------------------
// CanvasBrush
//-------------------------------------------------------
Canvas::Canvas(float width, float height)
CanvasBrush::CanvasBrush()
: render_target_(nullptr)
, fill_brush_(nullptr)
, line_brush_(nullptr)
@ -39,94 +36,76 @@ namespace easy2d
, stroke_width_(1.0f)
, stroke_(StrokeStyle::Miter)
{
// render_target_ = render::D2D.HwndRenderTarget;
render_target_->AddRef();
auto graphics = devices::Graphics::Instance();
render_target_ = graphics->GetRenderTarget();
ThrowIfFailed(
render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&fill_brush_
)
graphics->CreateSolidColorBrush(fill_brush_)
);
ThrowIfFailed(
render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&line_brush_
)
graphics->CreateSolidColorBrush(line_brush_)
);
this->SetClipEnabled(true);
this->SetWidth(width);
this->SetHeight(height);
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));
}
void Canvas::SetFillColor(const Color & color)
void CanvasBrush::SetFillColor(Color const& 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);
}
void Canvas::SetStrokeStyle(StrokeStyle stroke)
void CanvasBrush::SetStrokeStyle(StrokeStyle stroke)
{
SafeRelease(stroke_style_);
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();
}
Color Canvas::GetFillColor() const
Color CanvasBrush::GetFillColor() const
{
return fill_brush_->GetColor();
}
float Canvas::GetStrokeWidth() const
float CanvasBrush::GetStrokeWidth() const
{
return stroke_width_;
}
StrokeStyle Canvas::GetStrokeStyle() const
StrokeStyle CanvasBrush::GetStrokeStyle() const
{
return stroke_;
}
void Canvas::DrawLine(const Point & begin, const Point & end)
void CanvasBrush::DrawLine(const Point & begin, const Point & end)
{
render_target_->DrawLine(
D2D1::Point2F(begin.x, begin.y),
D2D1::Point2F(end.x, end.y),
line_brush_,
line_brush_.Get(),
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(
D2D1::Ellipse(
@ -137,13 +116,13 @@ namespace easy2d
radius,
radius
),
line_brush_,
line_brush_.Get(),
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(
D2D1::Ellipse(
@ -154,13 +133,13 @@ namespace easy2d
radius_x,
radius_y
),
line_brush_,
line_brush_.Get(),
stroke_width_,
stroke_style_
stroke_style_.Get()
);
}
void Canvas::DrawRect(const Rect & rect)
void CanvasBrush::DrawRect(const Rect & rect)
{
render_target_->DrawRectangle(
D2D1::RectF(
@ -169,13 +148,13 @@ namespace easy2d
rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height
),
line_brush_,
line_brush_.Get(),
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(
D2D1::RoundedRect(
@ -188,13 +167,13 @@ namespace easy2d
radius_x,
radius_y
),
line_brush_,
line_brush_.Get(),
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(
D2D1::Ellipse(
@ -205,11 +184,11 @@ namespace easy2d
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(
D2D1::Ellipse(
@ -220,11 +199,11 @@ namespace easy2d
radius_x,
radius_y
),
fill_brush_
fill_brush_.Get()
);
}
void Canvas::FillRect(const Rect & rect)
void CanvasBrush::FillRect(const Rect & rect)
{
render_target_->FillRectangle(
D2D1::RectF(
@ -233,11 +212,11 @@ namespace easy2d
rect.origin.x + rect.size.width,
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(
D2D1::RoundedRect(
@ -250,7 +229,40 @@ namespace easy2d
radius_x,
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
#include "Node.h"
#include <d2d1.h>
namespace easy2d
{
// ť­˛ź
class Canvas
: public Node
E2D_DECLARE_SMART_PTR(CanvasBrush);
// ť­ąĘ
class CanvasBrush
: public RefCounter
{
E2D_DISABLE_COPY(Canvas);
E2D_DISABLE_COPY(CanvasBrush);
public:
Canvas(
float width,
float height
);
CanvasBrush();
virtual ~Canvas();
// ÉčÖĂĎßĚőŃŐÉŤ
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;
virtual ~CanvasBrush();
// »­Ö±Ïß
void DrawLine(
@ -126,12 +92,74 @@ namespace easy2d
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:
float stroke_width_;
StrokeStyle stroke_;
ID2D1RenderTarget* render_target_;
ID2D1SolidColorBrush* fill_brush_;
ID2D1SolidColorBrush* line_brush_;
ID2D1StrokeStyle* stroke_style_;
float stroke_width_;
StrokeStyle stroke_;
cpRenderTarget render_target_;
cpSolidColorBrush fill_brush_;
cpSolidColorBrush line_brush_;
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)
, crop_rect_()
{
this->Load(res);
}
Image::Image(Resource& res, const Rect& crop_rect)
Image::Image(Resource const& res, Rect const& crop_rect)
: bitmap_(nullptr)
, crop_rect_()
{
@ -46,14 +46,14 @@ namespace easy2d
this->Crop(crop_rect);
}
Image::Image(const String & file_name)
Image::Image(String const& file_name)
: bitmap_(nullptr)
, crop_rect_()
{
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)
, crop_rect_()
{
@ -63,23 +63,24 @@ namespace easy2d
Image::~Image()
{
SafeRelease(bitmap_);
}
bool Image::Load(Resource& res)
bool Image::Load(Resource const& res)
{
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(res, &bitmap);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(bitmap_, res);
if (FAILED(hr))
{
logs::Errorln(hr, "Load Image from resource failed!");
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;
}
bool Image::Load(const String & file_name)
bool Image::Load(String const& file_name)
{
File image_file;
if (!image_file.Open(file_name))
@ -92,18 +93,20 @@ namespace easy2d
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
String image_file_path = image_file.GetPath();
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(image_file_path, &bitmap);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(bitmap_, image_file_path);
if (FAILED(hr))
{
logs::Errorln(hr, "Load Image from file failed!");
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;
}
void Image::Crop(const Rect& crop_rect)
void Image::Crop(Rect const& crop_rect)
{
if (bitmap_)
{
@ -179,31 +182,13 @@ namespace easy2d
return crop_rect_.origin;
}
const Rect & Image::GetCropRect() const
Rect const& Image::GetCropRect() const
{
return crop_rect_;
}
ID2D1Bitmap * Image::GetBitmap() const
cpBitmap const& Image::GetBitmap() const
{
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();
explicit Image(
Resource& res
Resource const& res
);
explicit Image(
Resource& res,
const Rect& crop_rect /* 裁剪矩形 */
Resource const& res,
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
);
explicit Image(
const String& file_name
String const& file_name
);
explicit Image(
const String& file_name,
const Rect& crop_rect /* 裁剪矩形 */
String const& file_name,
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
);
virtual ~Image();
// 加载图片资源
bool Load(
Resource& res
Resource const& res
);
// 加载图片资源
bool Load(
const String& file_name
String const& file_name
);
// 将图片裁剪为矩形
void Crop(
const Rect& crop_rect /* 裁剪矩形 */
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
);
// 获取宽度
@ -96,19 +96,12 @@ namespace easy2d
Point GetCropPos() const;
// 获取裁剪矩形
const Rect& GetCropRect() const;
Rect const& GetCropRect() const;
// 获取 ID2D1Bitmap 对象
ID2D1Bitmap * GetBitmap() const;
cpBitmap const& GetBitmap() const;
private:
// 设置 Bitmap
void SetBitmap(
ID2D1Bitmap * bitmap
);
private:
Rect crop_rect_;
ID2D1Bitmap* bitmap_;
protected:
Rect crop_rect_;
cpBitmap bitmap_;
};
}

View File

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

View File

@ -22,7 +22,6 @@
#include "base.hpp"
#include "audio.h"
#include "Resource.h"
#include <xaudio2.h>
namespace easy2d
{
@ -36,28 +35,28 @@ namespace easy2d
Music();
Music(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
Music(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
virtual ~Music();
// 打开音乐文件
bool Load(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 打开音乐资源
bool Load(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 播放
bool Play(
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
);
// 暂停

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,12 +22,12 @@
namespace easy2d
{
Task::Task(const Callback & func, const String & name)
Task::Task(const Callback & func, String const& 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)
, stopped_(false)
, run_times_(0)
@ -92,7 +92,7 @@ namespace easy2d
return running_;
}
const String& Task::GetName() const
String const& Task::GetName() const
{
return name_;
}

View File

@ -41,14 +41,14 @@ namespace easy2d
public:
explicit Task(
const Callback& func, /* 执行函数 */
const String& name = L"" /* ÈÎÎñÃû³Æ */
String const& name = L"" /* ÈÎÎñÃû³Æ */
);
explicit Task(
Callback const& func, /* 执行函数 */
Duration const& delay, /* 时间间隔(秒) */
int times = -1, /* 执行次数(设 -1 为永久执行) */
const String& name = L"" /* ÈÎÎñÃû³Æ */
String const& name = L"" /* ÈÎÎñÃû³Æ */
);
// 启动任务
@ -61,7 +61,7 @@ namespace easy2d
bool IsRunning() const;
// 获取任务名称
const String& GetName() const;
String const& GetName() const;
protected:
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)
{
@ -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)
{
@ -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)
{
@ -87,7 +87,7 @@ namespace easy2d
void TaskManager::StopAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->NextItem())
for (auto task = tasks_.First(); task; task = task->NextItem())
{
task->Stop();
}
@ -95,7 +95,7 @@ namespace easy2d
void TaskManager::StartAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->NextItem())
for (auto task = tasks_.First(); task; task = task->NextItem())
{
task->Start();
}
@ -103,7 +103,7 @@ namespace easy2d
void TaskManager::RemoveAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->NextItem())
for (auto task = tasks_.First(); task; task = task->NextItem())
{
task->stopped_ = true;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@
#include "BaseTypes.hpp"
#include "RefCounter.hpp"
#include "intrusive/SmartPointer.hpp"
#include "d2dres.hpp"
#ifndef E2D_DECLARE_SMART_PTR
#define E2D_DECLARE_SMART_PTR(class_name)\
@ -37,7 +37,6 @@
}
#endif
namespace easy2d
{
E2D_DECLARE_SMART_PTR(Image);
@ -80,14 +79,4 @@ namespace easy2d
E2D_DECLARE_NS_SMART_PTR(ui, Button);
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.
#pragma once
#include "../macros.h"
#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 intrusive
@ -33,65 +42,74 @@ namespace easy2d
public:
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_);
}
SmartPointer(const SmartPointer& other) : ptr_(other.ptr_)
SmartPointer(const SmartPointer& other) E2D_NOEXCEPT : ptr_(other.ptr_)
{
IntrusivePtrAddRef(ptr_);
}
template <typename U>
SmartPointer(const SmartPointer<U>& other) : ptr_(other.Get())
SmartPointer(const SmartPointer<U>& other) E2D_NOEXCEPT : ptr_(other.Get())
{
IntrusivePtrAddRef(ptr_);
}
SmartPointer(SmartPointer&& other)
SmartPointer(SmartPointer&& other) E2D_NOEXCEPT
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
~SmartPointer()
~SmartPointer() E2D_NOEXCEPT
{
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_);
}
inline Type* operator ->() const
{
E2D_INTRUSIVE_PTR_ASSERT(ptr_ != nullptr, "Invalid pointer");
return ptr_;
}
inline Type& operator *() const
{
E2D_INTRUSIVE_PTR_ASSERT(ptr_ != nullptr, "Invalid pointer");
return *ptr_;
}
inline operator bool() const { return ptr_ != nullptr; }
inline bool operator !() const { return ptr_ == 0; }
inline SmartPointer& operator =(const SmartPointer& other)
inline Type** operator &()
{
SmartPointer(other).Swap(*this);
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);
return *this;
}
inline SmartPointer& operator =(SmartPointer&& other)
inline SmartPointer& operator =(SmartPointer&& other) E2D_NOEXCEPT
{
IntrusivePtrRelease(ptr_);
ptr_ = other.ptr_;
@ -99,88 +117,90 @@ namespace easy2d
return *this;
}
inline SmartPointer& operator =(Type* p)
inline SmartPointer& operator =(Type* p) E2D_NOEXCEPT
{
SmartPointer(p).Swap(*this);
if (p != ptr_)
SmartPointer(p).Swap(*this);
return *this;
}
inline SmartPointer& operator =(nullptr_t)
inline SmartPointer& operator =(nullptr_t) E2D_NOEXCEPT
{
SmartPointer{}.Swap(*this);
if (nullptr != ptr_)
SmartPointer{}.Swap(*this);
return *this;
}
};
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();
}
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();
}
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();
}
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;
}
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;
}
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();
}
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();
}
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);
}
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);
}
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);
}
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);
}
}
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);
}
@ -188,7 +208,7 @@ namespace easy2d
// template class cannot specialize std::swap,
// so implement a swap function in easy2d namespace
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);
}

View File

@ -25,28 +25,47 @@ namespace easy2d
{
namespace modules
{
namespace
Shlwapi::Shlwapi()
{
int initialize_count = 0;
inline void SafeFreeLibrary(HMODULE instance)
shlwapi = LoadLibraryW(L"shlwapi.dll");
if (shlwapi)
{
if (instance)
FreeLibrary(instance);
PathFileExistsW = (PFN_PathFileExistsW)
GetProcAddress(shlwapi, "PathFileExistsW");
}
else
{
E2D_LOG("load shlapi.dll failed");
}
}
Module_XAudio2 XAudio2;
Module_MediaFoundation MediaFoundation;
void Init()
DirectX::DirectX()
{
initialize_count++;
if (initialize_count > 1)
return;
d2d = LoadLibraryW(L"d2d1.dll");
if (d2d)
{
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 =
{
L"xaudio2_9.dll",
@ -56,56 +75,59 @@ namespace easy2d
for (const auto& name : xaudio2_dll_names)
{
XAudio2.instance = LoadLibraryW(name);
if (XAudio2.instance)
xaudio2 = LoadLibraryW(name);
if (xaudio2)
{
XAudio2.XAudio2Create = (PFN_XAudio2Create)
GetProcAddress(XAudio2.instance, "XAudio2Create");
XAudio2Create = (PFN_XAudio2Create)
GetProcAddress(xaudio2, "XAudio2Create");
break;
}
}
MediaFoundation.mfplat = LoadLibraryW(L"Mfplat.dll");
if (MediaFoundation.mfplat)
if (!xaudio2)
{
MediaFoundation.MFStartup = (PFN_MFStartup)
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");
E2D_LOG("load xaudio2.dll failed");
}
}
void Destroy()
MediaFoundation::MediaFoundation()
{
initialize_count--;
if (initialize_count > 0)
return;
mfplat = LoadLibraryW(L"Mfplat.dll");
if (mfplat)
{
MFStartup = (PFN_MFStartup)
GetProcAddress(mfplat, "MFStartup");
E2D_LOG("Destroying modules");
MFShutdown = (PFN_MFShutdown)
GetProcAddress(mfplat, "MFShutdown");
SafeFreeLibrary(XAudio2.instance);
SafeFreeLibrary(MediaFoundation.mfplat);
SafeFreeLibrary(MediaFoundation.mfreadwrite);
MFCreateMediaType = (PFN_MFCreateMediaType)
GetProcAddress(mfplat, "MFCreateMediaType");
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
#include "macros.h"
#include <d2d1.h>
#include <dwrite.h>
#include <xaudio2.h>
#include <mfapi.h>
#include <mfidl.h>
@ -29,39 +31,68 @@ namespace easy2d
{
namespace modules
{
// modules can be initialized multiple times,
// but it needs to be destroyed every time
void Init();
void Destroy();
// XAudio2 functions
typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
struct Module_XAudio2
class Shlwapi
{
HMODULE instance;
HMODULE shlwapi;
// 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
typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
public:
XAudio2();
PFN_XAudio2Create XAudio2Create;
};
extern Module_XAudio2 XAudio2;
// MediaFoundation functions
typedef HRESULT(WINAPI *PFN_MFStartup)(ULONG, DWORD);
typedef HRESULT(WINAPI *PFN_MFShutdown)();
typedef HRESULT(WINAPI *PFN_MFCreateMediaType)(IMFMediaType**);
typedef HRESULT(WINAPI *PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
typedef HRESULT(WINAPI *PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
struct Module_MediaFoundation
class MediaFoundation
{
HMODULE mfplat;
HMODULE mfreadwrite;
// MediaFoundation functions
typedef HRESULT(WINAPI *PFN_MFStartup)(ULONG, DWORD);
typedef HRESULT(WINAPI *PFN_MFShutdown)();
typedef HRESULT(WINAPI *PFN_MFCreateMediaType)(IMFMediaType**);
typedef HRESULT(WINAPI *PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
typedef HRESULT(WINAPI *PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
public:
MediaFoundation();
PFN_MFStartup MFStartup;
PFN_MFShutdown MFShutdown;
PFN_MFCreateMediaType MFCreateMediaType;
@ -70,7 +101,5 @@ namespace easy2d
PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
};
extern Module_MediaFoundation MediaFoundation;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,11 +19,8 @@
// THE SOFTWARE.
#include "File.h"
#include "../base/modules.h"
#include <cwctype>
#include <shobjidl.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
namespace easy2d
{
@ -34,7 +31,7 @@ namespace easy2d
{
}
File::File(const String & file_name)
File::File(String const& file_name)
: file_path_(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())
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 false;
};
@ -75,12 +72,12 @@ namespace easy2d
bool File::Exists() const
{
if (::PathFileExists(file_path_.c_str()))
if (modules::Shlwapi().PathFileExistsW(file_path_.c_str()))
return true;
return false;
}
const String& File::GetPath() const
String const& File::GetPath() const
{
return file_path_;
}
@ -88,14 +85,10 @@ namespace easy2d
String File::GetExtension() const
{
String file_ext;
// 找到文件名中的最后一个 '.' 的位置
size_t pos = file_path_.find_last_of(L'.');
// 判断 pos 是否是有效位置
if (pos != String::npos)
{
// 截取扩展名
file_ext = file_path_.substr(pos);
// 转换为小写字母
std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower);
}
return file_ext;
@ -108,7 +101,7 @@ namespace easy2d
return false;
}
File File::Extract(Resource& res, const String& dest_file_name)
File File::Extract(Resource& res, String const& dest_file_name)
{
File file;
HANDLE file_handle = ::CreateFile(
@ -143,7 +136,7 @@ namespace easy2d
return file;
}
void File::AddSearchPath(const String & path)
void File::AddSearchPath(String const& path)
{
String tmp = path;
size_t pos = 0;
@ -163,136 +156,4 @@ namespace easy2d
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(
const String& file_name
String const& file_name
);
virtual ~File();
// 打开文件
bool Open(
const String& file_name
String const& file_name
);
// 文件是否存在
@ -48,7 +48,7 @@ namespace easy2d
bool Delete();
// 获取文件路径
const String& GetPath() const;
String const& GetPath() const;
// 获取文件扩展名
String GetExtension() const;
@ -56,25 +56,25 @@ namespace easy2d
// 释放资源到临时文件目录
static File Extract(
Resource& res, /* 资源 */
const String& dest_file_name /* 目标文件名 */
String const& dest_file_name /* 目标文件名 */
);
// 添加文件搜索路径
static void AddSearchPath(
const String& path
String const& path
);
// 弹出打开文件对话框
static File ShowOpenDialog(
const String& title = L"打开", /* 对话框标题 */
const String& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */
String const& title = L"打开", /* 对话框标题 */
String const& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */
);
// 弹出保存文件对话框
static File ShowSaveDialog(
const String& title = L"保存", /* 对话框标题 */
const String& def_file = L"", /* 默认保存的文件名 */
const String& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */
String const& title = L"保存", /* 对话框标题 */
String const& def_file = L"", /* 默认保存的文件名 */
String const& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */
);
protected:

View File

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

View File

@ -28,15 +28,15 @@ namespace easy2d
{
public:
// 获取数据的默认保存路径
static const String& GetDataPath();
static String const& GetDataPath();
// 获取临时文件目录
static const String& GetTemporaryPath();
static String const& GetTemporaryPath();
// 获取 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();
}
bool Player::Load(const String & file_path)
bool Player::Load(String const& file_path)
{
if (file_path.empty())
return false;
@ -54,7 +54,7 @@ namespace easy2d
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())
return false;
@ -70,7 +70,7 @@ namespace easy2d
return false;
}
void Player::Pause(const String & file_path)
void Player::Pause(String const& file_path)
{
if (file_path.empty())
return;
@ -80,7 +80,7 @@ namespace easy2d
musics_cache_[hash_code]->Pause();
}
void Player::Resume(const String & file_path)
void Player::Resume(String const& file_path)
{
if (file_path.empty())
return;
@ -90,7 +90,7 @@ namespace easy2d
musics_cache_[hash_code]->Resume();
}
void Player::Stop(const String & file_path)
void Player::Stop(String const& file_path)
{
if (file_path.empty())
return;
@ -100,7 +100,7 @@ namespace easy2d
musics_cache_[hash_code]->Stop();
}
bool Player::IsPlaying(const String & file_path)
bool Player::IsPlaying(String const& file_path)
{
if (file_path.empty())
return false;
@ -111,7 +111,7 @@ namespace easy2d
return false;
}
bool Player::Load(Resource& res)
bool Player::Load(Resource const& res)
{
size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code))
@ -131,7 +131,7 @@ namespace easy2d
return false;
}
bool Player::Play(Resource& res, int loop_count)
bool Player::Play(Resource const& res, int loop_count)
{
if (Load(res))
{
@ -145,28 +145,28 @@ namespace easy2d
return false;
}
void Player::Pause(Resource& res)
void Player::Pause(Resource const& res)
{
size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Pause();
}
void Player::Resume(Resource& res)
void Player::Resume(Resource const& res)
{
size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Resume();
}
void Player::Stop(Resource& res)
void Player::Stop(Resource const& res)
{
size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code))
musics_cache_[hash_code]->Stop();
}
bool Player::IsPlaying(Resource& res)
bool Player::IsPlaying(Resource const& res)
{
size_t hash_code = res.GetHashCode();
if (musics_cache_.end() != musics_cache_.find(hash_code))

View File

@ -36,64 +36,64 @@ namespace easy2d
// 渡속潼稜있栗都
bool Load(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 꺄렴稜있
bool Play(
const String& file_path, /* 音乐文件路径 */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
String const& file_path, /* 音乐文件路径 */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
);
// 董界稜있
void Pause(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 셨崎꺄렴稜있
void Resume(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 界岺稜있
void Stop(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 삿혤稜있꺄렴榴檄
bool IsPlaying(
const String& file_path /* 音乐文件路径 */
String const& file_path /* 音乐文件路径 */
);
// 渡속潼稜있栗都
bool Load(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 꺄렴稜있
bool Play(
Resource& res, /* 音乐资源 */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
Resource const& res, /* 音乐资源 */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
);
// 董界稜있
void Pause(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 셨崎꺄렴稜있
void Resume(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 界岺稜있
void Stop(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 삿혤稜있꺄렴榴檄
bool IsPlaying(
Resource& res /* 音乐资源 */
Resource const& res /* 音乐资源 */
);
// 삿혤稜좆
@ -101,7 +101,7 @@ namespace easy2d
// <20>零稜좆
void SetVolume(
float volume /* 1.0 为原始音量 */
float volume /* 1.0 为原始音量 */
);
// 董界杰唐稜있

View File

@ -40,7 +40,7 @@ namespace easy2d
}
}
WAVEFORMATEX* Transcoder::GetWaveFormatEx() const
const WAVEFORMATEX* Transcoder::GetWaveFormatEx() const
{
return wave_format_;
}
@ -51,7 +51,7 @@ namespace easy2d
IMFSourceReader* reader = nullptr;
hr = modules::MediaFoundation.MFCreateSourceReaderFromURL(
hr = modules::MediaFoundation().MFCreateSourceReaderFromURL(
file_path,
nullptr,
&reader
@ -67,7 +67,7 @@ namespace easy2d
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;
@ -92,12 +92,12 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = modules::MediaFoundation.MFCreateMFByteStreamOnStream(stream, &byte_stream);
hr = modules::MediaFoundation().MFCreateMFByteStreamOnStream(stream, &byte_stream);
}
if (SUCCEEDED(hr))
{
hr = modules::MediaFoundation.MFCreateSourceReaderFromByteStream(
hr = modules::MediaFoundation().MFCreateSourceReaderFromByteStream(
byte_stream,
nullptr,
&reader
@ -124,7 +124,7 @@ namespace easy2d
IMFMediaType* partial_type = nullptr;
IMFMediaType* uncompressed_type = nullptr;
hr = modules::MediaFoundation.MFCreateMediaType(&partial_type);
hr = modules::MediaFoundation().MFCreateMediaType(&partial_type);
if (SUCCEEDED(hr))
{
@ -168,7 +168,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
UINT32 size = 0;
hr = modules::MediaFoundation.MFCreateWaveFormatExFromMFMediaType(
hr = modules::MediaFoundation().MFCreateWaveFormatExFromMFMediaType(
uncompressed_type,
&wave_format_,
&size,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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