Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/stroked text #96

Merged
merged 7 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/D2DLibExport/D2DDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,19 @@ public D2DRectangleGeometry CreateRectangleGeometry(FLOAT width, FLOAT height)
public D2DRectangleGeometry CreateRectangleGeometry(D2DRect rect)
{
HANDLE rectGeometryHandle = D2D.CreateRectangleGeometry(this.Handle, ref rect);
return new D2DRectangleGeometry(this.Handle, rectGeometryHandle);
return new D2DRectangleGeometry(this, rectGeometryHandle);
}

public D2DPathGeometry CreatePathGeometry()
{
HANDLE geoHandle = D2D.CreatePathGeometry(this.Handle);
return new D2DPathGeometry(this.Handle, geoHandle);
return new D2DPathGeometry(this, geoHandle);
}

public D2DGeometry CreateEllipseGeometry(D2DPoint origin, D2DSize size)
{
var ellipse = new D2DEllipse(origin, size);
return new D2DGeometry(this.Handle, D2D.CreateEllipseGeometry(this.Handle, ref ellipse));
return new D2DGeometry(this, D2D.CreateEllipseGeometry(this.Handle, ref ellipse));
}

public D2DGeometry CreatePieGeometry(D2DPoint origin, D2DSize size, float startAngle, float endAngle)
Expand Down Expand Up @@ -143,6 +143,29 @@ public D2DGeometry CreatePieGeometry(D2DPoint origin, D2DSize size, float startA
return path;
}

public D2DPathGeometry CreateTextPathGeometry(string text, string fontName, float fontSize,
D2DFontWeight fontWeight = D2DFontWeight.Normal,
D2DFontStyle fontStyle = D2DFontStyle.Normal,
D2DFontStretch fontStretch = D2DFontStretch.Normal)
{
var fontFace = D2D.CreateFontFace(this.Handle, fontName, fontWeight, fontStyle, fontStretch);
if (fontFace == IntPtr.Zero)
{
throw new CreateFontFaceFailedException(fontName);
}

var pathHandler = D2D.CreateTextPathGeometry(this.Handle, text, fontFace, fontSize);

D2D.DestroyFontFace(fontFace);

if (pathHandler == IntPtr.Zero)
{
throw new CreatePathGeometryFailedException();
}

return new D2DPathGeometry(this, pathHandler);
}

