Skip to content

Commit 53c8d6d

Browse files
authored
Merge pull request sharpdx#898 from jclin/structs
DirectWrite enhancements
2 parents 5e9be87 + 18cb55a commit 53c8d6d

File tree

5 files changed

+161
-49
lines changed

5 files changed

+161
-49
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
namespace SharpDX.DirectWrite
22+
{
23+
public partial class FontFallback
24+
{
25+
/// <summary>
26+
/// <p>Determines an appropriate font to use to render the beginning range of text.</p>
27+
/// </summary>
28+
/// <param name="analysisSource"><dd> <p>The text source implementation holds the text and locale.</p> </dd></param>
29+
/// <param name="textPosition"><dd> <p>Starting position to analyze.</p> </dd></param>
30+
/// <param name="textLength"><dd> <p>Length of the text to analyze.</p> </dd></param>
31+
/// <param name="baseFontCollection"><dd> <p>Default font collection to use.</p> </dd></param>
32+
/// <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>
33+
/// <param name="baseWeight"><dd> <p>The desired weight.</p> </dd></param>
34+
/// <param name="baseStyle"><dd> <p>The desired style.</p> </dd></param>
35+
/// <param name="baseStretch"><dd> <p>The desired stretch.</p> </dd></param>
36+
/// <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>
37+
/// <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>
38+
/// <param name="scale"><dd> <p>Scale factor to multiply the em size of the returned font by.</p> </dd></param>
39+
public void MapCharacters(
40+
TextAnalysisSource analysisSource,
41+
int textPosition,
42+
int textLength,
43+
FontCollection baseFontCollection,
44+
string baseFamilyName,
45+
FontWeight baseWeight,
46+
FontStyle baseStyle,
47+
FontStretch baseStretch,
48+
out int mappedLength,
49+
out Font mappedFont,
50+
out float scale
51+
)
52+
{
53+
MapCharacters_(
54+
TextAnalysisSourceShadow.ToIntPtr(analysisSource),
55+
textPosition,
56+
textLength,
57+
baseFontCollection,
58+
baseFamilyName,
59+
baseWeight,
60+
baseStyle,
61+
baseStretch,
62+
out mappedLength,
63+
out mappedFont,
64+
out scale
65+
);
66+
}
67+
}
68+
}

Source/SharpDX.Direct2D1/DirectWrite/Mapping.xml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<!--
33
// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
4-
//
4+
//
55
// Permission is hereby granted, free of charge, to any person obtaining a copy
66
// of this software and associated documentation files (the "Software"), to deal
77
// in the Software without restriction, including without limitation the rights
88
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99
// copies of the Software, and to permit persons to whom the Software is
1010
// furnished to do so, subject to the following conditions:
11-
//
11+
//
1212
// The above copyright notice and this permission notice shall be included in
1313
// all copies or substantial portions of the Software.
14-
//
14+
//
1515
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -26,14 +26,14 @@
2626

2727
<namespace>SharpDX.DirectWrite</namespace>
2828
<assembly>SharpDX.Direct2D1</assembly>
29-
29+
3030
<include file="dwrite.h" attach="true" output="DirectWrite"/>
3131
<include file="dwrite_1.h" attach="true" output="DirectWrite"/>
3232
<include file="dwrite_2.h" attach="true" output="DirectWrite"/>
3333
<include file="dwrite_3.h" attach="true" output="DirectWrite"/>
3434

3535
<naming />
36-
36+
3737
<extension>
3838
<create class="DWrite" />
3939
</extension>
@@ -124,7 +124,7 @@
124124

125125
<map param="IDWriteFont::HasCharacter::exists" return="true" />
126126
<map param="IDWriteFont::GetInformationalStrings::exists" return="true" />
127-
127+
128128
<map method="IDWriteFontFace::GetFiles" visibility="internal" />
129129
<map method="IDWriteFontFace::GetDesignGlyphMetrics" visibility="internal" />
130130
<map method="IDWriteFontFace::GetGdiCompatibleGlyphMetrics" visibility="internal" />
@@ -133,6 +133,9 @@
133133
<map param="IDWriteFontFace::GetRecommendedRenderingMode::renderingMode" return="true" />
134134
<map method="IDWriteFontFace::TryGetFontTable" visibility="internal" />
135135
<map method="IDWriteFontFace::GetType" name="GetFaceType" />
136+
137+
<map param="IDWriteFontFallback::MapCharacters::mappedLength" attribute="out" />
138+
136139
<map param="IDWriteFontList::GetFont::font" return="true" />
137140
<map param="IDWriteFontFamily::GetFirstMatchingFont::matchingFont" return="true" />
138141
<map param="IDWriteFontFamily::GetMatchingFonts::matchingFonts" return="true" />
@@ -141,7 +144,7 @@
141144
<map param="IDWriteFontCollection::GetFontFromFontFace::font" return="true" />
142145
<map interface="IDWriteFontCollectionLoader" callback="true" callback-dual="false" />
143146
<map method="IDWriteFontFile::GetLoader" visibility="internal" property="false" />
144-
147+
145148
<map interface="IDWriteFontFileLoader" callback-visibility="public" callback="true" callback-dual="true" />
146149

