[CoreText] CTParagraphStyle uses the incorrect float return type. Fixes bug 54148. (#1975)
* [CoreText] Fix bug 54148 - CoreText.CTParagraphStyle does not pick up settings from CTParagraphStyleSettings https://bugzilla.xamarin.com/show_bug.cgi?id=54148 CTParagraphStyle float properties have the incorrect float return type, the headers state this API's returns CGFloats (aka nfloat) instead of floats this used to work ok fetching them due to there is no difference in size for 32 bits devices but once 64 bit devices appeared the API began to fail The actual method that fetches the values `CTParagraphStyleGetValueForSpecifier` asks for the size of the returned data and we used to give the size of a float which is incorrect in 64 bits devices and the API call just correctly returned false because it could not write back the value to us. Added tests for the full properties available on CTParagraphStyle * Add comment about the weird Dispose method implementation in CreateFromSettings
This commit is contained in:
Родитель
2a85ec1674
Коммит
3fe0d2010a
|
@ -375,7 +375,9 @@ namespace XamCore.CoreText {
|
||||||
}
|
}
|
||||||
handle = CTParagraphStyleCreate (settings, settings.Length);
|
handle = CTParagraphStyleCreate (settings, settings.Length);
|
||||||
}
|
}
|
||||||
|
// Yes this weird Dispose implementation is correct, this bugzilla
|
||||||
|
// comment explains more about it. TL;DR: check CTParagraphStyleSpecifierIntPtrsValue
|
||||||
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=54148#c4
|
||||||
i = 0;
|
i = 0;
|
||||||
foreach (var e in specifiers) {
|
foreach (var e in specifiers) {
|
||||||
e.Dispose (values, i);
|
e.Dispose (values, i);
|
||||||
|
@ -431,51 +433,121 @@ namespace XamCore.CoreText {
|
||||||
get {return (CTWritingDirection) GetByteValue (CTParagraphStyleSpecifier.BaseWritingDirection);}
|
get {return (CTWritingDirection) GetByteValue (CTParagraphStyleSpecifier.BaseWritingDirection);}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float FirstLineHeadIndent {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
FirstLineHeadIndent {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.FirstLineHeadIndent); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.FirstLineHeadIndent); }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe float GetFloatValue (CTParagraphStyleSpecifier spec)
|
unsafe
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
GetFloatValue (CTParagraphStyleSpecifier spec)
|
||||||
{
|
{
|
||||||
float value;
|
nfloat value;
|
||||||
if (!CTParagraphStyleGetValueForSpecifier (handle, spec, sizeof (float), &value))
|
if (!CTParagraphStyleGetValueForSpecifier (handle, spec, (nuint) sizeof (nfloat), &value))
|
||||||
throw new InvalidOperationException ("Unable to get property value.");
|
throw new InvalidOperationException ("Unable to get property value.");
|
||||||
return value;
|
return
|
||||||
|
#if !XAMCORE_4_0
|
||||||
|
(float)
|
||||||
|
#endif
|
||||||
|
value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float HeadIndent {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
HeadIndent {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.HeadIndent); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.HeadIndent); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float TailIndent {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
TailIndent {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.TailIndent); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.TailIndent); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float DefaultTabInterval {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
DefaultTabInterval {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.DefaultTabInterval); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.DefaultTabInterval); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float LineHeightMultiple {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
LineHeightMultiple {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.LineHeightMultiple); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.LineHeightMultiple); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float MaximumLineHeight {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
MaximumLineHeight {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.MaximumLineHeight); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.MaximumLineHeight); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float MinimumLineHeight {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
MinimumLineHeight {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.MinimumLineHeight); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.MinimumLineHeight); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float LineSpacing {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
LineSpacing {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.LineSpacing); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.LineSpacing); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float ParagraphSpacing {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
ParagraphSpacing {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.ParagraphSpacing); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.ParagraphSpacing); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public float ParagraphSpacingBefore {
|
public
|
||||||
|
#if XAMCORE_4_0
|
||||||
|
nfloat
|
||||||
|
#else
|
||||||
|
float
|
||||||
|
#endif
|
||||||
|
ParagraphSpacingBefore {
|
||||||
get { return GetFloatValue (CTParagraphStyleSpecifier.ParagraphSpacingBefore); }
|
get { return GetFloatValue (CTParagraphStyleSpecifier.ParagraphSpacingBefore); }
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// Unit tests for CTParagraphStyle
|
||||||
|
//
|
||||||
|
// Authors:
|
||||||
|
// Alex Soto <alexsoto@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright 2017 Xamarin Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if !__WATCHOS__
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
#if XAMCORE_2_0
|
||||||
|
using Foundation;
|
||||||
|
using CoreText;
|
||||||
|
#else
|
||||||
|
using MonoTouch.CoreText;
|
||||||
|
using MonoTouch.Foundation;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if XAMCORE_2_0
|
||||||
|
using RectangleF = CoreGraphics.CGRect;
|
||||||
|
using SizeF = CoreGraphics.CGSize;
|
||||||
|
using PointF = CoreGraphics.CGPoint;
|
||||||
|
#else
|
||||||
|
using nfloat = global::System.Single;
|
||||||
|
using nint = global::System.Int32;
|
||||||
|
using nuint = global::System.UInt32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MonoTouchFixtures.CoreText {
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[Preserve (AllMembers = true)]
|
||||||
|
public class CTParagraphStyleTests {
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StylePropertiesTest ()
|
||||||
|
{
|
||||||
|
var settings = new CTParagraphStyleSettings () {
|
||||||
|
TailIndent = 5,
|
||||||
|
ParagraphSpacingBefore = 5,
|
||||||
|
ParagraphSpacing = 5,
|
||||||
|
LineSpacing = 5,
|
||||||
|
MinimumLineHeight = 5,
|
||||||
|
MaximumLineHeight = 5,
|
||||||
|
LineHeightMultiple = 5,
|
||||||
|
DefaultTabInterval = 5,
|
||||||
|
HeadIndent = 5,
|
||||||
|
FirstLineHeadIndent = 5,
|
||||||
|
LineBreakMode = CTLineBreakMode.TruncatingHead,
|
||||||
|
BaseWritingDirection = CTWritingDirection.Natural,
|
||||||
|
Alignment = CTTextAlignment.Justified,
|
||||||
|
TabStops = new [] {
|
||||||
|
new CTTextTab (CTTextAlignment.Justified, 2),
|
||||||
|
new CTTextTab (CTTextAlignment.Natural, 1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var style = new CTParagraphStyle (settings);
|
||||||
|
Assert.DoesNotThrow (() => {
|
||||||
|
Assert.AreEqual (settings.TailIndent, style.TailIndent, "TailIndent");
|
||||||
|
Assert.AreEqual (settings.ParagraphSpacingBefore, style.ParagraphSpacingBefore, "ParagraphSpacingBefore");
|
||||||
|
Assert.AreEqual (settings.ParagraphSpacing, style.ParagraphSpacing, "ParagraphSpacing");
|
||||||
|
Assert.AreEqual (settings.LineSpacing, style.LineSpacing, "LineSpacing");
|
||||||
|
Assert.AreEqual (settings.MinimumLineHeight, style.MinimumLineHeight, "MinimumLineHeight");
|
||||||
|
Assert.AreEqual (settings.MaximumLineHeight, style.MaximumLineHeight, "MaximumLineHeight");
|
||||||
|
Assert.AreEqual (settings.LineHeightMultiple, style.LineHeightMultiple, "LineHeightMultiple");
|
||||||
|
Assert.AreEqual (settings.DefaultTabInterval, style.DefaultTabInterval, "DefaultTabInterval");
|
||||||
|
Assert.AreEqual (settings.HeadIndent, style.HeadIndent, "HeadIndent");
|
||||||
|
Assert.AreEqual (settings.FirstLineHeadIndent, style.FirstLineHeadIndent, "FirstLineHeadIndent");
|
||||||
|
Assert.AreEqual (settings.LineBreakMode, style.LineBreakMode, "LineBreakMode");
|
||||||
|
Assert.AreEqual (settings.BaseWritingDirection, style.BaseWritingDirection, "LineBreakMode");
|
||||||
|
Assert.AreEqual (settings.Alignment, style.Alignment, "Alignment");
|
||||||
|
|
||||||
|
var styleTabStops = style.GetTabStops ();
|
||||||
|
Assert.AreEqual (settings.TabStops.Count (), styleTabStops.Length, "TabStops");
|
||||||
|
Assert.True (styleTabStops.Any (t => t.Location == 2 && t.TextAlignment == CTTextAlignment.Justified));
|
||||||
|
Assert.True (styleTabStops.Any (t => t.Location == 1 && t.TextAlignment == CTTextAlignment.Natural));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -649,6 +649,7 @@
|
||||||
<Compile Include="AVFoundation\PlayerItemVideoOutputTest.cs" />
|
<Compile Include="AVFoundation\PlayerItemVideoOutputTest.cs" />
|
||||||
<Compile Include="mono\ConfigTest.cs" />
|
<Compile Include="mono\ConfigTest.cs" />
|
||||||
<Compile Include="OpenGLES\EAGLContext.cs" />
|
<Compile Include="OpenGLES\EAGLContext.cs" />
|
||||||
|
<Compile Include="CoreText\CTParagraphStyleTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче