//
//  GSBase.h
//  GlyphsCore
//
//  Created by Georg Seifert on 04.03.19.
//  Copyright © 2019 schriftgestaltung.de. All rights reserved.
//

#ifndef GSBase_h
#define GSBase_h

#define _GSDefineValidateOrDefault(TYPE, DEFAULT) \
	static inline TYPE TYPE##ValidateOrDefault(TYPE value) { \
		return TYPE##Validate(value) ? (value) : (DEFAULT); \
	}

#ifndef GSDeprecated
#define GSDeprecated(replacement) __attribute__((deprecated("", replacement)))
#endif

/// A version of the Glyphs source format.
///
/// The format version controls how model data is read and written.
/// Use ``GSFormatVersionCurrent`` unless the output must remain compatible with an earlier version of Glyphs.
/// Earlier formats cannot represent all current model data.
typedef NS_ENUM(uint8_t, GSFormatVersion) {
	/// The source format used by Glyphs 1 and Glyphs 2.
	GSFormatVersion1 = 1,
	/// The source format introduced by Glyphs 3.
	GSFormatVersion3 = 3,
	/// The source format introduced by Glyphs 4.
	GSFormatVersion4 = 4,
};

/// The most recent source format supported by the framework.
///
/// The value changes when a new source format is introduced.
static const GSFormatVersion GSFormatVersionCurrent NS_SWIFT_NAME(GSFormatVersion.current) = GSFormatVersion4;

/// Whether a value identifies a supported source format.
BOOL GSFormatVersionValidate(GSFormatVersion value);
/// A supported source format, or ``GSFormatVersionCurrent`` when the value is not supported.
_GSDefineValidateOrDefault(GSFormatVersion, GSFormatVersionCurrent);

/// The storage layout of a Glyphs source file.
typedef NS_ENUM(uint8_t, GSPackageType) {
	/// A single file containing all font data.
	GSPackageFlatFile NS_SWIFT_NAME(flatFile) = 1,
	/// A package containing font data and separate files for glyphs and other resources.
	GSPackageBundle NS_SWIFT_NAME(bundle) = 2,
};

/// Whether a value identifies a supported storage layout.
BOOL GSPackageTypeValidate(GSPackageType value);
/// A supported storage layout, or ``GSPackageFlatFile`` when the value is not supported.
_GSDefineValidateOrDefault(GSPackageType, GSPackageFlatFile);

/// Options that control the data written while saving Glyphs source data.
typedef NS_OPTIONS(uint8_t, GSSaveOptions) {
	/// Standard save behavior.
	GSSaveOptionDefault = 0,
	/// Uses autosave serialization behavior and preserves recovery metadata.
	GSSaveOptionAutosave = 1 << 0,
	/// Includes the last-change timestamp of each glyph.
	GSSaveOptionWriteLastChange = 1 << 1,
	/// Omits layers from serialized glyph data.
	GSSaveOptionExcludeLayers = 1 << 2,
};

/// Whether a value contains only supported save options.
BOOL GSSaveOptionsValidate(GSSaveOptions value);
/// Supported save options, or ``GSSaveOptionDefault`` when the value contains an unsupported option.
_GSDefineValidateOrDefault(GSSaveOptions, GSSaveOptionDefault);

/// The display size of handles used to edit graphical elements.
typedef NS_ENUM(uint8_t, GSHandleSize) {
	/// Small handles.
	GSHandleSizeSmall = 0,
	/// Regular handles.
	GSHandleSizeRegular = 1,
	/// Large handles.
	GSHandleSizeLarge = 2,
} NS_SWIFT_NAME(GSHandle.Size);

/// Whether a value identifies a supported handle size.
BOOL GSHandleSizeValidate(GSHandleSize value);
/// A supported handle size, or ``GSHandleSizeRegular`` when the value is not supported.
_GSDefineValidateOrDefault(GSHandleSize, GSHandleSizeRegular);

/// The type of path segment that the node describes.
///
/// A node with type ``GSNodeTypeOffCurve`` controls the curvature of the segment to the next on-curve node.
typedef NS_ENUM(uint8_t, GSNodeType) {
	/// Line to point.
	GSNodeTypeLine = 1,
	/// Cubic curve to point using two off-curve points.
	GSNodeTypeCubicCurve = 35,
	/// Quadratic curve to point using variable number of off-curve points.
	GSNodeTypeQuadraticCurve = 36,
	/// Quartic curve to point using three off-curve points.
	GSNodeTypeQuarticCurve = 38,
	/// Off-curve point.
	GSNodeTypeOffCurve = 65,
	/// Hobby curve to point.
	GSNodeTypeHobbyCurve = 37,
	/// Raph New Spiral
	GSNodeTypeRaphNewSpiral = 39,
	GSNodeTypeSpecial = 101,
} NS_SWIFT_NAME(GSNode.NodeType);

BOOL GSNodeTypeValidate(GSNodeType value);
_GSDefineValidateOrDefault(GSNodeType, GSNodeTypeLine);

