Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

Commit

Permalink
Merge pull request #898 from jclin/structs
Browse files Browse the repository at this point in the history
DirectWrite enhancements
  • Loading branch information
xoofx authored May 17, 2017
2 parents 5e9be87 + 18cb55a commit 53c8d6d
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 49 deletions.
68 changes: 68 additions & 0 deletions Source/SharpDX.Direct2D1/DirectWrite/FontFallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// 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 SharpDX.DirectWrite
{
public partial class FontFallback
{
/// <summary>
/// <p>Determines an appropriate font to use to render the beginning range of text.</p>
/// </summary>
/// <param name="analysisSource"><dd> <p>The text source implementation holds the text and locale.</p> </dd></param>
/// <param name="textPosition"><dd> <p>Starting position to analyze.</p> </dd></param>
/// <param name="textLength"><dd> <p>Length of the text to analyze.</p> </dd></param>
/// <param name="baseFontCollection"><dd> <p>Default font collection to use.</p> </dd></param>
/// <param name="baseFamilyName"><dd> <p>Family name of the base font. If you pass null, no matching will be done against the family.</p> </dd></param>
/// <param name="baseWeight"><dd> <p>The desired weight.</p> </dd></param>
/// <param name="baseStyle"><dd> <p>The desired style.</p> </dd></param>
/// <param name="baseStretch"><dd> <p>The desired stretch.</p> </dd></param>
/// <param name="mappedLength"><dd> <p>Length of text mapped to the mapped font. This will always be less than or equal to the text length and greater than zero (if the text length is non-zero) so the caller advances at least one character.</p> </dd></param>
/// <param name="mappedFont"><dd> <p>The font that should be used to render the first <em>mappedLength</em> characters of the text. If it returns <c>null</c>, that means that no font can render the text, and <em>mappedLength</em> is the number of characters to skip (rendered with a missing glyph).</p> </dd></param>
/// <param name="scale"><dd> <p>Scale factor to multiply the em size of the returned font by.</p> </dd></param>
public void MapCharacters(
TextAnalysisSource analysisSource,
int textPosition,
int textLength,
FontCollection baseFontCollection,
string baseFamilyName,
FontWeight baseWeight,
FontStyle baseStyle,
FontStretch baseStretch,
out int mappedLength,
out Font mappedFont,
out float scale
)
{
MapCharacters_(
TextAnalysisSourceShadow.ToIntPtr(analysisSource),
textPosition,
textLength,
baseFontCollection,
baseFamilyName,
baseWeight,
baseStyle,
baseStretch,
out mappedLength,
out mappedFont,
out scale
);
}
}
}
25 changes: 14 additions & 11 deletions Source/SharpDX.Direct2D1/DirectWrite/Mapping.xml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
//
//
// 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
Expand All @@ -26,14 +26,14 @@

<namespace>SharpDX.DirectWrite</namespace>
<assembly>SharpDX.Direct2D1</assembly>

<include file="dwrite.h" attach="true" output="DirectWrite"/>
<include file="dwrite_1.h" attach="true" output="DirectWrite"/>
<include file="dwrite_2.h" attach="true" output="DirectWrite"/>
<include file="dwrite_3.h" attach="true" output="DirectWrite"/>

<naming />

<extension>
<create class="DWrite" />
</extension>
Expand Down Expand Up @@ -124,7 +124,7 @@

<map param="IDWriteFont::HasCharacter::exists" return="true" />
<map param="IDWriteFont::GetInformationalStrings::exists" return="true" />

<map method="IDWriteFontFace::GetFiles" visibility="internal" />
<map method="IDWriteFontFace::GetDesignGlyphMetrics" visibility="internal" />
<map method="IDWriteFontFace::GetGdiCompatibleGlyphMetrics" visibility="internal" />
Expand All @@ -133,6 +133,9 @@
<map param="IDWriteFontFace::GetRecommendedRenderingMode::renderingMode" return="true" />
<map method="IDWriteFontFace::TryGetFontTable" visibility="internal" />
<map method="IDWriteFontFace::GetType" name="GetFaceType" />

<map param="IDWriteFontFallback::MapCharacters::mappedLength" attribute="out" />

<map param="IDWriteFontList::GetFont::font" return="true" />
<map param="IDWriteFontFamily::GetFirstMatchingFont::matchingFont" return="true" />
<map param="IDWriteFontFamily::GetMatchingFonts::matchingFonts" return="true" />
Expand All @@ -141,7 +144,7 @@
<map param="IDWriteFontCollection::GetFontFromFontFace::font" return="true" />
<map interface="IDWriteFontCollectionLoader" callback="true" callback-dual="false" />
<map method="IDWriteFontFile::GetLoader" visibility="internal" property="false" />

