mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	Fixed line endings and applied gitignore
This commit is contained in:
		@@ -1,71 +1,71 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "CanvasGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
Canvas::Canvas() :
 | 
			
		||||
	m_W(),
 | 
			
		||||
	m_H(),
 | 
			
		||||
	m_AccurateText(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Canvas::~Canvas()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Canvas* Canvas::Create(Renderer renderer)
 | 
			
		||||
{
 | 
			
		||||
	if (renderer == Renderer::GDIP)
 | 
			
		||||
	{
 | 
			
		||||
		return new CanvasGDIP();
 | 
			
		||||
	}
 | 
			
		||||
	else if (renderer == Renderer::D2D && IsWindows7OrGreater())
 | 
			
		||||
	{
 | 
			
		||||
		if (CanvasD2D::Initialize())
 | 
			
		||||
		{
 | 
			
		||||
			return new CanvasD2D();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CanvasD2D::Finalize();
 | 
			
		||||
	}
 | 
			
		||||
	else if (renderer == Renderer::PreferD2D)
 | 
			
		||||
	{
 | 
			
		||||
		if (Canvas* canvas = Create(Renderer::D2D))
 | 
			
		||||
		{
 | 
			
		||||
			return canvas;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return Create(Renderer::GDIP);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Canvas::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	m_W = w;
 | 
			
		||||
	m_H = h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "CanvasGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
Canvas::Canvas() :
 | 
			
		||||
	m_W(),
 | 
			
		||||
	m_H(),
 | 
			
		||||
	m_AccurateText(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Canvas::~Canvas()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Canvas* Canvas::Create(Renderer renderer)
 | 
			
		||||
{
 | 
			
		||||
	if (renderer == Renderer::GDIP)
 | 
			
		||||
	{
 | 
			
		||||
		return new CanvasGDIP();
 | 
			
		||||
	}
 | 
			
		||||
	else if (renderer == Renderer::D2D && IsWindows7OrGreater())
 | 
			
		||||
	{
 | 
			
		||||
		if (CanvasD2D::Initialize())
 | 
			
		||||
		{
 | 
			
		||||
			return new CanvasD2D();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CanvasD2D::Finalize();
 | 
			
		||||
	}
 | 
			
		||||
	else if (renderer == Renderer::PreferD2D)
 | 
			
		||||
	{
 | 
			
		||||
		if (Canvas* canvas = Create(Renderer::D2D))
 | 
			
		||||
		{
 | 
			
		||||
			return canvas;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return Create(Renderer::GDIP);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Canvas::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	m_W = w;
 | 
			
		||||
	m_H = h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,114 +1,114 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVAS_H_
 | 
			
		||||
#define RM_GFX_CANVAS_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
enum class Renderer
 | 
			
		||||
{
 | 
			
		||||
	GDIP,
 | 
			
		||||
	D2D,
 | 
			
		||||
 | 
			
		||||
	// Attempts to use D2D. If D2D is not available, fallbacks to use GDI+.
 | 
			
		||||
	PreferD2D
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Provides methods for drawing text, bitmaps, etc.
 | 
			
		||||
class __declspec(novtable) Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~Canvas();
 | 
			
		||||
 | 
			
		||||
	Canvas(const Canvas& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Creates the canvas using the specified rendering engine. May return nullptr.
 | 
			
		||||
	static Canvas* Create(Renderer renderer);
 | 
			
		||||
 | 
			
		||||
	int GetW() const { return m_W; }
 | 
			
		||||
	int GetH() const { return m_H; }
 | 
			
		||||
 | 
			
		||||
	void SetAccurateText(bool option) { m_AccurateText = option; }
 | 
			
		||||
 | 
			
		||||
	// Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been
 | 
			
		||||
	// called and has not yet been matched by a correspoding call to EndDraw.
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	// BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be
 | 
			
		||||
	// be called only between BeginDraw() and EndDraw().
 | 
			
		||||
	virtual bool BeginDraw() = 0;
 | 
			
		||||
	virtual void EndDraw() = 0;
 | 
			
		||||
 | 
			
		||||
	// Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw()
 | 
			
		||||
	// and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to
 | 
			
		||||
	// EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of
 | 
			
		||||
	// this class must not be called. 
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() = 0;
 | 
			
		||||
	virtual void EndGdiplusContext() = 0;
 | 
			
		||||
 | 
			
		||||
	// Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be
 | 
			
		||||
	// matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const
 | 
			
		||||
	// member functions of this class must not be called.
 | 
			
		||||
	virtual HDC GetDC() = 0;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) = 0;
 | 
			
		||||
 | 
			
		||||
	// The Create* functions allocate objects specific to this Canvas object.
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() = 0;
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() = 0;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0;
 | 
			
		||||
	virtual void ResetTransform() = 0;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) = 0;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	Canvas();
 | 
			
		||||
 | 
			
		||||
	int m_W;
 | 
			
		||||
	int m_H;
 | 
			
		||||
 | 
			
		||||
	// GDI+, by default, includes padding around the string and also has a larger character spacing
 | 
			
		||||
	// compared to DirectWrite. In order to minimize diffeences between the text renderers,
 | 
			
		||||
	// an option is provided to enable accurate (typographic) text rendering. If set to |true|,
 | 
			
		||||
	// it is expected that there is no padding around the text and that the output is similar to
 | 
			
		||||
	// the default DirectWrite output. Otherwise, the expected result should be similar to that of
 | 
			
		||||
	// non-typographic GDI+.
 | 
			
		||||
	bool m_AccurateText;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVAS_H_
 | 
			
		||||
#define RM_GFX_CANVAS_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
enum class Renderer
 | 
			
		||||
{
 | 
			
		||||
	GDIP,
 | 
			
		||||
	D2D,
 | 
			
		||||
 | 
			
		||||
	// Attempts to use D2D. If D2D is not available, fallbacks to use GDI+.
 | 
			
		||||
	PreferD2D
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Provides methods for drawing text, bitmaps, etc.
 | 
			
		||||
class __declspec(novtable) Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~Canvas();
 | 
			
		||||
 | 
			
		||||
	Canvas(const Canvas& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Creates the canvas using the specified rendering engine. May return nullptr.
 | 
			
		||||
	static Canvas* Create(Renderer renderer);
 | 
			
		||||
 | 
			
		||||
	int GetW() const { return m_W; }
 | 
			
		||||
	int GetH() const { return m_H; }
 | 
			
		||||
 | 
			
		||||
	void SetAccurateText(bool option) { m_AccurateText = option; }
 | 
			
		||||
 | 
			
		||||
	// Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been
 | 
			
		||||
	// called and has not yet been matched by a correspoding call to EndDraw.
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	// BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be
 | 
			
		||||
	// be called only between BeginDraw() and EndDraw().
 | 
			
		||||
	virtual bool BeginDraw() = 0;
 | 
			
		||||
	virtual void EndDraw() = 0;
 | 
			
		||||
 | 
			
		||||
	// Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw()
 | 
			
		||||
	// and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to
 | 
			
		||||
	// EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of
 | 
			
		||||
	// this class must not be called. 
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() = 0;
 | 
			
		||||
	virtual void EndGdiplusContext() = 0;
 | 
			
		||||
 | 
			
		||||
	// Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be
 | 
			
		||||
	// matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const
 | 
			
		||||
	// member functions of this class must not be called.
 | 
			
		||||
	virtual HDC GetDC() = 0;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) = 0;
 | 
			
		||||
 | 
			
		||||
	// The Create* functions allocate objects specific to this Canvas object.
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() = 0;
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() = 0;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0;
 | 
			
		||||
	virtual void ResetTransform() = 0;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) = 0;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	Canvas();
 | 
			
		||||
 | 
			
		||||
	int m_W;
 | 
			
		||||
	int m_H;
 | 
			
		||||
 | 
			
		||||
	// GDI+, by default, includes padding around the string and also has a larger character spacing
 | 
			
		||||
	// compared to DirectWrite. In order to minimize diffeences between the text renderers,
 | 
			
		||||
	// an option is provided to enable accurate (typographic) text rendering. If set to |true|,
 | 
			
		||||
	// it is expected that there is no padding around the text and that the output is similar to
 | 
			
		||||
	// the default DirectWrite output. Otherwise, the expected result should be similar to that of
 | 
			
		||||
	// non-typographic GDI+.
 | 
			
		||||
	bool m_AccurateText;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,484 +1,484 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "Util/DWriteFontCollectionLoader.h"
 | 
			
		||||
#include "Util/DWriteHelpers.h"
 | 
			
		||||
#include "Util/WICBitmapLockGDIP.h"
 | 
			
		||||
#include "../../Library/Litestep.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
D2D1_COLOR_F ToColorF(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
UINT CanvasD2D::c_Instances = 0;
 | 
			
		||||
Microsoft::WRL::ComPtr<ID2D1Factory1> CanvasD2D::c_D2DFactory;
 | 
			
		||||
Microsoft::WRL::ComPtr<IDWriteFactory1> CanvasD2D::c_DWFactory;
 | 
			
		||||
Microsoft::WRL::ComPtr<IDWriteGdiInterop> CanvasD2D::c_DWGDIInterop;
 | 
			
		||||
Microsoft::WRL::ComPtr<IWICImagingFactory> CanvasD2D::c_WICFactory;
 | 
			
		||||
 | 
			
		||||
CanvasD2D::CanvasD2D() : Canvas(),
 | 
			
		||||
	m_Bitmap(),
 | 
			
		||||
	m_TextAntiAliasing(false),
 | 
			
		||||
	m_CanUseAxisAlignClip(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CanvasD2D::~CanvasD2D()
 | 
			
		||||
{
 | 
			
		||||
	Finalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::Initialize()
 | 
			
		||||
{
 | 
			
		||||
	++c_Instances;
 | 
			
		||||
	if (c_Instances == 1)
 | 
			
		||||
	{
 | 
			
		||||
		if (!IsWindows7OrGreater()) return false;
 | 
			
		||||
 | 
			
		||||
		D2D1_FACTORY_OPTIONS fo = {};
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
		fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		HRESULT hr = D2D1CreateFactory(
 | 
			
		||||
			D2D1_FACTORY_TYPE_SINGLE_THREADED,
 | 
			
		||||
			fo,
 | 
			
		||||
			c_D2DFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = CoCreateInstance(
 | 
			
		||||
			CLSID_WICImagingFactory,
 | 
			
		||||
			nullptr,
 | 
			
		||||
			CLSCTX_INPROC_SERVER,
 | 
			
		||||
			IID_IWICImagingFactory,
 | 
			
		||||
			(LPVOID*)c_WICFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = DWriteCreateFactory(
 | 
			
		||||
			DWRITE_FACTORY_TYPE_SHARED,
 | 
			
		||||
			__uuidof(c_DWFactory),
 | 
			
		||||
			(IUnknown**)c_DWFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Finalize()
 | 
			
		||||
{
 | 
			
		||||
	--c_Instances;
 | 
			
		||||
	if (c_Instances == 0)
 | 
			
		||||
	{
 | 
			
		||||
		c_D2DFactory.Reset();
 | 
			
		||||
		c_WICFactory.Reset();
 | 
			
		||||
		c_DWGDIInterop.Reset();
 | 
			
		||||
 | 
			
		||||
		if (c_DWFactory)
 | 
			
		||||
		{
 | 
			
		||||
			c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
 | 
			
		||||
			c_DWFactory.Reset();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	__super::Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	m_Target.Reset();
 | 
			
		||||
 | 
			
		||||
	m_Bitmap.Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData()));
 | 
			
		||||
	m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::BeginDraw()
 | 
			
		||||
{
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndDraw()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::BeginTargetDraw()
 | 
			
		||||
{
 | 
			
		||||
	if (m_Target) return true;
 | 
			
		||||
 | 
			
		||||
	const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat(
 | 
			
		||||
		DXGI_FORMAT_B8G8R8A8_UNORM,
 | 
			
		||||
		D2D1_ALPHA_MODE_PREMULTIPLIED);
 | 
			
		||||
 | 
			
		||||
	const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
 | 
			
		||||
		D2D1_RENDER_TARGET_TYPE_DEFAULT,
 | 
			
		||||
		format,
 | 
			
		||||
		0.0f,	// Default DPI
 | 
			
		||||
		0.0f,	// Default DPI
 | 
			
		||||
		D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
 | 
			
		||||
 | 
			
		||||
	// A new Direct2D render target must be created for each sequence of Direct2D draw operations
 | 
			
		||||
	// since we use GDI+ to render to the same pixel data. Without creating a new render target
 | 
			
		||||
	// each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is
 | 
			
		||||
	// unaware of the changes made by GDI+. By creating a new render target and then releasing it
 | 
			
		||||
	// before the next GDI+ draw operations, we ensure that the pixel data result is as expected
 | 
			
		||||
	// Once GDI+ drawing is no longer needed, we change to recreate the render target only when the
 | 
			
		||||
	// bitmap size is changed.
 | 
			
		||||
	HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		SetTextAntiAliasing(m_TextAntiAliasing);
 | 
			
		||||
 | 
			
		||||
		m_Target->BeginDraw();
 | 
			
		||||
 | 
			
		||||
		// Apply any transforms that occurred before creation of |m_Target|.
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndTargetDraw()
 | 
			
		||||
{
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->EndDraw();
 | 
			
		||||
		m_Target.Reset();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
	return *m_GdipGraphics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HDC CanvasD2D::GetDC()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
 | 
			
		||||
	HDC dcMemory = CreateCompatibleDC(nullptr);
 | 
			
		||||
	SelectObject(dcMemory, m_Bitmap.GetHandle());
 | 
			
		||||
	return dcMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::ReleaseDC(HDC dc)
 | 
			
		||||
{
 | 
			
		||||
	DeleteDC(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::IsTransparentPixel(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false;
 | 
			
		||||
 | 
			
		||||
	bool transparent = true;
 | 
			
		||||
 | 
			
		||||
	DWORD* data = (DWORD*)m_Bitmap.GetData();
 | 
			
		||||
	if (data)
 | 
			
		||||
	{
 | 
			
		||||
		DWORD pixel = data[y * m_W + x];  // Top-down DIB.
 | 
			
		||||
		transparent = (pixel & 0xFF000000) != 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::UpdateTargetTransform()
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::Matrix gdipMatrix;
 | 
			
		||||
	m_GdipGraphics->GetTransform(&gdipMatrix);
 | 
			
		||||
 | 
			
		||||
	D2D1_MATRIX_3X2_F d2dMatrix;
 | 
			
		||||
	gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix);
 | 
			
		||||
 | 
			
		||||
	m_Target->SetTransform(d2dMatrix);
 | 
			
		||||
	m_CanUseAxisAlignClip =
 | 
			
		||||
		d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f &&
 | 
			
		||||
		d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->SetTransform(&matrix);
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::ResetTransform()
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->ResetTransform();
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->SetTransform(D2D1::Matrix3x2F::Identity());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy)
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->TranslateTransform(x, y);
 | 
			
		||||
	m_GdipGraphics->RotateTransform(angle);
 | 
			
		||||
	m_GdipGraphics->TranslateTransform(dx, dy);
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	// TODO: Set m_Target aliasing?
 | 
			
		||||
	m_GdipGraphics->SetSmoothingMode(
 | 
			
		||||
		enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
 | 
			
		||||
	m_GdipGraphics->SetPixelOffsetMode(
 | 
			
		||||
		enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetTextAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	// TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE?
 | 
			
		||||
	m_TextAntiAliasing = enable;
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->SetTextAntialiasMode(
 | 
			
		||||
			m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Clear(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->Clear(color);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Target->Clear(ToColorF(color));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	if (!BeginTargetDraw()) return;
 | 
			
		||||
 | 
			
		||||
	Gdiplus::Color color;
 | 
			
		||||
	brush.GetColor(&color);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
 | 
			
		||||
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
 | 
			
		||||
	if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	if (!formatD2D.CreateLayout(
 | 
			
		||||
			str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;
 | 
			
		||||
 | 
			
		||||
	D2D1_POINT_2F drawPosition;
 | 
			
		||||
	drawPosition.x = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_AccurateText)
 | 
			
		||||
		{
 | 
			
		||||
			const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			switch (formatD2D.GetHorizontalAlignment())
 | 
			
		||||
			{
 | 
			
		||||
			case HorizontalAlignment::Left: return rect.X + xOffset;
 | 
			
		||||
			case HorizontalAlignment::Right: return rect.X - xOffset;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return rect.X;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
	drawPosition.y = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility.
 | 
			
		||||
		float yPos = rect.Y - formatD2D.m_LineGap;
 | 
			
		||||
		switch (formatD2D.GetVerticalAlignment())
 | 
			
		||||
		{
 | 
			
		||||
		case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
 | 
			
		||||
		case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return yPos;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		D2D1_RECT_F clipRect = ToRectF(rect);
 | 
			
		||||
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			const D2D1_LAYER_PARAMETERS layerParams =
 | 
			
		||||
				D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
			m_Target->PushLayer(layerParams, nullptr);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopAxisAlignedClip();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopLayer();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText);
 | 
			
		||||
	rect.Width = metrics.width;
 | 
			
		||||
	rect.Height = metrics.height;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
 | 
			
		||||
{
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);
 | 
			
		||||
 | 
			
		||||
	const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width);
 | 
			
		||||
	rect.Width = metrics.width;
 | 
			
		||||
	rect.Height = metrics.height;
 | 
			
		||||
	lines = metrics.lineCount;
 | 
			
		||||
 | 
			
		||||
	if (rect.Height > 0.0f)
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ draws multi-line text even though the last line may be clipped slightly at the
 | 
			
		||||
		// bottom. This is a workaround to emulate that behaviour.
 | 
			
		||||
		rect.Height += 1.0f;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility: Zero height text has no visible lines.
 | 
			
		||||
		lines = 0;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
 | 
			
		||||
{
 | 
			
		||||
	if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height)
 | 
			
		||||
	{
 | 
			
		||||
		// If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path
 | 
			
		||||
		// to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on
 | 
			
		||||
		// scaled bitmaps.
 | 
			
		||||
		EndTargetDraw();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->DrawImage(
 | 
			
		||||
			bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are
 | 
			
		||||
	// not using a hardware accelerated render target. Nevertheless, we will use it to avoid
 | 
			
		||||
	// the EndDraw() call needed for GDI+ drawing.
 | 
			
		||||
	Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP();
 | 
			
		||||
	Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
 | 
			
		||||
	Gdiplus::Status status = bitmap->LockBits(
 | 
			
		||||
		&lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData());
 | 
			
		||||
	if (status == Gdiplus::Ok)
 | 
			
		||||
	{
 | 
			
		||||
		D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(
 | 
			
		||||
			D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
 | 
			
		||||
		Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dBitmap;
 | 
			
		||||
		HRESULT hr = m_Target->CreateSharedBitmap(
 | 
			
		||||
			__uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf());
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			auto rDst = ToRectF(dstRect);
 | 
			
		||||
			auto rSrc = ToRectF(srcRect);
 | 
			
		||||
			m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// D2D will still use the pixel data after this call (at the next Flush() or EndDraw()).
 | 
			
		||||
		bitmap->UnlockBits(bitmapLock->GetBitmapData());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bitmapLock->Release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->FillRectangle(&brush, rect);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Gdiplus::Color color;
 | 
			
		||||
	brush.GetColor(&color);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
 | 
			
		||||
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->FillRectangle(ToRectF(rect), solidBrush.Get());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "Util/DWriteFontCollectionLoader.h"
 | 
			
		||||
#include "Util/DWriteHelpers.h"
 | 
			
		||||
#include "Util/WICBitmapLockGDIP.h"
 | 
			
		||||
#include "../../Library/Litestep.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
D2D1_COLOR_F ToColorF(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
UINT CanvasD2D::c_Instances = 0;
 | 
			
		||||
Microsoft::WRL::ComPtr<ID2D1Factory1> CanvasD2D::c_D2DFactory;
 | 
			
		||||
Microsoft::WRL::ComPtr<IDWriteFactory1> CanvasD2D::c_DWFactory;
 | 
			
		||||
Microsoft::WRL::ComPtr<IDWriteGdiInterop> CanvasD2D::c_DWGDIInterop;
 | 
			
		||||
Microsoft::WRL::ComPtr<IWICImagingFactory> CanvasD2D::c_WICFactory;
 | 
			
		||||
 | 
			
		||||
CanvasD2D::CanvasD2D() : Canvas(),
 | 
			
		||||
	m_Bitmap(),
 | 
			
		||||
	m_TextAntiAliasing(false),
 | 
			
		||||
	m_CanUseAxisAlignClip(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CanvasD2D::~CanvasD2D()
 | 
			
		||||
{
 | 
			
		||||
	Finalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::Initialize()
 | 
			
		||||
{
 | 
			
		||||
	++c_Instances;
 | 
			
		||||
	if (c_Instances == 1)
 | 
			
		||||
	{
 | 
			
		||||
		if (!IsWindows7OrGreater()) return false;
 | 
			
		||||
 | 
			
		||||
		D2D1_FACTORY_OPTIONS fo = {};
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
		fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		HRESULT hr = D2D1CreateFactory(
 | 
			
		||||
			D2D1_FACTORY_TYPE_SINGLE_THREADED,
 | 
			
		||||
			fo,
 | 
			
		||||
			c_D2DFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = CoCreateInstance(
 | 
			
		||||
			CLSID_WICImagingFactory,
 | 
			
		||||
			nullptr,
 | 
			
		||||
			CLSCTX_INPROC_SERVER,
 | 
			
		||||
			IID_IWICImagingFactory,
 | 
			
		||||
			(LPVOID*)c_WICFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = DWriteCreateFactory(
 | 
			
		||||
			DWRITE_FACTORY_TYPE_SHARED,
 | 
			
		||||
			__uuidof(c_DWFactory),
 | 
			
		||||
			(IUnknown**)c_DWFactory.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
 | 
			
		||||
		hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
 | 
			
		||||
		if (FAILED(hr)) return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Finalize()
 | 
			
		||||
{
 | 
			
		||||
	--c_Instances;
 | 
			
		||||
	if (c_Instances == 0)
 | 
			
		||||
	{
 | 
			
		||||
		c_D2DFactory.Reset();
 | 
			
		||||
		c_WICFactory.Reset();
 | 
			
		||||
		c_DWGDIInterop.Reset();
 | 
			
		||||
 | 
			
		||||
		if (c_DWFactory)
 | 
			
		||||
		{
 | 
			
		||||
			c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
 | 
			
		||||
			c_DWFactory.Reset();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	__super::Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	m_Target.Reset();
 | 
			
		||||
 | 
			
		||||
	m_Bitmap.Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData()));
 | 
			
		||||
	m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::BeginDraw()
 | 
			
		||||
{
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndDraw()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::BeginTargetDraw()
 | 
			
		||||
{
 | 
			
		||||
	if (m_Target) return true;
 | 
			
		||||
 | 
			
		||||
	const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat(
 | 
			
		||||
		DXGI_FORMAT_B8G8R8A8_UNORM,
 | 
			
		||||
		D2D1_ALPHA_MODE_PREMULTIPLIED);
 | 
			
		||||
 | 
			
		||||
	const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
 | 
			
		||||
		D2D1_RENDER_TARGET_TYPE_DEFAULT,
 | 
			
		||||
		format,
 | 
			
		||||
		0.0f,	// Default DPI
 | 
			
		||||
		0.0f,	// Default DPI
 | 
			
		||||
		D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
 | 
			
		||||
 | 
			
		||||
	// A new Direct2D render target must be created for each sequence of Direct2D draw operations
 | 
			
		||||
	// since we use GDI+ to render to the same pixel data. Without creating a new render target
 | 
			
		||||
	// each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is
 | 
			
		||||
	// unaware of the changes made by GDI+. By creating a new render target and then releasing it
 | 
			
		||||
	// before the next GDI+ draw operations, we ensure that the pixel data result is as expected
 | 
			
		||||
	// Once GDI+ drawing is no longer needed, we change to recreate the render target only when the
 | 
			
		||||
	// bitmap size is changed.
 | 
			
		||||
	HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		SetTextAntiAliasing(m_TextAntiAliasing);
 | 
			
		||||
 | 
			
		||||
		m_Target->BeginDraw();
 | 
			
		||||
 | 
			
		||||
		// Apply any transforms that occurred before creation of |m_Target|.
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndTargetDraw()
 | 
			
		||||
{
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->EndDraw();
 | 
			
		||||
		m_Target.Reset();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
	return *m_GdipGraphics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::EndGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HDC CanvasD2D::GetDC()
 | 
			
		||||
{
 | 
			
		||||
	EndTargetDraw();
 | 
			
		||||
 | 
			
		||||
	HDC dcMemory = CreateCompatibleDC(nullptr);
 | 
			
		||||
	SelectObject(dcMemory, m_Bitmap.GetHandle());
 | 
			
		||||
	return dcMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::ReleaseDC(HDC dc)
 | 
			
		||||
{
 | 
			
		||||
	DeleteDC(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::IsTransparentPixel(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false;
 | 
			
		||||
 | 
			
		||||
	bool transparent = true;
 | 
			
		||||
 | 
			
		||||
	DWORD* data = (DWORD*)m_Bitmap.GetData();
 | 
			
		||||
	if (data)
 | 
			
		||||
	{
 | 
			
		||||
		DWORD pixel = data[y * m_W + x];  // Top-down DIB.
 | 
			
		||||
		transparent = (pixel & 0xFF000000) != 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::UpdateTargetTransform()
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::Matrix gdipMatrix;
 | 
			
		||||
	m_GdipGraphics->GetTransform(&gdipMatrix);
 | 
			
		||||
 | 
			
		||||
	D2D1_MATRIX_3X2_F d2dMatrix;
 | 
			
		||||
	gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix);
 | 
			
		||||
 | 
			
		||||
	m_Target->SetTransform(d2dMatrix);
 | 
			
		||||
	m_CanUseAxisAlignClip =
 | 
			
		||||
		d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f &&
 | 
			
		||||
		d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->SetTransform(&matrix);
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::ResetTransform()
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->ResetTransform();
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->SetTransform(D2D1::Matrix3x2F::Identity());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy)
 | 
			
		||||
{
 | 
			
		||||
	m_GdipGraphics->TranslateTransform(x, y);
 | 
			
		||||
	m_GdipGraphics->RotateTransform(angle);
 | 
			
		||||
	m_GdipGraphics->TranslateTransform(dx, dy);
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		UpdateTargetTransform();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	// TODO: Set m_Target aliasing?
 | 
			
		||||
	m_GdipGraphics->SetSmoothingMode(
 | 
			
		||||
		enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
 | 
			
		||||
	m_GdipGraphics->SetPixelOffsetMode(
 | 
			
		||||
		enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::SetTextAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	// TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE?
 | 
			
		||||
	m_TextAntiAliasing = enable;
 | 
			
		||||
 | 
			
		||||
	if (m_Target)
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->SetTextAntialiasMode(
 | 
			
		||||
			m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::Clear(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->Clear(color);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Target->Clear(ToColorF(color));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	if (!BeginTargetDraw()) return;
 | 
			
		||||
 | 
			
		||||
	Gdiplus::Color color;
 | 
			
		||||
	brush.GetColor(&color);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
 | 
			
		||||
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
 | 
			
		||||
	if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	if (!formatD2D.CreateLayout(
 | 
			
		||||
			str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;
 | 
			
		||||
 | 
			
		||||
	D2D1_POINT_2F drawPosition;
 | 
			
		||||
	drawPosition.x = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_AccurateText)
 | 
			
		||||
		{
 | 
			
		||||
			const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			switch (formatD2D.GetHorizontalAlignment())
 | 
			
		||||
			{
 | 
			
		||||
			case HorizontalAlignment::Left: return rect.X + xOffset;
 | 
			
		||||
			case HorizontalAlignment::Right: return rect.X - xOffset;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return rect.X;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
	drawPosition.y = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility.
 | 
			
		||||
		float yPos = rect.Y - formatD2D.m_LineGap;
 | 
			
		||||
		switch (formatD2D.GetVerticalAlignment())
 | 
			
		||||
		{
 | 
			
		||||
		case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
 | 
			
		||||
		case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return yPos;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		D2D1_RECT_F clipRect = ToRectF(rect);
 | 
			
		||||
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			const D2D1_LAYER_PARAMETERS layerParams =
 | 
			
		||||
				D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
			m_Target->PushLayer(layerParams, nullptr);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopAxisAlignedClip();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopLayer();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText);
 | 
			
		||||
	rect.Width = metrics.width;
 | 
			
		||||
	rect.Height = metrics.height;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
 | 
			
		||||
{
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);
 | 
			
		||||
 | 
			
		||||
	const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width);
 | 
			
		||||
	rect.Width = metrics.width;
 | 
			
		||||
	rect.Height = metrics.height;
 | 
			
		||||
	lines = metrics.lineCount;
 | 
			
		||||
 | 
			
		||||
	if (rect.Height > 0.0f)
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ draws multi-line text even though the last line may be clipped slightly at the
 | 
			
		||||
		// bottom. This is a workaround to emulate that behaviour.
 | 
			
		||||
		rect.Height += 1.0f;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility: Zero height text has no visible lines.
 | 
			
		||||
		lines = 0;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
 | 
			
		||||
{
 | 
			
		||||
	if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height)
 | 
			
		||||
	{
 | 
			
		||||
		// If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path
 | 
			
		||||
		// to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on
 | 
			
		||||
		// scaled bitmaps.
 | 
			
		||||
		EndTargetDraw();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->DrawImage(
 | 
			
		||||
			bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are
 | 
			
		||||
	// not using a hardware accelerated render target. Nevertheless, we will use it to avoid
 | 
			
		||||
	// the EndDraw() call needed for GDI+ drawing.
 | 
			
		||||
	Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP();
 | 
			
		||||
	Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
 | 
			
		||||
	Gdiplus::Status status = bitmap->LockBits(
 | 
			
		||||
		&lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData());
 | 
			
		||||
	if (status == Gdiplus::Ok)
 | 
			
		||||
	{
 | 
			
		||||
		D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(
 | 
			
		||||
			D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
 | 
			
		||||
		Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dBitmap;
 | 
			
		||||
		HRESULT hr = m_Target->CreateSharedBitmap(
 | 
			
		||||
			__uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf());
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			auto rDst = ToRectF(dstRect);
 | 
			
		||||
			auto rSrc = ToRectF(srcRect);
 | 
			
		||||
			m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// D2D will still use the pixel data after this call (at the next Flush() or EndDraw()).
 | 
			
		||||
		bitmap->UnlockBits(bitmapLock->GetBitmapData());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bitmapLock->Release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Target)  // Use GDI+ if D2D render target has not been created.
 | 
			
		||||
	{
 | 
			
		||||
		m_GdipGraphics->FillRectangle(&brush, rect);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Gdiplus::Color color;
 | 
			
		||||
	brush.GetColor(&color);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
 | 
			
		||||
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		m_Target->FillRectangle(ToRectF(rect), solidBrush.Get());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,118 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVASD2D_H_
 | 
			
		||||
#define RM_GFX_CANVASD2D_H_
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "FontCollectionD2D.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "Util/WICBitmapDIB.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
#include <d2d1_1.h>
 | 
			
		||||
#include <d2d1helper.h>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
#include <wrl/client.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a Direct2D/DirectWrite implementation of Canvas.
 | 
			
		||||
class CanvasD2D : public Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static bool Initialize();
 | 
			
		||||
	static void Finalize();
 | 
			
		||||
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	virtual bool BeginDraw();
 | 
			
		||||
	virtual void EndDraw();
 | 
			
		||||
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() override;
 | 
			
		||||
	virtual void EndGdiplusContext() override;
 | 
			
		||||
 | 
			
		||||
	virtual HDC GetDC() override;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) override;
 | 
			
		||||
	
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); }
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
 | 
			
		||||
	virtual void ResetTransform() override;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) override;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) override;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class Canvas;
 | 
			
		||||
	friend class FontCollectionD2D;
 | 
			
		||||
	friend class TextFormatD2D;
 | 
			
		||||
 | 
			
		||||
	CanvasD2D();
 | 
			
		||||
	~CanvasD2D();
 | 
			
		||||
 | 
			
		||||
	CanvasD2D(const CanvasD2D& other) = delete;
 | 
			
		||||
	CanvasD2D& operator=(CanvasD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	bool BeginTargetDraw();
 | 
			
		||||
	void EndTargetDraw();
 | 
			
		||||
 | 
			
		||||
	// Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|.
 | 
			
		||||
	void UpdateTargetTransform();
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target;
 | 
			
		||||
 | 
			
		||||
	// Underlying pixel data shared by both m_Target and m_GdipBitmap.
 | 
			
		||||
	Util::WICBitmapDIB m_Bitmap;
 | 
			
		||||
 | 
			
		||||
	// GDI+ objects that share the pixel data of m_Bitmap.
 | 
			
		||||
	std::unique_ptr<Gdiplus::Graphics> m_GdipGraphics;
 | 
			
		||||
	std::unique_ptr<Gdiplus::Bitmap> m_GdipBitmap;
 | 
			
		||||
 | 
			
		||||
	bool m_TextAntiAliasing;
 | 
			
		||||
 | 
			
		||||
	// |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used.
 | 
			
		||||
	bool m_CanUseAxisAlignClip;
 | 
			
		||||
 | 
			
		||||
	static UINT c_Instances;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IDWriteGdiInterop> c_DWGDIInterop;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IWICImagingFactory> c_WICFactory;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVASD2D_H_
 | 
			
		||||
#define RM_GFX_CANVASD2D_H_
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "FontCollectionD2D.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "Util/WICBitmapDIB.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
#include <d2d1_1.h>
 | 
			
		||||
#include <d2d1helper.h>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
#include <wrl/client.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a Direct2D/DirectWrite implementation of Canvas.
 | 
			
		||||
class CanvasD2D : public Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static bool Initialize();
 | 
			
		||||
	static void Finalize();
 | 
			
		||||
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	virtual bool BeginDraw();
 | 
			
		||||
	virtual void EndDraw();
 | 
			
		||||
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() override;
 | 
			
		||||
	virtual void EndGdiplusContext() override;
 | 
			
		||||
 | 
			
		||||
	virtual HDC GetDC() override;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) override;
 | 
			
		||||
	
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); }
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
 | 
			
		||||
	virtual void ResetTransform() override;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) override;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) override;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class Canvas;
 | 
			
		||||
	friend class FontCollectionD2D;
 | 
			
		||||
	friend class TextFormatD2D;
 | 
			
		||||
 | 
			
		||||
	CanvasD2D();
 | 
			
		||||
	~CanvasD2D();
 | 
			
		||||
 | 
			
		||||
	CanvasD2D(const CanvasD2D& other) = delete;
 | 
			
		||||
	CanvasD2D& operator=(CanvasD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	bool BeginTargetDraw();
 | 
			
		||||
	void EndTargetDraw();
 | 
			
		||||
 | 
			
		||||
	// Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|.
 | 
			
		||||
	void UpdateTargetTransform();
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target;
 | 
			
		||||
 | 
			
		||||
	// Underlying pixel data shared by both m_Target and m_GdipBitmap.
 | 
			
		||||
	Util::WICBitmapDIB m_Bitmap;
 | 
			
		||||
 | 
			
		||||
	// GDI+ objects that share the pixel data of m_Bitmap.
 | 
			
		||||
	std::unique_ptr<Gdiplus::Graphics> m_GdipGraphics;
 | 
			
		||||
	std::unique_ptr<Gdiplus::Bitmap> m_GdipBitmap;
 | 
			
		||||
 | 
			
		||||
	bool m_TextAntiAliasing;
 | 
			
		||||
 | 
			
		||||
	// |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used.
 | 
			
		||||
	bool m_CanUseAxisAlignClip;
 | 
			
		||||
 | 
			
		||||
	static UINT c_Instances;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IDWriteGdiInterop> c_DWGDIInterop;
 | 
			
		||||
	static Microsoft::WRL::ComPtr<IWICImagingFactory> c_WICFactory;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,242 +1,242 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "CanvasGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
CanvasGDIP::CanvasGDIP() : Canvas(),
 | 
			
		||||
	m_DIBSection(),
 | 
			
		||||
	m_DIBSectionPixels()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CanvasGDIP::~CanvasGDIP()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSection)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSection);
 | 
			
		||||
		m_DIBSection = nullptr;
 | 
			
		||||
		m_DIBSectionPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	__super::Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	Dispose();
 | 
			
		||||
 | 
			
		||||
	BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
 | 
			
		||||
	bh.bV4Width = w;
 | 
			
		||||
	bh.bV4Height = -h;	// Top-down DIB
 | 
			
		||||
	bh.bV4Planes = 1;
 | 
			
		||||
	bh.bV4BitCount = 32;
 | 
			
		||||
	bh.bV4V4Compression = BI_BITFIELDS;
 | 
			
		||||
	bh.bV4RedMask = 0x00FF0000;
 | 
			
		||||
	bh.bV4GreenMask = 0x0000FF00;
 | 
			
		||||
	bh.bV4BlueMask = 0x000000FF;
 | 
			
		||||
	bh.bV4AlphaMask = 0xFF000000;
 | 
			
		||||
 | 
			
		||||
	m_DIBSection = CreateDIBSection(
 | 
			
		||||
		nullptr,
 | 
			
		||||
		(BITMAPINFO*)&bh,
 | 
			
		||||
		DIB_RGB_COLORS,
 | 
			
		||||
		(void**)&m_DIBSectionPixels,
 | 
			
		||||
		nullptr,
 | 
			
		||||
		0);
 | 
			
		||||
 | 
			
		||||
	// Create GDI+ bitmap from the DIBSection pixels
 | 
			
		||||
	m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels));
 | 
			
		||||
	m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::BeginDraw()
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault);
 | 
			
		||||
	m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::EndDraw()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
	return *m_Graphics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::EndGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HDC CanvasGDIP::GetDC()
 | 
			
		||||
{
 | 
			
		||||
	HDC dcMemory = CreateCompatibleDC(nullptr);
 | 
			
		||||
	SelectObject(dcMemory, m_DIBSection);
 | 
			
		||||
	return dcMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::ReleaseDC(HDC dc)
 | 
			
		||||
{
 | 
			
		||||
	DeleteDC(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::IsTransparentPixel(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H)
 | 
			
		||||
	{
 | 
			
		||||
		DWORD pixel = m_DIBSectionPixels[y * m_W + x];  // top-down DIB
 | 
			
		||||
		return ((pixel & 0xFF000000) != 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetTransform(&matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::ResetTransform()
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->ResetTransform();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->TranslateTransform(x, y);
 | 
			
		||||
	m_Graphics->RotateTransform(angle);
 | 
			
		||||
	m_Graphics->TranslateTransform(dx, dy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetSmoothingMode(
 | 
			
		||||
		enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
 | 
			
		||||
	m_Graphics->SetPixelOffsetMode(
 | 
			
		||||
		enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetTextAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetTextRenderingHint(
 | 
			
		||||
		enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Clear(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	if (color.GetValue() == 0x00000000)
 | 
			
		||||
	{
 | 
			
		||||
		memset(m_DIBSectionPixels, 0, m_W * m_H * 4);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		m_Graphics->Clear(color);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Graphics->DrawString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &brush);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Gdiplus::Status status = m_Graphics->MeasureString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &rect);
 | 
			
		||||
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	// Set trimming and format temporarily.
 | 
			
		||||
	const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming();
 | 
			
		||||
	stringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
 | 
			
		||||
 | 
			
		||||
	const INT stringFormatFlags = stringFormat.GetFormatFlags();
 | 
			
		||||
	stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip);
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	INT linesFilled = 0;
 | 
			
		||||
	const Gdiplus::Status status = m_Graphics->MeasureString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled);
 | 
			
		||||
	lines = linesFilled;
 | 
			
		||||
 | 
			
		||||
	// Restore old options.
 | 
			
		||||
	stringFormat.SetTrimming(stringTrimming);
 | 
			
		||||
	stringFormat.SetFormatFlags(stringFormatFlags);
 | 
			
		||||
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->FillRectangle(&brush, rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "CanvasGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
CanvasGDIP::CanvasGDIP() : Canvas(),
 | 
			
		||||
	m_DIBSection(),
 | 
			
		||||
	m_DIBSectionPixels()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CanvasGDIP::~CanvasGDIP()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSection)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSection);
 | 
			
		||||
		m_DIBSection = nullptr;
 | 
			
		||||
		m_DIBSectionPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Resize(int w, int h)
 | 
			
		||||
{
 | 
			
		||||
	__super::Resize(w, h);
 | 
			
		||||
 | 
			
		||||
	Dispose();
 | 
			
		||||
 | 
			
		||||
	BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
 | 
			
		||||
	bh.bV4Width = w;
 | 
			
		||||
	bh.bV4Height = -h;	// Top-down DIB
 | 
			
		||||
	bh.bV4Planes = 1;
 | 
			
		||||
	bh.bV4BitCount = 32;
 | 
			
		||||
	bh.bV4V4Compression = BI_BITFIELDS;
 | 
			
		||||
	bh.bV4RedMask = 0x00FF0000;
 | 
			
		||||
	bh.bV4GreenMask = 0x0000FF00;
 | 
			
		||||
	bh.bV4BlueMask = 0x000000FF;
 | 
			
		||||
	bh.bV4AlphaMask = 0xFF000000;
 | 
			
		||||
 | 
			
		||||
	m_DIBSection = CreateDIBSection(
 | 
			
		||||
		nullptr,
 | 
			
		||||
		(BITMAPINFO*)&bh,
 | 
			
		||||
		DIB_RGB_COLORS,
 | 
			
		||||
		(void**)&m_DIBSectionPixels,
 | 
			
		||||
		nullptr,
 | 
			
		||||
		0);
 | 
			
		||||
 | 
			
		||||
	// Create GDI+ bitmap from the DIBSection pixels
 | 
			
		||||
	m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels));
 | 
			
		||||
	m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::BeginDraw()
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault);
 | 
			
		||||
	m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::EndDraw()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
	return *m_Graphics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::EndGdiplusContext()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HDC CanvasGDIP::GetDC()
 | 
			
		||||
{
 | 
			
		||||
	HDC dcMemory = CreateCompatibleDC(nullptr);
 | 
			
		||||
	SelectObject(dcMemory, m_DIBSection);
 | 
			
		||||
	return dcMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::ReleaseDC(HDC dc)
 | 
			
		||||
{
 | 
			
		||||
	DeleteDC(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::IsTransparentPixel(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H)
 | 
			
		||||
	{
 | 
			
		||||
		DWORD pixel = m_DIBSectionPixels[y * m_W + x];  // top-down DIB
 | 
			
		||||
		return ((pixel & 0xFF000000) != 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetTransform(&matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::ResetTransform()
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->ResetTransform();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->TranslateTransform(x, y);
 | 
			
		||||
	m_Graphics->RotateTransform(angle);
 | 
			
		||||
	m_Graphics->TranslateTransform(dx, dy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetSmoothingMode(
 | 
			
		||||
		enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
 | 
			
		||||
	m_Graphics->SetPixelOffsetMode(
 | 
			
		||||
		enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::SetTextAntiAliasing(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->SetTextRenderingHint(
 | 
			
		||||
		enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::Clear(const Gdiplus::Color& color)
 | 
			
		||||
{
 | 
			
		||||
	if (color.GetValue() == 0x00000000)
 | 
			
		||||
	{
 | 
			
		||||
		memset(m_DIBSectionPixels, 0, m_W * m_H * 4);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		m_Graphics->Clear(color);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Graphics->DrawString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &brush);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Gdiplus::Status status = m_Graphics->MeasureString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &rect);
 | 
			
		||||
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
 | 
			
		||||
{
 | 
			
		||||
	Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
 | 
			
		||||
	Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
 | 
			
		||||
 | 
			
		||||
	// Set trimming and format temporarily.
 | 
			
		||||
	const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming();
 | 
			
		||||
	stringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
 | 
			
		||||
 | 
			
		||||
	const INT stringFormatFlags = stringFormat.GetFormatFlags();
 | 
			
		||||
	stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip);
 | 
			
		||||
 | 
			
		||||
	if (m_AccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		tStringFormat.SetTrimming(stringFormat.GetTrimming());
 | 
			
		||||
		tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
 | 
			
		||||
		tStringFormat.SetAlignment(stringFormat.GetAlignment());
 | 
			
		||||
		tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	INT linesFilled = 0;
 | 
			
		||||
	const Gdiplus::Status status = m_Graphics->MeasureString(
 | 
			
		||||
		str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
 | 
			
		||||
		m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled);
 | 
			
		||||
	lines = linesFilled;
 | 
			
		||||
 | 
			
		||||
	// Restore old options.
 | 
			
		||||
	stringFormat.SetTrimming(stringTrimming);
 | 
			
		||||
	stringFormat.SetFormatFlags(stringFormatFlags);
 | 
			
		||||
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
 | 
			
		||||
{
 | 
			
		||||
	m_Graphics->FillRectangle(&brush, rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,90 +1,90 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVASGDIP_H_
 | 
			
		||||
#define RM_GFX_CANVASGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
#include "TextFormatGDIP.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a GDI+ implementation of Canvas.
 | 
			
		||||
class CanvasGDIP : public Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	virtual bool BeginDraw();
 | 
			
		||||
	virtual void EndDraw();
 | 
			
		||||
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() override;
 | 
			
		||||
	virtual void EndGdiplusContext() override;
 | 
			
		||||
 | 
			
		||||
	virtual HDC GetDC() override;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) override;
 | 
			
		||||
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); }
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
 | 
			
		||||
	virtual void ResetTransform() override;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) override;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) override;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class Canvas;
 | 
			
		||||
 | 
			
		||||
	CanvasGDIP();
 | 
			
		||||
	~CanvasGDIP();
 | 
			
		||||
 | 
			
		||||
	CanvasGDIP(const CanvasGDIP& other) = delete;
 | 
			
		||||
	CanvasGDIP& operator=(CanvasGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Gdiplus::Graphics> m_Graphics;
 | 
			
		||||
	std::unique_ptr<Gdiplus::Bitmap> m_Bitmap;
 | 
			
		||||
	HBITMAP m_DIBSection;
 | 
			
		||||
	LPDWORD m_DIBSectionPixels;
 | 
			
		||||
 | 
			
		||||
	//static ULONG_PTR c_GdiToken;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_CANVASGDIP_H_
 | 
			
		||||
#define RM_GFX_CANVASGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
#include "TextFormatGDIP.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a GDI+ implementation of Canvas.
 | 
			
		||||
class CanvasGDIP : public Canvas
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual void Resize(int w, int h);
 | 
			
		||||
 | 
			
		||||
	virtual bool BeginDraw();
 | 
			
		||||
	virtual void EndDraw();
 | 
			
		||||
 | 
			
		||||
	virtual Gdiplus::Graphics& BeginGdiplusContext() override;
 | 
			
		||||
	virtual void EndGdiplusContext() override;
 | 
			
		||||
 | 
			
		||||
	virtual HDC GetDC() override;
 | 
			
		||||
	virtual void ReleaseDC(HDC dc) override;
 | 
			
		||||
 | 
			
		||||
	virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); }
 | 
			
		||||
	virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool IsTransparentPixel(int x, int y) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
 | 
			
		||||
	virtual void ResetTransform() override;
 | 
			
		||||
	virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetAntiAliasing(bool enable) override;
 | 
			
		||||
	virtual void SetTextAntiAliasing(bool enable) override;
 | 
			
		||||
 | 
			
		||||
	virtual void Clear(const Gdiplus::Color& color) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
	virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
 | 
			
		||||
	virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
 | 
			
		||||
 | 
			
		||||
	virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
 | 
			
		||||
 | 
			
		||||
	virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class Canvas;
 | 
			
		||||
 | 
			
		||||
	CanvasGDIP();
 | 
			
		||||
	~CanvasGDIP();
 | 
			
		||||
 | 
			
		||||
	CanvasGDIP(const CanvasGDIP& other) = delete;
 | 
			
		||||
	CanvasGDIP& operator=(CanvasGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Gdiplus::Graphics> m_Graphics;
 | 
			
		||||
	std::unique_ptr<Gdiplus::Bitmap> m_Bitmap;
 | 
			
		||||
	HBITMAP m_DIBSection;
 | 
			
		||||
	LPDWORD m_DIBSectionPixels;
 | 
			
		||||
 | 
			
		||||
	//static ULONG_PTR c_GdiToken;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,32 +1,32 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollection::FontCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollection::~FontCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollection::FontCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollection::~FontCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,43 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTION_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTION_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Interface for a collection of fonts that may or may not be installed on the system.
 | 
			
		||||
class __declspec(novtable) FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollection();
 | 
			
		||||
 | 
			
		||||
	FontCollection(const FontCollection& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Adds a file to the collection. Returns true if the file was successfully added.
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollection();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTION_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTION_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Interface for a collection of fonts that may or may not be installed on the system.
 | 
			
		||||
class __declspec(novtable) FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollection();
 | 
			
		||||
 | 
			
		||||
	FontCollection(const FontCollection& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Adds a file to the collection. Returns true if the file was successfully added.
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollection();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,79 +1,79 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollectionD2D.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "Util/DWriteFontCollectionLoader.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollectionD2D::FontCollectionD2D() : FontCollection(),
 | 
			
		||||
	m_Collection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollectionD2D::~FontCollectionD2D()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FontCollectionD2D::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	for (IDWriteFontFile* fileReference : m_FileReferences)
 | 
			
		||||
	{
 | 
			
		||||
		fileReference->Release();
 | 
			
		||||
	}
 | 
			
		||||
	m_FileReferences.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionD2D::InitializeCollection()
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Collection)
 | 
			
		||||
	{
 | 
			
		||||
		auto loader = Util::DWriteFontCollectionLoader::GetInstance();
 | 
			
		||||
		CanvasD2D::c_DWFactory->CreateCustomFontCollection(
 | 
			
		||||
			loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_Collection != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionD2D::AddFile(const WCHAR* file)
 | 
			
		||||
{
 | 
			
		||||
	// If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to
 | 
			
		||||
	// an existing collection. The collection will be recreated on the next call to
 | 
			
		||||
	// InitializeCollection().
 | 
			
		||||
	if (m_Collection)
 | 
			
		||||
	{
 | 
			
		||||
		m_Collection->Release();
 | 
			
		||||
		m_Collection = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	IDWriteFontFile* fileReference;
 | 
			
		||||
	HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		m_FileReferences.push_back(fileReference);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollectionD2D.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "Util/DWriteFontCollectionLoader.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollectionD2D::FontCollectionD2D() : FontCollection(),
 | 
			
		||||
	m_Collection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollectionD2D::~FontCollectionD2D()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FontCollectionD2D::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	for (IDWriteFontFile* fileReference : m_FileReferences)
 | 
			
		||||
	{
 | 
			
		||||
		fileReference->Release();
 | 
			
		||||
	}
 | 
			
		||||
	m_FileReferences.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionD2D::InitializeCollection()
 | 
			
		||||
{
 | 
			
		||||
	if (!m_Collection)
 | 
			
		||||
	{
 | 
			
		||||
		auto loader = Util::DWriteFontCollectionLoader::GetInstance();
 | 
			
		||||
		CanvasD2D::c_DWFactory->CreateCustomFontCollection(
 | 
			
		||||
			loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_Collection != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionD2D::AddFile(const WCHAR* file)
 | 
			
		||||
{
 | 
			
		||||
	// If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to
 | 
			
		||||
	// an existing collection. The collection will be recreated on the next call to
 | 
			
		||||
	// InitializeCollection().
 | 
			
		||||
	if (m_Collection)
 | 
			
		||||
	{
 | 
			
		||||
		m_Collection->Release();
 | 
			
		||||
		m_Collection = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	IDWriteFontFile* fileReference;
 | 
			
		||||
	HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		m_FileReferences.push_back(fileReference);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,56 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTIOND2D_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTIOND2D_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D.
 | 
			
		||||
class FontCollectionD2D final : public FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollectionD2D();
 | 
			
		||||
 | 
			
		||||
	FontCollectionD2D(const FontCollectionD2D& other) = delete;
 | 
			
		||||
	FontCollectionD2D& operator=(FontCollectionD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollectionD2D();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasD2D;
 | 
			
		||||
	friend class TextFormatD2D;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	bool InitializeCollection();
 | 
			
		||||
 | 
			
		||||
	std::vector<IDWriteFontFile*> m_FileReferences;
 | 
			
		||||
	IDWriteFontCollection* m_Collection;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTIOND2D_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTIOND2D_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D.
 | 
			
		||||
class FontCollectionD2D final : public FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollectionD2D();
 | 
			
		||||
 | 
			
		||||
	FontCollectionD2D(const FontCollectionD2D& other) = delete;
 | 
			
		||||
	FontCollectionD2D& operator=(FontCollectionD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollectionD2D();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasD2D;
 | 
			
		||||
	friend class TextFormatD2D;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	bool InitializeCollection();
 | 
			
		||||
 | 
			
		||||
	std::vector<IDWriteFontFile*> m_FileReferences;
 | 
			
		||||
	IDWriteFontCollection* m_Collection;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,54 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollectionGDIP::FontCollectionGDIP() : FontCollection(),
 | 
			
		||||
	m_PrivateCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollectionGDIP::~FontCollectionGDIP()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FontCollectionGDIP::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	if (m_PrivateCollection)
 | 
			
		||||
	{
 | 
			
		||||
		delete m_PrivateCollection;
 | 
			
		||||
		m_PrivateCollection = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionGDIP::AddFile(const WCHAR* file)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_PrivateCollection)
 | 
			
		||||
	{
 | 
			
		||||
		m_PrivateCollection = new Gdiplus::PrivateFontCollection();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file);
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
FontCollectionGDIP::FontCollectionGDIP() : FontCollection(),
 | 
			
		||||
	m_PrivateCollection()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FontCollectionGDIP::~FontCollectionGDIP()
 | 
			
		||||
{
 | 
			
		||||
	Dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FontCollectionGDIP::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	if (m_PrivateCollection)
 | 
			
		||||
	{
 | 
			
		||||
		delete m_PrivateCollection;
 | 
			
		||||
		m_PrivateCollection = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FontCollectionGDIP::AddFile(const WCHAR* file)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_PrivateCollection)
 | 
			
		||||
	{
 | 
			
		||||
		m_PrivateCollection = new Gdiplus::PrivateFontCollection();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file);
 | 
			
		||||
	return status == Gdiplus::Ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,55 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTIONGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
 | 
			
		||||
namespace Gdiplus {
 | 
			
		||||
class PrivateFontCollection;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP.
 | 
			
		||||
class FontCollectionGDIP final : public FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollectionGDIP();
 | 
			
		||||
 | 
			
		||||
	FontCollectionGDIP(const FontCollectionGDIP& other) = delete;
 | 
			
		||||
	FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollectionGDIP();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasGDIP;
 | 
			
		||||
	friend class TextFormatGDIP;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	Gdiplus::PrivateFontCollection* m_PrivateCollection;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_
 | 
			
		||||
#define RM_GFX_FONTCOLLECTIONGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "FontCollection.h"
 | 
			
		||||
 | 
			
		||||
namespace Gdiplus {
 | 
			
		||||
class PrivateFontCollection;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP.
 | 
			
		||||
class FontCollectionGDIP final : public FontCollection
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~FontCollectionGDIP();
 | 
			
		||||
 | 
			
		||||
	FontCollectionGDIP(const FontCollectionGDIP& other) = delete;
 | 
			
		||||
	FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool AddFile(const WCHAR* file) override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	FontCollectionGDIP();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasGDIP;
 | 
			
		||||
	friend class TextFormatGDIP;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	Gdiplus::PrivateFontCollection* m_PrivateCollection;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,44 +1,44 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormat::TextFormat() :
 | 
			
		||||
	m_HorizontalAlignment(HorizontalAlignment::Left),
 | 
			
		||||
	m_VerticalAlignment(VerticalAlignment::Top)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormat::~TextFormat()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	m_HorizontalAlignment = alignment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormat::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	m_VerticalAlignment = alignment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormat::TextFormat() :
 | 
			
		||||
	m_HorizontalAlignment(HorizontalAlignment::Left),
 | 
			
		||||
	m_VerticalAlignment(VerticalAlignment::Top)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormat::~TextFormat()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	m_HorizontalAlignment = alignment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormat::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	m_VerticalAlignment = alignment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,80 +1,80 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMAT_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMAT_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
class FontCollection;
 | 
			
		||||
 | 
			
		||||
enum class HorizontalAlignment : BYTE
 | 
			
		||||
{
 | 
			
		||||
	Left,
 | 
			
		||||
	Center,
 | 
			
		||||
	Right
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class VerticalAlignment : BYTE
 | 
			
		||||
{
 | 
			
		||||
	Top,
 | 
			
		||||
	Center,
 | 
			
		||||
	Bottom
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Represents the logical font properties used to format text.
 | 
			
		||||
class __declspec(novtable) TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~TextFormat();
 | 
			
		||||
 | 
			
		||||
	TextFormat(const TextFormat& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Returns true if this TextFormat object is valid for use in draw operations.
 | 
			
		||||
	virtual bool IsInitialized() const = 0;
 | 
			
		||||
 | 
			
		||||
	// Sets the logical properties of the font to use. If the font is not found in the system font
 | 
			
		||||
	// collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr.
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) = 0;
 | 
			
		||||
 | 
			
		||||
	// Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this
 | 
			
		||||
	// TextFormat object will produce clipped text with an ellipsis if the text overflows the
 | 
			
		||||
	// bounding rectangle. 
 | 
			
		||||
	virtual void SetTrimming(bool trim) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment);
 | 
			
		||||
	HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment);
 | 
			
		||||
	VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	TextFormat();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	HorizontalAlignment m_HorizontalAlignment;
 | 
			
		||||
	VerticalAlignment m_VerticalAlignment;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMAT_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMAT_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
class FontCollection;
 | 
			
		||||
 | 
			
		||||
enum class HorizontalAlignment : BYTE
 | 
			
		||||
{
 | 
			
		||||
	Left,
 | 
			
		||||
	Center,
 | 
			
		||||
	Right
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class VerticalAlignment : BYTE
 | 
			
		||||
{
 | 
			
		||||
	Top,
 | 
			
		||||
	Center,
 | 
			
		||||
	Bottom
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Represents the logical font properties used to format text.
 | 
			
		||||
class __declspec(novtable) TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~TextFormat();
 | 
			
		||||
 | 
			
		||||
	TextFormat(const TextFormat& other) = delete;
 | 
			
		||||
 | 
			
		||||
	// Returns true if this TextFormat object is valid for use in draw operations.
 | 
			
		||||
	virtual bool IsInitialized() const = 0;
 | 
			
		||||
 | 
			
		||||
	// Sets the logical properties of the font to use. If the font is not found in the system font
 | 
			
		||||
	// collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr.
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) = 0;
 | 
			
		||||
 | 
			
		||||
	// Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this
 | 
			
		||||
	// TextFormat object will produce clipped text with an ellipsis if the text overflows the
 | 
			
		||||
	// bounding rectangle. 
 | 
			
		||||
	virtual void SetTrimming(bool trim) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment);
 | 
			
		||||
	HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment);
 | 
			
		||||
	VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	TextFormat();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	HorizontalAlignment m_HorizontalAlignment;
 | 
			
		||||
	VerticalAlignment m_VerticalAlignment;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,367 +1,367 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "Util/DWriteHelpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormatD2D::TextFormatD2D() :
 | 
			
		||||
	m_ExtraHeight(),
 | 
			
		||||
	m_LineGap(),
 | 
			
		||||
	m_Trimming()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormatD2D::~TextFormatD2D()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	m_TextFormat.Reset();
 | 
			
		||||
	m_TextLayout.Reset();
 | 
			
		||||
	m_InlineEllipsis.Reset();
 | 
			
		||||
 | 
			
		||||
	m_ExtraHeight = 0.0f;
 | 
			
		||||
	m_LineGap = 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TextFormatD2D::CreateLayout(
 | 
			
		||||
	const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation)
 | 
			
		||||
{
 | 
			
		||||
	bool strChanged = false;
 | 
			
		||||
	if (strLen != m_LastString.length() ||
 | 
			
		||||
		memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		strChanged = true;
 | 
			
		||||
		m_LastString.assign(str, strLen);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The width and height of a DirectWrite layout must be non-negative.
 | 
			
		||||
	maxW = max(0.0f, maxW);
 | 
			
		||||
	maxH = max(0.0f, maxH);
 | 
			
		||||
 | 
			
		||||
	if (m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they
 | 
			
		||||
		// would be clipped. This is arguably a bad 'feature', but some in some cases the height
 | 
			
		||||
		// might be just a pixel or two too small. In order to render those cases correctly (but
 | 
			
		||||
		// still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of
 | 
			
		||||
		// the layout.
 | 
			
		||||
		maxH += 2.0f;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (m_TextLayout && !strChanged)
 | 
			
		||||
	{
 | 
			
		||||
		if (maxW != m_TextLayout->GetMaxWidth())
 | 
			
		||||
		{
 | 
			
		||||
			m_TextLayout->SetMaxWidth(maxW);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (maxH != m_TextLayout->GetMaxHeight())
 | 
			
		||||
		{
 | 
			
		||||
			m_TextLayout->SetMaxHeight(maxH);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		CanvasD2D::c_DWFactory->CreateTextLayout(
 | 
			
		||||
			str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf());
 | 
			
		||||
		if (!m_TextLayout) return false;
 | 
			
		||||
 | 
			
		||||
		if (gdiEmulation)
 | 
			
		||||
		{
 | 
			
		||||
			Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
			m_TextLayout.As(&textLayout1);
 | 
			
		||||
 | 
			
		||||
			const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			const float emOffset = xOffset / 24.0f;
 | 
			
		||||
			const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
			textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		UINT32 lineCount = 0;
 | 
			
		||||
		DWRITE_LINE_METRICS lineMetrics[2];
 | 
			
		||||
		HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			// If only one line is visible, disable wrapping so that as much text as possible is shown
 | 
			
		||||
			// after trimming.
 | 
			
		||||
			// TODO: Fix this for when more than one line is visible.
 | 
			
		||||
			if (lineCount >= 2 &&
 | 
			
		||||
				lineMetrics[0].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].height == 0.0f)
 | 
			
		||||
			{
 | 
			
		||||
				m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetProperties(
 | 
			
		||||
	const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
	const FontCollection* fontCollection)
 | 
			
		||||
{
 | 
			
		||||
	auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
 | 
			
		||||
 | 
			
		||||
	Dispose();
 | 
			
		||||
 | 
			
		||||
	WCHAR dwriteFamilyName[LF_FACESIZE];
 | 
			
		||||
	DWRITE_FONT_WEIGHT dwriteFontWeight =
 | 
			
		||||
		bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR;
 | 
			
		||||
	DWRITE_FONT_STYLE dwriteFontStyle =
 | 
			
		||||
		italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
 | 
			
		||||
	DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL;
 | 
			
		||||
	const float dwriteFontSize = size * (4.0f / 3.0f);
 | 
			
		||||
 | 
			
		||||
	// |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font
 | 
			
		||||
	// using the GDI family name and then create a text format using the DirectWrite family name
 | 
			
		||||
	// obtained from it.
 | 
			
		||||
	HRESULT hr = Util::GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
		CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle,
 | 
			
		||||
		dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		hr = CanvasD2D::c_DWFactory->CreateTextFormat(
 | 
			
		||||
			dwriteFamilyName,
 | 
			
		||||
			nullptr,
 | 
			
		||||
			dwriteFontWeight,
 | 
			
		||||
			dwriteFontStyle,
 | 
			
		||||
			dwriteFontStretch,
 | 
			
		||||
			dwriteFontSize,
 | 
			
		||||
			L"",
 | 
			
		||||
			&m_TextFormat);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (FAILED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFontCollection* dwriteFontCollection = nullptr;
 | 
			
		||||
 | 
			
		||||
		// If |fontFamily| is not in the system collection, use the font collection from
 | 
			
		||||
		// |fontCollectionD2D| if possible.
 | 
			
		||||
		if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) &&
 | 
			
		||||
			(fontCollectionD2D && fontCollectionD2D->InitializeCollection()))
 | 
			
		||||
		{
 | 
			
		||||
			IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
				fontCollectionD2D->m_Collection, fontFamily);
 | 
			
		||||
			if (dwriteFont)
 | 
			
		||||
			{
 | 
			
		||||
				hr = Util::GetFamilyNameFromDWriteFont(
 | 
			
		||||
					dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
				if (SUCCEEDED(hr))
 | 
			
		||||
				{
 | 
			
		||||
					fontFamily = dwriteFamilyName;
 | 
			
		||||
					Util::GetPropertiesFromDWriteFont(
 | 
			
		||||
						dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle,
 | 
			
		||||
						&dwriteFontStretch);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				dwriteFont->Release();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			dwriteFontCollection = fontCollectionD2D->m_Collection;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Fallback in case above fails.
 | 
			
		||||
		hr = CanvasD2D::c_DWFactory->CreateTextFormat(
 | 
			
		||||
			fontFamily,
 | 
			
		||||
			dwriteFontCollection,
 | 
			
		||||
			dwriteFontWeight,
 | 
			
		||||
			dwriteFontStyle,
 | 
			
		||||
			dwriteFontStretch,
 | 
			
		||||
			dwriteFontSize,
 | 
			
		||||
			L"",
 | 
			
		||||
			&m_TextFormat);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		SetHorizontalAlignment(GetHorizontalAlignment());
 | 
			
		||||
		SetVerticalAlignment(GetVerticalAlignment());
 | 
			
		||||
 | 
			
		||||
		// Get the family name to in case CreateTextFormat() fallbacked on some other family name.
 | 
			
		||||
		hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
		if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFontFamily> fontFamily;
 | 
			
		||||
		UINT32 familyNameIndex;
 | 
			
		||||
		BOOL exists;
 | 
			
		||||
		if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) ||
 | 
			
		||||
			FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) ||
 | 
			
		||||
			FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf())))
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFont> font;
 | 
			
		||||
		hr = fontFamily->GetFirstMatchingFont(
 | 
			
		||||
			m_TextFormat->GetFontWeight(),
 | 
			
		||||
			m_TextFormat->GetFontStretch(),
 | 
			
		||||
			m_TextFormat->GetFontStyle(),
 | 
			
		||||
			font.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
		DWRITE_FONT_METRICS fmetrics;
 | 
			
		||||
		font->GetMetrics(&fmetrics);
 | 
			
		||||
 | 
			
		||||
		// GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is
 | 
			
		||||
		// |false|. The bottom padding seems to be based on the font metrics so we can calculate it
 | 
			
		||||
		// once and keep using it regardless of the actual string. In some cases, GDI+ also adds
 | 
			
		||||
		// the line gap to the overall height so we will store it as well.
 | 
			
		||||
		const float pixelsPerDesignUnit =  dwriteFontSize / (float)fmetrics.designUnitsPerEm;
 | 
			
		||||
		m_ExtraHeight =
 | 
			
		||||
			(((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit;
 | 
			
		||||
		m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Dispose();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics(
 | 
			
		||||
	const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth)
 | 
			
		||||
{
 | 
			
		||||
	// GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it.
 | 
			
		||||
	bool strippedLastNewLine = false;
 | 
			
		||||
	if (strLen > 2 && str[strLen - 1] == L'\n')
 | 
			
		||||
	{
 | 
			
		||||
		strippedLastNewLine = true;
 | 
			
		||||
		--strLen;
 | 
			
		||||
 | 
			
		||||
		if (str[strLen - 1] == L'\r')
 | 
			
		||||
		{
 | 
			
		||||
			--strLen;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DWRITE_TEXT_METRICS metrics = {0};
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextLayout> textLayout;
 | 
			
		||||
	HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout(
 | 
			
		||||
		str,
 | 
			
		||||
		strLen,
 | 
			
		||||
		m_TextFormat.Get(),
 | 
			
		||||
		maxWidth,
 | 
			
		||||
		10000,
 | 
			
		||||
		textLayout.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
		if (gdiEmulation)
 | 
			
		||||
		{
 | 
			
		||||
			Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
			textLayout.As(&textLayout1);
 | 
			
		||||
 | 
			
		||||
			const float emOffset = xOffset / 24.0f;
 | 
			
		||||
			const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
			textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		textLayout->GetMetrics(&metrics);
 | 
			
		||||
		if (metrics.width > 0.0f)
 | 
			
		||||
		{
 | 
			
		||||
			if (gdiEmulation)
 | 
			
		||||
			{
 | 
			
		||||
				metrics.width += xOffset * 2;
 | 
			
		||||
				metrics.height += m_ExtraHeight;
 | 
			
		||||
 | 
			
		||||
				// GDI+ compatibility: If the string contains a newline (even if it is the
 | 
			
		||||
				// stripped last character), GDI+ adds the line gap to the overall height.
 | 
			
		||||
				if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr)
 | 
			
		||||
				{
 | 
			
		||||
					metrics.height += m_LineGap;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted
 | 
			
		||||
				// from the overall height if the string does not contain newlines.
 | 
			
		||||
				if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr)
 | 
			
		||||
				{
 | 
			
		||||
					metrics.height -= m_LineGap;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			// GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width
 | 
			
		||||
			// strings.
 | 
			
		||||
			metrics.height = 0.0f;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return metrics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetTrimming(bool trim)
 | 
			
		||||
{
 | 
			
		||||
	m_Trimming = trim;
 | 
			
		||||
	IDWriteInlineObject* inlineObject = nullptr;
 | 
			
		||||
	DWRITE_TRIMMING trimming = {};
 | 
			
		||||
	DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP;
 | 
			
		||||
	if (trim)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_InlineEllipsis)
 | 
			
		||||
		{
 | 
			
		||||
			CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign(
 | 
			
		||||
				m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		inlineObject = m_InlineEllipsis.Get();
 | 
			
		||||
		trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
 | 
			
		||||
		wordWrapping = DWRITE_WORD_WRAPPING_WRAP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_TextFormat->SetTrimming(&trimming, inlineObject);
 | 
			
		||||
	m_TextFormat->SetWordWrapping(wordWrapping);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	__super::SetHorizontalAlignment(alignment);
 | 
			
		||||
 | 
			
		||||
	if (m_TextFormat)
 | 
			
		||||
	{
 | 
			
		||||
		m_TextFormat->SetTextAlignment(
 | 
			
		||||
			(alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING :
 | 
			
		||||
			(alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER :
 | 
			
		||||
			DWRITE_TEXT_ALIGNMENT_TRAILING);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	__super::SetVerticalAlignment(alignment);
 | 
			
		||||
	
 | 
			
		||||
	if (m_TextFormat)
 | 
			
		||||
	{
 | 
			
		||||
		m_TextFormat->SetParagraphAlignment(
 | 
			
		||||
			(alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR :
 | 
			
		||||
			(alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER :
 | 
			
		||||
			DWRITE_PARAGRAPH_ALIGNMENT_FAR);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "CanvasD2D.h"
 | 
			
		||||
#include "Util/DWriteHelpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormatD2D::TextFormatD2D() :
 | 
			
		||||
	m_ExtraHeight(),
 | 
			
		||||
	m_LineGap(),
 | 
			
		||||
	m_Trimming()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormatD2D::~TextFormatD2D()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::Dispose()
 | 
			
		||||
{
 | 
			
		||||
	m_TextFormat.Reset();
 | 
			
		||||
	m_TextLayout.Reset();
 | 
			
		||||
	m_InlineEllipsis.Reset();
 | 
			
		||||
 | 
			
		||||
	m_ExtraHeight = 0.0f;
 | 
			
		||||
	m_LineGap = 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TextFormatD2D::CreateLayout(
 | 
			
		||||
	const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation)
 | 
			
		||||
{
 | 
			
		||||
	bool strChanged = false;
 | 
			
		||||
	if (strLen != m_LastString.length() ||
 | 
			
		||||
		memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		strChanged = true;
 | 
			
		||||
		m_LastString.assign(str, strLen);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The width and height of a DirectWrite layout must be non-negative.
 | 
			
		||||
	maxW = max(0.0f, maxW);
 | 
			
		||||
	maxH = max(0.0f, maxH);
 | 
			
		||||
 | 
			
		||||
	if (m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they
 | 
			
		||||
		// would be clipped. This is arguably a bad 'feature', but some in some cases the height
 | 
			
		||||
		// might be just a pixel or two too small. In order to render those cases correctly (but
 | 
			
		||||
		// still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of
 | 
			
		||||
		// the layout.
 | 
			
		||||
		maxH += 2.0f;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (m_TextLayout && !strChanged)
 | 
			
		||||
	{
 | 
			
		||||
		if (maxW != m_TextLayout->GetMaxWidth())
 | 
			
		||||
		{
 | 
			
		||||
			m_TextLayout->SetMaxWidth(maxW);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (maxH != m_TextLayout->GetMaxHeight())
 | 
			
		||||
		{
 | 
			
		||||
			m_TextLayout->SetMaxHeight(maxH);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		CanvasD2D::c_DWFactory->CreateTextLayout(
 | 
			
		||||
			str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf());
 | 
			
		||||
		if (!m_TextLayout) return false;
 | 
			
		||||
 | 
			
		||||
		if (gdiEmulation)
 | 
			
		||||
		{
 | 
			
		||||
			Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
			m_TextLayout.As(&textLayout1);
 | 
			
		||||
 | 
			
		||||
			const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			const float emOffset = xOffset / 24.0f;
 | 
			
		||||
			const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
			textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		UINT32 lineCount = 0;
 | 
			
		||||
		DWRITE_LINE_METRICS lineMetrics[2];
 | 
			
		||||
		HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			// If only one line is visible, disable wrapping so that as much text as possible is shown
 | 
			
		||||
			// after trimming.
 | 
			
		||||
			// TODO: Fix this for when more than one line is visible.
 | 
			
		||||
			if (lineCount >= 2 &&
 | 
			
		||||
				lineMetrics[0].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].height == 0.0f)
 | 
			
		||||
			{
 | 
			
		||||
				m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetProperties(
 | 
			
		||||
	const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
	const FontCollection* fontCollection)
 | 
			
		||||
{
 | 
			
		||||
	auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
 | 
			
		||||
 | 
			
		||||
	Dispose();
 | 
			
		||||
 | 
			
		||||
	WCHAR dwriteFamilyName[LF_FACESIZE];
 | 
			
		||||
	DWRITE_FONT_WEIGHT dwriteFontWeight =
 | 
			
		||||
		bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR;
 | 
			
		||||
	DWRITE_FONT_STYLE dwriteFontStyle =
 | 
			
		||||
		italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
 | 
			
		||||
	DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL;
 | 
			
		||||
	const float dwriteFontSize = size * (4.0f / 3.0f);
 | 
			
		||||
 | 
			
		||||
	// |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font
 | 
			
		||||
	// using the GDI family name and then create a text format using the DirectWrite family name
 | 
			
		||||
	// obtained from it.
 | 
			
		||||
	HRESULT hr = Util::GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
		CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle,
 | 
			
		||||
		dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		hr = CanvasD2D::c_DWFactory->CreateTextFormat(
 | 
			
		||||
			dwriteFamilyName,
 | 
			
		||||
			nullptr,
 | 
			
		||||
			dwriteFontWeight,
 | 
			
		||||
			dwriteFontStyle,
 | 
			
		||||
			dwriteFontStretch,
 | 
			
		||||
			dwriteFontSize,
 | 
			
		||||
			L"",
 | 
			
		||||
			&m_TextFormat);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (FAILED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFontCollection* dwriteFontCollection = nullptr;
 | 
			
		||||
 | 
			
		||||
		// If |fontFamily| is not in the system collection, use the font collection from
 | 
			
		||||
		// |fontCollectionD2D| if possible.
 | 
			
		||||
		if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) &&
 | 
			
		||||
			(fontCollectionD2D && fontCollectionD2D->InitializeCollection()))
 | 
			
		||||
		{
 | 
			
		||||
			IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
				fontCollectionD2D->m_Collection, fontFamily);
 | 
			
		||||
			if (dwriteFont)
 | 
			
		||||
			{
 | 
			
		||||
				hr = Util::GetFamilyNameFromDWriteFont(
 | 
			
		||||
					dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
				if (SUCCEEDED(hr))
 | 
			
		||||
				{
 | 
			
		||||
					fontFamily = dwriteFamilyName;
 | 
			
		||||
					Util::GetPropertiesFromDWriteFont(
 | 
			
		||||
						dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle,
 | 
			
		||||
						&dwriteFontStretch);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				dwriteFont->Release();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			dwriteFontCollection = fontCollectionD2D->m_Collection;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Fallback in case above fails.
 | 
			
		||||
		hr = CanvasD2D::c_DWFactory->CreateTextFormat(
 | 
			
		||||
			fontFamily,
 | 
			
		||||
			dwriteFontCollection,
 | 
			
		||||
			dwriteFontWeight,
 | 
			
		||||
			dwriteFontStyle,
 | 
			
		||||
			dwriteFontStretch,
 | 
			
		||||
			dwriteFontSize,
 | 
			
		||||
			L"",
 | 
			
		||||
			&m_TextFormat);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		SetHorizontalAlignment(GetHorizontalAlignment());
 | 
			
		||||
		SetVerticalAlignment(GetVerticalAlignment());
 | 
			
		||||
 | 
			
		||||
		// Get the family name to in case CreateTextFormat() fallbacked on some other family name.
 | 
			
		||||
		hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName));
 | 
			
		||||
		if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFontFamily> fontFamily;
 | 
			
		||||
		UINT32 familyNameIndex;
 | 
			
		||||
		BOOL exists;
 | 
			
		||||
		if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) ||
 | 
			
		||||
			FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) ||
 | 
			
		||||
			FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf())))
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Microsoft::WRL::ComPtr<IDWriteFont> font;
 | 
			
		||||
		hr = fontFamily->GetFirstMatchingFont(
 | 
			
		||||
			m_TextFormat->GetFontWeight(),
 | 
			
		||||
			m_TextFormat->GetFontStretch(),
 | 
			
		||||
			m_TextFormat->GetFontStyle(),
 | 
			
		||||
			font.GetAddressOf());
 | 
			
		||||
		if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
		DWRITE_FONT_METRICS fmetrics;
 | 
			
		||||
		font->GetMetrics(&fmetrics);
 | 
			
		||||
 | 
			
		||||
		// GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is
 | 
			
		||||
		// |false|. The bottom padding seems to be based on the font metrics so we can calculate it
 | 
			
		||||
		// once and keep using it regardless of the actual string. In some cases, GDI+ also adds
 | 
			
		||||
		// the line gap to the overall height so we will store it as well.
 | 
			
		||||
		const float pixelsPerDesignUnit =  dwriteFontSize / (float)fmetrics.designUnitsPerEm;
 | 
			
		||||
		m_ExtraHeight =
 | 
			
		||||
			(((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit;
 | 
			
		||||
		m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Dispose();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics(
 | 
			
		||||
	const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth)
 | 
			
		||||
{
 | 
			
		||||
	// GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it.
 | 
			
		||||
	bool strippedLastNewLine = false;
 | 
			
		||||
	if (strLen > 2 && str[strLen - 1] == L'\n')
 | 
			
		||||
	{
 | 
			
		||||
		strippedLastNewLine = true;
 | 
			
		||||
		--strLen;
 | 
			
		||||
 | 
			
		||||
		if (str[strLen - 1] == L'\r')
 | 
			
		||||
		{
 | 
			
		||||
			--strLen;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DWRITE_TEXT_METRICS metrics = {0};
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextLayout> textLayout;
 | 
			
		||||
	HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout(
 | 
			
		||||
		str,
 | 
			
		||||
		strLen,
 | 
			
		||||
		m_TextFormat.Get(),
 | 
			
		||||
		maxWidth,
 | 
			
		||||
		10000,
 | 
			
		||||
		textLayout.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
		if (gdiEmulation)
 | 
			
		||||
		{
 | 
			
		||||
			Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
			textLayout.As(&textLayout1);
 | 
			
		||||
 | 
			
		||||
			const float emOffset = xOffset / 24.0f;
 | 
			
		||||
			const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
			textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		textLayout->GetMetrics(&metrics);
 | 
			
		||||
		if (metrics.width > 0.0f)
 | 
			
		||||
		{
 | 
			
		||||
			if (gdiEmulation)
 | 
			
		||||
			{
 | 
			
		||||
				metrics.width += xOffset * 2;
 | 
			
		||||
				metrics.height += m_ExtraHeight;
 | 
			
		||||
 | 
			
		||||
				// GDI+ compatibility: If the string contains a newline (even if it is the
 | 
			
		||||
				// stripped last character), GDI+ adds the line gap to the overall height.
 | 
			
		||||
				if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr)
 | 
			
		||||
				{
 | 
			
		||||
					metrics.height += m_LineGap;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted
 | 
			
		||||
				// from the overall height if the string does not contain newlines.
 | 
			
		||||
				if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr)
 | 
			
		||||
				{
 | 
			
		||||
					metrics.height -= m_LineGap;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			// GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width
 | 
			
		||||
			// strings.
 | 
			
		||||
			metrics.height = 0.0f;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return metrics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetTrimming(bool trim)
 | 
			
		||||
{
 | 
			
		||||
	m_Trimming = trim;
 | 
			
		||||
	IDWriteInlineObject* inlineObject = nullptr;
 | 
			
		||||
	DWRITE_TRIMMING trimming = {};
 | 
			
		||||
	DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP;
 | 
			
		||||
	if (trim)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_InlineEllipsis)
 | 
			
		||||
		{
 | 
			
		||||
			CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign(
 | 
			
		||||
				m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		inlineObject = m_InlineEllipsis.Get();
 | 
			
		||||
		trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
 | 
			
		||||
		wordWrapping = DWRITE_WORD_WRAPPING_WRAP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_TextFormat->SetTrimming(&trimming, inlineObject);
 | 
			
		||||
	m_TextFormat->SetWordWrapping(wordWrapping);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	__super::SetHorizontalAlignment(alignment);
 | 
			
		||||
 | 
			
		||||
	if (m_TextFormat)
 | 
			
		||||
	{
 | 
			
		||||
		m_TextFormat->SetTextAlignment(
 | 
			
		||||
			(alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING :
 | 
			
		||||
			(alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER :
 | 
			
		||||
			DWRITE_TEXT_ALIGNMENT_TRAILING);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	__super::SetVerticalAlignment(alignment);
 | 
			
		||||
	
 | 
			
		||||
	if (m_TextFormat)
 | 
			
		||||
	{
 | 
			
		||||
		m_TextFormat->SetParagraphAlignment(
 | 
			
		||||
			(alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR :
 | 
			
		||||
			(alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER :
 | 
			
		||||
			DWRITE_PARAGRAPH_ALIGNMENT_FAR);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,81 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMATD2D_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMATD2D_H_
 | 
			
		||||
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
#include <wrl/client.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D.
 | 
			
		||||
class TextFormatD2D : public TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	TextFormatD2D();
 | 
			
		||||
	virtual ~TextFormatD2D();
 | 
			
		||||
 | 
			
		||||
	TextFormatD2D(const TextFormatD2D& other) = delete;
 | 
			
		||||
	TextFormatD2D& operator=(TextFormatD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsInitialized() const override { return m_TextFormat != nullptr; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTrimming(bool trim) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasD2D;
 | 
			
		||||
 | 
			
		||||
	friend class Common_Gfx_TextFormatD2D_Test;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	// Creates a new DirectWrite text layout if |str| has changed since last call. Since creating
 | 
			
		||||
	// the layout is costly, it is more efficient to keep reusing the text layout until the text
 | 
			
		||||
	// changes. Returns true if the layout is valid for use.
 | 
			
		||||
	bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
 | 
			
		||||
 | 
			
		||||
	DWRITE_TEXT_METRICS GetMetrics(
 | 
			
		||||
		const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextFormat> m_TextFormat;
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextLayout> m_TextLayout;
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteInlineObject> m_InlineEllipsis;
 | 
			
		||||
 | 
			
		||||
	std::wstring m_LastString;
 | 
			
		||||
 | 
			
		||||
	// Used to emulate GDI+ behaviour.
 | 
			
		||||
	float m_ExtraHeight;
 | 
			
		||||
	float m_LineGap;
 | 
			
		||||
 | 
			
		||||
	// Contains the value passed to the last call of of SetTrimming().
 | 
			
		||||
	bool m_Trimming;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMATD2D_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMATD2D_H_
 | 
			
		||||
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
#include <wrl/client.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D.
 | 
			
		||||
class TextFormatD2D : public TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	TextFormatD2D();
 | 
			
		||||
	virtual ~TextFormatD2D();
 | 
			
		||||
 | 
			
		||||
	TextFormatD2D(const TextFormatD2D& other) = delete;
 | 
			
		||||
	TextFormatD2D& operator=(TextFormatD2D other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsInitialized() const override { return m_TextFormat != nullptr; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTrimming(bool trim) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasD2D;
 | 
			
		||||
 | 
			
		||||
	friend class Common_Gfx_TextFormatD2D_Test;
 | 
			
		||||
 | 
			
		||||
	void Dispose();
 | 
			
		||||
 | 
			
		||||
	// Creates a new DirectWrite text layout if |str| has changed since last call. Since creating
 | 
			
		||||
	// the layout is costly, it is more efficient to keep reusing the text layout until the text
 | 
			
		||||
	// changes. Returns true if the layout is valid for use.
 | 
			
		||||
	bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
 | 
			
		||||
 | 
			
		||||
	DWRITE_TEXT_METRICS GetMetrics(
 | 
			
		||||
		const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextFormat> m_TextFormat;
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteTextLayout> m_TextLayout;
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteInlineObject> m_InlineEllipsis;
 | 
			
		||||
 | 
			
		||||
	std::wstring m_LastString;
 | 
			
		||||
 | 
			
		||||
	// Used to emulate GDI+ behaviour.
 | 
			
		||||
	float m_ExtraHeight;
 | 
			
		||||
	float m_LineGap;
 | 
			
		||||
 | 
			
		||||
	// Contains the value passed to the last call of of SetTrimming().
 | 
			
		||||
	bool m_Trimming;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,83 +1,83 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "../UnitTest.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TEST_CLASS(Common_Gfx_TextFormatD2D_Test)
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	std::unique_ptr<Canvas> m_D2D;
 | 
			
		||||
 | 
			
		||||
	Common_Gfx_TextFormatD2D_Test() :
 | 
			
		||||
		m_D2D(Canvas::Create(Gfx::Renderer::D2D))
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Handle this in CanvasD2D.
 | 
			
		||||
		ULONG_PTR gdiplusToken;
 | 
			
		||||
		Gdiplus::GdiplusStartupInput gdiplusStartupInput;
 | 
			
		||||
		Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
 | 
			
		||||
 | 
			
		||||
		m_D2D->Resize(10, 10);
 | 
			
		||||
		m_D2D->SetAntiAliasing(true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TEST_METHOD(TestInaccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
 | 
			
		||||
		textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
 | 
			
		||||
 | 
			
		||||
		DWRITE_TEXT_METRICS metrics;
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test", 4, true);
 | 
			
		||||
		Assert::AreEqual(26, (int)metrics.width);
 | 
			
		||||
		Assert::AreEqual(16, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test", 4, false);
 | 
			
		||||
		Assert::AreEqual(21, (int)metrics.width);
 | 
			
		||||
		Assert::AreEqual(14, (int)metrics.height);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TEST_METHOD(TestTrailingNewlineGdipCompatibility)
 | 
			
		||||
	{
 | 
			
		||||
		std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
 | 
			
		||||
		textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
 | 
			
		||||
 | 
			
		||||
		DWRITE_TEXT_METRICS metrics;
 | 
			
		||||
		
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n", 5, false);
 | 
			
		||||
		Assert::AreEqual(15, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n", 6, false);
 | 
			
		||||
		Assert::AreEqual(15, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n ", 6, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n ", 7, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n\n", 6, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "Canvas.h"
 | 
			
		||||
#include "TextFormatD2D.h"
 | 
			
		||||
#include "../UnitTest.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TEST_CLASS(Common_Gfx_TextFormatD2D_Test)
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	std::unique_ptr<Canvas> m_D2D;
 | 
			
		||||
 | 
			
		||||
	Common_Gfx_TextFormatD2D_Test() :
 | 
			
		||||
		m_D2D(Canvas::Create(Gfx::Renderer::D2D))
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Handle this in CanvasD2D.
 | 
			
		||||
		ULONG_PTR gdiplusToken;
 | 
			
		||||
		Gdiplus::GdiplusStartupInput gdiplusStartupInput;
 | 
			
		||||
		Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
 | 
			
		||||
 | 
			
		||||
		m_D2D->Resize(10, 10);
 | 
			
		||||
		m_D2D->SetAntiAliasing(true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TEST_METHOD(TestInaccurateText)
 | 
			
		||||
	{
 | 
			
		||||
		std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
 | 
			
		||||
		textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
 | 
			
		||||
 | 
			
		||||
		DWRITE_TEXT_METRICS metrics;
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test", 4, true);
 | 
			
		||||
		Assert::AreEqual(26, (int)metrics.width);
 | 
			
		||||
		Assert::AreEqual(16, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test", 4, false);
 | 
			
		||||
		Assert::AreEqual(21, (int)metrics.width);
 | 
			
		||||
		Assert::AreEqual(14, (int)metrics.height);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TEST_METHOD(TestTrailingNewlineGdipCompatibility)
 | 
			
		||||
	{
 | 
			
		||||
		std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
 | 
			
		||||
		textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
 | 
			
		||||
 | 
			
		||||
		DWRITE_TEXT_METRICS metrics;
 | 
			
		||||
		
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n", 5, false);
 | 
			
		||||
		Assert::AreEqual(15, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n", 6, false);
 | 
			
		||||
		Assert::AreEqual(15, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n ", 6, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n ", 7, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\n\n", 6, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
		metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false);
 | 
			
		||||
		Assert::AreEqual(30, (int)metrics.height);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,134 +1,134 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormatGDIP.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormatGDIP::TextFormatGDIP()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormatGDIP::~TextFormatGDIP()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetProperties(
 | 
			
		||||
	const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
	const FontCollection* fontCollection)
 | 
			
		||||
{
 | 
			
		||||
	auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection;
 | 
			
		||||
 | 
			
		||||
	m_Font.reset();
 | 
			
		||||
 | 
			
		||||
	m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily));
 | 
			
		||||
	if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
	{
 | 
			
		||||
		m_FontFamily.reset();
 | 
			
		||||
 | 
			
		||||
		// Not found in system collection so try the private collection.
 | 
			
		||||
		if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection)
 | 
			
		||||
		{
 | 
			
		||||
			m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection));
 | 
			
		||||
			if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_FontFamily.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Gdiplus::FontStyle style = Gdiplus::FontStyleRegular;
 | 
			
		||||
	if (bold && italic)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleBoldItalic;
 | 
			
		||||
	}
 | 
			
		||||
	else if (bold)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleBold;
 | 
			
		||||
	}
 | 
			
		||||
	else if (italic)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleItalic;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (size != 0)
 | 
			
		||||
	{
 | 
			
		||||
		// Adjust the font size with screen DPI.
 | 
			
		||||
		HDC dc = GetDC(0);
 | 
			
		||||
		const int dpi = GetDeviceCaps(dc, LOGPIXELSX);
 | 
			
		||||
		ReleaseDC(0, dc);
 | 
			
		||||
		const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi);
 | 
			
		||||
 | 
			
		||||
		if (m_FontFamily)
 | 
			
		||||
		{
 | 
			
		||||
			m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style));
 | 
			
		||||
			if (m_Font->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_Font.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!m_Font)
 | 
			
		||||
		{
 | 
			
		||||
			// Use default font ("Arial" or GenericSansSerif).
 | 
			
		||||
			m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style));
 | 
			
		||||
			if (m_Font->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_Font.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetTrimming(bool trim)
 | 
			
		||||
{
 | 
			
		||||
	if (trim)
 | 
			
		||||
	{
 | 
			
		||||
		m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter);
 | 
			
		||||
		m_StringFormat.SetFormatFlags(0x0);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
 | 
			
		||||
		m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch");
 | 
			
		||||
 | 
			
		||||
	__super::SetHorizontalAlignment(alignment);
 | 
			
		||||
	m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch");
 | 
			
		||||
 | 
			
		||||
	__super::SetVerticalAlignment(alignment);
 | 
			
		||||
	m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "TextFormatGDIP.h"
 | 
			
		||||
#include "FontCollectionGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
TextFormatGDIP::TextFormatGDIP()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextFormatGDIP::~TextFormatGDIP()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetProperties(
 | 
			
		||||
	const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
	const FontCollection* fontCollection)
 | 
			
		||||
{
 | 
			
		||||
	auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection;
 | 
			
		||||
 | 
			
		||||
	m_Font.reset();
 | 
			
		||||
 | 
			
		||||
	m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily));
 | 
			
		||||
	if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
	{
 | 
			
		||||
		m_FontFamily.reset();
 | 
			
		||||
 | 
			
		||||
		// Not found in system collection so try the private collection.
 | 
			
		||||
		if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection)
 | 
			
		||||
		{
 | 
			
		||||
			m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection));
 | 
			
		||||
			if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_FontFamily.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Gdiplus::FontStyle style = Gdiplus::FontStyleRegular;
 | 
			
		||||
	if (bold && italic)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleBoldItalic;
 | 
			
		||||
	}
 | 
			
		||||
	else if (bold)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleBold;
 | 
			
		||||
	}
 | 
			
		||||
	else if (italic)
 | 
			
		||||
	{
 | 
			
		||||
		style = Gdiplus::FontStyleItalic;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (size != 0)
 | 
			
		||||
	{
 | 
			
		||||
		// Adjust the font size with screen DPI.
 | 
			
		||||
		HDC dc = GetDC(0);
 | 
			
		||||
		const int dpi = GetDeviceCaps(dc, LOGPIXELSX);
 | 
			
		||||
		ReleaseDC(0, dc);
 | 
			
		||||
		const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi);
 | 
			
		||||
 | 
			
		||||
		if (m_FontFamily)
 | 
			
		||||
		{
 | 
			
		||||
			m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style));
 | 
			
		||||
			if (m_Font->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_Font.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!m_Font)
 | 
			
		||||
		{
 | 
			
		||||
			// Use default font ("Arial" or GenericSansSerif).
 | 
			
		||||
			m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style));
 | 
			
		||||
			if (m_Font->GetLastStatus() != Gdiplus::Ok)
 | 
			
		||||
			{
 | 
			
		||||
				m_Font.reset();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetTrimming(bool trim)
 | 
			
		||||
{
 | 
			
		||||
	if (trim)
 | 
			
		||||
	{
 | 
			
		||||
		m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter);
 | 
			
		||||
		m_StringFormat.SetFormatFlags(0x0);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
 | 
			
		||||
		m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch");
 | 
			
		||||
 | 
			
		||||
	__super::SetHorizontalAlignment(alignment);
 | 
			
		||||
	m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment)
 | 
			
		||||
{
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch");
 | 
			
		||||
	static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch");
 | 
			
		||||
 | 
			
		||||
	__super::SetVerticalAlignment(alignment);
 | 
			
		||||
	m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,60 +1,60 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMATGDIP_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMATGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP.
 | 
			
		||||
class TextFormatGDIP : public TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	TextFormatGDIP();
 | 
			
		||||
	virtual ~TextFormatGDIP();
 | 
			
		||||
 | 
			
		||||
	TextFormatGDIP(const TextFormatGDIP& other) = delete;
 | 
			
		||||
	TextFormatGDIP& operator=(TextFormatGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsInitialized() const override { return m_Font != nullptr; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTrimming(bool trim) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasGDIP;
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Gdiplus::Font> m_Font;
 | 
			
		||||
	std::unique_ptr<Gdiplus::FontFamily> m_FontFamily;
 | 
			
		||||
	Gdiplus::StringFormat m_StringFormat;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_TEXTFORMATGDIP_H_
 | 
			
		||||
#define RM_GFX_TEXTFORMATGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include "TextFormat.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
 | 
			
		||||
// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP.
 | 
			
		||||
class TextFormatGDIP : public TextFormat
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	TextFormatGDIP();
 | 
			
		||||
	virtual ~TextFormatGDIP();
 | 
			
		||||
 | 
			
		||||
	TextFormatGDIP(const TextFormatGDIP& other) = delete;
 | 
			
		||||
	TextFormatGDIP& operator=(TextFormatGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	virtual bool IsInitialized() const override { return m_Font != nullptr; }
 | 
			
		||||
 | 
			
		||||
	virtual void SetProperties(
 | 
			
		||||
		const WCHAR* fontFamily, int size, bool bold, bool italic,
 | 
			
		||||
		const FontCollection* fontCollection) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetTrimming(bool trim) override;
 | 
			
		||||
 | 
			
		||||
	virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
 | 
			
		||||
	virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class CanvasGDIP;
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Gdiplus::Font> m_Font;
 | 
			
		||||
	std::unique_ptr<Gdiplus::FontFamily> m_FontFamily;
 | 
			
		||||
	Gdiplus::StringFormat m_StringFormat;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,67 +1,67 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteFontCollectionLoader.h"
 | 
			
		||||
#include "DWriteFontFileEnumerator.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance()
 | 
			
		||||
{
 | 
			
		||||
	static DWriteFontCollectionLoader s_Instance;
 | 
			
		||||
	return &s_Instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	// This is a singleton class so return a dummy value.
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release()
 | 
			
		||||
{
 | 
			
		||||
	// This is a singleton class so return a dummy value.
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	if (riid == IID_IUnknown ||
 | 
			
		||||
		riid == __uuidof(IDWriteFontCollectionLoader))
 | 
			
		||||
	{
 | 
			
		||||
		*ppvObject = this;
 | 
			
		||||
		return S_OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*ppvObject = nullptr;
 | 
			
		||||
	return E_NOINTERFACE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey(
 | 
			
		||||
	IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize,
 | 
			
		||||
	IDWriteFontFileEnumerator** fontFileEnumerator)
 | 
			
		||||
{
 | 
			
		||||
	*fontFileEnumerator = new DWriteFontFileEnumerator(
 | 
			
		||||
		*(const std::vector<IDWriteFontFile*>*)collectionKey);
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteFontCollectionLoader.h"
 | 
			
		||||
#include "DWriteFontFileEnumerator.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance()
 | 
			
		||||
{
 | 
			
		||||
	static DWriteFontCollectionLoader s_Instance;
 | 
			
		||||
	return &s_Instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	// This is a singleton class so return a dummy value.
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release()
 | 
			
		||||
{
 | 
			
		||||
	// This is a singleton class so return a dummy value.
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	if (riid == IID_IUnknown ||
 | 
			
		||||
		riid == __uuidof(IDWriteFontCollectionLoader))
 | 
			
		||||
	{
 | 
			
		||||
		*ppvObject = this;
 | 
			
		||||
		return S_OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*ppvObject = nullptr;
 | 
			
		||||
	return E_NOINTERFACE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey(
 | 
			
		||||
	IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize,
 | 
			
		||||
	IDWriteFontFileEnumerator** fontFileEnumerator)
 | 
			
		||||
{
 | 
			
		||||
	*fontFileEnumerator = new DWriteFontFileEnumerator(
 | 
			
		||||
		*(const std::vector<IDWriteFontFile*>*)collectionKey);
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
 | 
			
		||||
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements the IDWriteFontCollectionLoader interface as a singleton object. When
 | 
			
		||||
// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using
 | 
			
		||||
// |fontCollectionKey| (which is assumed to be a pointer to std::vector<IDWriteFontFile*>).
 | 
			
		||||
class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static DWriteFontCollectionLoader* GetInstance();
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE AddRef() override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE Release() override;
 | 
			
		||||
 | 
			
		||||
	// IFontCollectionLoader
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
 | 
			
		||||
		IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize,
 | 
			
		||||
		IDWriteFontFileEnumerator** fontFileEnumerator) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	DWriteFontCollectionLoader() {}
 | 
			
		||||
	DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
 | 
			
		||||
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements the IDWriteFontCollectionLoader interface as a singleton object. When
 | 
			
		||||
// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using
 | 
			
		||||
// |fontCollectionKey| (which is assumed to be a pointer to std::vector<IDWriteFontFile*>).
 | 
			
		||||
class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static DWriteFontCollectionLoader* GetInstance();
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE AddRef() override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE Release() override;
 | 
			
		||||
 | 
			
		||||
	// IFontCollectionLoader
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
 | 
			
		||||
		IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize,
 | 
			
		||||
		IDWriteFontFileEnumerator** fontFileEnumerator) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	DWriteFontCollectionLoader() {}
 | 
			
		||||
	DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,78 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteFontFileEnumerator.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles) :
 | 
			
		||||
	m_RefCount(1),
 | 
			
		||||
	m_FontFiles(fontFiles),
 | 
			
		||||
	m_CurrentFontFileIndex(-1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	if (riid == IID_IUnknown ||
 | 
			
		||||
		riid == __uuidof(IDWriteFontFileEnumerator))
 | 
			
		||||
	{
 | 
			
		||||
		*ppvObject = this;
 | 
			
		||||
		AddRef();
 | 
			
		||||
		return S_OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*ppvObject = nullptr;
 | 
			
		||||
	return E_NOINTERFACE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile)
 | 
			
		||||
{
 | 
			
		||||
	*hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size());
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex];
 | 
			
		||||
	currentFontFile->AddRef();
 | 
			
		||||
	*fontFile = currentFontFile;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteFontFileEnumerator.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles) :
 | 
			
		||||
	m_RefCount(1),
 | 
			
		||||
	m_FontFiles(fontFiles),
 | 
			
		||||
	m_CurrentFontFileIndex(-1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	if (riid == IID_IUnknown ||
 | 
			
		||||
		riid == __uuidof(IDWriteFontFileEnumerator))
 | 
			
		||||
	{
 | 
			
		||||
		*ppvObject = this;
 | 
			
		||||
		AddRef();
 | 
			
		||||
		return S_OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*ppvObject = nullptr;
 | 
			
		||||
	return E_NOINTERFACE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile)
 | 
			
		||||
{
 | 
			
		||||
	*hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size());
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex];
 | 
			
		||||
	currentFontFile->AddRef();
 | 
			
		||||
	*fontFile = currentFontFile;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,56 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements IDWriteFontFileEnumerator by enumerating over std::vector<IDWriteFontFile*>.
 | 
			
		||||
class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles);
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE AddRef() override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE Release() override;
 | 
			
		||||
 | 
			
		||||
	// IDWriteFontFileEnumerator
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override;
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	ULONG m_RefCount;
 | 
			
		||||
 | 
			
		||||
	const std::vector<IDWriteFontFile*>& m_FontFiles;
 | 
			
		||||
 | 
			
		||||
	// Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as
 | 
			
		||||
	// required by IDWriteFontFileEnumerator.
 | 
			
		||||
	int m_CurrentFontFileIndex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements IDWriteFontFileEnumerator by enumerating over std::vector<IDWriteFontFile*>.
 | 
			
		||||
class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles);
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE AddRef() override;
 | 
			
		||||
	virtual ULONG STDMETHODCALLTYPE Release() override;
 | 
			
		||||
 | 
			
		||||
	// IDWriteFontFileEnumerator
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override;
 | 
			
		||||
	virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	ULONG m_RefCount;
 | 
			
		||||
 | 
			
		||||
	const std::vector<IDWriteFontFile*>& m_FontFiles;
 | 
			
		||||
 | 
			
		||||
	// Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as
 | 
			
		||||
	// required by IDWriteFontFileEnumerator.
 | 
			
		||||
	int m_CurrentFontFileIndex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,218 +1,218 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteHelpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
HRESULT GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
	IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize)
 | 
			
		||||
{
 | 
			
		||||
	HRESULT hr = E_FAIL;
 | 
			
		||||
	IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName);
 | 
			
		||||
	if (dwriteFont)
 | 
			
		||||
	{
 | 
			
		||||
		hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			GetPropertiesFromDWriteFont(
 | 
			
		||||
				dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dwriteFont->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GetPropertiesFromDWriteFont(
 | 
			
		||||
	IDWriteFont* dwriteFont, const bool bold, const bool italic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH* dwriteFontStretch)
 | 
			
		||||
{
 | 
			
		||||
	*dwriteFontWeight = dwriteFont->GetWeight();
 | 
			
		||||
	if (bold)
 | 
			
		||||
	{
 | 
			
		||||
		if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
 | 
			
		||||
		{
 | 
			
		||||
			*dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
 | 
			
		||||
		}
 | 
			
		||||
		else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
 | 
			
		||||
		{
 | 
			
		||||
			// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
 | 
			
		||||
			// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
 | 
			
		||||
			// increase the weight a little more for similar results with GDI+.
 | 
			
		||||
			// TODO: Is +100 enough?
 | 
			
		||||
			*dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*dwriteFontStyle = dwriteFont->GetStyle();
 | 
			
		||||
	if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
 | 
			
		||||
	{
 | 
			
		||||
		*dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*dwriteFontStretch = dwriteFont->GetStretch();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteGdiInterop> dwGdiInterop;
 | 
			
		||||
	HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		LOGFONT lf = {};
 | 
			
		||||
		wcscpy_s(lf.lfFaceName, gdiFamilyName);
 | 
			
		||||
		lf.lfHeight = -12;
 | 
			
		||||
		lf.lfWeight = FW_DONTCARE;
 | 
			
		||||
		lf.lfCharSet = DEFAULT_CHARSET;
 | 
			
		||||
		lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
 | 
			
		||||
		lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 | 
			
		||||
		lf.lfQuality = ANTIALIASED_QUALITY;
 | 
			
		||||
		lf.lfPitchAndFamily = VARIABLE_PITCH;
 | 
			
		||||
 | 
			
		||||
		IDWriteFont* dwFont;
 | 
			
		||||
		hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			return dwFont;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteFontFamily* dwriteFontFamily;
 | 
			
		||||
	HRESULT hr = font->GetFontFamily(&dwriteFontFamily);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize);
 | 
			
		||||
		dwriteFontFamily->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFontFamily(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteLocalizedStrings* dwFamilyNames;
 | 
			
		||||
	HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Determine the best index?
 | 
			
		||||
		hr = dwFamilyNames->GetString(0, buffer, bufferSize);
 | 
			
		||||
		dwFamilyNames->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName)
 | 
			
		||||
{
 | 
			
		||||
	bool result = false;
 | 
			
		||||
	IDWriteFontCollection* systemFontCollection;
 | 
			
		||||
	HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		UINT32 familyNameIndex;
 | 
			
		||||
		BOOL familyNameFound;
 | 
			
		||||
		HRESULT hr = systemFontCollection->FindFamilyName(
 | 
			
		||||
			familyName, &familyNameIndex, &familyNameFound);
 | 
			
		||||
		if (SUCCEEDED(hr) && familyNameFound)
 | 
			
		||||
		{
 | 
			
		||||
			result = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		systemFontCollection->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> strings;
 | 
			
		||||
	BOOL stringsExist;
 | 
			
		||||
	font->GetInformationalStrings(
 | 
			
		||||
		DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist);
 | 
			
		||||
	if (strings && stringsExist)
 | 
			
		||||
	{
 | 
			
		||||
		return strings->GetString(0, buffer, bufferSize);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return E_FAIL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	const UINT32 fontFamilyFontCount = fontFamily->GetFontCount();
 | 
			
		||||
	for (UINT32 j = 0; j < fontFamilyFontCount; ++j)
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFont* font;
 | 
			
		||||
		HRESULT hr = fontFamily->GetFont(j, &font);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			WCHAR buffer[LF_FACESIZE];
 | 
			
		||||
			hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer));
 | 
			
		||||
			if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0)
 | 
			
		||||
			{
 | 
			
		||||
				return font;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			font->Release();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
	IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount();
 | 
			
		||||
	for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i)
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFontFamily* fontFamily;
 | 
			
		||||
		HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName(
 | 
			
		||||
				fontFamily, gdiFamilyName);
 | 
			
		||||
			fontFamily->Release();
 | 
			
		||||
 | 
			
		||||
			if (font)
 | 
			
		||||
			{
 | 
			
		||||
				return font;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "DWriteHelpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
HRESULT GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
	IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize)
 | 
			
		||||
{
 | 
			
		||||
	HRESULT hr = E_FAIL;
 | 
			
		||||
	IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName);
 | 
			
		||||
	if (dwriteFont)
 | 
			
		||||
	{
 | 
			
		||||
		hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			GetPropertiesFromDWriteFont(
 | 
			
		||||
				dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dwriteFont->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GetPropertiesFromDWriteFont(
 | 
			
		||||
	IDWriteFont* dwriteFont, const bool bold, const bool italic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH* dwriteFontStretch)
 | 
			
		||||
{
 | 
			
		||||
	*dwriteFontWeight = dwriteFont->GetWeight();
 | 
			
		||||
	if (bold)
 | 
			
		||||
	{
 | 
			
		||||
		if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
 | 
			
		||||
		{
 | 
			
		||||
			*dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
 | 
			
		||||
		}
 | 
			
		||||
		else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
 | 
			
		||||
		{
 | 
			
		||||
			// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
 | 
			
		||||
			// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
 | 
			
		||||
			// increase the weight a little more for similar results with GDI+.
 | 
			
		||||
			// TODO: Is +100 enough?
 | 
			
		||||
			*dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*dwriteFontStyle = dwriteFont->GetStyle();
 | 
			
		||||
	if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
 | 
			
		||||
	{
 | 
			
		||||
		*dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*dwriteFontStretch = dwriteFont->GetStretch();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteGdiInterop> dwGdiInterop;
 | 
			
		||||
	HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		LOGFONT lf = {};
 | 
			
		||||
		wcscpy_s(lf.lfFaceName, gdiFamilyName);
 | 
			
		||||
		lf.lfHeight = -12;
 | 
			
		||||
		lf.lfWeight = FW_DONTCARE;
 | 
			
		||||
		lf.lfCharSet = DEFAULT_CHARSET;
 | 
			
		||||
		lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
 | 
			
		||||
		lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 | 
			
		||||
		lf.lfQuality = ANTIALIASED_QUALITY;
 | 
			
		||||
		lf.lfPitchAndFamily = VARIABLE_PITCH;
 | 
			
		||||
 | 
			
		||||
		IDWriteFont* dwFont;
 | 
			
		||||
		hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			return dwFont;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteFontFamily* dwriteFontFamily;
 | 
			
		||||
	HRESULT hr = font->GetFontFamily(&dwriteFontFamily);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize);
 | 
			
		||||
		dwriteFontFamily->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFontFamily(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	IDWriteLocalizedStrings* dwFamilyNames;
 | 
			
		||||
	HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Determine the best index?
 | 
			
		||||
		hr = dwFamilyNames->GetString(0, buffer, bufferSize);
 | 
			
		||||
		dwFamilyNames->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName)
 | 
			
		||||
{
 | 
			
		||||
	bool result = false;
 | 
			
		||||
	IDWriteFontCollection* systemFontCollection;
 | 
			
		||||
	HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection);
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	{
 | 
			
		||||
		UINT32 familyNameIndex;
 | 
			
		||||
		BOOL familyNameFound;
 | 
			
		||||
		HRESULT hr = systemFontCollection->FindFamilyName(
 | 
			
		||||
			familyName, &familyNameIndex, &familyNameFound);
 | 
			
		||||
		if (SUCCEEDED(hr) && familyNameFound)
 | 
			
		||||
		{
 | 
			
		||||
			result = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		systemFontCollection->Release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
 | 
			
		||||
{
 | 
			
		||||
	Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> strings;
 | 
			
		||||
	BOOL stringsExist;
 | 
			
		||||
	font->GetInformationalStrings(
 | 
			
		||||
		DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist);
 | 
			
		||||
	if (strings && stringsExist)
 | 
			
		||||
	{
 | 
			
		||||
		return strings->GetString(0, buffer, bufferSize);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return E_FAIL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	const UINT32 fontFamilyFontCount = fontFamily->GetFontCount();
 | 
			
		||||
	for (UINT32 j = 0; j < fontFamilyFontCount; ++j)
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFont* font;
 | 
			
		||||
		HRESULT hr = fontFamily->GetFont(j, &font);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			WCHAR buffer[LF_FACESIZE];
 | 
			
		||||
			hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer));
 | 
			
		||||
			if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0)
 | 
			
		||||
			{
 | 
			
		||||
				return font;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			font->Release();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
	IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName)
 | 
			
		||||
{
 | 
			
		||||
	const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount();
 | 
			
		||||
	for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i)
 | 
			
		||||
	{
 | 
			
		||||
		IDWriteFontFamily* fontFamily;
 | 
			
		||||
		HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName(
 | 
			
		||||
				fontFamily, gdiFamilyName);
 | 
			
		||||
			fontFamily->Release();
 | 
			
		||||
 | 
			
		||||
			if (font)
 | 
			
		||||
			{
 | 
			
		||||
				return font;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,58 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEHELPERS_H_
 | 
			
		||||
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style,
 | 
			
		||||
// and stretch.
 | 
			
		||||
HRESULT GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
	IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize);
 | 
			
		||||
 | 
			
		||||
void GetPropertiesFromDWriteFont(
 | 
			
		||||
	IDWriteFont* dwriteFont, const bool bold, const bool italic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH* dwriteFontStretch);
 | 
			
		||||
 | 
			
		||||
// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For
 | 
			
		||||
// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas
 | 
			
		||||
// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font
 | 
			
		||||
// style.
 | 
			
		||||
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily);
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize);
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFontFamily(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize);
 | 
			
		||||
 | 
			
		||||
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName);
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
	IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName);
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_
 | 
			
		||||
#define RM_GFX_UTIL_DWRITEHELPERS_H_
 | 
			
		||||
 | 
			
		||||
#include <dwrite_1.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style,
 | 
			
		||||
// and stretch.
 | 
			
		||||
HRESULT GetDWritePropertiesFromGDIProperties(
 | 
			
		||||
	IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize);
 | 
			
		||||
 | 
			
		||||
void GetPropertiesFromDWriteFont(
 | 
			
		||||
	IDWriteFont* dwriteFont, const bool bold, const bool italic,
 | 
			
		||||
	DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
 | 
			
		||||
	DWRITE_FONT_STRETCH* dwriteFontStretch);
 | 
			
		||||
 | 
			
		||||
// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For
 | 
			
		||||
// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas
 | 
			
		||||
// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font
 | 
			
		||||
// style.
 | 
			
		||||
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily);
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize);
 | 
			
		||||
 | 
			
		||||
HRESULT GetFamilyNameFromDWriteFontFamily(
 | 
			
		||||
	IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize);
 | 
			
		||||
 | 
			
		||||
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName);
 | 
			
		||||
 | 
			
		||||
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
 | 
			
		||||
	IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName);
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,136 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapDIB.h"
 | 
			
		||||
#include "WICBitmapLockDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapDIB::WICBitmapDIB() :
 | 
			
		||||
	m_DIBSectionBuffer(),
 | 
			
		||||
	m_DIBSectionBufferPixels(),
 | 
			
		||||
	m_W(0),
 | 
			
		||||
	m_H(0)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WICBitmapDIB::~WICBitmapDIB()
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSectionBuffer);
 | 
			
		||||
		m_DIBSectionBufferPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WICBitmapDIB::Resize(UINT w, UINT h)
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSectionBuffer);
 | 
			
		||||
		m_DIBSectionBufferPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_W = w;
 | 
			
		||||
	m_H = h;
 | 
			
		||||
 | 
			
		||||
	BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
 | 
			
		||||
	bh.bV4Width = (LONG)m_W;
 | 
			
		||||
	bh.bV4Height = -(LONG)m_H;	// Top-down DIB
 | 
			
		||||
	bh.bV4Planes = 1;
 | 
			
		||||
	bh.bV4BitCount = 32;
 | 
			
		||||
	bh.bV4V4Compression = BI_BITFIELDS;
 | 
			
		||||
	bh.bV4RedMask = 0x00FF0000;
 | 
			
		||||
	bh.bV4GreenMask = 0x0000FF00;
 | 
			
		||||
	bh.bV4BlueMask = 0x000000FF;
 | 
			
		||||
	bh.bV4AlphaMask = 0xFF000000;
 | 
			
		||||
 | 
			
		||||
	m_DIBSectionBuffer = CreateDIBSection(
 | 
			
		||||
		nullptr,
 | 
			
		||||
		(BITMAPINFO*)&bh,
 | 
			
		||||
		DIB_RGB_COLORS,
 | 
			
		||||
		(void**)&m_DIBSectionBufferPixels,
 | 
			
		||||
		nullptr,
 | 
			
		||||
		0);
 | 
			
		||||
 | 
			
		||||
	assert(m_DIBSectionBufferPixels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release()
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	if (puiWidth) *puiWidth = m_W;
 | 
			
		||||
	if (puiHeight) *puiHeight = m_H;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock)
 | 
			
		||||
{
 | 
			
		||||
	if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock);
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapDIB.h"
 | 
			
		||||
#include "WICBitmapLockDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapDIB::WICBitmapDIB() :
 | 
			
		||||
	m_DIBSectionBuffer(),
 | 
			
		||||
	m_DIBSectionBufferPixels(),
 | 
			
		||||
	m_W(0),
 | 
			
		||||
	m_H(0)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WICBitmapDIB::~WICBitmapDIB()
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSectionBuffer);
 | 
			
		||||
		m_DIBSectionBufferPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WICBitmapDIB::Resize(UINT w, UINT h)
 | 
			
		||||
{
 | 
			
		||||
	if (m_DIBSectionBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		DeleteObject(m_DIBSectionBuffer);
 | 
			
		||||
		m_DIBSectionBufferPixels = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_W = w;
 | 
			
		||||
	m_H = h;
 | 
			
		||||
 | 
			
		||||
	BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
 | 
			
		||||
	bh.bV4Width = (LONG)m_W;
 | 
			
		||||
	bh.bV4Height = -(LONG)m_H;	// Top-down DIB
 | 
			
		||||
	bh.bV4Planes = 1;
 | 
			
		||||
	bh.bV4BitCount = 32;
 | 
			
		||||
	bh.bV4V4Compression = BI_BITFIELDS;
 | 
			
		||||
	bh.bV4RedMask = 0x00FF0000;
 | 
			
		||||
	bh.bV4GreenMask = 0x0000FF00;
 | 
			
		||||
	bh.bV4BlueMask = 0x000000FF;
 | 
			
		||||
	bh.bV4AlphaMask = 0xFF000000;
 | 
			
		||||
 | 
			
		||||
	m_DIBSectionBuffer = CreateDIBSection(
 | 
			
		||||
		nullptr,
 | 
			
		||||
		(BITMAPINFO*)&bh,
 | 
			
		||||
		DIB_RGB_COLORS,
 | 
			
		||||
		(void**)&m_DIBSectionBufferPixels,
 | 
			
		||||
		nullptr,
 | 
			
		||||
		0);
 | 
			
		||||
 | 
			
		||||
	assert(m_DIBSectionBufferPixels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release()
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	if (puiWidth) *puiWidth = m_W;
 | 
			
		||||
	if (puiHeight) *puiHeight = m_H;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock)
 | 
			
		||||
{
 | 
			
		||||
	if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock);
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,76 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPDIB_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this
 | 
			
		||||
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
//
 | 
			
		||||
// This class does not follow the COM reference count model. RTTI is used instead. This class
 | 
			
		||||
// implements only the bare essentials in order to use a DIB section as a Direct2D render target.
 | 
			
		||||
class WICBitmapDIB : public IWICBitmap
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapDIB();
 | 
			
		||||
	~WICBitmapDIB();
 | 
			
		||||
 | 
			
		||||
	WICBitmapDIB(const WICBitmapDIB& other) = delete;
 | 
			
		||||
	WICBitmapDIB& operator=(WICBitmapDIB other) = delete;
 | 
			
		||||
 | 
			
		||||
	void Resize(UINT w, UINT h);
 | 
			
		||||
 | 
			
		||||
	HBITMAP GetHandle() const { return m_DIBSectionBuffer; }
 | 
			
		||||
	BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; }
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapSource
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
	IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY);
 | 
			
		||||
	IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette);
 | 
			
		||||
	IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer);
 | 
			
		||||
 | 
			
		||||
	// IWICBitmap
 | 
			
		||||
	IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock);
 | 
			
		||||
	IFACEMETHOD(SetPalette)(IWICPalette* pIPalette);
 | 
			
		||||
	IFACEMETHOD(SetResolution)(double dpiX, double dpiY);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class WICBitmapLockDIB;
 | 
			
		||||
 | 
			
		||||
	HBITMAP m_DIBSectionBuffer;
 | 
			
		||||
	LPDWORD m_DIBSectionBufferPixels;
 | 
			
		||||
	UINT m_W;
 | 
			
		||||
	UINT m_H;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPDIB_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this
 | 
			
		||||
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
//
 | 
			
		||||
// This class does not follow the COM reference count model. RTTI is used instead. This class
 | 
			
		||||
// implements only the bare essentials in order to use a DIB section as a Direct2D render target.
 | 
			
		||||
class WICBitmapDIB : public IWICBitmap
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapDIB();
 | 
			
		||||
	~WICBitmapDIB();
 | 
			
		||||
 | 
			
		||||
	WICBitmapDIB(const WICBitmapDIB& other) = delete;
 | 
			
		||||
	WICBitmapDIB& operator=(WICBitmapDIB other) = delete;
 | 
			
		||||
 | 
			
		||||
	void Resize(UINT w, UINT h);
 | 
			
		||||
 | 
			
		||||
	HBITMAP GetHandle() const { return m_DIBSectionBuffer; }
 | 
			
		||||
	BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; }
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapSource
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
	IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY);
 | 
			
		||||
	IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette);
 | 
			
		||||
	IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer);
 | 
			
		||||
 | 
			
		||||
	// IWICBitmap
 | 
			
		||||
	IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock);
 | 
			
		||||
	IFACEMETHOD(SetPalette)(IWICPalette* pIPalette);
 | 
			
		||||
	IFACEMETHOD(SetResolution)(double dpiX, double dpiY);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class WICBitmapLockDIB;
 | 
			
		||||
 | 
			
		||||
	HBITMAP m_DIBSectionBuffer;
 | 
			
		||||
	LPDWORD m_DIBSectionBufferPixels;
 | 
			
		||||
	UINT m_W;
 | 
			
		||||
	UINT m_H;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,91 +1,91 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapLockDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) :
 | 
			
		||||
	m_Bitmap(bitmap),
 | 
			
		||||
	m_Rect(lockRect),
 | 
			
		||||
	m_RefCount(1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WICBitmapLockDIB::~WICBitmapLockDIB()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	return m_Bitmap->GetSize(puiWidth, puiHeight);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride)
 | 
			
		||||
{
 | 
			
		||||
	UINT width = 0;
 | 
			
		||||
	m_Bitmap->GetSize(&width, nullptr);
 | 
			
		||||
 | 
			
		||||
	if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4;
 | 
			
		||||
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
 | 
			
		||||
{
 | 
			
		||||
	UINT stride = 0;
 | 
			
		||||
	GetStride(&stride);
 | 
			
		||||
 | 
			
		||||
	if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height;
 | 
			
		||||
	if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X];
 | 
			
		||||
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	return m_Bitmap->GetPixelFormat(pPixelFormat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapLockDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) :
 | 
			
		||||
	m_Bitmap(bitmap),
 | 
			
		||||
	m_Rect(lockRect),
 | 
			
		||||
	m_RefCount(1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WICBitmapLockDIB::~WICBitmapLockDIB()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	return m_Bitmap->GetSize(puiWidth, puiHeight);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride)
 | 
			
		||||
{
 | 
			
		||||
	UINT width = 0;
 | 
			
		||||
	m_Bitmap->GetSize(&width, nullptr);
 | 
			
		||||
 | 
			
		||||
	if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4;
 | 
			
		||||
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
 | 
			
		||||
{
 | 
			
		||||
	UINT stride = 0;
 | 
			
		||||
	GetStride(&stride);
 | 
			
		||||
 | 
			
		||||
	if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height;
 | 
			
		||||
	if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X];
 | 
			
		||||
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	return m_Bitmap->GetPixelFormat(pPixelFormat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,62 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
#include "WICBitmapDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this
 | 
			
		||||
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
class WICBitmapLockDIB : public IWICBitmapLock
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect);
 | 
			
		||||
	virtual ~WICBitmapLockDIB();
 | 
			
		||||
 | 
			
		||||
	void Resize(UINT w, UINT h);
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapLock
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetStride)(UINT* pcbStride);
 | 
			
		||||
	IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete;
 | 
			
		||||
	WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete;
 | 
			
		||||
 | 
			
		||||
	WICBitmapDIB* m_Bitmap;
 | 
			
		||||
	const WICRect* m_Rect;
 | 
			
		||||
	UINT m_RefCount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
#include "WICBitmapDIB.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this
 | 
			
		||||
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
class WICBitmapLockDIB : public IWICBitmapLock
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect);
 | 
			
		||||
	virtual ~WICBitmapLockDIB();
 | 
			
		||||
 | 
			
		||||
	void Resize(UINT w, UINT h);
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapLock
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetStride)(UINT* pcbStride);
 | 
			
		||||
	IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete;
 | 
			
		||||
	WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete;
 | 
			
		||||
 | 
			
		||||
	WICBitmapDIB* m_Bitmap;
 | 
			
		||||
	const WICRect* m_Rect;
 | 
			
		||||
	UINT m_RefCount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,82 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapLockGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapLockGDIP::WICBitmapLockGDIP() :
 | 
			
		||||
	m_RefCount(1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	*puiWidth = m_BitmapData.Width;
 | 
			
		||||
	*puiHeight = m_BitmapData.Height;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride)
 | 
			
		||||
{
 | 
			
		||||
	*pcbStride = m_BitmapData.Stride;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
 | 
			
		||||
{
 | 
			
		||||
	assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
 | 
			
		||||
	*pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height;
 | 
			
		||||
	*ppbData = (BYTE*)m_BitmapData.Scan0;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
 | 
			
		||||
	*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "WICBitmapLockGDIP.h"
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
WICBitmapLockGDIP::WICBitmapLockGDIP() :
 | 
			
		||||
	m_RefCount(1)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject)
 | 
			
		||||
{
 | 
			
		||||
	return E_NOTIMPL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef()
 | 
			
		||||
{
 | 
			
		||||
	++m_RefCount;
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release()
 | 
			
		||||
{
 | 
			
		||||
	--m_RefCount;
 | 
			
		||||
	if (m_RefCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		delete this;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m_RefCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight)
 | 
			
		||||
{
 | 
			
		||||
	*puiWidth = m_BitmapData.Width;
 | 
			
		||||
	*puiHeight = m_BitmapData.Height;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride)
 | 
			
		||||
{
 | 
			
		||||
	*pcbStride = m_BitmapData.Stride;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
 | 
			
		||||
{
 | 
			
		||||
	assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
 | 
			
		||||
	*pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height;
 | 
			
		||||
	*ppbData = (BYTE*)m_BitmapData.Scan0;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
 | 
			
		||||
{
 | 
			
		||||
	assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
 | 
			
		||||
	*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
 | 
			
		||||
	return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 
 | 
			
		||||
@@ -1,61 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is
 | 
			
		||||
// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
class WICBitmapLockGDIP : public IWICBitmapLock
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapLockGDIP();
 | 
			
		||||
 | 
			
		||||
	Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; }
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapLock
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetStride)(UINT* pcbStride);
 | 
			
		||||
	IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete;
 | 
			
		||||
	WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	Gdiplus::BitmapData m_BitmapData;
 | 
			
		||||
	UINT m_RefCount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (C) 2013 Birunthan Mohanathas
 | 
			
		||||
 | 
			
		||||
  This program is free software; you can redistribute it and/or
 | 
			
		||||
  modify it under the terms of the GNU General Public License
 | 
			
		||||
  as published by the Free Software Foundation; either version 2
 | 
			
		||||
  of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful,
 | 
			
		||||
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
  GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  along with this program; if not, write to the Free Software
 | 
			
		||||
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
 | 
			
		||||
#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <ole2.h>  // For Gdiplus.h.
 | 
			
		||||
#include <GdiPlus.h>
 | 
			
		||||
#include <wincodec.h>
 | 
			
		||||
 | 
			
		||||
namespace Gfx {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is
 | 
			
		||||
// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread.
 | 
			
		||||
class WICBitmapLockGDIP : public IWICBitmapLock
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	WICBitmapLockGDIP();
 | 
			
		||||
 | 
			
		||||
	Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; }
 | 
			
		||||
 | 
			
		||||
	// IUnknown
 | 
			
		||||
	IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
 | 
			
		||||
	IFACEMETHOD_(ULONG, AddRef)();
 | 
			
		||||
	IFACEMETHOD_(ULONG, Release)();
 | 
			
		||||
 | 
			
		||||
	// IWICBitmapLock
 | 
			
		||||
	IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
 | 
			
		||||
	IFACEMETHOD(GetStride)(UINT* pcbStride);
 | 
			
		||||
	IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
 | 
			
		||||
	IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete;
 | 
			
		||||
	WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete;
 | 
			
		||||
 | 
			
		||||
	Gdiplus::BitmapData m_BitmapData;
 | 
			
		||||
	UINT m_RefCount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace Util
 | 
			
		||||
}  // namespace Gfx
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user