static const GSNodeType LINE GSDeprecated("GSNodeTypeLine") = GSNodeTypeLine;
static const GSNodeType CURVE GSDeprecated("GSNodeTypeCubicCurve") = GSNodeTypeCubicCurve;
static const GSNodeType OFFCURVE GSDeprecated("GSNodeTypeOffCurve") = GSNodeTypeOffCurve;
static const GSNodeType QCURVE GSDeprecated("GSNodeTypeQuadraticCurve") = GSNodeTypeQuadraticCurve;
static const GSNodeType QUART GSDeprecated("GSNodeTypeQuarticCurve") = GSNodeTypeQuarticCurve;
static const GSNodeType HOBBYCURVE GSDeprecated("GSNodeTypeHobbyCurve") = GSNodeTypeHobbyCurve;
static const GSNodeType SPECIAL GSDeprecated("GSNodeTypeSpecial") = GSNodeTypeSpecial;

/// The transition of a path through an on-curve node.
typedef NS_ENUM(uint8_t, GSNodeConnection) {
	/// The incoming and outgoing path segments are independent.
	GSNodeConnectionSharp = 0,
	/// The incoming and outgoing path segments are required to meet at the same angle.
	GSNodeConnectionSmooth = 100,
	/// The connection is adjusted for a more refined transition from the incoming to the outgoing path segment.
	///
	/// When one path segment is a line and the other a cubic curve, then the position of the node and of the off-curve nodes is adjusted for a smoother transition.
	/// An additional curve segment may be added on export to allow for a finer transition curvature.
	///
	/// When both path segments are cubic curves, then the position of the node is adjusted for a smoother transition.
	GSNodeConnectionSuperSmooth = 102,
} NS_SWIFT_NAME(GSNode.Connection);

BOOL GSNodeConnectionValidate(GSNodeConnection value);
_GSDefineValidateOrDefault(GSNodeConnection, GSNodeConnectionSharp);

static const GSNodeConnection SHARP GSDeprecated("GSNodeConnectionSharp") = GSNodeConnectionSharp;
static const GSNodeConnection SMOOTH GSDeprecated("GSNodeConnectionSmooth") = GSNodeConnectionSmooth;

/// The handle size used by editing tools.
extern GSHandleSize HandleSizeMode NS_SWIFT_UI_ACTOR;

/// Flags controlling which associated data is included when copying fonts, glyphs, and layers.
///
/// The effect of a flag depends on the type of object being copied.
typedef NS_OPTIONS(uint8_t, GSGlyphCopyOptions) {
	/// Does not include any glyph layers.
	GSGlyphCopyNoLayers = 0,
	/// Includes master layers.
	GSGlyphCopyMasterLayers = 1 << 0,
	/// Includes special layers, such as Intermediate and Alternative layers.
	GSGlyphCopySpecialLayers = 1 << 1,
	/// Includes additional ordinary layers.
	GSGlyphCopyBackupLayers = 1 << 2,
	/// Includes the background layer of each copied layer.
	GSGlyphCopyBackground = 1 << 3,
	/// Creates an undo manager for each copied glyph.
	GSGlyphCopyUndoManager = 1 << 4,
	/// Includes editing data such as guides, annotations, selection, and background images.
	GSGlyphCopyExtras = 1 << 5,
	/// Optimizes layer copying for callers that guarantee exclusive access to the copies.
	GSGlyphCopySkipLock = 1 << 6,
};

/// Master and special layers.
extern const GSGlyphCopyOptions GSGlyphCopyMasterAndSpecialLayers;
/// Master and special layers.
extern const GSGlyphCopyOptions GSGlyphCopyAllLayers GSDeprecated("GSGlyphCopyMasterAndSpecialLayers");
/// All copyable glyph and layer data.
extern const GSGlyphCopyOptions GSGlyphCopyAll;
/// Master layers without background or additional editing data.
extern const GSGlyphCopyOptions GSGlyphCopyThin;

/// A key identifying a font information property.
///
/// Property values can be defined by a font, font master, or instance and can be localized where supported.
typedef NSString *GSPropertyName NS_TYPED_EXTENSIBLE_ENUM;

/// Posted after a document has opened.
///
/// The notification object is the document.
extern NSNotificationName const GSDocumentWasOpenedNotification;
/// Posted when a document window becomes active.
///
/// The notification object is the window controller.
extern NSNotificationName const GSDocumentActivateNotification;
/// Posted when a document window becomes inactive.
///
/// The notification object is the window controller.
extern NSNotificationName const GSDocumentDeactivateNotification;
/// Posted before a document window closes.
///
/// The notification object is the document.
extern NSNotificationName const GSDocumentWillCloseNotification;
/// Posted after a document has closed.
///
/// The notification object is the document.
extern NSNotificationName const GSDocumentDidCloseNotification;

/// Requests that observers update interface state affected by the notification object.
extern NSNotificationName const GSUpdateInterface;
/// Posted when the frame available to the edit view changes.
///
/// The notification object is the edit view controller.
extern NSNotificationName const GSUpdateEditViewFrame;
/// Posted when the compiled feature state of a font changes.
///
/// The notification object is the font.
extern NSNotificationName const GSFeaturesChanged;
/// Posted when the instances of a font change.
///
/// The notification object is the font.
extern NSNotificationName const GSInstancesChanged;

/// Posted after an undo or redo operation.
///
/// The notification object is the document.
/// The `text` entry in `userInfo` contains a localized description of the operation.
extern NSNotificationName const GSUndoNotification;