147150
<map interface="IDWriteFontFileEnumerator" callback="true" callback-dual="false" />
@@ -152,7 +155,7 @@
152155
<map param="logFont" type="void" attribute="in" />
153156
<map param="IDWriteGdiInterop::CreateBitmapRenderTarget::renderTarget" return="true" />
154157
<map param="IDWriteGdiInterop::CreateFontFaceFromHdc::fontFace" return="true" />
155-
158+
156159
<map method="IDWriteGdiInterop1::.*?LOGFONT" visibility="internal" />
157160
<map param="logFont" type="void" attribute="in" />
158161
<map param="IDWriteGdiInterop1::CreateBitmapRenderTarget::renderTarget" return="true" />
@@ -208,14 +211,14 @@
208211
<map method="IDWriteTextLayout::GetLineMetrics" check="false"/>
209212
<map method="IDWriteTextLayout::HitTestTextRange" check="false"/>
210213
<map method="IDWriteTextLayout::GetClusterMetrics" check="false"/>
211-
214+
212215
<map method="IDWriteLocalFontFileLoader::GetFilePath.*" visibility="internal"/>
213216
<map method="IDWriteLocalFontFileLoader::GetLastWriteTimeFromKey" visibility="internal"/>
214217

215218
<map method="IDWriteBitmapRenderTarget::DrawGlyphRun" visibility="private"/>
216219
<map param="IDWriteBitmapRenderTarget::DrawGlyphRun::textColor" type="int"/>
217-
218-
220+
221+
219222
<map param="IDWriteRemoteFontFileStream::BeginDownload::asyncResult" return="true" />
220223
<map method="IDWriteAsyncResult::GetResult" check="false"/>
221224

Source/Tools/SharpGen/CppModel/CppStruct.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ public class CppStruct : CppElement
3535
[XmlAttribute("align")]
3636
public int Align { get; set; }
3737

38+
/// <summary>
39+
/// Gets or sets the name of the parent.
40+
/// </summary>
41+
/// <value>The name of the parent.</value>
42+
[XmlAttribute("base")]
43+
public string ParentName { get; set; }
44+
3845
/// <summary>
3946
/// Gets the fields.
4047
/// </summary>

Source/Tools/SharpGen/Generator/StructTransform.cs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -94,53 +94,65 @@ private void Process(CsStruct csStruct)
9494
if (csStruct.IsFullyMapped)
9595
return;
9696

97-
// Set IsFullyMappy in order to avoid recursive mapping
98-
csStruct.IsFullyMapped = true;
97+
// Set IsFullyMappy in order to avoid recursive mapping
98+
csStruct.IsFullyMapped = true;
9999

100-
// Get the associated CppStruct and CSharpTag
101-
var cppStruct = (CppStruct)csStruct.CppElement;
102-
bool hasMarshalType = csStruct.HasMarshalType;
100+
// Get the associated CppStruct and CSharpTag
101+
var cppStruct = (CppStruct)csStruct.CppElement;
102+
bool hasMarshalType = csStruct.HasMarshalType;
103103

104-
// If this structure need to me moved to another container, move it now
105-
foreach (var keyValuePair in _mapMoveStructToInner)
104+
// If this structure need to me moved to another container, move it now
105+
foreach (var keyValuePair in _mapMoveStructToInner)
106+
{
107+
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
106108
{
107-
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
108-
{
109-
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
110-
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
111-
// Remove the struct from his container
112-
csStruct.Parent.Remove(csStruct);
113-
// Add this struct to the new container struct
114-
destSharpStruct.Add(csStruct);
115-
}
109+
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
110+
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
111+
// Remove the struct from his container
112+
csStruct.Parent.Remove(csStruct);
113+
// Add this struct to the new container struct
114+
destSharpStruct.Add(csStruct);
116115
}
116+
}
117+
118+
// Current offset of a field
119+
int currentFieldAbsoluteOffset = 0;
117120

118-
// Current offset of a field
119-
int currentFieldAbsoluteOffset = 0;
121+
// Last field offset
122+
int previousFieldOffsetIndex = -1;
120123

121-
int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count;
124+
// Size of the last field
125+
int previousFieldSize = 0;
122126

127+
//
128+
int maxSizeOfField = 0;
123129

124-
// Last field offset
125-
int previousFieldOffsetIndex = -1;
130+
bool isInUnion = false;
126131

127-
// Size of the last field
128-
int previousFieldSize = 0;
132+
int cumulatedBitOffset = 0;
129133

130-
//
131-
int maxSizeOfField = 0;
132134

133-
bool isInUnion = false;
135+
var inheritedStructs = new Stack<CppStruct>();
136+
var currentStruct = cppStruct;
137+
while (currentStruct != null && currentStruct.ParentName != currentStruct.Name)
138+
{
139+
inheritedStructs.Push(currentStruct);
140+
currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct;
141+
}
134142

