Skip to content

Commit

Permalink
resolved merge conflict after rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Jun 3, 2017
1 parent 10946dc commit 8c5dd95
Show file tree
Hide file tree
Showing 5 changed files with 1,054 additions and 0 deletions.
240 changes: 240 additions & 0 deletions Sources/Cairo/Context.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
//
// Context.swift
// Cairo
//
// Created by Alsey Coleman Miller on 1/31/16.
// Copyright © 2016 PureSwift. All rights reserved.
//

import CCairo

/// Cairo Context
public final class Context {

// MARK: - Properties

public let surface: Surface

// MARK: - Internal Properties

internal var internalPointer: OpaquePointer

// MARK: - Initialization

deinit {

cairo_destroy(internalPointer)
}

/// Creates a new `Context` with all graphics state parameters set to default values
/// and with `surface` as a target surface.
public init(surface: Surface) {

// create
let internalPointer = cairo_create(surface.internalPointer)

assert(internalPointer != nil, "Could not create internal pointer")

// set values
self.internalPointer = internalPointer
self.surface = surface
}

// MARK: - Methods

/// Makes a copy of the current state of the context and saves it on an internal stack of saved states.
/// When `restore()` is called, the context will be restored to the saved state.
/// Multiple calls to `save()` and `restore()` can be nested;
/// each call to `restore()` restores the state from the matching paired cairo_save().
public func save() {

cairo_save(internalPointer)
}

/// Restores the context to the state saved by a preceding call to `save()` and removes that state from the stack of saved states.
public func restore() {

cairo_restore(internalPointer)
}

/// Temporarily redirects drawing to an intermediate surface known as a group.
/// The redirection lasts until the group is completed by a call to `popGroup()`.
/// These calls provide the result of any drawing to the group as a pattern,
/// (either as an explicit object, or set as the source pattern).
///
/// This group functionality can be convenient for performing intermediate compositing.
/// One common use of a group is to render objects as opaque within the group,
/// (so that they occlude each other), and then blend the result with translucence onto the destination.
public func pushGroup(content: Content? = nil) {

if let content = content {

cairo_push_group_with_content(internalPointer, cairo_content_t(rawValue: content.rawValue))

} else {

cairo_push_group(internalPointer)
}
}

/// Terminates the redirection begun by a call to `pushGroup()` and
/// returns a new pattern containing the results of all drawing operations performed to the group.
public func popGroup() -> Pattern {

let patternPointer = cairo_pop_group(internalPointer)

let pattern = Pattern(patternPointer)

return pattern
}

/// Terminates the redirection begun by a call to `pushGroup()`
/// and installs the resulting pattern as the source pattern in the given context.
public func popGroupToSource() {

cairo_pop_group_to_source(internalPointer)
}

public func setSource(color: (red: Double, green: Double, blue: Double)) {

cairo_set_source_rgb(internalPointer, color.red, color.green, color.blue)
}

public func setSource(color: (red: Double, green: Double, blue: Double, alpha: Double)) {

cairo_set_source_rgba(internalPointer, color.red, color.green, color.blue, color.alpha)
}

public func setSource(pattern: Pattern) {

cairo_set_source(internalPointer, pattern.internalPointer)
}

public func stroke() {

cairo_stroke(internalPointer)
}

public func fill() {

cairo_fill(internalPointer)
}

public func paint(alpha: Double? = nil) {

if let alpha = alpha {

cairo_paint_with_alpha(internalPointer, alpha)
}
else {

cairo_paint(internalPointer)
}
}

/// Adds a closed sub-path rectangle of the given size to the current path at position `(x , y)` in user-space coordinates.
public func addRectangle(x: Double, y: Double, width: Double, height: Double) {

cairo_rectangle(internalPointer, x, y, width, height)
}

/// Adds a circular arc of the given radius to the current path.
/// The arc is centered at (xc , yc ), begins at angle1 and proceeds in the direction of increasing angles to end at
/// angle2 . If angle2 is less than angle1 it will be progressively increased by 2*M_PI until it is greater than angle1 .
///
/// If there is a current point, an initial line segment will be added to the path to connect the current point to
/// the beginning of the arc. If this initial line is undesired, it can be avoided by calling `newSubpath()` before calling `addArc()`.
///
/// Angles are measured in radians.
/// An angle of `0.0` is in the direction of the positive X axis (in user space).
/// An angle of `M_PI/2.0` radians (90 degrees) is in the direction of the positive Y axis (in user space).
/// Angles increase in the direction from the positive X axis toward the positive Y axis.
/// So with the default transformation matrix, angles increase in a clockwise direction.
///
/// (To convert from degrees to radians, use `degrees * (M_PI / 180.)`.)
///
/// This method gives the arc in the direction of increasing angles; see `arcNegative()`
/// to get the arc in the direction of decreasing angles.
public func addArc(center: (x: Double, y: Double), radius: Double, angle: (Double, Double), negative: Bool = false) {

if negative {

cairo_arc_negative(internalPointer, center.x, center.y, radius, angle.0, angle.1)

} else {

cairo_arc(internalPointer, center.x, center.y, radius, angle.0, angle.1)
}
}

/// Creates a copy of the current path and returns it to the user as a `Path`.
public func copyPath() -> Path {

let pathPointer = cairo_copy_path(internalPointer)

return Path(pathPointer)
}

/// Gets a flattened copy of the current path.
public func copyFlatPath() -> Path {

let pathPointer = cairo_copy_path_flat(internalPointer)

return Path(pathPointer)
}

public func setFont(size: Double) {

cairo_set_font_size(internalPointer, size)
}

public func setFont(face: (family: String, slant: FontSlant, weight: FontWeight)) {

cairo_select_font_face(internalPointer, face.family, cairo_font_slant_t(face.slant.rawValue), cairo_font_weight_t(face.weight.rawValue))
}

public func move(to coordinate: (x: Double, y: Double)) {

cairo_move_to(internalPointer, coordinate.x, coordinate.y)
}

public func line(to coordinate: (x: Double, y: Double)) {

cairo_line_to(internalPointer, coordinate.x, coordinate.y)
}

public func show(text: String) {

cairo_show_text(internalPointer, text)
}

public func scale(x: Double, y: Double) {

cairo_scale(internalPointer, x, y)
}

// MARK: - Accessors

/// Gets the current destination surface for the context.
///
/// This is either the original target surface or the target surface for the current group
/// as started by the most recent call to `pushGroup()`.
public var groupTarget: Surface {

let surfacePointer = cairo_get_group_target(internalPointer)

let surface = Surface(surfacePointer)

return surface
}

public var lineWidth: Double {

get { return cairo_get_line_width(internalPointer) }

set { cairo_set_line_width(internalPointer, newValue) }
}


}

17 changes: 17 additions & 0 deletions Sources/UnitTests/CairoTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// CairoTest.h
// Cairo
//
// Created by Alsey Coleman Miller on 5/8/16.
// Copyright © 2016 PureSwift. All rights reserved.
//

@import Foundation;

@interface CairoTest : NSObject

+ (void)helloWikipedia:(NSString *)filename;

+ (void)sourceX:(NSString *)filename;

@end
93 changes: 93 additions & 0 deletions Sources/UnitTests/CairoTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// CairoTest.m
// Cairo
//
// Created by Alsey Coleman Miller on 5/8/16.
// Copyright © 2016 PureSwift. All rights reserved.
//

#import "CairoTest.h"
#import <cairo/cairo.h>

@implementation CairoTest

+ (void)helloWikipedia:(NSString *)filename
{
cairo_t *cr;
cairo_surface_t *surface;
cairo_pattern_t *pattern;
int x,y;

const char *cString = [filename cStringUsingEncoding: NSUTF8StringEncoding];

surface =
(cairo_surface_t *)cairo_svg_surface_create(cString, 100.0, 100.0);
cr = cairo_create(surface);

/* Draw the squares in the background */
for (x=0; x<10; x++)
for (y=0; y<10; y++)
cairo_rectangle(cr, x*10.0, y*10.0, 5, 5);

pattern = cairo_pattern_create_radial(50, 50, 5, 50, 50, 50);
cairo_pattern_add_color_stop_rgb(pattern, 0, 0.75, 0.15, 0.99);
cairo_pattern_add_color_stop_rgb(pattern, 0.9, 1, 1, 1);

cairo_set_source(cr, pattern);
cairo_fill(cr);

/* Writing in the foreground */
cairo_set_font_size (cr, 15);
cairo_select_font_face (cr, "Georgia",
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_source_rgb (cr, 0, 0, 0);

cairo_move_to(cr, 10, 25);
cairo_show_text(cr, "Hallo");

cairo_move_to(cr, 10, 75);
cairo_show_text(cr, "Wikipedia!");

cairo_destroy (cr);
cairo_surface_destroy (surface);
}

+ (void)sourceX:(NSString *)filename
{
cairo_surface_t *surface;
cairo_t *cr;
const char *cString = [filename cStringUsingEncoding: NSUTF8StringEncoding];

surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 120, 120);
cr = cairo_create (surface);
/* Examples are in 1.0 x 1.0 coordinate space */
cairo_scale (cr, 120, 120);

/* Drawing code goes here */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, 1, 1);
cairo_move_to (cr, 1, 0);
cairo_line_to (cr, 0, 1);
cairo_set_line_width (cr, 0.2);
cairo_stroke (cr);

cairo_rectangle (cr, 0, 0, 0.5, 0.5);
cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
cairo_fill (cr);

cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 1, 0, 0.60);
cairo_fill (cr);

cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 0, 1, 0.40);
cairo_fill (cr);

/* Write output and clean up */
cairo_surface_write_to_png (surface, cString);
cairo_destroy (cr);
cairo_surface_destroy (surface);
}

@end
Loading

0 comments on commit 8c5dd95

Please sign in to comment.