Fixed line endings and applied gitignore

This commit is contained in:
2014-07-26 09:43:40 +03:00
parent 0c57cabe56
commit 7cba5cc109
542 changed files with 112014 additions and 119759 deletions

View File

@ -1,85 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{19312085-AA51-4BD6-BE92-4B6098CCA539}</ProjectGuid>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Lib>
<LinkTimeCodeGeneration Condition="'$(Configuration)'=='Release'">true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="Gfx\Canvas.cpp" />
<ClCompile Include="Gfx\CanvasD2D.cpp" />
<ClCompile Include="Gfx\CanvasGDIP.cpp" />
<ClCompile Include="Gfx\FontCollection.cpp" />
<ClCompile Include="Gfx\FontCollectionD2D.cpp" />
<ClCompile Include="Gfx\FontCollectionGDIP.cpp" />
<ClCompile Include="Gfx\TextFormat.cpp" />
<ClCompile Include="Gfx\TextFormatD2D.cpp" />
<ClCompile Include="Gfx\TextFormatGDIP.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp" />
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StdAfx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StringUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="Dialog.h" />
<ClInclude Include="Gfx\Canvas.h" />
<ClInclude Include="Gfx\CanvasD2D.h" />
<ClInclude Include="Gfx\CanvasGDIP.h" />
<ClInclude Include="Gfx\FontCollection.h" />
<ClInclude Include="Gfx\FontCollectionD2D.h" />
<ClInclude Include="Gfx\FontCollectionGDIP.h" />
<ClInclude Include="Gfx\TextFormat.h" />
<ClInclude Include="Gfx\TextFormatD2D.h" />
<ClInclude Include="Gfx\TextFormatGDIP.h" />
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h" />
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h" />
<ClInclude Include="Gfx\Util\DWriteHelpers.h" />
<ClInclude Include="Gfx\Util\WICBitmapDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UnitTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{19312085-AA51-4BD6-BE92-4B6098CCA539}</ProjectGuid>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Lib>
<LinkTimeCodeGeneration Condition="'$(Configuration)'=='Release'">true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="Gfx\Canvas.cpp" />
<ClCompile Include="Gfx\CanvasD2D.cpp" />
<ClCompile Include="Gfx\CanvasGDIP.cpp" />
<ClCompile Include="Gfx\FontCollection.cpp" />
<ClCompile Include="Gfx\FontCollectionD2D.cpp" />
<ClCompile Include="Gfx\FontCollectionGDIP.cpp" />
<ClCompile Include="Gfx\TextFormat.cpp" />
<ClCompile Include="Gfx\TextFormatD2D.cpp" />
<ClCompile Include="Gfx\TextFormatGDIP.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp" />
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StdAfx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StringUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="Dialog.h" />
<ClInclude Include="Gfx\Canvas.h" />
<ClInclude Include="Gfx\CanvasD2D.h" />
<ClInclude Include="Gfx\CanvasGDIP.h" />
<ClInclude Include="Gfx\FontCollection.h" />
<ClInclude Include="Gfx\FontCollectionD2D.h" />
<ClInclude Include="Gfx\FontCollectionGDIP.h" />
<ClInclude Include="Gfx\TextFormat.h" />
<ClInclude Include="Gfx\TextFormatD2D.h" />
<ClInclude Include="Gfx\TextFormatGDIP.h" />
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h" />
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h" />
<ClInclude Include="Gfx\Util\DWriteHelpers.h" />
<ClInclude Include="Gfx\Util\WICBitmapDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UnitTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,124 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StringUtil.cpp" />
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="Gfx\Canvas.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollection.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormat.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dialog.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="UnitTest.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Gfx\Canvas.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollection.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormat.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteHelpers.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Gfx">
<UniqueIdentifier>{263d9d8c-b463-4f2a-87ab-5f6575a4cc38}</UniqueIdentifier>
</Filter>
<Filter Include="Gfx\Util">
<UniqueIdentifier>{c3efb431-e0f5-4085-9b07-33a7e34c4baa}</UniqueIdentifier>
</Filter>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StringUtil.cpp" />
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="Gfx\Canvas.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollection.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormat.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dialog.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="UnitTest.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Gfx\Canvas.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollection.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormat.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteHelpers.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Gfx">
<UniqueIdentifier>{263d9d8c-b463-4f2a-87ab-5f6575a4cc38}</UniqueIdentifier>
</Filter>
<Filter Include="Gfx\Util">
<UniqueIdentifier>{c3efb431-e0f5-4085-9b07-33a7e34c4baa}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -1,33 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{442084A6-2069-4927-B0C9-51525A720CB2}</ProjectGuid>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<PropertyGroup>
<OutDir>$(IntDir)</OutDir>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="MathParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PathUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StringUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="Common.vcxproj">
<Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{442084A6-2069-4927-B0C9-51525A720CB2}</ProjectGuid>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<PropertyGroup>
<OutDir>$(IntDir)</OutDir>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="MathParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PathUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StringUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="Common.vcxproj">
<Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="PathUtil_Test.cpp" />
<ClCompile Include="StringUtil_Test.cpp" />
<ClCompile Include="MathParser_Test.cpp" />
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="PathUtil_Test.cpp" />
<ClCompile Include="StringUtil_Test.cpp" />
<ClCompile Include="MathParser_Test.cpp" />
</ItemGroup>
</Project>

View File