135-
int cumulatedBitOffset = 0;
143+
while (inheritedStructs.Count > 0)
144+
{
145+
currentStruct = inheritedStructs.Pop();
146+
147+
int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;
136148

137149
// -------------------------------------------------------------------------------
138150
// Iterate on all fields and perform mapping
139151
// -------------------------------------------------------------------------------
140152
for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
141153
{
142-
var cppField = (CppField) cppStruct.Items[fieldIndex];
143-
Logger.RunInContext(cppField.ToString(), () =>
154+
var cppField = (CppField)currentStruct.Items[fieldIndex];
155+
Logger.RunInContext(cppField.ToString(), () =>
144156
{
145157
var fieldStruct = Manager.GetCsType<CsField>(cppField, true);
146158
csStruct.Add(fieldStruct);
@@ -196,9 +208,9 @@ private void Process(CsStruct csStruct)
196208

197209
var nextFieldIndex = fieldIndex + 1;
198210
if ((previousFieldOffsetIndex == cppField.Offset)
199-
|| (nextFieldIndex < fieldCount && ((CppField)cppStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
211+
|| (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
200212
{
201-
if(previousFieldOffsetIndex != cppField.Offset)
213+
if (previousFieldOffsetIndex != cppField.Offset)
202214
{
203215
maxSizeOfField = 0;
204216
}
@@ -214,10 +226,11 @@ private void Process(CsStruct csStruct)
214226
previousFieldOffsetIndex = cppField.Offset;
215227
});
216228
}
229+
}
217230

218231
// In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union
219232
// using pointers, we can't)
220-
if(csStruct.ExplicitLayout)
233+
if (csStruct.ExplicitLayout)
221234
{
222235
var fieldList = csStruct.Fields.ToList();
223236
for(int i = 0; i < fieldList.Count; i++)

Source/Tools/SharpGen/Parser/CppParser.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -866,9 +866,9 @@ private CppInterface ParseInterface(XElement xElement)
866866
var cppInterface = xElement.Annotation<CppInterface>();
867867
if (cppInterface != null)
868868
return cppInterface;
869-
869+
870870
// Else, create a new CppInterface
871-
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
871+
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
872872
xElement.AddAnnotation(cppInterface);
873873

874874
// Enter Interface description
@@ -1007,18 +1007,23 @@ private CppField ParseField(XElement xElement)
10071007
/// <returns>A C++ struct parsed</returns>
10081008
private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0)
10091009
{
1010+
var cppStruct = xElement.Annotation<CppStruct>();
1011+
if (cppStruct != null)
1012+
return cppStruct;
1013+
10101014
// Build struct name directly from the struct name or based on the parent
10111015
var structName = xElement.AttributeValue("name") ?? "";
10121016
if (cppParent != null)
10131017
{
1014-
if (string.IsNullOrEmpty(structName))
1018+
if (string.IsNullOrEmpty(structName))
10151019
structName = cppParent.Name + "_INNER_" + innerAnonymousIndex;
10161020
else
10171021
structName = cppParent.Name + "_" + structName + "_INNER";
10181022
}
10191023

10201024
// Create struct
1021-
var cppStruct = new CppStruct { Name = structName };
1025+
cppStruct = new CppStruct { Name = structName };
1026+
xElement.AddAnnotation(cppStruct);
10221027
bool isUnion = (xElement.Name.LocalName == CastXml.TagUnion);
10231028

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

1042+
var basesValue = xElement.AttributeValue("bases");
1043+
var bases = basesValue != null ? basesValue.Split(' ') : Enumerable.Empty<string>();
1044+
foreach (var xElementBaseId in bases)
1045+
{
1046+
if (string.IsNullOrEmpty(xElementBaseId))
1047+
continue;
1048+
1049+
var xElementBase = _mapIdToXElement[xElementBaseId];
1050+
1051+
CppStruct cppStructBase = null;
1052+
Logger.RunInContext("Base", () => { cppStructBase = ParseStructOrUnion(xElementBase); });
1053+
1054+
if (string.IsNullOrEmpty(cppStructBase.ParentName))
1055+
cppStruct.ParentName = cppStructBase.Name;
1056+
}
1057+
10371058
// Parse all fields
10381059
int fieldOffset = 0;
10391060
int innerStructCount = 0;
@@ -1077,7 +1098,7 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
10771098
// Get the type name from the inner-struct and set it to the field
10781099
cppField.TypeName = fieldSubStruct.Name;
10791100
_currentCppInclude.Add(fieldSubStruct);
1080-
}
1101+
}
10811102
}
10821103

10831104
// Go to next field offset if not in union
@@ -1465,7 +1486,7 @@ private static string ConvertFundamentalType(string typeName)
14651486
default:
14661487
Logger.Error("Unhandled partial type [{0}] from Fundamental type [{1}]", type, typeName);
14671488
break;
1468-
}
1489+
}
14691490
}
14701491

14711492
if (longCount == 1 && outputType == "double")

0 commit comments

Comments
 (0)