/// The style of the default figure glyphs in a font.
///
/// This classification is used when generating OpenType features for alternate figure styles.
typedef NS_ENUM(uint8_t, GSFigureStyles) {
	/// The default figure style has not been determined.
	GSFigureStylesNotTested NS_SWIFT_NAME(notTested) = 0,
	/// The font does not contain default figure glyphs.
	GSFigureStylesNoFigures NS_SWIFT_NAME(noFigures) = 1,
	/// Tabular old-style figures.
	GSFigureStylesTosf NS_SWIFT_NAME(tabularOldStyle) = 2,
	/// Proportional old-style figures.
	GSFigureStylesOsf NS_SWIFT_NAME(proportionalOldStyle) = 3,
	/// Tabular lining figures.
	GSFigureStylesTf NS_SWIFT_NAME(tabularLining) = 4,
	/// Proportional lining figures.
	GSFigureStylesLf NS_SWIFT_NAME(proportionalLining) = 5,
};

/// Whether a value identifies a supported default figure style.
BOOL GSFigureStylesValidate(GSFigureStyles value);
/// A supported default figure style, or ``GSFigureStylesNotTested`` when the value is not supported.
_GSDefineValidateOrDefault(GSFigureStyles, GSFigureStylesNotTested);

/// The progression of glyphs and lines in text.
///
/// Writing directions use separate bits for bidirectional text, right-to-left glyph progression, vertical glyph progression, and left-to-right line progression.
/// Use the following complete values for text layout:
///
/// | Direction | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
/// | --- | --- | --- | --- | --- |
/// | Left-to-right, top-to-bottom | 0 | 0 | 0 | 0 |
/// | Bidirectional | 0 | 0 | 0 | 1 |
/// | Right-to-left, top-to-bottom | 0 | 0 | 1 | 0 |
/// | Top-to-bottom, right-to-left | 0 | 1 | 0 | 0 |
/// | Top-to-bottom, left-to-right | 1 | 1 | 0 | 0 |
typedef NS_OPTIONS(uint8_t, GSWritingDirection) {
	/// No inherent horizontal writing direction.
	GSWritingDirectionBIDI NS_SWIFT_NAME(bidi) = 1,
	/// Glyphs advance left-to-right and lines advance top-to-bottom.
	///
	/// This value has no bits set.
	GSWritingDirectionLeftToRight NS_SWIFT_NAME(leftToRight) = 0, // bit one and two not set
	/// Glyphs advance right-to-left and lines advance top-to-bottom.
	GSWritingDirectionRightToLeft NS_SWIFT_NAME(rightToLeft) = 1 << 1,
	/// Glyphs advance top-to-bottom and lines advance right-to-left.
	GSWritingDirectionVertical NS_SWIFT_NAME(vertical) = 1 << 2,
	/// Makes lines advance left-to-right in vertical text.
	///
	/// Combine this option with ``GSWritingDirectionVertical``.
	GSWritingDirectionLineToRight NS_SWIFT_NAME(lineToRight) = 1 << 3,

	/// Selects contextual kerning data.
	///
	/// This value is not a text layout direction and is not combined with direction values.
	GSKerningTypeContext NS_SWIFT_NAME(kerningTypeContext) = 1 << 7,
};

#define GSWritingDirectionIsLTR(d) ((d & GSWritingDirectionRightToLeft) == 0)
#define GSWritingDirectionIsRTL(d) ((d & GSWritingDirectionRightToLeft) == GSWritingDirectionRightToLeft)
#define GSWritingDirectionIsHorizontal(d) ((d & GSWritingDirectionVertical) == 0)
#define GSWritingDirectionIsVertical(d) ((d & GSWritingDirectionVertical) == GSWritingDirectionVertical)
#define GSWritingDirectionIsLineToRight(d) ((d & GSWritingDirectionLineToRight) == GSWritingDirectionLineToRight) && ((d & GSWritingDirectionVertical) == GSWritingDirectionVertical)
#define GSWritingDirectionIsLineToLeft(d) ((d & GSWritingDirectionLineToRight) == 0) && ((d & GSWritingDirectionVertical) == GSWritingDirectionVertical)

/// Whether a value contains only recognized writing-direction and kerning-selector bits.
BOOL GSWritingDirectionValidate(GSWritingDirection value);
/// A value containing only recognized bits, or ``GSWritingDirectionLeftToRight`` when the value contains an unsupported bit.
_GSDefineValidateOrDefault(GSWritingDirection, GSWritingDirectionLeftToRight);

/// A direction of progression along the horizontal axis.
typedef NS_CLOSED_ENUM(uint8_t, GSHorizontalLayoutDirection) {
	/// Progresses left-to-right.
	GSHorizontalLayoutDirectionLeftToRight,
	/// Progresses right-to-left.
	GSHorizontalLayoutDirectionRightToLeft,
} NS_SWIFT_NAME(GSLayoutDirection.Horizontal);

/// The axis along which characters progress.
typedef NS_CLOSED_ENUM(uint8_t, GSLayoutOrientation) {
	/// Characters progress along the horizontal axis.
	GSLayoutOrientationHorizontal,
	/// Characters progress along the vertical axis.
	GSLayoutOrientationVertical,
} NS_SWIFT_NAME(GSLayoutDirection.Orientation);

/// A resolved combination of character and line directions.
typedef NS_ENUM(uint8_t, GSLayoutDirection) {
	/// Characters progress left-to-right and lines progress top-to-bottom.
	GSLayoutDirectionLeftTopRightTopToBottom,
	/// Characters progress right-to-left and lines progress top-to-bottom.
	GSLayoutDirectionRightTopLeftTopToBottom,
	/// Characters progress top-to-bottom and lines progress left-to-right.
	GSLayoutDirectionTopToBottomLeftTopRight,
	/// Characters progress top-to-bottom and lines progress right-to-left.
	GSLayoutDirectionTopToBottomRightTopLeft,
};