<map interface="IDWriteFontFileLoader" callback-visibility="public" callback="true" callback-dual="true" />

<map interface="IDWriteFontFileEnumerator" callback="true" callback-dual="false" />
Expand All @@ -152,7 +155,7 @@
<map param="logFont" type="void" attribute="in" />
<map param="IDWriteGdiInterop::CreateBitmapRenderTarget::renderTarget" return="true" />
<map param="IDWriteGdiInterop::CreateFontFaceFromHdc::fontFace" return="true" />

<map method="IDWriteGdiInterop1::.*?LOGFONT" visibility="internal" />
<map param="logFont" type="void" attribute="in" />
<map param="IDWriteGdiInterop1::CreateBitmapRenderTarget::renderTarget" return="true" />
Expand Down Expand Up @@ -208,14 +211,14 @@
<map method="IDWriteTextLayout::GetLineMetrics" check="false"/>
<map method="IDWriteTextLayout::HitTestTextRange" check="false"/>
<map method="IDWriteTextLayout::GetClusterMetrics" check="false"/>

<map method="IDWriteLocalFontFileLoader::GetFilePath.*" visibility="internal"/>
<map method="IDWriteLocalFontFileLoader::GetLastWriteTimeFromKey" visibility="internal"/>

<map method="IDWriteBitmapRenderTarget::DrawGlyphRun" visibility="private"/>
<map param="IDWriteBitmapRenderTarget::DrawGlyphRun::textColor" type="int"/>


<map param="IDWriteRemoteFontFileStream::BeginDownload::asyncResult" return="true" />
<map method="IDWriteAsyncResult::GetResult" check="false"/>

Expand Down
7 changes: 7 additions & 0 deletions Source/Tools/SharpGen/CppModel/CppStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ public class CppStruct : CppElement
[XmlAttribute("align")]
public int Align { get; set; }

/// <summary>
/// Gets or sets the name of the parent.
/// </summary>
/// <value>The name of the parent.</value>
[XmlAttribute("base")]
public string ParentName { get; set; }

/// <summary>
/// Gets the fields.
/// </summary>
Expand Down
77 changes: 45 additions & 32 deletions Source/Tools/SharpGen/Generator/StructTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,53 +94,65 @@ private void Process(CsStruct csStruct)
if (csStruct.IsFullyMapped)
return;

// Set IsFullyMappy in order to avoid recursive mapping
csStruct.IsFullyMapped = true;
// Set IsFullyMappy in order to avoid recursive mapping
csStruct.IsFullyMapped = true;

// Get the associated CppStruct and CSharpTag
var cppStruct = (CppStruct)csStruct.CppElement;
bool hasMarshalType = csStruct.HasMarshalType;
// Get the associated CppStruct and CSharpTag
var cppStruct = (CppStruct)csStruct.CppElement;
bool hasMarshalType = csStruct.HasMarshalType;

// If this structure need to me moved to another container, move it now
foreach (var keyValuePair in _mapMoveStructToInner)
// If this structure need to me moved to another container, move it now
foreach (var keyValuePair in _mapMoveStructToInner)
{
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
{
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
{
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
// Remove the struct from his container
csStruct.Parent.Remove(csStruct);
// Add this struct to the new container struct
destSharpStruct.Add(csStruct);
}
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
// Remove the struct from his container
csStruct.Parent.Remove(csStruct);
// Add this struct to the new container struct
destSharpStruct.Add(csStruct);
}
}

// Current offset of a field
int currentFieldAbsoluteOffset = 0;

// Current offset of a field
int currentFieldAbsoluteOffset = 0;
// Last field offset
int previousFieldOffsetIndex = -1;

int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count;
// Size of the last field
int previousFieldSize = 0;

//
int maxSizeOfField = 0;

// Last field offset
int previousFieldOffsetIndex = -1;
bool isInUnion = false;

// Size of the last field
int previousFieldSize = 0;
int cumulatedBitOffset = 0;

//
int maxSizeOfField = 0;

bool isInUnion = false;
var inheritedStructs = new Stack<CppStruct>();
var currentStruct = cppStruct;
while (currentStruct != null && currentStruct.ParentName != currentStruct.Name)
{
inheritedStructs.Push(currentStruct);
currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct;
}