@ -1,50 +1,50 @@
/*
Copyright (C) 2012 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 "ControlTemplate.h"
namespace ControlTemplate
{
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString)
{
for (UINT i = 0; i < ctCount; ++i)
{
const Control& ct = cts[i];
WCHAR* text = ct.textId ? getString(ct.textId) : nullptr;
RECT r = { ct.x, ct.y, ct.w, ct.h };
MapDialogRect(parent, &r);
HWND wnd = CreateWindowEx(
ct.exStyle,
ct.name,
text,
ct.style,
r.left, r.top, r.right, r.bottom,
parent,
(HMENU)ct.id,
nullptr,
nullptr);
SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE);
}
}
/*
Copyright (C) 2012 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 "ControlTemplate.h"
namespace ControlTemplate
{
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString)
{
for (UINT i = 0; i < ctCount; ++i)
{
const Control& ct = cts[i];
WCHAR* text = ct.textId ? getString(ct.textId) : nullptr;
RECT r = { ct.x, ct.y, ct.w, ct.h };
MapDialogRect(parent, &r);
HWND wnd = CreateWindowEx(
ct.exStyle,
ct.name,
text,
ct.style,
r.left, r.top, r.right, r.bottom,
parent,
(HMENU)ct.id,
nullptr,
nullptr);
SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE);
}
}
} // namespace ControlTemplate

View File

@ -1,89 +1,89 @@
/*
Copyright (C) 2012 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_COMMON_CONTROLTEMPLATE_H_
#define RM_COMMON_CONTROLTEMPLATE_H_
#include <Windows.h>
namespace ControlTemplate
{
struct Control
{
const WCHAR* name;
WORD id;
WORD textId;
short x;
short y;
short w;
short h;
DWORD style;
DWORD exStyle;
};
typedef WCHAR* (*GetStringFunc)(UINT id);
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString);
// Helpers to declare control structs.
#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \
{ name, id, textId, x, y, w, h, WS_CHILD | style, exStyle }
#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle)
#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle)
#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle)
#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle)
#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle)
#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle)
#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle)
#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle)
#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle)
#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle)
#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle)
} // namespace ControlTemplate
/*
Copyright (C) 2012 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_COMMON_CONTROLTEMPLATE_H_
#define RM_COMMON_CONTROLTEMPLATE_H_
#include <Windows.h>
namespace ControlTemplate
{
struct Control
{
const WCHAR* name;
WORD id;
WORD textId;
short x;
short y;
short w;
short h;
DWORD style;
DWORD exStyle;
};
typedef WCHAR* (*GetStringFunc)(UINT id);
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString);
// Helpers to declare control structs.
#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \
{ name, id, textId, x, y, w, h, WS_CHILD | style, exStyle }
#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle)
#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle)
#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle)
#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle)
#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle)
#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle)
#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle)
#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle)
#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle)
#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle)
#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle)
} // namespace ControlTemplate
#endif

View File

@ -1,260 +1,260 @@
/*
Copyright (C) 2012 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 "Dialog.h"
HWND Dialog::c_ActiveDialogWindow = nullptr;
//
// BaseDialog
//
BaseDialog::BaseDialog() :
m_Window()
{
}
/*
** Create (if not already) and show the dialog.
**
*/
void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
if (m_Window)
{
// Show existing window.
ShowWindow(m_Window, SW_SHOW);
SetForegroundWindow(m_Window);
return;
}
const WCHAR* font = L"MS Shell Dlg 2";
const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR);
const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR);
const size_t dataSize = sizeof(DLGTEMPLATE) +
sizeof(WCHAR) + // Menu array.
sizeof(WCHAR) + // Class array.
titleSize + // Title array.
sizeof(WORD) + // Font point size.
fontSize; // Font array.
DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize];
dt->style = style | DS_SHELLFONT | WS_VISIBLE;
dt->dwExtendedStyle = exStyle;
dt->cdit = 0;
dt->x = x;
dt->y = y;
dt->cx = w;
dt->cy = h;
BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE);
// Menu array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Class array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Title array.
memcpy(dtExtra, title, titleSize);
dtExtra += titleSize;
// Font point size.
*(WORD*)dtExtra = 8;
dtExtra += sizeof(WORD);
// Font array.
memcpy(dtExtra, font, fontSize);
if (modeless)
{
CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
else
{
DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
delete [] dt;
}
void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString)
{
ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString);
}
INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG)
{
BaseDialog* dialog = (BaseDialog*)lParam;
dialog->m_Window = hWnd;
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog);
SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
return FALSE;
}
INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
//
// Dialog
//
Dialog::Dialog() : BaseDialog(),
m_Font(),
m_FontBold()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfMenuFont);
ncm.lfMenuFont.lfWeight = FW_BOLD;
ncm.lfMenuFont.lfHeight -= 2;
m_FontBold = CreateFontIndirect(&ncm.lfMenuFont);
}
Dialog::~Dialog()
{
DestroyWindow(m_Window);
DeleteObject(m_Font);
DeleteObject(m_FontBold);
}
void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
Show(title, x, y, w, h, style, exStyle, parent, modeless);
}
INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam)
{
c_ActiveDialogWindow = wParam ? m_Window : nullptr;
return FALSE;
}
bool Dialog::HandleMessage(MSG& msg)
{
if (c_ActiveDialogWindow)
{
if (IsDialogMessage(c_ActiveDialogWindow, &msg))
{
return true;
}
}
return false;
}
/*
** Subclass button control to draw arrow on the right.
**
*/
void Dialog::SetMenuButton(HWND button)
{
SetWindowSubclass(button, MenuButtonProc, 0, 0);
}
LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_PAINT:
{
// Draw arrow on top of the button
RECT buttonRect;
GetClientRect(hWnd, &buttonRect);
int arrowX = buttonRect.right - 18;
int arrowY = buttonRect.top + 4;
RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 };
HDC dc = GetDC(hWnd);
const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented
DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE);
DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags);
ReleaseDC(hWnd, dc);
}
break;
case WM_GETTEXT:
{
// Append 3 spaces to the button text to move text to the left so
// that it looks better with BS_CENTER.
WCHAR* str = (WCHAR*)lParam + result;
str[0] = str[1] = str[2] = L' ';
str[3] = '\0';
result += 3;
}
break;
case WM_GETTEXTLENGTH:
result += 3;
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass);
break;
}
return result;
}
//
// Tab
//
Dialog::Tab::Tab() : BaseDialog(),
m_Initialized(false)
{
}
void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner)
{
const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
const DWORD exStyle = WS_EX_CONTROLPARENT;
Show(L"", x, y, w, h, style, exStyle, owner, true);
EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB);
}
Dialog::Tab::~Tab()
{
DestroyWindow(m_Window);
}
void Dialog::Tab::Activate()
{
if (!m_Initialized)
{
Initialize();
}
EnableWindow(m_Window, TRUE);
BringWindowToTop(m_Window);
}
/*
Copyright (C) 2012 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 "Dialog.h"
HWND Dialog::c_ActiveDialogWindow = nullptr;
//
// BaseDialog
//
BaseDialog::BaseDialog() :
m_Window()
{
}
/*
** Create (if not already) and show the dialog.
**
*/
void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
if (m_Window)
{
// Show existing window.
ShowWindow(m_Window, SW_SHOW);
SetForegroundWindow(m_Window);
return;
}
const WCHAR* font = L"MS Shell Dlg 2";
const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR);
const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR);
const size_t dataSize = sizeof(DLGTEMPLATE) +
sizeof(WCHAR) + // Menu array.
sizeof(WCHAR) + // Class array.
titleSize + // Title array.
sizeof(WORD) + // Font point size.
fontSize; // Font array.
DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize];
dt->style = style | DS_SHELLFONT | WS_VISIBLE;
dt->dwExtendedStyle = exStyle;
dt->cdit = 0;
dt->x = x;
dt->y = y;
dt->cx = w;
dt->cy = h;
BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE);
// Menu array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Class array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Title array.
memcpy(dtExtra, title, titleSize);
dtExtra += titleSize;
// Font point size.
*(WORD*)dtExtra = 8;
dtExtra += sizeof(WORD);
// Font array.
memcpy(dtExtra, font, fontSize);
if (modeless)
{
CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
else
{
DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
delete [] dt;
}
void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString)
{
ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString);
}
INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG)
{
BaseDialog* dialog = (BaseDialog*)lParam;
dialog->m_Window = hWnd;
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog);
SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
return FALSE;
}
INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
//
// Dialog
//
Dialog::Dialog() : BaseDialog(),
m_Font(),
m_FontBold()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfMenuFont);
ncm.lfMenuFont.lfWeight = FW_BOLD;
ncm.lfMenuFont.lfHeight -= 2;
m_FontBold = CreateFontIndirect(&ncm.lfMenuFont);
}
Dialog::~Dialog()
{
DestroyWindow(m_Window);
DeleteObject(m_Font);
DeleteObject(m_FontBold);
}
void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
Show(title, x, y, w, h, style, exStyle, parent, modeless);
}
INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam)
{
c_ActiveDialogWindow = wParam ? m_Window : nullptr;
return FALSE;
}
bool Dialog::HandleMessage(MSG& msg)
{
if (c_ActiveDialogWindow)
{
if (IsDialogMessage(c_ActiveDialogWindow, &msg))
{
return true;
}
}
return false;
}
/*
** Subclass button control to draw arrow on the right.
**
*/
void Dialog::SetMenuButton(HWND button)
{
SetWindowSubclass(button, MenuButtonProc, 0, 0);
}
LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_PAINT:
{
// Draw arrow on top of the button
RECT buttonRect;
GetClientRect(hWnd, &buttonRect);
int arrowX = buttonRect.right - 18;
int arrowY = buttonRect.top + 4;
RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 };
HDC dc = GetDC(hWnd);
const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented
DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE);
DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags);
ReleaseDC(hWnd, dc);
}
break;
case WM_GETTEXT:
{
// Append 3 spaces to the button text to move text to the left so
// that it looks better with BS_CENTER.
WCHAR* str = (WCHAR*)lParam + result;
str[0] = str[1] = str[2] = L' ';
str[3] = '\0';
result += 3;
}
break;
case WM_GETTEXTLENGTH:
result += 3;
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass);
break;
}
return result;
}
//
// Tab
//
Dialog::Tab::Tab() : BaseDialog(),
m_Initialized(false)
{
}
void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner)
{
const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
const DWORD exStyle = WS_EX_CONTROLPARENT;
Show(L"", x, y, w, h, style, exStyle, owner, true);
EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB);
}
Dialog::Tab::~Tab()
{
DestroyWindow(m_Window);
}
void Dialog::Tab::Activate()
{
if (!m_Initialized)
{
Initialize();
}
EnableWindow(m_Window, TRUE);
BringWindowToTop(m_Window);
}

