<commit_before>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, <NAME> & <NAME>
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name Style
 *
 * @class Style is used for changing the visual styles of items
 * contained within a Paper.js project and is returned by
 * {@link Item#style} and {@link Project#currentStyle}.
 *
 * All properties of Style are also reflected directly in {@link Item},
 * i.e.: {@link Item#fillColor}.
 *
 * To set multiple style properties in one go, you can pass an object to
 * {@link Item#style}. This is a convenient way to define a style once and
 * apply it to a series of items:
 *
 * @classexample {@paperscript}
 *
 * var path = new Path.Circle(new Point(80, 50), 30);
 * path.style = {
 * 	fillColor: new Color(1, 0, 0),
 * 	strokeColor: 'black',
 * 	strokeWidth: 5
 * };
 *
 * @classexample
 * var text = new PointText(new Point(50, 50));
 * text.content = 'Hello world.';
 * text.style = {
 * 	fontSize: 50,
 * 	fillColor: 'black',
 * };
 *
 * @classexample
 * var text = new PointText(new Point(0,0));
 * text.fillColor = 'black';
 * text.content = 'Hello world.';
 * text.justification = 'center';
 */
var Style = this.Style = Base.extend(new function() {
	// windingRule / resolution / fillOverprint / strokeOverprint are currently
	// not supported.
	var defaults = {
		// path styles
		fillColor: undefined,
		strokeColor: undefined,
		strokeWidth: 1,
		strokeCap: 'butt',
		strokeJoin: 'miter',
		miterLimit: 10,
		dashOffset: 0,
		dashArray: [],
		// character styles
		font: 'sans-serif',
		fontSize: 12,
		leading: null,
		// paragraph styles
		justification: 'left'
	};

	var flags = {
		strokeWidth: /*#=*/ Change.STROKE,
		strokeCap: /*#=*/ Change.STROKE,
		strokeJoin: /*#=*/ Change.STROKE,
		miterLimit: /*#=*/ Change.STROKE,
		font: /*#=*/ Change.GEOMETRY,
		fontSize: /*#=*/ Change.GEOMETRY,
		leading: /*#=*/ Change.GEOMETRY,
		justification: /*#=*/ Change.GEOMETRY
	};

	var item = {},
		fields = {
			_defaults: defaults,
			// Override default fillColor for text items
			_textDefaults: Base.merge(defaults, {
				fillColor: new Color() // black
			})
		};

	Base.each(defaults, function(value, key) {
		var isColor = /Color$/.test(key),
			part = Base.capitalize(key),
			flag = flags[key],
			set = 'set' + part,
			get = 'get' + part;

		// Define getters and setters to be injected into this class
		fields[set] = function(value) {
			var children = this._item && this._item._children;
			// Clone color objects since they reference their owner
			// value = isColor ? Color.read(arguments, 0, 0, true) : value;
			// Only unify styles on children of Groups, excluding CompoundPaths.
			if (children && children.length > 0
					&& this._item._type !== 'compound-path') {
				for (var i = 0, l = children.length; i < l; i++)
					children[i]._style[set](value);
			} else {
				var old = this._values[key];
				if (old === undefined || !Base.equals(old, value)) {
					if (isColor) {
						if (old)
							delete old._owner;
						if (value && value.constructor === Color)
							value._owner = this._item;
					}
					this._values[key] = value;
					// Notify the item of the style change STYLE is always set,
					// additional flags come from flags, as used for STROKE:
					if (this._item)
						this._item._changed(flag || /*#=*/ Change.STYLE);
				}
			}
		};

		fields[get] = function() {
			var value,
				children = this._item && this._item._children;
			// If this item has children, walk through all of them and see if
			// they all have the same style.
			if (!children || children.length === 0
					|| this._item._type === 'compound-path') {
				var value = this._values[key];
				if (value === undefined) {
					value = this._defaults[key];
					if (value && value.clone)
						value = value.clone();
					this._values[key] = value;
				} else if (isColor && !(value instanceof Color)) {
					this._values[key] = value = Color.read([value], 0, 0, true, true);
					if (value)
						value._owner = this._item;
				}
				return value;
			}
			for (var i = 0, l = children.length; i < l; i++) {
				var childValue = children[i]._style[get]();
				if (!value) {
					value = childValue;
				} else if (!Base.equals(value, childValue)) {
					// If there is another item with a different
					// style, the style is not defined:
					return undefined;
				}
			}
			return value;
		};

		// Inject style getters and setters into the Item class, which redirect
		// calls to the linked style object.
		item[get] = function() {
			return this._style[get]();
		};

		item[set] = function(value) {
			this._style[set](value);
		};
	});

	Item.inject(item);
	return fields;
}, /** @lends Style# */{
	initialize: function(style) {
		// Keep values in a separate object that we can iterate over.
		this._values = {};
		if (this._item instanceof TextItem)
			this._defaults = this._textDefaults;
		if (style) {
			// If the passed style object is also a Style, clone its clonable
			// fields rather than simply copying them.
			var isStyle = style instanceof Style,
				// Use the other stlyle's _values object for iteration
				values = isStyle ? style._values : style;
			for (var key in values) {
				if (key in this._defaults) {<commit_msg>Document new approach to styles.<commit_after>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, <NAME> & <NAME>
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name Style
 *
 * @class Style is used for changing the visual styles of items
 * contained within a Paper.js project and is returned by
 * {@link Item#style} and {@link Project#currentStyle}.
 *
 * All properties of Style are also reflected directly in {@link Item},
 * i.e.: {@link Item#fillColor}.
 *
 * To set multiple style properties in one go, you can pass an object to
 * {@link Item#style}. This is a convenient way to define a style once and
 * apply it to a series of items:
 *
 * @classexample {@paperscript}
 *
 * var path = new Path.Circle(new Point(80, 50), 30);
 * path.style = {
 * 	fillColor: new Color(1, 0, 0),
 * 	strokeColor: 'black',
 * 	strokeWidth: 5
 * };
 *
 * @classexample
 * var text = new PointText(new Point(50, 50));
 * text.content = 'Hello world.';
 * text.style = {
 * 	fontSize: 50,
 * 	fillColor: 'black',
 * };
 *
 * @classexample
 * var text = new PointText(new Point(0,0));
 * text.fillColor = 'black';
 * text.content = 'Hello world.';
 * text.justification = 'center';
 */
var Style = this.Style = Base.extend(new function() {
	// windingRule / resolution / fillOverprint / strokeOverprint are currently
	// not supported.
	var defaults = {
		// path styles
		fillColor: undefined,
		strokeColor: undefined,
		strokeWidth: 1,
		strokeCap: 'butt',
		strokeJoin: 'miter',
		miterLimit: 10,
		dashOffset: 0,
		dashArray: [],
		// character styles
		font: 'sans-serif',
		fontSize: 12,
		leading: null,
		// paragraph styles
		justification: 'left'
	};

	var flags = {
		strokeWidth: /*#=*/ Change.STROKE,
		strokeCap: /*#=*/ Change.STROKE,
		strokeJoin: /*#=*/ Change.STROKE,
		miterLimit: /*#=*/ Change.STROKE,
		font: /*#=*/ Change.GEOMETRY,
		fontSize: /*#=*/ Change.GEOMETRY,
		leading: /*#=*/ Change.GEOMETRY,
		justification: /*#=*/ Change.GEOMETRY
	};

	var item = {},
		fields = {
			_defaults: defaults,
			// Override default fillColor for text items
			_textDefaults: Base.merge(defaults, {
				fillColor: new Color() // black
			})
		};

	Base.each(defaults, function(value, key) {
		var isColor = /Color$/.test(key),
			part = Base.capitalize(key),
			flag = flags[key],
			set = 'set' + part,
			get = 'get' + part;

		// Define getters and setters to be injected into this class.
		// This is how style values are handled:
		// - Style values are all stored in this._values
		// - The style object starts with an empty _values object, with fallback
		//   on _defaults through code in the getter below.
		// - Only the styles that are explicitely set on the object get defined
		//   in _values.
		// - Color values are not stored as converted colors immediately. The
		//   raw value is stored, and conversion only happens in the getter.
		fields[set] = function(value) {
			var children = this._item && this._item._children;
			// Clone color objects since they reference their owner
			// value = isColor ? Color.read(arguments, 0, 0, true) : value;
			// Only unify styles on children of Groups, excluding CompoundPaths.
			if (children && children.length > 0
					&& this._item._type !== 'compound-path') {
				for (var i = 0, l = children.length; i < l; i++)
					children[i]._style[set](value);
			} else {
				var old = this._values[key];
				if (old != value) {
					if (isColor) {
						if (old)
							delete old._owner;
						if (value && value.constructor === Color)
							value._owner = this._item;
					}
					// Note: We do not convert the values to Colors in the 
					// setter. This only happens once the getter is called.
					this._values[key] = value;
					// Notify the item of the style change STYLE is always set,
					// additional flags come from flags, as used for STROKE:
					if (this._item)
						this._item._changed(flag || /*#=*/ Change.STYLE);
				}
			}
		};

		fields[get] = function() {
			var value,
				children = this._item && this._item._children;
			// If this item has children, walk through all of them and see if
			// they all have the same style.
			if (!children || children.length === 0
					|| this._item._type === 'compound-path') {
				var value = this._values[key];
				if (value === undefined) {
					value = this._defaults[key];
					if (value && value.clone)
						value = value.clone();
					this._values[key] = value;
				} else if (isColor && !(value && value.constructor === Color)) {
					// Convert to a Color and stored result of conversion.
					this._values[key] = value = Color.read(
							[value], 0, 0, true, true); // readNull
					if (value)
						value._owner = this._item;
				}
				return value;
			}
			for (var i = 0, l = children.length; i < l; i++) {
				var childValue = children[i]._style[get]();
				if (!value) {
					value = childValue;
				} else if (!Base.equals(value, childValue)) {
					// If there is another item with a different
					// style, the style is not defined:
					return undefined;
				}
			}
			return value;
		};

		// Inject style getters and setters into the Item class, which redirect
		// calls to the linked style object.
		item[get] = function() {
			return this._style[get]();
		};

		item[set] = function(value) {
			this._style[set](value);
		};
	});

	Item.inject(item);
	return fields;
}, /** @lends Style# */{
	initialize: function(style) {
		// We keep values in a separate object that we can iterate over.
		this._values = {};
		if (this._item instanceof TextItem)
			this._defaults = this._textDefaults;
		if (style) {
			// If the passed style object is also a Style, clone its clonable
			// fields rather than simply copying them.
			var isStyle = style instanceof Style,
				// Use the other stlyle's _values object for iteration
				values = isStyle ? style._values : style;
			for (var key in values) {
				if (key in this._defaults) {
{'fraction_non_alphanumeric': 0.13962823981150188, 'fraction_numerical': 0.006981411990575094, 'mean_word_length': 2.8391959798994977, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3469238', 'n_tokens_mistral': 4277, 'n_tokens_neox': 3620, 'n_words': 1204}