/// Resolves a writing direction to a layout direction.
///
/// The standalone bidirectional and contextual-kerning values resolve to ``GSLayoutDirectionLeftTopRightTopToBottom``.
/// The vertical and line-progression bits take precedence over horizontal progression bits.
///
/// - Parameter writingDirection: The encoded writing direction.
/// - Returns: The corresponding resolved layout direction.
GSLayoutDirection GSLayoutDirectionFromWritingDirection(GSWritingDirection writingDirection) NS_SWIFT_NAME(GSLayoutDirection.init(_:));

/// Encodes a layout direction as a writing direction.
///
/// - Parameter layoutDirection: The resolved layout direction.
/// - Returns: The corresponding writing-direction bits.
GSWritingDirection GSWritingDirectionFromLayoutDirection(GSLayoutDirection layoutDirection) NS_SWIFT_NAME(GSWritingDirection.init(_:));

/// Returns the progression along the horizontal axis.
///
/// This is the character direction for horizontal layouts and the line direction for vertical layouts.
///
/// - Parameter layoutDirection: The resolved layout direction.
GSHorizontalLayoutDirection GSHorizontalLayoutDirectionFromLayoutDirection(GSLayoutDirection layoutDirection) NS_SWIFT_NAME(getter:GSLayoutDirection.horizontalDirection(self:));

/// Returns the axis along which characters progress.
///
/// - Parameter layoutDirection: The resolved layout direction.
GSLayoutOrientation GSLayoutOrientationFromLayoutDirection(GSLayoutDirection layoutDirection) NS_SWIFT_NAME(getter:GSLayoutDirection.orientation(self:));

/// A policy or result of automatically positioning a component.
typedef NS_ENUM(int8_t, GSComponentAlignment) {
	/// The component was not positioned automatically.
	GSAlignmentNoAligned NS_SWIFT_NAME(none) = -2,
	/// Automatic positioning is disabled.
	GSAlignmentDisable NS_SWIFT_NAME(disabled) = -1,
	/// Automatic positioning follows the normal eligibility rules.
	GSAlignmentDefault NS_SWIFT_NAME(default) = 0,
	/// Automatic positioning is enabled regardless of normal alignment eligibility.
	GSAlignmentForce NS_SWIFT_NAME(forced) = 1,
	/// Both coordinates were positioned automatically.
	GSAlignmentAligned NS_SWIFT_NAME(aligned) = 2,
	/// Only the horizontal coordinate is positioned automatically.
	GSAlignmentHorizontal NS_SWIFT_NAME(horizontal) = 3,
} NS_SWIFT_NAME(GSComponent.Alignment);

/// Whether a value is valid as an automatic-positioning policy.
static inline BOOL GSComponentAlignmentIsPolicyValue(GSComponentAlignment value) NS_SWIFT_NAME(getter:GSComponentAlignment.isPolicyValue(self:)) {
	switch (value) {
		case GSAlignmentDisable:
		case GSAlignmentDefault:
		case GSAlignmentForce:
		case GSAlignmentHorizontal:
			return YES;
		case GSAlignmentNoAligned:
		case GSAlignmentAligned:
			return NO;
	}
	return NO;
}

/// Whether a value is valid as an automatic-positioning result or unevaluated state.
static inline BOOL GSComponentAlignmentIsEffectiveValue(GSComponentAlignment value) NS_SWIFT_NAME(getter:GSComponentAlignment.isEffectiveValue(self:)) {
	switch (value) {
		case GSAlignmentNoAligned:
		case GSAlignmentDefault:
		case GSAlignmentAligned:
		case GSAlignmentHorizontal:
			return YES;
		case GSAlignmentDisable:
		case GSAlignmentForce:
			return NO;
	}
	return NO;
}

BOOL GSComponentAlignmentValidate(GSComponentAlignment value);
_GSDefineValidateOrDefault(GSComponentAlignment, GSAlignmentDefault);

/// The orientation for coordinate values.
typedef NS_ENUM(int8_t, GSElementOrientation) {
	/// The *x* axis advances left-to-right.
	///
	/// For example, an `x` value of `0` places a point on the left edge of the layer box.
	GSAlignmentLeft NS_SWIFT_NAME(left) = 0,
	/// The *x* axis advances left-to-right from the center of the layer box.
	///
	/// For example, an `x` value of `0` places a point in the center of the layer box.
	GSAlignmentCenter NS_SWIFT_NAME(center) = 2,
	/// The *x* axis advances right-to-left.
	///
	/// For example, an `x` value of `0` places a point on the right edge of the layer box.
	GSAlignmentRight NS_SWIFT_NAME(right) = 1,
};

BOOL GSElementOrientationValidate(GSElementOrientation value);
_GSDefineValidateOrDefault(GSElementOrientation, GSAlignmentLeft);

/// A placement or fitting option for attaching a corner or cap component to a path.
///
/// Placement values are mutually exclusive.
typedef NS_ENUM(int8_t, GSElementAttachment) {
	/// Aligns the component with the left side of the attachment.
	GSElementAttachmentLeft = 0,
	/// Centers the component on the attachment.
	GSElementAttachmentCenter = 2,
	/// Aligns the component with the right side of the attachment.
	GSElementAttachmentRight = 1,
	/// Preserves the component orientation instead of aligning it with either side of the attachment.
	GSElementAttachmentNeutral = 4,
};