View File

@ -1,97 +1,97 @@
/*
Copyright (C) 2012 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_COMMON_DIALOG_H_
#define RM_COMMON_DIALOG_H_
#include <Windows.h>
#include "ControlTemplate.h"
// Shared base class for Dialog and Tab.
class BaseDialog
{
public:
HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); }
protected:
BaseDialog();
virtual ~BaseDialog() {}
void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless);
void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString);
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; }
HWND m_Window;
private:
BaseDialog(const BaseDialog& r);
static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
class Dialog : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
static bool HandleMessage(MSG& msg);
protected:
class Tab : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
bool IsInitialized() { return m_Initialized; }
void Activate();
virtual void Initialize() {}
virtual void Resize(int w, int h) {}
protected:
Tab();
virtual ~Tab();
void CreateTabWindow(short x, short y, short w, short h, HWND owner);
bool m_Initialized;
};
Dialog();
virtual ~Dialog();
void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true);
INT_PTR OnActivate(WPARAM wParam, LPARAM lParam);
static void SetMenuButton(HWND button);
HFONT m_Font;
HFONT m_FontBold;
private:
Dialog(const Dialog& r);
static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static HWND c_ActiveDialogWindow;
};
#endif
/*
Copyright (C) 2012 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_COMMON_DIALOG_H_
#define RM_COMMON_DIALOG_H_
#include <Windows.h>
#include "ControlTemplate.h"
// Shared base class for Dialog and Tab.
class BaseDialog
{
public:
HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); }
protected:
BaseDialog();
virtual ~BaseDialog() {}
void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless);
void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString);
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; }
HWND m_Window;
private:
BaseDialog(const BaseDialog& r);
static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
class Dialog : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
static bool HandleMessage(MSG& msg);
protected:
class Tab : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
bool IsInitialized() { return m_Initialized; }
void Activate();
virtual void Initialize() {}
virtual void Resize(int w, int h) {}
protected:
Tab();
virtual ~Tab();
void CreateTabWindow(short x, short y, short w, short h, HWND owner);
bool m_Initialized;
};
Dialog();
virtual ~Dialog();
void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true);
INT_PTR OnActivate(WPARAM wParam, LPARAM lParam);
static void SetMenuButton(HWND button);
HFONT m_Font;
HFONT m_FontBold;
private:
Dialog(const Dialog& r);
static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static HWND c_ActiveDialogWindow;
};
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,39 @@
/*
Copyright (C) 2011 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.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#ifndef RM_COMMON_MATHPARSER_H_
#define RM_COMMON_MATHPARSER_H_
#include <Windows.h>
namespace MathParser
{
typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context);
const WCHAR* Check(const WCHAR* formula);
const WCHAR* CheckedParse(const WCHAR* formula, double* result);
const WCHAR* Parse(
const WCHAR* formula, double* result,
GetValueFunc getValue = nullptr, void* getValueContext = nullptr);
bool IsDelimiter(WCHAR ch);
};
/*
Copyright (C) 2011 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.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#ifndef RM_COMMON_MATHPARSER_H_
#define RM_COMMON_MATHPARSER_H_
#include <Windows.h>
namespace MathParser
{
typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context);
const WCHAR* Check(const WCHAR* formula);
const WCHAR* CheckedParse(const WCHAR* formula, double* result);
const WCHAR* Parse(
const WCHAR* formula, double* result,
GetValueFunc getValue = nullptr, void* getValueContext = nullptr);
bool IsDelimiter(WCHAR ch);
};
#endif

View File

@ -1,124 +1,124 @@
/*
Copyright (C) 2013 Rainmeter Team
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 "MathParser.h"
#include "UnitTest.h"
namespace MathParser {
TEST_CLASS(Common_MathParser_Test)
{
public:
void ParseAssert(double expected, const WCHAR* formula)
{
double value = 0.0;
Assert::IsNull(Parse(formula, &value));
Assert::AreEqual(expected, value);
}
TEST_METHOD(TestParse)
{
ParseAssert(5.0, L"5");
ParseAssert(5.0, L" 5 ");
ParseAssert(5.0, L"((((5))))");
ParseAssert(10.0, L"(5 + 5)");
ParseAssert(-10.0, L"(-5 - 5)");
ParseAssert(10.0, L"-(-5-5)");
ParseAssert(10.0, L"-(-5+-5)");
ParseAssert(1.0, L"1 && 1");
ParseAssert(0.0, L"1 && 0");
ParseAssert(1.0, L"1 || 1");
ParseAssert(1.0, L"1 || -1");
ParseAssert(0.0, L"1 < 2 && 2 > 1");
ParseAssert(1.0, L"(1 < 2) && (2 > 1)");
ParseAssert(sin(50.0), L"sin(50)");
ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)");
ParseAssert(1.0, L"01");
ParseAssert(11.0, L"011");
ParseAssert(3.0, L"0b11");
ParseAssert(10.0, L"0xA");
ParseAssert(10.0, L"0o12");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(3.0, L"0 ? 2 : 3");
ParseAssert(5.0, L"1 ? (2 + 3) : 3");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5");
ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5");
ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)");
ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))");
ParseAssert(1.0, L"trunc(1.5)");
ParseAssert(-1.0, L"trunc(-1.5)");
ParseAssert(2.0, L"round(1.555)");
ParseAssert(1.56, L"round(1.555, 2)");
double value;
Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value));
Assert::IsNotNull(Parse(L"++1", &value));
Assert::IsNotNull(Parse(L"((1)", &value));
Assert::IsNotNull(Parse(L"1 / 0", &value));
Assert::IsNotNull(Parse(L"1 &&", &value));
Assert::IsNotNull(Parse(L"a", &value));
Assert::IsNull(Parse(L"e", &value));
Assert::AreEqual(2, (int)value);
Assert::IsNull(Parse(L"pi", &value));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"pi", &value, GetValueHelper));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper));
Assert::AreEqual(15.0, value);
Assert::IsNull(Parse(L"bbb", &value, GetValueHelper));
Assert::AreEqual(20.0, value);
Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1));
Assert::AreEqual(30.0, value);
}
static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context)
{
if (wcsncmp(str, L"a", len) == 0)
{
*value = 10.0;
return true;
}
else if (wcsncmp(str, L"bbb", len) == 0)
{
*value = 20.0;
return true;
}
else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1)
{
*value = 30.0;
return true;
}
else if (wcsncmp(str, L"pi", len) == 0)
{
*value = 40.0;
return true;
}
return false;
}
};
} // namespace StringUtil
/*
Copyright (C) 2013 Rainmeter Team
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 "MathParser.h"
#include "UnitTest.h"
namespace MathParser {
TEST_CLASS(Common_MathParser_Test)
{
public:
void ParseAssert(double expected, const WCHAR* formula)
{
double value = 0.0;
Assert::IsNull(Parse(formula, &value));
Assert::AreEqual(expected, value);
}
TEST_METHOD(TestParse)
{
ParseAssert(5.0, L"5");
ParseAssert(5.0, L" 5 ");
ParseAssert(5.0, L"((((5))))");
ParseAssert(10.0, L"(5 + 5)");
ParseAssert(-10.0, L"(-5 - 5)");
ParseAssert(10.0, L"-(-5-5)");
ParseAssert(10.0, L"-(-5+-5)");
ParseAssert(1.0, L"1 && 1");
ParseAssert(0.0, L"1 && 0");
ParseAssert(1.0, L"1 || 1");
ParseAssert(1.0, L"1 || -1");
ParseAssert(0.0, L"1 < 2 && 2 > 1");
ParseAssert(1.0, L"(1 < 2) && (2 > 1)");
ParseAssert(sin(50.0), L"sin(50)");
ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)");
ParseAssert(1.0, L"01");
ParseAssert(11.0, L"011");
ParseAssert(3.0, L"0b11");
ParseAssert(10.0, L"0xA");
ParseAssert(10.0, L"0o12");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(3.0, L"0 ? 2 : 3");
ParseAssert(5.0, L"1 ? (2 + 3) : 3");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5");
ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5");
ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)");
ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))");
ParseAssert(1.0, L"trunc(1.5)");
ParseAssert(-1.0, L"trunc(-1.5)");
ParseAssert(2.0, L"round(1.555)");
ParseAssert(1.56, L"round(1.555, 2)");
double value;
Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value));
Assert::IsNotNull(Parse(L"++1", &value));
Assert::IsNotNull(Parse(L"((1)", &value));
Assert::IsNotNull(Parse(L"1 / 0", &value));
Assert::IsNotNull(Parse(L"1 &&", &value));
Assert::IsNotNull(Parse(L"a", &value));
Assert::IsNull(Parse(L"e", &value));
Assert::AreEqual(2, (int)value);
Assert::IsNull(Parse(L"pi", &value));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"pi", &value, GetValueHelper));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper));
Assert::AreEqual(15.0, value);
Assert::IsNull(Parse(L"bbb", &value, GetValueHelper));
Assert::AreEqual(20.0, value);
Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1));
Assert::AreEqual(30.0, value);
}
static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context)
{
if (wcsncmp(str, L"a", len) == 0)
{
*value = 10.0;
return true;
}
else if (wcsncmp(str, L"bbb", len) == 0)
{
*value = 20.0;
return true;
}
else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1)
{
*value = 30.0;
return true;
}
else if (wcsncmp(str, L"pi", len) == 0)
{
*value = 40.0;
return true;
}
return false;
}
};
} // namespace StringUtil

View File

@ -1,64 +1,64 @@
/*
Copyright (C) 2012 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 "MenuTemplate.h"
HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString)
{
UINT itemIndex = 0;
return CreateSubMenu(items, itemIndex, itemCount, getString);
}
HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString)
{
HMENU menu = CreatePopupMenu();
do
{
const MenuTemplate& item = items[itemIndex];
++itemIndex;
UINT itemFlags = MF_STRING;
UINT_PTR itemId = item.id;
const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr;
if (item.type == MenuItem_ItemGrayed)
{
itemFlags |= MF_GRAYED;
}
else if (item.type == MenuItem_Separator)
{
itemFlags = MF_SEPARATOR;
}
else if (item.type == MenuItem_SubMenuBegin)
{
itemFlags = MF_POPUP;
itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString);
}
else if (item.type == MenuItem_SubMenuEnd)
{
return menu;
}
AppendMenu(menu, itemFlags, itemId, itemText);
}
while (itemIndex < itemCount);
return menu;
}
/*
Copyright (C) 2012 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 "MenuTemplate.h"
HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString)
{
UINT itemIndex = 0;
return CreateSubMenu(items, itemIndex, itemCount, getString);
}
HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString)
{
HMENU menu = CreatePopupMenu();
do
{
const MenuTemplate& item = items[itemIndex];
++itemIndex;
UINT itemFlags = MF_STRING;
UINT_PTR itemId = item.id;
const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr;
if (item.type == MenuItem_ItemGrayed)
{
itemFlags |= MF_GRAYED;
}
else if (item.type == MenuItem_Separator)
{
itemFlags = MF_SEPARATOR;
}
else if (item.type == MenuItem_SubMenuBegin)
{
itemFlags = MF_POPUP;
itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString);
}
else if (item.type == MenuItem_SubMenuEnd)
{
return menu;
}
AppendMenu(menu, itemFlags, itemId, itemText);
}
while (itemIndex < itemCount);
return menu;
}

View File

@ -1,52 +1,52 @@
/*
Copyright (C) 2012 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_COMMON_MENUTEMPLATE_H_
#define RM_COMMON_MENUTEMPLATE_H_
#include <Windows.h>
struct MenuTemplate
{
BYTE type;
WORD id;
WORD idText;
typedef WCHAR* (*GetStringFunc)(UINT id);
static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString);
private:
static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString);
};
enum MenuTemplateItem
{
MenuItem_Item,
MenuItem_ItemGrayed,
MenuItem_Separator,
MenuItem_SubMenuBegin,
MenuItem_SubMenuEnd
};
#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ }
#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ }
#define MENU_SEPARATOR() { MenuItem_Separator }
#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd }
#endif
/*
Copyright (C) 2012 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_COMMON_MENUTEMPLATE_H_
#define RM_COMMON_MENUTEMPLATE_H_
#include <Windows.h>
struct MenuTemplate
{
BYTE type;
WORD id;
WORD idText;
typedef WCHAR* (*GetStringFunc)(UINT id);
static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString);
private:
static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString);
};
enum MenuTemplateItem
{
MenuItem_Item,
MenuItem_ItemGrayed,
MenuItem_Separator,
MenuItem_SubMenuBegin,
MenuItem_SubMenuEnd
};
#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ }
#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ }
#define MENU_SEPARATOR() { MenuItem_Separator }
#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd }
#endif

View File

@ -1,149 +1,149 @@
/*
Copyright (C) 2013 Rainmeter Team
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 "PathUtil.h"
namespace PathUtil {
bool IsSeparator(WCHAR ch)
{
return ch == L'\\' || ch == L'/';
}
bool IsDotOrDotDot(const WCHAR* path)
{
return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0'));
}
bool IsUNC(const std::wstring& path)
{
return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]);
}
bool IsAbsolute(const std::wstring& path)
{
return (path.find(L":\\") != std::wstring::npos ||
path.find(L":/") != std::wstring::npos ||
IsUNC(path));
}
void AppendBacklashIfMissing(std::wstring& path)
{
if (!path.empty() && !IsSeparator(path[path.length() - 1]))
{
path += L'\\';
}
}
std::wstring GetFolderFromFilePath(const std::wstring& filePath)
{
std::wstring::size_type pos = filePath.find_last_of(L"\\/");
if (pos != std::wstring::npos)
{
return filePath.substr(0, pos + 1);
}
return L".\\";
}
/*
** Extracts volume path from program path.
** E.g.:
** "C:\path\" to "C:"
** "\\server\share\" to "\\server\share"
** "\\server\C:\path\" to "\\server\C:"
*/
std::wstring GetVolume(const std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find_first_of(L':')) != std::wstring::npos)
{
return path.substr(0, pos + 1);
}
else if (IsUNC(path))
{
if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos)
{
std::wstring::size_type pos2;
if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos ||
pos != (path.length() - 1))
{
pos = pos2;
}
}
return path.substr(0, pos);
}
return std::wstring();
}
void ExpandEnvironmentVariables(std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
DWORD bufSize = 4096;
WCHAR* buffer = new WCHAR[bufSize];
// %APPDATA% is a special case.
pos = path.find(L"%APPDATA%", pos);
if (pos != std::wstring::npos)
{
HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer);
if (SUCCEEDED(hr))
{
size_t len = wcslen(buffer);
do
{
path.replace(pos, 9, buffer, len);
}
while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos);
}
}
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
// Expand the environment variables.
do
{
DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize);
if (ret == 0) // Error
{
break;
}
if (ret <= bufSize) // Fits in the buffer
{
path.assign(buffer, ret - 1);
break;
}
delete [] buffer;
bufSize = ret;
buffer = new WCHAR[bufSize];
}
while (true);
}
delete [] buffer;
}
}
} // namespace PathUtil
/*
Copyright (C) 2013 Rainmeter Team
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 "PathUtil.h"
namespace PathUtil {
bool IsSeparator(WCHAR ch)
{
return ch == L'\\' || ch == L'/';
}
bool IsDotOrDotDot(const WCHAR* path)
{
return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0'));
}
bool IsUNC(const std::wstring& path)
{
return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]);
}
bool IsAbsolute(const std::wstring& path)
{
return (path.find(L":\\") != std::wstring::npos ||
path.find(L":/") != std::wstring::npos ||
IsUNC(path));
}
void AppendBacklashIfMissing(std::wstring& path)
{
if (!path.empty() && !IsSeparator(path[path.length() - 1]))
{
path += L'\\';
}
}
std::wstring GetFolderFromFilePath(const std::wstring& filePath)
{
std::wstring::size_type pos = filePath.find_last_of(L"\\/");
if (pos != std::wstring::npos)
{
return filePath.substr(0, pos + 1);
}
return L".\\";
}
/*
** Extracts volume path from program path.
** E.g.:
** "C:\path\" to "C:"
** "\\server\share\" to "\\server\share"
** "\\server\C:\path\" to "\\server\C:"
*/
std::wstring GetVolume(const std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find_first_of(L':')) != std::wstring::npos)
{
return path.substr(0, pos + 1);
}
else if (IsUNC(path))
{
if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos)
{
std::wstring::size_type pos2;
if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos ||
pos != (path.length() - 1))
{
pos = pos2;
}
}
return path.substr(0, pos);
}
return std::wstring();
}
void ExpandEnvironmentVariables(std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
DWORD bufSize = 4096;
WCHAR* buffer = new WCHAR[bufSize];
// %APPDATA% is a special case.
pos = path.find(L"%APPDATA%", pos);
if (pos != std::wstring::npos)
{
HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer);
if (SUCCEEDED(hr))
{
size_t len = wcslen(buffer);
do
{
path.replace(pos, 9, buffer, len);
}
while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos);
}
}
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
// Expand the environment variables.
do
{
DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize);
if (ret == 0) // Error
{
break;
}
if (ret <= bufSize) // Fits in the buffer
{
path.assign(buffer, ret - 1);
break;
}
delete [] buffer;
bufSize = ret;
buffer = new WCHAR[bufSize];
}
while (true);
}
delete [] buffer;
}
}
} // namespace PathUtil

View File

@ -1,45 +1,45 @@
/*
Copyright (C) 2013 Rainmeter Team
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_COMMON_PATHUTIL_H_
#define RM_COMMON_PATHUTIL_H_
#include <Windows.h>
#include <string>
namespace PathUtil {
bool IsSeparator(WCHAR ch);
bool IsDotOrDotDot(const WCHAR* path);
bool IsUNC(const std::wstring& path);
bool IsAbsolute(const std::wstring& path);
void AppendBacklashIfMissing(std::wstring& path);
std::wstring GetFolderFromFilePath(const std::wstring& filePath);
std::wstring GetVolume(const std::wstring& path);
void ExpandEnvironmentVariables(std::wstring& strPath);
} // namespace PathUtil
#endif
/*
Copyright (C) 2013 Rainmeter Team
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_COMMON_PATHUTIL_H_
#define RM_COMMON_PATHUTIL_H_
#include <Windows.h>
#include <string>
namespace PathUtil {
bool IsSeparator(WCHAR ch);
bool IsDotOrDotDot(const WCHAR* path);
bool IsUNC(const std::wstring& path);
bool IsAbsolute(const std::wstring& path);
void AppendBacklashIfMissing(std::wstring& path);
std::wstring GetFolderFromFilePath(const std::wstring& filePath);
std::wstring GetVolume(const std::wstring& path);
void ExpandEnvironmentVariables(std::wstring& strPath);
} // namespace PathUtil
#endif

View File

@ -1,106 +1,106 @@
/*
Copyright (C) 2013 Rainmeter Team
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 "PathUtil.h"
#include "UnitTest.h"
#include <Shlobj.h>
namespace PathUtil {
TEST_CLASS(Common_PathUtil_Test)
{
public:
TEST_METHOD(TestIsSeparator)
{
Assert::IsTrue(IsSeparator(L'\\'));
Assert::IsTrue(IsSeparator(L'/'));
Assert::IsFalse(IsSeparator(L'.'));
}
TEST_METHOD(TestIsDotOrDotDot)
{
Assert::IsTrue(IsDotOrDotDot(L"."));
Assert::IsTrue(IsDotOrDotDot(L".."));
Assert::IsFalse(IsDotOrDotDot(L"..."));
Assert::IsFalse(IsDotOrDotDot(L""));
}
TEST_METHOD(TestIsUNC)
{
Assert::IsTrue(IsUNC(L"\\\\server"));
Assert::IsTrue(IsUNC(L"//server"));
}
TEST_METHOD(TestIsAbsolute)
{
Assert::IsTrue(IsAbsolute(L"\\\\server"));
Assert::IsTrue(IsAbsolute(L"C:\\test"));
Assert::IsTrue(IsAbsolute(L"C:/test"));
Assert::IsFalse(IsAbsolute(L"C:"));
}
TEST_METHOD(TestAppendBacklashIfMissing)
{
std::wstring path;
AppendBacklashIfMissing(path);
Assert::IsTrue(path.empty());
std::wstring path2 = L"C:\\test";
AppendBacklashIfMissing(path2);
Assert::IsTrue(path2 == L"C:\\test\\");
std::wstring path3 = L"C:\\test\\";
AppendBacklashIfMissing(path3);
Assert::IsTrue(path3 == L"C:\\test\\");
}
TEST_METHOD(TestGetFolderFromFilePath)
{
Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\");
}
TEST_METHOD(TestGetVolume)
{
Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:");
Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share");
Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:");
}
TEST_METHOD(TestExpandEnvironmentVariables)
{
WCHAR appdataPath[MAX_PATH];
SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath);
WCHAR windirPath[MAX_PATH];
ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH);
std::wstring test = L"%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test);
Assert::IsTrue(test == appdataPath);
std::wstring test2 = L"%APPDATA%%WINDIR%";
PathUtil::ExpandEnvironmentVariables(test2);
Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath));
std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test3);
Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath));
}
};
} // namespace PathUtil
/*
Copyright (C) 2013 Rainmeter Team
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 "PathUtil.h"
#include "UnitTest.h"
#include <Shlobj.h>
namespace PathUtil {
TEST_CLASS(Common_PathUtil_Test)
{
public:
TEST_METHOD(TestIsSeparator)
{
Assert::IsTrue(IsSeparator(L'\\'));
Assert::IsTrue(IsSeparator(L'/'));
Assert::IsFalse(IsSeparator(L'.'));
}
TEST_METHOD(TestIsDotOrDotDot)
{
Assert::IsTrue(IsDotOrDotDot(L"."));
Assert::IsTrue(IsDotOrDotDot(L".."));
Assert::IsFalse(IsDotOrDotDot(L"..."));
Assert::IsFalse(IsDotOrDotDot(L""));
}
TEST_METHOD(TestIsUNC)
{
Assert::IsTrue(IsUNC(L"\\\\server"));
Assert::IsTrue(IsUNC(L"//server"));
}
TEST_METHOD(TestIsAbsolute)
{
Assert::IsTrue(IsAbsolute(L"\\\\server"));
Assert::IsTrue(IsAbsolute(L"C:\\test"));
Assert::IsTrue(IsAbsolute(L"C:/test"));
Assert::IsFalse(IsAbsolute(L"C:"));
}
TEST_METHOD(TestAppendBacklashIfMissing)
{
std::wstring path;
AppendBacklashIfMissing(path);
Assert::IsTrue(path.empty());
std::wstring path2 = L"C:\\test";
AppendBacklashIfMissing(path2);
Assert::IsTrue(path2 == L"C:\\test\\");
std::wstring path3 = L"C:\\test\\";
AppendBacklashIfMissing(path3);
Assert::IsTrue(path3 == L"C:\\test\\");
}
TEST_METHOD(TestGetFolderFromFilePath)
{
Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\");
}
TEST_METHOD(TestGetVolume)
{
Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:");
Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share");
Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:");
}
TEST_METHOD(TestExpandEnvironmentVariables)
{
WCHAR appdataPath[MAX_PATH];
SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath);
WCHAR windirPath[MAX_PATH];
ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH);
std::wstring test = L"%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test);
Assert::IsTrue(test == appdataPath);
std::wstring test2 = L"%APPDATA%%WINDIR%";
PathUtil::ExpandEnvironmentVariables(test2);
Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath));
std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test3);
Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath));
}
};
} // namespace PathUtil

View File

@ -1,102 +1,102 @@
/*
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 "Platform.h"
namespace Platform {
LPCWSTR GetPlatformName()
{
const bool isServer = IsWindowsServer();
// Note: Place newer versions at the top.
if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1";
if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8";
if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7";
if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista";
if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP";
return L"Unknown";
}
std::wstring GetPlatformFriendlyName()
{
std::wstring name;
WCHAR buffer[256];
DWORD size = _countof(buffer);
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += buffer;
name += L' ';
name += Is64BitWindows() ? L"64" : L"32";
name += L"-bit";
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS ||
RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L" (build ";
name += buffer;
name += L')';
}
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L' ';
name += buffer;
}
}
RegCloseKey(hKey);
}
else
{
name = L"Windows version unknown";
}
return name;
}
/*
** Returns |true| if running on 64-bit Windows.
*/
bool Is64BitWindows()
{
#if _WIN64
return true;
#endif
auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
BOOL isWow64 = FALSE;
return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
}
return false;
}
/*
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 "Platform.h"
namespace Platform {
LPCWSTR GetPlatformName()
{
const bool isServer = IsWindowsServer();
// Note: Place newer versions at the top.
if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1";
if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8";
if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7";
if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista";
if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP";
return L"Unknown";
}
std::wstring GetPlatformFriendlyName()
{
std::wstring name;
WCHAR buffer[256];
DWORD size = _countof(buffer);
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += buffer;
name += L' ';
name += Is64BitWindows() ? L"64" : L"32";
name += L"-bit";
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS ||
RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L" (build ";
name += buffer;
name += L')';
}
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L' ';
name += buffer;
}
}
RegCloseKey(hKey);
}
else
{
name = L"Windows version unknown";
}
return name;
}
/*
** Returns |true| if running on 64-bit Windows.
*/
bool Is64BitWindows()
{
#if _WIN64
return true;
#endif
auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
BOOL isWow64 = FALSE;
return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
}
return false;
}
} // namespace Platform

View File

@ -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.
*/
#ifndef RM_COMMON_PLATFORM_H_
#define RM_COMMON_PLATFORM_H_
#include <string>
namespace Platform {
LPCWSTR GetPlatformName();
std::wstring GetPlatformFriendlyName();
bool Is64BitWindows();
} // namespace Platform
#endif
/*
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_COMMON_PLATFORM_H_
#define RM_COMMON_PLATFORM_H_
#include <string>
namespace Platform {
LPCWSTR GetPlatformName();
std::wstring GetPlatformFriendlyName();
bool Is64BitWindows();
} // namespace Platform
#endif

View File

@ -1,92 +1,92 @@
/*
Copyright (C) 2011 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_COMMON_RAWSTRING_H_
#define RM_COMMON_RAWSTRING_H_
#include <malloc.h>
class RawString
{
public:
RawString() :
m_String()
{
}
RawString(const wchar_t* str) :
m_String(str_alloc(str))
{
}
RawString(const RawString& rhs) :
m_String(str_alloc(rhs.c_str()))
{
}
~RawString()
{
clear();
}
RawString& operator=(const wchar_t* rhs)
{
clear();
m_String = str_alloc(rhs);
return *this;
}
RawString& operator=(const RawString& rhs)
{
if (&rhs != this)
{
clear();
m_String = str_alloc(rhs.m_String);
}
return *this;
}
const wchar_t* c_str() const
{
return m_String ? m_String : L"";
}
bool empty() const
{
return !m_String || !(*m_String);
}
void clear()
{
if (m_String)
{
free(m_String);
m_String = nullptr;
}
}
private:
wchar_t* str_alloc(const wchar_t* str)
{
return str ? _wcsdup(str) : nullptr;
}
wchar_t* m_String;
};
#endif
/*
Copyright (C) 2011 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_COMMON_RAWSTRING_H_
#define RM_COMMON_RAWSTRING_H_
#include <malloc.h>
class RawString
{
public:
RawString() :
m_String()
{
}
RawString(const wchar_t* str) :
m_String(str_alloc(str))
{
}
RawString(const RawString& rhs) :
m_String(str_alloc(rhs.c_str()))
{
}
~RawString()
{
clear();
}
RawString& operator=(const wchar_t* rhs)
{
clear();
m_String = str_alloc(rhs);
return *this;
}
RawString& operator=(const RawString& rhs)
{
if (&rhs != this)
{
clear();
m_String = str_alloc(rhs.m_String);
}
return *this;
}
const wchar_t* c_str() const
{
return m_String ? m_String : L"";
}
bool empty() const
{
return !m_String || !(*m_String);
}
void clear()
{
if (m_String)
{
free(m_String);
m_String = nullptr;
}
}
private:
wchar_t* str_alloc(const wchar_t* str)
{
return str ? _wcsdup(str) : nullptr;
}
wchar_t* m_String;
};
#endif

View File

@ -1,95 +1,95 @@
/*
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 "StringUtil.h"
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen, int cp)
{
std::string narrowStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)wcslen(str);
}
int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr);
if (bufLen > 0)
{
narrowStr.resize(bufLen);
WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr);
}
}
return narrowStr;
}
std::wstring Widen(const char* str, int strLen, int cp)
{
std::wstring wideStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)strlen(str);
}
int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0);
if (bufLen > 0)
{
wideStr.resize(bufLen);
MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen);
}
}
return wideStr;
}
/*
** Escapes reserved PCRE regex metacharacters.
*/
void EscapeRegExp(std::wstring& str)
{
size_t start = 0;
while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos)
{
str.insert(start, L"\\");
start += 2;
}
}
/*
** Escapes reserved URL characters.
*/
void EncodeUrl(std::wstring& str)
{
size_t pos = 0;
while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos)
{
WCHAR buffer[3];
_snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]);
str[pos] = L'%';
str.insert(pos + 1, buffer);
pos += 3;
}
}
} // namespace StringUtil
/*
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 "StringUtil.h"
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen, int cp)
{
std::string narrowStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)wcslen(str);
}
int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr);
if (bufLen > 0)
{
narrowStr.resize(bufLen);
WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr);
}
}
return narrowStr;
}
std::wstring Widen(const char* str, int strLen, int cp)
{
std::wstring wideStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)strlen(str);
}
int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0);
if (bufLen > 0)
{
wideStr.resize(bufLen);
MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen);
}
}
return wideStr;
}
/*
** Escapes reserved PCRE regex metacharacters.
*/
void EscapeRegExp(std::wstring& str)
{
size_t start = 0;
while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos)
{
str.insert(start, L"\\");
start += 2;
}
}
/*
** Escapes reserved URL characters.
*/
void EncodeUrl(std::wstring& str)
{
size_t pos = 0;
while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos)
{
WCHAR buffer[3];
_snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]);
str[pos] = L'%';
str.insert(pos + 1, buffer);
pos += 3;
}
}
} // namespace StringUtil