public D2DBitmap? LoadBitmap(byte[] buffer)
{
return this.LoadBitmap(buffer, 0, (uint)buffer.Length);
Expand Down
6 changes: 3 additions & 3 deletions src/D2DLibExport/D2DGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ namespace unvell.D2DLib
{
public class D2DGeometry : D2DObject
{
internal HANDLE DeviceHandle { get; private set; }
internal D2DDevice Device { get; private set; }

internal D2DGeometry(HANDLE deviceHandle, HANDLE geoHandle)
internal D2DGeometry(D2DDevice device, HANDLE geoHandle)
: base(geoHandle)
{
this.DeviceHandle = deviceHandle;
this.Device = device;
}

// FIXME: TO be implemented
Expand Down
32 changes: 32 additions & 0 deletions src/D2DLibExport/D2DGraphics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,38 @@ public void DrawText(string text, D2DColor color, string fontName, float fontSiz
fontWeight, fontStyle, fontStretch, halign, valign);
}

public void DrawStrokedText(string text, D2DPoint location,
D2DColor strokeColor, float strokeWidth,
D2DColor fillColor,
string fontName, float fontSize,
D2DFontWeight fontWeight = D2DFontWeight.Normal,
D2DFontStyle fontStyle = D2DFontStyle.Normal,
D2DFontStretch fontStretch = D2DFontStretch.Normal)
{
this.DrawStrokedText(text, location.x, location.y, strokeColor, strokeWidth, fillColor,
fontName, fontSize, fontWeight, fontStyle, fontStretch);
}

public void DrawStrokedText(string text, float x, float y,
D2DColor strokeColor, float strokeWidth,
D2DColor fillColor,
string fontName, float fontSize,
D2DFontWeight fontWeight = D2DFontWeight.Normal,
D2DFontStyle fontStyle = D2DFontStyle.Normal,
D2DFontStretch fontStretch = D2DFontStretch.Normal)
{
using (var textPath = this.Device.CreateTextPathGeometry(text, fontName, fontSize,
fontWeight, fontStyle, fontStretch))
{
this.TranslateTransform(x, y);

this.FillPath(textPath, fillColor);
this.DrawPath(textPath, strokeColor, strokeWidth);

this.TranslateTransform(-x, -y);
}
}

public D2DSize MeasureText(string text, string fontName, float fontSize, D2DSize placeSize)
{
D2DSize outputSize = placeSize;
Expand Down
13 changes: 13 additions & 0 deletions src/D2DLibExport/D2DLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,19 @@ public static extern void MeasureText([In] HANDLE ctx, [In] string text, [In] st
[In] DWriteTextAlignment halign = DWriteTextAlignment.Leading,
[In] DWriteParagraphAlignment valign = DWriteParagraphAlignment.Near);

[DllImport(DLL_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern HANDLE CreateFontFace([In] HANDLE context, [In] string fontName,
[In] D2DFontWeight fontWeight = D2DFontWeight.Normal,
[In] D2DFontStyle fontStyle = D2DFontStyle.Normal,
[In] D2DFontStretch fontStretch = D2DFontStretch.Normal);

[DllImport(DLL_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern void DestroyFontFace(HANDLE fontFaceHandle);

[DllImport(DLL_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern HANDLE CreateTextPathGeometry(HANDLE ctx, [In] string text,
HANDLE fontFaceHandle, FLOAT fontSize);

#endregion // Text

#region Geometry
Expand Down
32 changes: 16 additions & 16 deletions src/D2DLibExport/D2DPathGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ namespace unvell.D2DLib
{
public class D2DPathGeometry : D2DGeometry
{
internal D2DPathGeometry(HANDLE deviceHandle, HANDLE pathHandle)
: base(deviceHandle, pathHandle)
internal D2DPathGeometry(D2DDevice device, HANDLE pathHandle)
: base(device, pathHandle)
{
}

public void SetStartPoint(FLOAT x, FLOAT y)
{
this.SetStartPoint(new D2DPoint(x, y));
}
public void SetStartPoint(FLOAT x, FLOAT y)
{
this.SetStartPoint(new D2DPoint(x, y));
}

public void SetStartPoint(D2DPoint startPoint)
{
Expand All @@ -51,15 +51,15 @@ public void AddBeziers(D2DBezierSegment[] bezierSegments)
D2D.AddPathBeziers(this.Handle, bezierSegments);
}

// TODO: unnecessary API and it doesn't work very well, consider to remove
//public void AddEllipse(D2DEllipse ellipse)
//{
// D2D.AddPathEllipse(this.Handle, ref ellipse);
//}
// TODO: unnecessary API and it doesn't work very well, consider to remove
//public void AddEllipse(D2DEllipse ellipse)
//{
// D2D.AddPathEllipse(this.Handle, ref ellipse);
//}

public void AddArc(D2DPoint endPoint, D2DSize size, FLOAT sweepAngle,
D2DArcSize arcSize = D2DArcSize.Small,
D2DSweepDirection sweepDirection = D2DSweepDirection.Clockwise)
public void AddArc(D2DPoint endPoint, D2DSize size, FLOAT sweepAngle,
D2DArcSize arcSize = D2DArcSize.Small,
D2DSweepDirection sweepDirection = D2DSweepDirection.Clockwise)
{
D2D.AddPathArc(this.Handle, endPoint, size, sweepAngle, arcSize, sweepDirection);
}
Expand All @@ -81,8 +81,8 @@ public void ClosePath()

public override void Dispose()
{
if (this.Handle != IntPtr.Zero) D2D.DestroyPathGeometry(this.Handle);
this.handle = IntPtr.Zero;
if (this.Handle != IntPtr.Zero) D2D.DestroyPathGeometry(this.Handle);
this.handle = IntPtr.Zero;
}
}
}
4 changes: 2 additions & 2 deletions src/D2DLibExport/D2DPieGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ namespace unvell.D2DLib
{
public class D2DPieGeometry : D2DGeometry
{
internal D2DPieGeometry(HANDLE deviceHandle, HANDLE pathHandle)
: base(deviceHandle, pathHandle)
internal D2DPieGeometry(D2DDevice device, HANDLE pathHandle)
: base(device, pathHandle)
{
}

Expand Down
4 changes: 2 additions & 2 deletions src/D2DLibExport/D2DRectangleGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ namespace unvell.D2DLib
{
public class D2DRectangleGeometry : D2DGeometry
{
internal D2DRectangleGeometry(HANDLE deviceHandle, HANDLE geoHandle)
: base(deviceHandle, geoHandle)
internal D2DRectangleGeometry(D2DDevice device, HANDLE geoHandle)
: base(device, geoHandle)
{
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/D2DLibExport/Exceptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* MIT License
*
* Copyright (c) 2009-2022 Jingwood, unvell.com. All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace unvell.D2DLib
{
public class CreateFontFaceFailedException : Exception
{
public CreateFontFaceFailedException(string fontName) :
base("Create font face failed by specified font name: " + fontName)
{
}
}

public class CreatePathGeometryFailedException : Exception
{
public CreatePathGeometryFailedException()
{
}
}
}
91 changes: 91 additions & 0 deletions src/Examples/SampleCode/StrokedText.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* MIT License
*
* Copyright (c) 2009-2022 Jingwood, unvell.com. All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

namespace unvell.D2DLib.Examples.SampleCode
{
public partial class StrokedText : ExampleForm
{
public StrokedText()
{
Text = "Stroked Text Drawing - d2dlib Examples";
BackColor = Color.White;
}

D2DPathGeometry textPath1, textPath2;

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

// Exception will be thrown when the specified font not found in the Windows OS
textPath1 = this.Device.CreateTextPathGeometry("Hello World", "Arial", 36, D2DFontWeight.ExtraBold);
}

protected override void OnRender(D2DGraphics g)
{
base.OnRender(g);

//
// Example 1: Create a path geometry from text and render it
//
// change the location to draw the text
g.TranslateTransform(100, 100);

g.FillPath(this.textPath1, D2DColor.Yellow);
g.DrawPath(this.textPath1, D2DColor.Blue, 3);

// restore the location after drawing text
g.TranslateTransform(-100, -100);



//
// Example 2: Use a helper method to draw a stroked text in simplest way
//
g.DrawStrokedText("Stroked text rendered using D2DLib", 100, 200,
D2DColor.DarkOliveGreen, 2, D2DColor.LightCyan, "Consolas", 24);



// Example 3: Text in non-English language (Unicode fonts)
// The characters in the text must exist in the font.
// This case only works in a Japanese language Windows.
//
//var textPath2 = this.Device.CreateTextPathGeometry("こんにちは、世界", "MS Gothic", 28);

//g.TranslateTransform(100, 300);
//g.DrawPath(textPath2, D2DColor.DarkGreen);
//g.TranslateTransform(-100, -300);

}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

this.textPath1?.Dispose();
//this.textPath2?.Dispose();
}
}
}
4 changes: 2 additions & 2 deletions src/d2dlib/Context.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* MIT License
*
* Copyright (c) 2009-2021 Jingwood, unvell.com. All right reserved.
Expand Down Expand Up @@ -176,4 +176,4 @@ extern "C"
D2DLIB_API void TestDraw(HANDLE context);
}

#endif /* __D2DLIB_H__ */
#endif /* __D2DLIB_H__ */
4 changes: 2 additions & 2 deletions src/d2dlib/Geometry.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* MIT License
*
* Copyright (c) 2009-2021 Jingwood, unvell.com. All right reserved.
Expand Down Expand Up @@ -445,4 +445,4 @@ void GetGeometryTransformedBounds(HANDLE pathCtx, __in D2D1_MATRIX_3X2_F* mat3x2
{
D2DPathContext* pathContext = reinterpret_cast<D2DPathContext*>(pathCtx);
pathContext->path->GetBounds(mat3x2, rect);
}
}
Loading