/// Whether a value is a supported attachment constant.
BOOL GSElementAttachmentValidate(GSElementAttachment value);
/// A supported attachment constant, or ``GSElementAttachmentLeft`` when the value is not supported.
_GSDefineValidateOrDefault(GSElementAttachment, GSElementAttachmentLeft);

/// The case classification of a glyph.
typedef NS_ENUM(uint8_t, GSCase) {
	/// No case classification applies.
	GSNoCase NS_SWIFT_NAME(none) = 0,
	/// Uppercase.
	GSUppercase NS_SWIFT_NAME(uppercase) = 1,
	/// Lowercase.
	GSLowercase NS_SWIFT_NAME(lowercase) = 2,
	/// Small caps.
	GSSmallcaps NS_SWIFT_NAME(smallCaps) = 3,
	/// A minor form, such as a superscript, subscript, numerator, denominator, or ordinal.
	GSMinor NS_SWIFT_NAME(minor) = 4,
	/// A case classification not represented by the other values.
	GSOtherCase NS_SWIFT_NAME(other) = 5,
};

/// Whether a value identifies a supported case classification.
BOOL GSCaseValidate(GSCase value);
/// A supported case classification, or ``GSNoCase`` when the value is not supported.
_GSDefineValidateOrDefault(GSCase, GSNoCase);

/// An outline format used to export a static or variable OpenType font.
///
/// The format determines the outline table and curve representation of the exported font.
typedef NS_ENUM(uint8_t, GSOutlineFormat) {
	/// No outline format has been selected.
	GSOutlineFormatUnknown = 0,
	/// Static cubic outlines in a CFF table.
	GSOutlineFormatCFF = 1,
	/// Static cubic outlines in a CFF2 table.
	GSOutlineFormatCFF2 = 7,
	/// Variable cubic outlines in a CFF2 table.
	GSOutlineFormatVariableCFF2 = 4,
	/// Static quadratic outlines in a `glyf` table.
	GSOutlineFormatTrueType = 2,
	/// Variable quadratic outlines in a `glyf` table.
	GSOutlineFormatVariableTT NS_SWIFT_NAME(variableTrueType) = 3,
	/// Static cubic outlines in a `glyf` table.
	///
	/// > Important: This format is not well-supported by Glyphs API and other software.
	GSOutlineFormatTTCubic NS_SWIFT_NAME(trueTypeCubic) = 5,
	/// Variable cubic outlines in a `glyf` table.
	///
	/// > Important: This format is not well-supported by Glyphs API and other software.
	GSOutlineFormatVariableTTCubic NS_SWIFT_NAME(variableTrueTypeCubic) = 6,
};

static const GSOutlineFormat GSOutlineFormatVariableCFF = GSOutlineFormatVariableCFF2;

/// Whether a value identifies a supported outline format.
BOOL GSOutlineFormatValidate(GSOutlineFormat value);
/// A supported outline format, or ``GSOutlineFormatUnknown`` when the value is not supported.
_GSDefineValidateOrDefault(GSOutlineFormat, GSOutlineFormatUnknown);

/// Whether an outline format uses conventional quadratic TrueType outlines.
#define GSOutlineFormatIsTT(o) ((o == GSOutlineFormatTrueType) || (o == GSOutlineFormatVariableTT))
/// Whether an outline format uses a CFF or CFF2 table.
#define GSOutlineFormatIsCubic(o) ((o == GSOutlineFormatCFF) || (o == GSOutlineFormatVariableCFF) || (o == GSOutlineFormatCFF2))
/// Whether an outline format represents a static font.
#define GSOutlineFormatIsStatic(o) ((o == GSOutlineFormatTrueType) || (o == GSOutlineFormatCFF) || (o == GSOutlineFormatTTCubic) || (o == GSOutlineFormatCFF2))
/// Whether an outline format represents a variable font.
#define GSOutlineFormatIsVariable(o) ((o == GSOutlineFormatVariableTT) || (o == GSOutlineFormatVariableCFF) || (o == GSOutlineFormatVariableTTCubic))

typedef NS_ENUM(uint8_t, GSImageType) {
	GSImageTypeUnknown = 0,
	GSImageTypePng = 1,
	GSImageTypeTif NS_SWIFT_NAME(tiff) = 2,
	GSImageTypeJpg NS_SWIFT_NAME(jpeg) = 3,
	GSImageTypeSvg = 4,
	GSImageTypePdf = 5,
};

BOOL GSImageTypeValidate(GSImageType value);
_GSDefineValidateOrDefault(GSImageType, GSImageTypeUnknown);

typedef NS_ENUM(uint8_t, GSLabelColor) {
	GSLabelColorRed = 0,
	GSLabelColorOrange = 1,
	GSLabelColorBrown = 2,
	GSLabelColorYellow = 3,
	GSLabelColorGreen = 4,
	GSLabelColorDarkGreen = 5,
	GSLabelColorCyan = 6,
	GSLabelColorBlue = 7,
	GSLabelColorViolet = 8,
	GSLabelColorRose = 9,
	GSLabelColorGray = 10,
	GSLabelColorBlack = 11,
	GSLabelColorNoColor = 0xff,
};

BOOL GSLabelColorValidate(GSLabelColor value);
_GSDefineValidateOrDefault(GSLabelColor, GSLabelColorNoColor);

static const uint8_t GSLabelColorMaxColor NS_SWIFT_NAME(GSLabelColor.maxColorRawValue) = GSLabelColorBlack;

typedef NSString *GSFontFormat NS_TYPED_EXTENSIBLE_ENUM;
extern GSFontFormat const GSFontFormatPlainName;
extern GSFontFormat const GSFontFormatOTFName;
extern GSFontFormat const GSFontFormatTTFName;
extern GSFontFormat const GSFontFormatTTCubicName;
extern GSFontFormat const GSFontFormatWOFFName;
extern GSFontFormat const GSFontFormatWOFF2Name;

/// The font format identifier corresponding to an outline format.
GSFontFormat GSNameForOutlineFormat(GSOutlineFormat outlineFormat);
/// The file extension conventionally used for an outline format.
///
/// An unknown outline format uses the `otf` extension.
NSString *GSFileExtensionForOutlineFormat(GSOutlineFormat outlineFormat);

typedef NSString *GSImageExportSetting NS_TYPED_EXTENSIBLE_ENUM;
extern GSImageExportSetting const GSImageExportSettingsPresets;
extern GSImageExportSetting const GSImageExportSettingsActive;
extern GSImageExportSetting const GSImageExportSettingsSize;
extern GSImageExportSetting const GSImageExportSettingsPadding;
extern GSImageExportSetting const GSImageExportSettingsFactor;
extern GSImageExportSetting const GSImageExportSettingsFormat;
extern GSImageExportSetting const GSImageExportSettingsName;
extern GSImageExportSetting const GSImageExportSettingsFilename;
extern GSImageExportSetting const GSImageExportSettingsPath;
extern GSImageExportSetting const GSImageExportSettingsFormatPdf;
extern GSImageExportSetting const GSImageExportSettingsFormatPng;
extern GSImageExportSetting const GSImageExportSettingsFormatSvg;
extern GSImageExportSetting const GSImageExportSettingsUserDataKey;
extern GSImageExportSetting const GSImageExportSettingsUserDataOldKey;
extern GSImageExportSetting const GSImageExportSettingsDefaultsPathKey;

// backwards compatibility
// TODO: remove in final Glyphs 3
extern GSImageExportSetting const GSImageExportSettingsUserDataWidthKey;
extern GSImageExportSetting const GSImageExportSettingsUserDataHeightKey;
extern GSImageExportSetting const GSImageExportSettingsUserDataPathKey;
extern GSImageExportSetting const GSImageExportSettingsUserDataScaleKey;

typedef NSString *GSLanguageTag NS_TYPED_EXTENSIBLE_ENUM;

FOUNDATION_EXPORT GSLanguageTag kGSLanguageDefault;
FOUNDATION_EXPORT GSLanguageTag kGSLanguageEnglish;

typedef NSString *GSScriptTag NS_TYPED_EXTENSIBLE_ENUM;

FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDefault;

FOUNDATION_EXPORT GSScriptTag const kGSScriptTagAdlam;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagAhom;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagAnatolianHieroglyphs;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagArabic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagArmenian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagAvestan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBalinese;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBamum;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBassaVah;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBatak;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBengali;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBengaliV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBhaiksuki;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBopomofo;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBrahmi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBraille;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBuginese;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagBuhid;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagByzantineMusic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCanadianSyllabics;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCarian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCaucasianAlbanian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagChakma;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCham;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCherokee;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagChorasmian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCJKIdeographic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCoptic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCypriotSyllabary;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCyproMinoan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagCyrillic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDeseret;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDevanagari;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDevanagariV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDivesAkuru;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDogra;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagDuployan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagEgyptianHieroglyphs;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagElbasan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagElymaic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagEthiopic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGeorgian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGlagolitic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGothic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGrantha;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGreek;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGujarati;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGujaratiV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGunjalaGondi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGurmukhi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGurmukhiV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHangul;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHangulJamo;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHanifiRohingya;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHanunoo;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHatran;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHebrew;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagHiragana;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagImperialAramaic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagInscriptionalPahlavi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagInscriptionalParthian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagJavanese;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKaithi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKannada;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKannadaV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKatakana;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKayahLi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKharosthi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKhitanSmallScript;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKhmer;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKhojki;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKhudawadi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLao;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLatin;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLepcha;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLimbu;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLinearA;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLinearB;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLisu; // (Fraser)
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLycian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagLydian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMahajani;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMakasar;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMalayalam;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMalayalamV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMandaic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagManichaean;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMarchen;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMasaramGondi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMath;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMedefaidrin;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMeeteiMayek; // (Meithei, Meetei)
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMendeKikakui;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMeroiticCursive;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMeroiticHieroglyphs;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMiao;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagModi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMongolian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMro;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMultani;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMusicalSymbols;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMyanmar;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagMyanmarV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNabataean;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNandinagari;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNewa;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNewTaiLue;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNKo;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNushu;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNyiakengPuachueHmong;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOdia; // (formerly Oriya)
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOdiaV2; // (formerly Oriya v.2)
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOgham;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOlChiki;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldItalic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagRovas;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldNorthArabian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldPermic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldPersianCuneiform;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldSogdian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldSouthArabian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldTurkic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOldUyghur;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOsage;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOsmanya;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPahawhHmong;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPalmyrene;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPauCinHau;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPhagsPa;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPhoenician;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagPsalterPahlavi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagRejang;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagRunic;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSamaritan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSaurashtra;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSharada;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagShavian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSiddham;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSignWriting;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSinhala;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSogdian;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSoraSompeng;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSoyombo;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSumeroAkkadianCuneiform;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSundanese;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSylotiNagri;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSyriac;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTagalog;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTagbanwa;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTaiLe;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTaiTham; // (Lanna)
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTaiViet;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTakri;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTamil;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTamilV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTangsa;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTangut;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTelugu;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTeluguV2;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagThaana;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagThai;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTibetan;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTifinagh;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTirhuta;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagToto;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagUgariticCuneiform;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagVai;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagVithkuqi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagWancho;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagWarangCiti;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagYezidi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagYi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagZanabazarSquare;

FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKawi;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagNagMundari;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGaray;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagGurungKhema;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagKiratRai;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagOlOnal;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagSunuwar;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTodhri;
FOUNDATION_EXPORT GSScriptTag const kGSScriptTagTuluTigalari;

typedef NSString *GSScriptID NS_TYPED_EXTENSIBLE_ENUM;

FOUNDATION_EXPORT GSScriptID const kGSScriptIDAdlam;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDAhom;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDAnatolianHieroglyphs;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDArabic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDArmenian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDAvestan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBalinese;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBamum;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBassaVah;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBatak;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBengali;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBhaiksuki;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBopomofo;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBrahmi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBraille;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBuginese;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBuhid;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDByzantineMusic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCanadianSyllabics;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCarian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCaucasianAlbanian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDChakma;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCham;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCherokee;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDChorasmian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCJK;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCoptic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCypriotSyllabary;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCyproMinoan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDCyrillic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDDeseret;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDDevanagari;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDDivesAkuru;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDDogra;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDDuployan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDEgyptianHieroglyphs;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDElbasan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDElymaic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDEtruscan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDEthiopic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGeorgian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGlagolitic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGothic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGrantha;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGreek;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGujarati;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGunjalaGondi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGurmukhi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHangul;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHangulJamo;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHanifiRohingya;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHanunoo;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHatran;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHebrew;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDHiragana;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDImperialAramaic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDInscriptionalPahlavi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDInscriptionalParthian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDJavanese;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKaithi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKannada;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKatakana;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKayahLi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKharosthi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKhitanSmallScript;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKhmer;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKhojki;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKhudawadi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLao;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLatin;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLepcha;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLimbu;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLinearA;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLinearB;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLisu; // (Fraser)
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLycian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDLydian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMahajani;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMakasar;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMalayalam;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMandaic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDManichaean;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMarchen;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMasaramGondi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMath;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMedefaidrin;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMeeteiMayek; // (Meithei, Meetei)
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMendeKikakui;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMeroiticCursive;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMeroiticHieroglyphs;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMiao;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDModi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMongolian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMro;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMultani;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMusicalSymbols;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDMyanmar;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNabataean;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNandinagari;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNewa;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNewTaiLue;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNKo;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNushu;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNyiakengPuachueHmong;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOriya;  // (should be Odia)
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOscan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOgham;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOlChiki;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldItalic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldGeorgian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldNorthArabian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldPermic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldPersianCuneiform;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldSogdian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldSouthArabian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldTurkic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOldUyghur;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOsage;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOsmanya;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPahawhHmong;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPalmyrene;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPauCinHau;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPhagsPa;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPhoenician;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDPsalterPahlavi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDRejang;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDRovas;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDRunic;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSamaritan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSaurashtra;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSharada;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDShavian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSiddham;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSignWriting;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSinhala;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSogdian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSoraSompeng;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSoyombo;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSumeroAkkadianCuneiform;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSundanese;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSylotiNagri;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSyriac;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTagalog;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTagbanwa;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTaiLe;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTaiTham; // (Lanna)
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTaiViet;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTakri;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTamil;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTangsa;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTangut;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTelugu;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDThaana;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDThai;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTibetan;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTifinagh;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTirhuta;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDToto;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDUgariticCuneiform;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDUmbrian;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDVai;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDVithkuqi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDWancho;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDWarangCiti;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDYezidi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDYi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDZanabazarSquare;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKawi;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDNagMundari;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGaray;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDGurungKhema;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDKiratRai;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDOlOnal;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDSunuwar;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTodhri;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDTuluTigalari;
FOUNDATION_EXPORT GSScriptID const kGSScriptIDBlackLetter;

typedef NSString *GSEditViewGlyphName NS_TYPED_EXTENSIBLE_ENUM;
/// Signals a placeholder layer.
FOUNDATION_EXPORT GSEditViewGlyphName const GSPlaceholderKey;
/// The name of a line break layer.
FOUNDATION_EXPORT GSEditViewGlyphName const GSNewLineKey;

/// Grid settings used to round coordinates.
///
/// The effective horizontal and vertical lengths determine the rounding intervals.
/// The main lengths, subdivisions, and slope retain the source grid configuration.
typedef struct GSGridSettings {
	/// The effective interval for rounding horizontal coordinates.
	CGFloat lengthHorizontal;
	/// The effective interval for rounding vertical coordinates.
	CGFloat lengthVertical;

	/// The horizontal length of the main grid before subdivision.
	uint32_t mainHorizontal;
	/// The vertical length of the main grid before subdivision.
	uint32_t mainVertical;
	/// The number of horizontal subdivisions of the main grid.
	uint32_t subDivisionHorizontal;
	/// The number of vertical subdivisions of the main grid.
	uint32_t subDivisionVertical;
	/// The rise component of the grid slope.
	int32_t slopeRise;
	/// The run component of the grid slope.
	int32_t slopeRun;
} GSGridSettings;

/// The tolerance used when comparing coordinates.
extern CGFloat const MinPrecisionThreshold;
/// The threshold a grid interval must exceed to enable coordinate rounding.
extern CGFloat const MinMeaningfulGrid;

/// Whether the grid enables coordinate rounding.
BOOL GSIsMeaningfulGrid(GSGridSettings grid);
/// Whether either effective grid interval is at least one unit.
BOOL GSIsUnitGridOrMore(GSGridSettings grid);
/// A grid with one-unit intervals in both directions.
extern const GSGridSettings GSUnitGrid NS_SWIFT_NAME(GSGridSettings.unit);
/// Grid settings that disable coordinate rounding.
extern const GSGridSettings GSZeroGrid NS_SWIFT_NAME(GSGridSettings.zero);
/// Grid settings with the same effective interval in both directions.
/// - Parameter length: The interval used to round coordinates.
GSGridSettings GSMakeGridSetting(CGFloat length);

/// Extension in the spirit of `CGRectNull`.
static const CGPoint GSPointNull NS_SWIFT_NAME(CGPoint.null) = {INFINITY, INFINITY};

inline BOOL GSPointIsNull(CGPoint p) NS_SWIFT_NAME(getter:GSPoint.isNull(self:)) {
	return CGPointEqualToPoint(p, (CGPoint){INFINITY, INFINITY});
}

typedef NSString *GSDrawingOption NS_TYPED_EXTENSIBLE_ENUM;
extern GSDrawingOption const GSDrawingOptionDarkModeKey;
extern GSDrawingOption const GSDrawingOptionVibrancy;
extern GSDrawingOption const GSDrawingOptionHasBackground;
extern GSDrawingOption const GSDrawingOptionScaleKey;
extern GSDrawingOption const GSDrawingOptionIndexKey;

typedef NS_OPTIONS(NSUInteger, GSDrawStackFeature) {
	/// Subtraction masks are not pre-applied to the slice.
	///
	/// Supporting this feature requires handling masks in `GSDrawSlice.masks` with mask of type of `GSMaskTypeSubtract`.
	GSDrawStackFeatureSubtractionMasks = 1 << 0,
	/// Intersection masks are not pre-applied to the slice.
	///
	/// Supporting this feature requires handling masks in `GSDrawSlice.masks` with mask type of `GSMaskTypeIntersect`.
	GSDrawStackFeatureIntersectionMasks = 1 << 1,
	/// Strokes are not written to separate draw stack slices.
	///
	/// If this feature is not supported, then shapes with strokes are split into two consecutive slices.
	/// The first slice as if no stroke attributes were applied.
	/// The second slice containing only the path of the expanded outline with the stroke attributes (color, gradient, etc.) rewritten as fill attributes.
	/// If `GSDrawStackFeatureCompositionGroups` is also supported, then the two slices are grouped.
	///
	/// Supporting this feature requires handling `GSShapeKeyStrokeWidth` and related attributes.
	GSDrawStackFeatureStrokes = 1 << 2,
	/// A composition groups combines multiple composition elements, allowing, for example, a mask to be applied to an entire group while maintaining the inner structure of the group.
	/// Otherwise, the members of the group are merged into a single path element.
	///
	/// Composition groups result from
	/// - `GSGroupShape` shapes
	/// - components, either if `GSDrawStackFeatureStaticComponents` is unsupported or the component is smart
	///
	/// Supporting this feature requires handling `GSDrawGroupSlice`.
	GSDrawStackFeatureCompositionGroups = 1 << 3,
	/// Components (excluding smart components) are not converted to paths and instead are maintained.
	///
	/// Supporting this feature requires handling `GSDrawComponentSlice`.
	GSDrawStackFeatureStaticComponents = 1 << 4,
	/// Supporting this feature requires handling `GSDrawImageSlice`.
	GSDrawStackFeatureImages = 1 << 5,
	/// Supporting this feature requires handling `GSDrawTextSlice`.
	GSDrawStackFeatureText = 1 << 6,
	/// Inserts error slices into the draw stack when a slice cannot be created.
	///
	/// The error slice contains an error code indicating the source of the error.
	/// For example, a component with a missing base glyph constitutes an error.
	///
	/// Simply drop support for this feature to skip such slices.
	///
	/// Supporting this feature requires handling `GSDrawErrorSlice`.
	GSDrawStackFeatureErrors = 1 << 7,
};

typedef struct GSIntersectResultsStruct {
	NSPoint results[16];
	uint8 count;
} GSIntersectResultsStruct;

#if DEBUG
	void GSDebugBreak(void);
#else
#define GSDebugBreak()
#endif

#endif /* GSBase_h */
