CPF/CPF.Mac/Mac/CoreText/CTParagraphStyle.cs
2023-11-21 23:05:03 +08:00

170 lines
5.2 KiB
C#

using CPF.Mac.CoreFoundation;
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreText
{
[Since(3, 2)]
public class CTParagraphStyle : INativeObject, IDisposable
{
internal IntPtr handle;
public IntPtr Handle => handle;
public CTTextAlignment Alignment => (CTTextAlignment)GetByteValue(CTParagraphStyleSpecifier.Alignment);
public CTLineBreakMode LineBreakMode => (CTLineBreakMode)GetByteValue(CTParagraphStyleSpecifier.Alignment);
public CTWritingDirection BaseWritingDirection => (CTWritingDirection)GetByteValue(CTParagraphStyleSpecifier.Alignment);
public float FirstLineHeadIndent => GetFloatValue(CTParagraphStyleSpecifier.FirstLineHeadIndent);
public float HeadIndent => GetFloatValue(CTParagraphStyleSpecifier.HeadIndent);
public float TailIndent => GetFloatValue(CTParagraphStyleSpecifier.TailIndent);
public float DefaultTabInterval => GetFloatValue(CTParagraphStyleSpecifier.DefaultTabInterval);
public float LineHeightMultiple => GetFloatValue(CTParagraphStyleSpecifier.LineHeightMultiple);
public float MaximumLineHeight => GetFloatValue(CTParagraphStyleSpecifier.MaximumLineHeight);
public float MinimumLineHeight => GetFloatValue(CTParagraphStyleSpecifier.MinimumLineHeight);
public float LineSpacing => GetFloatValue(CTParagraphStyleSpecifier.LineSpacing);
public float ParagraphSpacing => GetFloatValue(CTParagraphStyleSpecifier.ParagraphSpacing);
public float ParagraphSpacingBefore => GetFloatValue(CTParagraphStyleSpecifier.ParagraphSpacingBefore);
internal CTParagraphStyle(IntPtr handle, bool owns)
{
if (handle == IntPtr.Zero)
{
throw ConstructorError.ArgumentNull(this, "handle");
}
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
~CTParagraphStyle()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")]
private static extern IntPtr CTParagraphStyleCreate(CTParagraphStyleSetting[] settings, int settingCount);
public CTParagraphStyle(CTParagraphStyleSettings settings)
{
handle = ((settings == null) ? CTParagraphStyleCreate(null, 0) : CreateFromSettings(settings));
if (handle == IntPtr.Zero)
{
throw ConstructorError.Unknown(this);
}
}
private unsafe static IntPtr CreateFromSettings(CTParagraphStyleSettings s)
{
IntPtr zero = IntPtr.Zero;
List<CTParagraphStyleSpecifierValue> specifiers = s.GetSpecifiers();
CTParagraphStyleSetting[] array = new CTParagraphStyleSetting[specifiers.Count];
CTParagraphStyleSettingValue[] array2 = new CTParagraphStyleSettingValue[specifiers.Count];
int num = 0;
foreach (CTParagraphStyleSpecifierValue item in specifiers)
{
item.WriteValue(array2, num);
array[num].spec = item.Spec;
array[num].valueSize = (uint)item.ValueSize;
num++;
}
fixed (CTParagraphStyleSettingValue* ptr = array2)
{
for (num = 0; num < array.Length; num++)
{
byte* value = &ptr[num].int8;
array[num].value = (IntPtr)(void*)value;
}
zero = CTParagraphStyleCreate(array, array.Length);
}
num = 0;
foreach (CTParagraphStyleSpecifierValue item2 in specifiers)
{
item2.Dispose(array2, num);
}
return zero;
}
public CTParagraphStyle()
: this(null)
{
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")]
private static extern IntPtr CTParagraphStyleCreateCopy(IntPtr paragraphStyle);
public CTParagraphStyle Clone()
{
return new CTParagraphStyle(CTParagraphStyleCreateCopy(handle), owns: true);
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")]
private unsafe static extern bool CTParagraphStyleGetValueForSpecifier(IntPtr paragraphStyle, CTParagraphStyleSpecifier spec, uint valueBufferSize, void* valueBuffer);
public unsafe CTTextTab[] GetTabStops()
{
IntPtr value = default(IntPtr);
if (!CTParagraphStyleGetValueForSpecifier(handle, CTParagraphStyleSpecifier.TabStops, (uint)IntPtr.Size, &value))
{
throw new InvalidOperationException("Unable to get property value.");
}
if (value == IntPtr.Zero)
{
return new CTTextTab[0];
}
return NSArray.ArrayFromHandle(value, (IntPtr p) => new CTTextTab(p, owns: false));
}
private unsafe byte GetByteValue(CTParagraphStyleSpecifier spec)
{
byte result = default(byte);
if (!CTParagraphStyleGetValueForSpecifier(handle, spec, 1u, &result))
{
throw new InvalidOperationException("Unable to get property value.");
}
return result;
}
private unsafe float GetFloatValue(CTParagraphStyleSpecifier spec)
{
float result = default(float);
if (!CTParagraphStyleGetValueForSpecifier(handle, spec, 4u, &result))
{
throw new InvalidOperationException("Unable to get property value.");
}
return result;
}
}
}