View File

@ -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.
*/
#ifndef RM_COMMON_STRINGUTIL_H_
#define RM_COMMON_STRINGUTIL_H_
#include <Windows.h>
#include <algorithm>
#include <locale>
#include <string>
/*
** Helper class for case insensitive find function.
*/
template<typename CharT>
struct Is_Equal
{
Is_Equal(const std::locale& loc) : locale(loc) { }
bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); }
private:
const std::locale& locale;
};
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP);
inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); }
inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); }
inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); }
std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP);
inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); }
inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); }
inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); }
void EscapeRegExp(std::wstring& str);
void EncodeUrl(std::wstring& str);
/*
** Case insensitive find function for std::string and std::wstring.
**
** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296
*/
template<typename T>
std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale())
{
T::const_iterator iter = std::search(str1.begin(), str1.end(),
str2.begin(), str2.end(), Is_Equal<T::value_type>(loc));
if (iter != str1.end())
{
return (iter - str1.begin());
}
return -1; // not found
}
} // namespace StringUtil
#endif
/*
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_COMMON_STRINGUTIL_H_
#define RM_COMMON_STRINGUTIL_H_
#include <Windows.h>
#include <algorithm>
#include <locale>
#include <string>
/*
** Helper class for case insensitive find function.
*/
template<typename CharT>
struct Is_Equal
{
Is_Equal(const std::locale& loc) : locale(loc) { }
bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); }
private:
const std::locale& locale;
};
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP);
inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); }
inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); }
inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); }
std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP);
inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); }
inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); }
inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); }
void EscapeRegExp(std::wstring& str);
void EncodeUrl(std::wstring& str);
/*
** Case insensitive find function for std::string and std::wstring.
**
** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296
*/
template<typename T>
std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale())
{
T::const_iterator iter = std::search(str1.begin(), str1.end(),
str2.begin(), str2.end(), Is_Equal<T::value_type>(loc));
if (iter != str1.end())
{
return (iter - str1.begin());
}
return -1; // not found
}
} // namespace StringUtil
#endif

