//
//  GSPenProtocol.h
//  GlyphsCore
//
//  Created by Georg Seifert on 16.11.11.
//  Copyright 2011 schriftgestaltung.de. All rights reserved.
//

#import <GlyphsCore/GSNode.h>
#import <GlyphsCore/GSShape.h>

@class GSLayer;
@class GSComponent;
@class FTPointArray;
@class GSShadow;
@class GSGradient;
@class GSImage;

@protocol GSPenProtocol

/** Begin a new sub path, set the current point to 'pt'. You must
end each sub path with a call to pen.closePath() or pen.endPath().
*/
- (void)moveTo:(NSPoint)pt NS_SWIFT_NAME(movePen(to:));

/** Draw a straight line from the current point to 'pt'.*/
- (void)lineTo:(NSPoint)pt NS_SWIFT_NAME(linePen(to:));

/** Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve
(control) points. If the number of control points is > 2, the
segment is split into multiple bezier segments.
*/
- (void)curveTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 NS_SWIFT_NAME(curve(to:off1:off2:));

/** Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve
points. When the last point has an X coordinate of `NSNotFound`,
then there is no on-curve end point. Instead, the implied on-curve
point is placed half-way between the last and first off-curve point.

If no off-curve points are given, performs a line-to operation to the on-curve point.

- Parameter points: A sequence of zero or more off-curve points followed by a single on-curve point.
- Parameter count: The total number of points in `points`. A count of `0` is invalid.
*/
- (void)qCurveWithPoints:(const NSPoint * __counted_by(count))points count:(NSUInteger)count NS_SWIFT_NAME(quadraticCurve(points:count:));

/// Draw a whole sting of quadratic curve segments.
///
/// Usually, implementations of this just call `-qCurveWithPoints:count:` with the points and count of the `FTPointArray`.
/// Therefore, prefer using `-qCurveWithPoints:count:` instead when possible.
- (void)qCurveTo:(FTPointArray *)points NS_SWIFT_NAME(quadraticCurve(to:));

/** Close the current sub path. You must call either pen.closePath()
or pen.endPath() after each sub path.
 */
- (void)closePath;

/** End the current sub path, but don't close it. You must call
either pen.closePath() or pen.endPath() after each sub path.
 */
- (void)endPath;

- (void)addComponent:(GSComponent *)component transformation:(NSAffineTransform *)transformation;

/// Appends the contents of another pen to this pen.
///
/// Requires that the other pen is of the same type as this pen in the general case.
/// Specific pen implementations may also accept pen arguments of other types.
- (void)append:(NSObject<GSPenProtocol> *)pen;

@property (readonly, nonatomic) NSPoint lastPoint;

@property (nonatomic, readonly) BOOL hasContent;

@optional

@property (nonatomic, strong) NSAffineTransform *transform;

/**
To initialize stuff
*/
- (void)startGlyph:(GSLayer *)layer;
- (void)endGlyph:(GSLayer *)layer;

- (void)startPath:(NSDictionary *)attributes;

- (void)clear;

/// starts an empty new path
- (void)beginPath;

- (void)moveTo:(NSPoint)pt objects:(NSArray *)objects;
- (void)moveTo:(NSPoint)pt connection:(GSNodeConnection)connection selected:(BOOL)selected attributes:(NSDictionary *)attributes;

- (void)lineTo:(NSPoint)pt objects:(NSArray *)objects;
- (void)lineTo:(NSPoint)pt connection:(GSNodeConnection)connection selected:(BOOL)selected attributes:(NSDictionary *)attributes;

- (void)qCurveWithPoints:(const NSPoint * __counted_by(count))points count:(NSUInteger)count objects:(NSArray *)objects;

- (void)curveTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 objects:(NSArray *)objects;
- (void)curveTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 connection:(GSNodeConnection)connection selected:(BOOL)selected;
- (void)curveTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 connection:(GSNodeConnection)connection selected:(BOOL)selected attributes:(NSDictionary *)attributes;

- (void)quartTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 off3:(NSPoint)off3;
- (void)quartTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 off3:(NSPoint)off3 objects:(NSArray *)objects;
- (void)quartTo:(NSPoint)pt off1:(NSPoint)off1 off2:(NSPoint)off2 off3:(NSPoint)off3 connection:(GSNodeConnection)connection selected:(BOOL)selected attributes:(NSDictionary *)attributes;

- (void)setHints:(NSArray *)hints;

@property (assign) BOOL ignoreSingleNodes;

- (void)setLastPoint:(NSPoint)point;

@property (nonatomic, readonly) BOOL closed NS_SWIFT_NAME(isClosed);

/// drawing attributes
@property (nonatomic, strong) NSColor *fillColor;
@property (nonatomic, strong) NSColor *strokeColor;
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic) GSLineCapStyle lineCapStyle;
@property (nonatomic) GSLineJoinStyle lineJoinStyle;
- (void)setShadow:(GSShadow *)shadow;
- (void)setGradient:(GSGradient *)gradient bounds:(NSRect)bounds;
- (void)setIdentifier:(NSString *)identifier;

// store the grid for that drawing operation. Getting it from the layer it too slow (going through the master, now)
@property GSGridSettings grid;

- (void)addImage:(GSImage *)image;

- (void)drawInPen:(NSObject<GSPenProtocol> *)pen;

@end
