mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Change the way context dependent font sizes are handled by delegating handling to view.
Closes #425
This commit is contained in:
parent
2b4ecfa669
commit
0aa73d90c5
10 changed files with 135 additions and 90 deletions
|
@ -118,7 +118,7 @@ var PaperScope = Base.extend(/** @lends PaperScope# */{
|
||||||
* @bean
|
* @bean
|
||||||
*/
|
*/
|
||||||
getView: function() {
|
getView: function() {
|
||||||
return this.project && this.project.view;
|
return this.project && this.project.getView();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -103,7 +103,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
if (point)
|
if (point)
|
||||||
matrix.translate(point);
|
matrix.translate(point);
|
||||||
matrix._owner = this;
|
matrix._owner = this;
|
||||||
this._style = new Style(project._currentStyle, this);
|
this._style = new Style(project._currentStyle, this, project);
|
||||||
// If _project is already set, the item was already moved into the DOM
|
// If _project is already set, the item was already moved into the DOM
|
||||||
// hierarchy. Used by Layer, where it's added to project.layers instead
|
// hierarchy. Used by Layer, where it's added to project.layers instead
|
||||||
if (!this._project) {
|
if (!this._project) {
|
||||||
|
@ -154,7 +154,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
install: function(type) {
|
install: function(type) {
|
||||||
// If the view requires counting of installed mouse events,
|
// If the view requires counting of installed mouse events,
|
||||||
// increase the counters now according to mouseFlags
|
// increase the counters now according to mouseFlags
|
||||||
var counters = this._project.view._eventCounters;
|
var counters = this.getView()._eventCounters;
|
||||||
if (counters) {
|
if (counters) {
|
||||||
for (var key in mouseFlags) {
|
for (var key in mouseFlags) {
|
||||||
counters[key] = (counters[key] || 0)
|
counters[key] = (counters[key] || 0)
|
||||||
|
@ -165,7 +165,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
uninstall: function(type) {
|
uninstall: function(type) {
|
||||||
// If the view requires counting of installed mouse events,
|
// If the view requires counting of installed mouse events,
|
||||||
// decrease the counters now according to mouseFlags
|
// decrease the counters now according to mouseFlags
|
||||||
var counters = this._project.view._eventCounters;
|
var counters = this.getView()._eventCounters;
|
||||||
if (counters) {
|
if (counters) {
|
||||||
for (var key in mouseFlags)
|
for (var key in mouseFlags)
|
||||||
counters[key] -= mouseFlags[key][type] || 0;
|
counters[key] -= mouseFlags[key][type] || 0;
|
||||||
|
@ -194,7 +194,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
_animateItem: function(animate) {
|
_animateItem: function(animate) {
|
||||||
this._project.view._animateItem(this, animate);
|
this.getView()._animateItem(this, animate);
|
||||||
},
|
},
|
||||||
|
|
||||||
_serialize: function(options, dictionary) {
|
_serialize: function(options, dictionary) {
|
||||||
|
@ -1225,6 +1225,15 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
this._installEvents(true);
|
this._installEvents(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The view that this item belongs to.
|
||||||
|
* @type View
|
||||||
|
* @bean
|
||||||
|
*/
|
||||||
|
getView: function() {
|
||||||
|
return this._project.getView();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides Callback#_installEvents to also call _installEvents on all
|
* Overrides Callback#_installEvents to also call _installEvents on all
|
||||||
* children.
|
* children.
|
||||||
|
@ -1566,8 +1575,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
*/
|
*/
|
||||||
rasterize: function(resolution) {
|
rasterize: function(resolution) {
|
||||||
var bounds = this.getStrokeBounds(),
|
var bounds = this.getStrokeBounds(),
|
||||||
view = this._project.view,
|
scale = (resolution || this.getView().getResolution()) / 72,
|
||||||
scale = (resolution || view && view.getResolution() || 72) / 72,
|
|
||||||
// Floor top-left corner and ceil bottom-right corner, to never
|
// Floor top-left corner and ceil bottom-right corner, to never
|
||||||
// blur or cut pixels.
|
// blur or cut pixels.
|
||||||
topLeft = bounds.getTopLeft().floor(),
|
topLeft = bounds.getTopLeft().floor(),
|
||||||
|
@ -1686,7 +1694,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// chain already to determine the rough bounds.
|
// chain already to determine the rough bounds.
|
||||||
var matrix = this._matrix,
|
var matrix = this._matrix,
|
||||||
parentTotalMatrix = options._totalMatrix,
|
parentTotalMatrix = options._totalMatrix,
|
||||||
view = this._project.view,
|
view = this.getView(),
|
||||||
// Keep the accumulated matrices up to this item in options, so we
|
// Keep the accumulated matrices up to this item in options, so we
|
||||||
// can keep calculating the correct _tolerancePadding values.
|
// can keep calculating the correct _tolerancePadding values.
|
||||||
totalMatrix = options._totalMatrix = parentTotalMatrix
|
totalMatrix = options._totalMatrix = parentTotalMatrix
|
||||||
|
@ -1694,7 +1702,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// If this is the first one in the recursion, factor in the
|
// If this is the first one in the recursion, factor in the
|
||||||
// zoom of the view and the globalMatrix of the item.
|
// zoom of the view and the globalMatrix of the item.
|
||||||
: this.getGlobalMatrix().clone().preConcatenate(
|
: this.getGlobalMatrix().clone().preConcatenate(
|
||||||
view ? view._matrix : new Matrix()),
|
view._matrix),
|
||||||
// Calculate the transformed padding as 2D size that describes the
|
// Calculate the transformed padding as 2D size that describes the
|
||||||
// transformed tolerance circle / ellipse. Make sure it's never 0
|
// transformed tolerance circle / ellipse. Make sure it's never 0
|
||||||
// since we're using it for division.
|
// since we're using it for division.
|
||||||
|
|
|
@ -298,13 +298,13 @@ var Raster = Item.extend(/** @lends Raster# */{
|
||||||
image;
|
image;
|
||||||
|
|
||||||
function loaded() {
|
function loaded() {
|
||||||
var view = that._project.view;
|
var view = that.getView();
|
||||||
if (view)
|
if (view) {
|
||||||
paper = view._scope;
|
paper = view._scope;
|
||||||
that.setImage(image);
|
that.setImage(image);
|
||||||
that.fire('load');
|
that.fire('load');
|
||||||
if (view)
|
|
||||||
view.update();
|
view.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#*/ if (__options.environment == 'browser') {
|
/*#*/ if (__options.environment == 'browser') {
|
||||||
|
|
|
@ -43,20 +43,23 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
* Note that when working with PaperScript, a project is automatically
|
* Note that when working with PaperScript, a project is automatically
|
||||||
* created for us and the {@link PaperScope#project} variable points to it.
|
* created for us and the {@link PaperScope#project} variable points to it.
|
||||||
*
|
*
|
||||||
* @param {View|HTMLCanvasElement} view Either a view object or an HTML
|
* @param {HTMLCanvasElement} element an HTML anvas element that should be
|
||||||
* Canvas element that should be wrapped in a newly created view.
|
* used as the element for the view.
|
||||||
*/
|
*/
|
||||||
initialize: function Project(view) {
|
initialize: function Project(element) {
|
||||||
// Activate straight away by passing true to PaperScopeItem constructor,
|
// Activate straight away by passing true to PaperScopeItem constructor,
|
||||||
// so paper.project is set, as required by Layer and DoumentView
|
// so paper.project is set, as required by Layer and DoumentView
|
||||||
// constructors.
|
// constructors.
|
||||||
PaperScopeItem.call(this, true);
|
PaperScopeItem.call(this, true);
|
||||||
this.layers = [];
|
this.layers = [];
|
||||||
this.symbols = [];
|
this.symbols = [];
|
||||||
this._currentStyle = new Style();
|
this._currentStyle = new Style(null, null, this);
|
||||||
this.activeLayer = new Layer();
|
this.activeLayer = new Layer();
|
||||||
if (view)
|
// If no view is provided, we create a 1x1 px canvas view just so we
|
||||||
this.view = view instanceof View ? view : View.create(view);
|
// have something to do size calculations with.
|
||||||
|
// (e.g. PointText#_getBounds)
|
||||||
|
this._view = View.create(this,
|
||||||
|
element || CanvasProvider.getCanvas(1, 1));
|
||||||
this._selectedItems = {};
|
this._selectedItems = {};
|
||||||
this._selectedItemCount = 0;
|
this._selectedItemCount = 0;
|
||||||
// See Item#draw() for an explanation of _updateVersion
|
// See Item#draw() for an explanation of _updateVersion
|
||||||
|
@ -110,8 +113,8 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
remove: function remove() {
|
remove: function remove() {
|
||||||
if (!remove.base.call(this))
|
if (!remove.base.call(this))
|
||||||
return false;
|
return false;
|
||||||
if (this.view)
|
if (this._view)
|
||||||
this.view.remove();
|
this._view.remove();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -119,7 +122,11 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
* The reference to the project's view.
|
* The reference to the project's view.
|
||||||
* @name Project#view
|
* @name Project#view
|
||||||
* @type View
|
* @type View
|
||||||
|
* @bean
|
||||||
*/
|
*/
|
||||||
|
getView: function() {
|
||||||
|
return this._view;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently active path style. All selected items and newly
|
* The currently active path style. All selected items and newly
|
||||||
|
|
|
@ -136,10 +136,11 @@ var Style = Base.extend(new function() {
|
||||||
// - Color values are not stored as converted colors immediately. The
|
// - Color values are not stored as converted colors immediately. The
|
||||||
// raw value is stored, and conversion only happens in the getter.
|
// raw value is stored, and conversion only happens in the getter.
|
||||||
fields[set] = function(value) {
|
fields[set] = function(value) {
|
||||||
var children = this._item && this._item._children;
|
var owner = this._owner,
|
||||||
|
children = owner && owner._children;
|
||||||
// Only unify styles on children of Groups, excluding CompoundPaths.
|
// Only unify styles on children of Groups, excluding CompoundPaths.
|
||||||
if (children && children.length > 0
|
if (children && children.length > 0
|
||||||
&& this._item._type !== 'compound-path') {
|
&& !(owner instanceof CompoundPath)) {
|
||||||
for (var i = 0, l = children.length; i < l; i++)
|
for (var i = 0, l = children.length; i < l; i++)
|
||||||
children[i]._style[set](value);
|
children[i]._style[set](value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,28 +155,29 @@ var Style = Base.extend(new function() {
|
||||||
// converted and cloned in the getter further down.
|
// converted and cloned in the getter further down.
|
||||||
if (value._owner)
|
if (value._owner)
|
||||||
value = value.clone();
|
value = value.clone();
|
||||||
value._owner = this._item;
|
value._owner = owner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Note: We do not convert the values to Colors in the
|
// Note: We do not convert the values to Colors in the
|
||||||
// setter. This only happens once the getter is called.
|
// setter. This only happens once the getter is called.
|
||||||
this._values[key] = value;
|
this._values[key] = value;
|
||||||
// Notify the item of the style change STYLE is always set,
|
// Notify the owner of the style change STYLE is always set,
|
||||||
// additional flags come from flags, as used for STROKE:
|
// additional flags come from flags, as used for STROKE:
|
||||||
if (this._item)
|
if (owner)
|
||||||
this._item._changed(flag || /*#=*/ Change.STYLE);
|
owner._changed(flag || /*#=*/ Change.STYLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fields[get] = function(_dontMerge) {
|
fields[get] = function(_dontMerge) {
|
||||||
var value,
|
var owner = this._owner,
|
||||||
children = this._item && this._item._children;
|
children = owner && owner._children,
|
||||||
// If this item has children, walk through all of them and see if
|
value;
|
||||||
|
// If the owner has children, walk through all of them and see if
|
||||||
// they all have the same style.
|
// they all have the same style.
|
||||||
// If true is passed for _dontMerge, don't merge children styles
|
// If true is passed for _dontMerge, don't merge children styles
|
||||||
if (!children || children.length === 0 || _dontMerge
|
if (!children || children.length === 0 || _dontMerge
|
||||||
|| this._item instanceof CompoundPath) {
|
|| owner instanceof CompoundPath) {
|
||||||
var value = this._values[key];
|
var value = this._values[key];
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
value = this._defaults[key];
|
value = this._defaults[key];
|
||||||
|
@ -187,7 +189,7 @@ var Style = Base.extend(new function() {
|
||||||
this._values[key] = value = Color.read([value], 0,
|
this._values[key] = value = Color.read([value], 0,
|
||||||
{ readNull: true, clone: true });
|
{ readNull: true, clone: true });
|
||||||
if (value)
|
if (value)
|
||||||
value._owner = this._item;
|
value._owner = owner;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +198,7 @@ var Style = Base.extend(new function() {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
value = childValue;
|
value = childValue;
|
||||||
} else if (!Base.equals(value, childValue)) {
|
} else if (!Base.equals(value, childValue)) {
|
||||||
// If there is another item with a different
|
// If there is another child with a different
|
||||||
// style, the style is not defined:
|
// style, the style is not defined:
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -220,11 +222,12 @@ var Style = Base.extend(new function() {
|
||||||
}, /** @lends Style# */{
|
}, /** @lends Style# */{
|
||||||
_class: 'Style',
|
_class: 'Style',
|
||||||
|
|
||||||
initialize: function Style(style, _item) {
|
initialize: function Style(style, _owner, _project) {
|
||||||
// We keep values in a separate object that we can iterate over.
|
// We keep values in a separate object that we can iterate over.
|
||||||
this._values = {};
|
this._values = {};
|
||||||
this._item = _item;
|
this._owner = _owner;
|
||||||
if (_item instanceof TextItem)
|
this._project = _owner && _owner._project || _project || paper.project;
|
||||||
|
if (_owner instanceof TextItem)
|
||||||
this._defaults = this._textDefaults;
|
this._defaults = this._textDefaults;
|
||||||
if (style)
|
if (style)
|
||||||
this.set(style);
|
this.set(style);
|
||||||
|
@ -269,17 +272,27 @@ var Style = Base.extend(new function() {
|
||||||
return !!this.getShadowColor() && this.getShadowBlur() > 0;
|
return !!this.getShadowColor() && this.getShadowBlur() > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The view that this style belongs to.
|
||||||
|
* @type View
|
||||||
|
* @bean
|
||||||
|
*/
|
||||||
|
getView: function() {
|
||||||
|
return this._project.getView();
|
||||||
|
},
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
|
|
||||||
getFontStyle: function() {
|
getFontStyle: function() {
|
||||||
var size = this.getFontSize();
|
var fontSize = this.getFontSize();
|
||||||
// To prevent an obscure iOS 7 crash, we have to convert the size to a
|
// To prevent an obscure iOS 7 crash, we have to convert the size to a
|
||||||
// string first before passing it to the regular expression.
|
// string first before passing it to the regular expression.
|
||||||
// This nonsensical statement would also prevent the bug, prooving that
|
// The following nonsensical statement would also prevent the bug,
|
||||||
// the issue is not the regular expression itself, but something deeper
|
// prooving that the issue is not the regular expression itself, but
|
||||||
// down in the optimizer: if (size === 0) size = 0;
|
// something deeper down in the optimizer:
|
||||||
|
// `if (size === 0) size = 0;`
|
||||||
return this.getFontWeight()
|
return this.getFontWeight()
|
||||||
+ ' ' + size + (/[a-z]/i.test(size + '') ? ' ' : 'px ')
|
+ ' ' + fontSize + (/\w/i.test(fontSize + '') ? ' ' : 'px ')
|
||||||
+ this.getFontFamily();
|
+ this.getFontFamily();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -297,8 +310,11 @@ var Style = Base.extend(new function() {
|
||||||
|
|
||||||
getLeading: function getLeading() {
|
getLeading: function getLeading() {
|
||||||
// Override leading to return fontSize * 1.2 by default.
|
// Override leading to return fontSize * 1.2 by default.
|
||||||
var leading = getLeading.base.call(this);
|
var leading = getLeading.base.call(this),
|
||||||
return leading != null ? leading : this.getFontSize() * 1.2;
|
fontSize = this.getFontSize();
|
||||||
|
if (/pt|em|%|px/.test(fontSize))
|
||||||
|
fontSize = this.getView().getPixelSize(fontSize);
|
||||||
|
return leading != null ? leading : fontSize * 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DOCS: why isn't the example code showing up?
|
// DOCS: why isn't the example code showing up?
|
||||||
|
|
|
@ -404,7 +404,7 @@ new function() {
|
||||||
exportSVG: function(options) {
|
exportSVG: function(options) {
|
||||||
options = setOptions(options);
|
options = setOptions(options);
|
||||||
var layers = this.layers,
|
var layers = this.layers,
|
||||||
size = this.view.getSize(),
|
size = this.getView().getSize(),
|
||||||
node = createElement('svg', {
|
node = createElement('svg', {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
|
|
|
@ -531,7 +531,7 @@ new function() {
|
||||||
paper = scope;
|
paper = scope;
|
||||||
var item = importSVG(svg, isRoot, options),
|
var item = importSVG(svg, isRoot, options),
|
||||||
onLoad = options.onLoad,
|
onLoad = options.onLoad,
|
||||||
view = scope.project && scope.project.view;
|
view = scope.project && scope.getView();
|
||||||
if (onLoad)
|
if (onLoad)
|
||||||
onLoad.call(this, item);
|
onLoad.call(this, item);
|
||||||
view.update();
|
view.update();
|
||||||
|
|
|
@ -88,7 +88,6 @@ var PointText = TextItem.extend(/** @lends PointText# */{
|
||||||
lines = this._lines,
|
lines = this._lines,
|
||||||
leading = style.getLeading(),
|
leading = style.getLeading(),
|
||||||
shadowColor = ctx.shadowColor;
|
shadowColor = ctx.shadowColor;
|
||||||
|
|
||||||
ctx.font = style.getFontStyle();
|
ctx.font = style.getFontStyle();
|
||||||
ctx.textAlign = style.getJustification();
|
ctx.textAlign = style.getJustification();
|
||||||
for (var i = 0, l = lines.length; i < l; i++) {
|
for (var i = 0, l = lines.length; i < l; i++) {
|
||||||
|
@ -103,36 +102,24 @@ var PointText = TextItem.extend(/** @lends PointText# */{
|
||||||
ctx.strokeText(line, 0, 0);
|
ctx.strokeText(line, 0, 0);
|
||||||
ctx.translate(0, leading);
|
ctx.translate(0, leading);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}, new function() {
|
|
||||||
var measureCtx = null;
|
|
||||||
|
|
||||||
return {
|
_getBounds: function(getter, matrix) {
|
||||||
_getBounds: function(getter, matrix) {
|
var style = this._style,
|
||||||
// Create an in-memory canvas on which to do the measuring
|
lines = this._lines,
|
||||||
if (!measureCtx)
|
numLines = lines.length,
|
||||||
measureCtx = CanvasProvider.getContext(1, 1);
|
justification = style.getJustification(),
|
||||||
var style = this._style,
|
leading = style.getLeading(),
|
||||||
lines = this._lines,
|
width = this.getView().getTextWidth(style.getFontStyle(), lines),
|
||||||
count = lines.length,
|
x = 0;
|
||||||
justification = style.getJustification(),
|
// Adjust for different justifications.
|
||||||
leading = style.getLeading(),
|
if (justification !== 'left')
|
||||||
x = 0;
|
x -= width / (justification === 'center' ? 2: 1);
|
||||||
// Measure the real width of the text. Unfortunately, there is no
|
// Until we don't have baseline measuring, assume 1 / 4 leading as a
|
||||||
// sane way to measure text height with canvas
|
// rough guess:
|
||||||
measureCtx.font = style.getFontStyle();
|
var bounds = new Rectangle(x,
|
||||||
var width = 0;
|
numLines ? - 0.75 * leading : 0,
|
||||||
for (var i = 0; i < count; i++)
|
width, numLines * leading);
|
||||||
width = Math.max(width, measureCtx.measureText(lines[i]).width);
|
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
|
||||||
// Adjust for different justifications
|
}
|
||||||
if (justification !== 'left')
|
|
||||||
x -= width / (justification === 'center' ? 2: 1);
|
|
||||||
// Until we don't have baseline measuring, assume 1 / 4 leading as a
|
|
||||||
// rough guess:
|
|
||||||
var bounds = new Rectangle(x,
|
|
||||||
count ? - 0.75 * leading : 0,
|
|
||||||
width, count * leading);
|
|
||||||
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
||||||
* @name CanvasView#initialize
|
* @name CanvasView#initialize
|
||||||
* @param {Size} size the size of the canvas to be created
|
* @param {Size} size the size of the canvas to be created
|
||||||
*/
|
*/
|
||||||
initialize: function CanvasView(canvas) {
|
initialize: function CanvasView(project, canvas) {
|
||||||
// Handle canvas argument
|
// Handle canvas argument
|
||||||
if (!(canvas instanceof HTMLCanvasElement)) {
|
if (!(canvas instanceof HTMLCanvasElement)) {
|
||||||
// See if the arguments describe the view size:
|
// See if the arguments describe the view size:
|
||||||
|
@ -56,7 +56,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
||||||
this._pixelRatio = deviceRatio / backingStoreRatio;
|
this._pixelRatio = deviceRatio / backingStoreRatio;
|
||||||
}
|
}
|
||||||
/*#*/ } // __options.environment == 'browser'
|
/*#*/ } // __options.environment == 'browser'
|
||||||
View.call(this, canvas);
|
View.call(this, project, canvas);
|
||||||
},
|
},
|
||||||
|
|
||||||
_setViewSize: function(size) {
|
_setViewSize: function(size) {
|
||||||
|
@ -77,13 +77,40 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provide size in any of the units allowed in the browser to
|
||||||
|
* pixels, by the use of the context.font property.
|
||||||
|
*/
|
||||||
|
getPixelSize: function(size) {
|
||||||
|
var ctx = this._context,
|
||||||
|
prevFont = ctx.font;
|
||||||
|
ctx.font = size + ' serif';
|
||||||
|
size = parseFloat(ctx.font);
|
||||||
|
ctx.font = prevFont;
|
||||||
|
return size;
|
||||||
|
},
|
||||||
|
|
||||||
|
getTextWidth: function(font, lines) {
|
||||||
|
var ctx = this._context,
|
||||||
|
prevFont = ctx.font,
|
||||||
|
width = 0;
|
||||||
|
ctx.font = font;
|
||||||
|
// Measure the real width of the text. Unfortunately, there is no sane
|
||||||
|
// way to measure text height with canvas.
|
||||||
|
for (var i = 0, l = lines.length; i < l; i++)
|
||||||
|
width = Math.max(width, ctx.measureText(lines[i]).width);
|
||||||
|
ctx.font = prevFont;
|
||||||
|
return width;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the view if there are changes.
|
* Updates the view if there are changes.
|
||||||
*
|
*
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
if (!this._project._needsUpdate)
|
var project = this._project;
|
||||||
|
if (!project || !project._needsUpdate)
|
||||||
return false;
|
return false;
|
||||||
// Initial tests conclude that clearing the canvas using clearRect
|
// Initial tests conclude that clearing the canvas using clearRect
|
||||||
// is always faster than setting canvas.width = canvas.width
|
// is always faster than setting canvas.width = canvas.width
|
||||||
|
@ -91,8 +118,8 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
||||||
var ctx = this._context,
|
var ctx = this._context,
|
||||||
size = this._viewSize;
|
size = this._viewSize;
|
||||||
ctx.clearRect(0, 0, size.width + 1, size.height + 1);
|
ctx.clearRect(0, 0, size.width + 1, size.height + 1);
|
||||||
this._project.draw(ctx, this._matrix, this._pixelRatio);
|
project.draw(ctx, this._matrix, this._pixelRatio);
|
||||||
this._project._needsUpdate = false;
|
project._needsUpdate = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, new function() { // Item based mouse handling:
|
}, new function() { // Item based mouse handling:
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
var View = Base.extend(Callback, /** @lends View# */{
|
var View = Base.extend(Callback, /** @lends View# */{
|
||||||
_class: 'View',
|
_class: 'View',
|
||||||
|
|
||||||
initialize: function View(element) {
|
initialize: function View(project, element) {
|
||||||
// Store reference to the currently active global paper scope, and the
|
// Store reference to the currently active global paper scope, and the
|
||||||
// active project, which will be represented by this view
|
// active project, which will be represented by this view
|
||||||
this._scope = paper;
|
this._project = project;
|
||||||
this._project = paper.project;
|
this._scope = project._scope;
|
||||||
this._element = element;
|
this._element = element;
|
||||||
var size;
|
var size;
|
||||||
/*#*/ if (__options.environment == 'browser') {
|
/*#*/ if (__options.environment == 'browser') {
|
||||||
|
@ -139,8 +139,8 @@ var View = Base.extend(Callback, /** @lends View# */{
|
||||||
View._views.splice(View._views.indexOf(this), 1);
|
View._views.splice(View._views.indexOf(this), 1);
|
||||||
delete View._viewsById[this._id];
|
delete View._viewsById[this._id];
|
||||||
// Unlink from project
|
// Unlink from project
|
||||||
if (this._project.view == this)
|
if (this._project._view === this)
|
||||||
this._project.view = null;
|
this._project._view = null;
|
||||||
/*#*/ if (__options.environment == 'browser') {
|
/*#*/ if (__options.environment == 'browser') {
|
||||||
// Uninstall event handlers again for this view.
|
// Uninstall event handlers again for this view.
|
||||||
DomEvent.remove(this._element, this._viewEvents);
|
DomEvent.remove(this._element, this._viewEvents);
|
||||||
|
@ -658,14 +658,14 @@ var View = Base.extend(Callback, /** @lends View# */{
|
||||||
_viewsById: {},
|
_viewsById: {},
|
||||||
_id: 0,
|
_id: 0,
|
||||||
|
|
||||||
create: function(element) {
|
create: function(project, element) {
|
||||||
/*#*/ if (__options.environment == 'browser') {
|
/*#*/ if (__options.environment == 'browser') {
|
||||||
if (typeof element === 'string')
|
if (typeof element === 'string')
|
||||||
element = document.getElementById(element);
|
element = document.getElementById(element);
|
||||||
/*#*/ } // __options.environment == 'browser'
|
/*#*/ } // __options.environment == 'browser'
|
||||||
// Factory to provide the right View subclass for a given element.
|
// Factory to provide the right View subclass for a given element.
|
||||||
// Produces only CanvasViews for now:
|
// Produces only CanvasViews for now:
|
||||||
return new CanvasView(element);
|
return new CanvasView(project, element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, new function() {
|
}, new function() {
|
||||||
|
|
Loading…
Reference in a new issue