View File

@ -1,58 +1,58 @@
/*
Copyright (C) 2013 Rainmeter Team
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 "StringUtil.h"
#include "UnitTest.h"
namespace StringUtil {
TEST_CLASS(Common_StringUtil_Test)
{
public:
TEST_METHOD(TestWiden)
{
Assert::AreEqual(L"test", Widen("test").c_str());
Assert::AreEqual(L"te", Widen("test", 2).c_str());
Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str());
Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str());
}
TEST_METHOD(TestNarrow)
{
Assert::AreEqual("test", Narrow(L"test").c_str());
Assert::AreEqual("te", Narrow(L"test", 2).c_str());
Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str());
Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str());
}
TEST_METHOD(TestEscapeRegExp)
{
std::wstring str = L"\\^$|(test)[{. ing+*?";
EscapeRegExp(str);
Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str());
}
TEST_METHOD(TestEncodeUrl)
{
std::wstring str = L" !*'();:@test&=+$,/?#[ing]";
EncodeUrl(str);
Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str());
}
};
} // namespace StringUtil
/*
Copyright (C) 2013 Rainmeter Team
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 "StringUtil.h"
#include "UnitTest.h"
namespace StringUtil {
TEST_CLASS(Common_StringUtil_Test)
{
public:
TEST_METHOD(TestWiden)
{
Assert::AreEqual(L"test", Widen("test").c_str());
Assert::AreEqual(L"te", Widen("test", 2).c_str());
Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str());
Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str());
}
TEST_METHOD(TestNarrow)
{
Assert::AreEqual("test", Narrow(L"test").c_str());
Assert::AreEqual("te", Narrow(L"test", 2).c_str());
Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str());
Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str());
}
TEST_METHOD(TestEscapeRegExp)
{
std::wstring str = L"\\^$|(test)[{. ing+*?";
EscapeRegExp(str);
Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str());
}
TEST_METHOD(TestEncodeUrl)
{
std::wstring str = L" !*'();:@test&=+$,/?#[ing]";
EncodeUrl(str);
Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str());
}
};
} // namespace StringUtil

View File

@ -1,56 +1,56 @@
/*
Copyright (C) 2013 Rainmeter Team
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_COMMON_TIMER_H_
#define RM_COMMON_TIMER_H_
#include <Windows.h>
// Performs timing using the high-resolution performance counter.
class Timer
{
public:
void Start()
{
QueryPerformanceCounter(&m_Start);
}
void Stop()
{
QueryPerformanceCounter(&m_Stop);
}
// Returns the elapsed time in milliseconds.
double GetElapsed() const
{
static LARGE_INTEGER s_Frequency = []()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency;
} ();
return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart;
}
private:
LARGE_INTEGER m_Start;
LARGE_INTEGER m_Stop;
};
#endif
/*
Copyright (C) 2013 Rainmeter Team
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_COMMON_TIMER_H_
#define RM_COMMON_TIMER_H_
#include <Windows.h>
// Performs timing using the high-resolution performance counter.
class Timer
{
public:
void Start()
{
QueryPerformanceCounter(&m_Start);
}
void Stop()
{
QueryPerformanceCounter(&m_Stop);
}
// Returns the elapsed time in milliseconds.
double GetElapsed() const
{
static LARGE_INTEGER s_Frequency = []()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency;
} ();
return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart;
}
private:
LARGE_INTEGER m_Start;
LARGE_INTEGER m_Stop;
};
#endif

View File

@ -1,26 +1,26 @@
/*
Copyright (C) 2013 Rainmeter Team
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 <CppUnitTest.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a
// simpler version, which seems to work fine.
#undef TEST_CLASS
#define TEST_CLASS(className) class className : public TestClass<className>
/*
Copyright (C) 2013 Rainmeter Team
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 <CppUnitTest.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a
// simpler version, which seems to work fine.
#undef TEST_CLASS
#define TEST_CLASS(className) class className : public TestClass<className>