int cumulatedBitOffset = 0;
while (inheritedStructs.Count > 0)
{
currentStruct = inheritedStructs.Pop();

int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;

// -------------------------------------------------------------------------------
// Iterate on all fields and perform mapping
// -------------------------------------------------------------------------------
for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
{
var cppField = (CppField) cppStruct.Items[fieldIndex];
Logger.RunInContext(cppField.ToString(), () =>
var cppField = (CppField)currentStruct.Items[fieldIndex];
Logger.RunInContext(cppField.ToString(), () =>
{
var fieldStruct = Manager.GetCsType<CsField>(cppField, true);
csStruct.Add(fieldStruct);
Expand Down Expand Up @@ -196,9 +208,9 @@ private void Process(CsStruct csStruct)

var nextFieldIndex = fieldIndex + 1;
if ((previousFieldOffsetIndex == cppField.Offset)
|| (nextFieldIndex < fieldCount && ((CppField)cppStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
|| (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
{
if(previousFieldOffsetIndex != cppField.Offset)
if (previousFieldOffsetIndex != cppField.Offset)
{
maxSizeOfField = 0;
}
Expand All @@ -214,10 +226,11 @@ private void Process(CsStruct csStruct)
previousFieldOffsetIndex = cppField.Offset;
});
}
}

// In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union
// using pointers, we can't)
if(csStruct.ExplicitLayout)
if (csStruct.ExplicitLayout)
{
var fieldList = csStruct.Fields.ToList();
for(int i = 0; i < fieldList.Count; i++)
Expand Down
33 changes: 27 additions & 6 deletions Source/Tools/SharpGen/Parser/CppParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -866,9 +866,9 @@ private CppInterface ParseInterface(XElement xElement)
var cppInterface = xElement.Annotation<CppInterface>();
if (cppInterface != null)
return cppInterface;

// Else, create a new CppInterface
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
xElement.AddAnnotation(cppInterface);

// Enter Interface description
Expand Down Expand Up @@ -1007,18 +1007,23 @@ private CppField ParseField(XElement xElement)
/// <returns>A C++ struct parsed</returns>
private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0)
{
var cppStruct = xElement.Annotation<CppStruct>();
if (cppStruct != null)
return cppStruct;

// Build struct name directly from the struct name or based on the parent
var structName = xElement.AttributeValue("name") ?? "";
if (cppParent != null)
{
if (string.IsNullOrEmpty(structName))
if (string.IsNullOrEmpty(structName))
structName = cppParent.Name + "_INNER_" + innerAnonymousIndex;
else
structName = cppParent.Name + "_" + structName + "_INNER";
}

// Create struct
var cppStruct = new CppStruct { Name = structName };
cppStruct = new CppStruct { Name = structName };
xElement.AddAnnotation(cppStruct);
bool isUnion = (xElement.Name.LocalName == CastXml.TagUnion);

// Get align from structure
Expand All @@ -1034,6 +1039,22 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
// Enter struct/union description
Logger.PushContext("{0}:[{1}]", xElement.Name.LocalName, cppStruct.Name);

var basesValue = xElement.AttributeValue("bases");
var bases = basesValue != null ? basesValue.Split(' ') : Enumerable.Empty<string>();
foreach (var xElementBaseId in bases)
{
if (string.IsNullOrEmpty(xElementBaseId))
continue;

var xElementBase = _mapIdToXElement[xElementBaseId];

CppStruct cppStructBase = null;
Logger.RunInContext("Base", () => { cppStructBase = ParseStructOrUnion(xElementBase); });

if (string.IsNullOrEmpty(cppStructBase.ParentName))
cppStruct.ParentName = cppStructBase.Name;
}

// Parse all fields
int fieldOffset = 0;
int innerStructCount = 0;
Expand Down Expand Up @@ -1077,7 +1098,7 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
// Get the type name from the inner-struct and set it to the field
cppField.TypeName = fieldSubStruct.Name;
_currentCppInclude.Add(fieldSubStruct);
}
}
}

// Go to next field offset if not in union
Expand Down Expand Up @@ -1465,7 +1486,7 @@ private static string ConvertFundamentalType(string typeName)
default:
Logger.Error("Unhandled partial type [{0}] from Fundamental type [{1}]", type, typeName);
break;
}
}
}

if (longCount == 1 && outputType == "double")
Expand Down

0 comments on commit 53c8d6d

Please sign in to comment.