support for retina displays, integrates #1063 - IN PROGRESS

This has bee designed and written by the amazing Bartosz Leper
(@bl-nero). Since I totally suck at Git and find myself incompetent to
resolve merge conflicts, I’ve decided to manually copy Bartosz’s
changes mostly verbatim over, tweaking them only ever so slightly in
ways that don’t alter their functionality, except for introducing a
tiny test so current Safari still loads Snap, albeit not in retina
mode. THIS IT NOT READY FOR RELEASE YET, IT’S WORK IN PROGRESS. Get it?
Thanks!
dev
Jens Mönig 2016-05-10 20:33:44 +02:00
rodzic 483e55a70f
commit 179d93f103
8 zmienionych plików z 274 dodań i 56 usunięć

Wyświetl plik

@ -149,7 +149,7 @@ isSnapObject, copy*/
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2016-May-04'; modules.blocks = '2016-May-10';
var SyntaxElementMorph; var SyntaxElementMorph;
var BlockMorph; var BlockMorph;
@ -2664,7 +2664,7 @@ BlockMorph.prototype.showHelp = function () {
} }
pic.onload = function () { pic.onload = function () {
help = newCanvas(new Point(pic.width, pic.height)); help = newCanvas(new Point(pic.width, pic.height), true); // nonRetina
ctx = help.getContext('2d'); ctx = help.getContext('2d');
ctx.drawImage(pic, 0, 0); ctx.drawImage(pic, 0, 0);
new DialogBoxMorph().inform( new DialogBoxMorph().inform(

9
gui.js
Wyświetl plik

@ -70,7 +70,7 @@ isSnapObject*/
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.gui = '2016-May-09'; modules.gui = '2016-May-10';
// Declarations // Declarations
@ -2903,7 +2903,7 @@ IDE_Morph.prototype.importMedia = function (mediaType) {
}; };
frame.addContents(icon); frame.addContents(icon);
img.onload = function () { img.onload = function () {
var canvas = newCanvas(new Point(img.width, img.height)); var canvas = newCanvas(new Point(img.width, img.height), true);
canvas.getContext('2d').drawImage(img, 0, 0); canvas.getContext('2d').drawImage(img, 0, 0);
icon.object = new Costume(canvas, item.name); icon.object = new Costume(canvas, item.name);
icon.refresh(); icon.refresh();
@ -2911,7 +2911,7 @@ IDE_Morph.prototype.importMedia = function (mediaType) {
img.src = url; img.src = url;
}); });
dialog.popUp(world); dialog.popUp(world);
dialog.setExtent(new Point(390, 300)); dialog.setExtent(new Point(400, 300));
dialog.setCenter(world.center()); dialog.setCenter(world.center());
dialog.drawNew(); dialog.drawNew();
@ -2931,7 +2931,7 @@ IDE_Morph.prototype.aboutSnap = function () {
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn, module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
world = this.world(); world = this.world();
aboutTxt = 'Snap! 4.0.7.2\nBuild Your Own Blocks\n\n' aboutTxt = 'Snap! 4.0.8 - dev -\nBuild Your Own Blocks\n\n'
+ 'Copyright \u24B8 2016 Jens M\u00F6nig and ' + 'Copyright \u24B8 2016 Jens M\u00F6nig and '
+ 'Brian Harvey\n' + 'Brian Harvey\n'
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n' + 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
@ -2968,6 +2968,7 @@ IDE_Morph.prototype.aboutSnap = function () {
+ '\ncountless bugfixes and optimizations' + '\ncountless bugfixes and optimizations'
+ '\nKartik Chandra: Paint Editor' + '\nKartik Chandra: Paint Editor'
+ '\nMichael Ball: Time/Date UI, many bugfixes' + '\nMichael Ball: Time/Date UI, many bugfixes'
+ '\nBartosz Leper: Retina Display Support'
+ '\n"Ava" Yuan Yuan: Graphic Effects' + '\n"Ava" Yuan Yuan: Graphic Effects'
+ '\nKyle Hotchkiss: Block search design' + '\nKyle Hotchkiss: Block search design'
+ '\nIan Reynolds: UI Design, Event Bindings, ' + '\nIan Reynolds: UI Design, Event Bindings, '

Wyświetl plik

@ -2928,3 +2928,5 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
* Media import dialog with thumbnail, thanks to @ubertao! * Media import dialog with thumbnail, thanks to @ubertao!
== v4.0.7.2 ==== == v4.0.7.2 ====
* in progress: Retina Display Support, thanks, Bartosz Leper!!

Wyświetl plik

@ -42,7 +42,7 @@
/*global modules, contains*/ /*global modules, contains*/
modules.locale = '2016-May-09'; modules.locale = '2016-May-10';
// Global stuff // Global stuff
@ -167,11 +167,11 @@ SnapTranslator.dict.it = {
'language_name': 'language_name':
'Italiano', 'Italiano',
'language_translator': 'language_translator':
'Stefano Federici, Alberto Firpo', 'Stefano Federici, Alberto Firpo, Massimo Ghisalberti',
'translator_e-mail': 'translator_e-mail':
's_federici@yahoo.com, albertofirpo12@gmail.com', 's_federici@yahoo.com, albertofirpo12@gmail.com, zairik@gmail.com',
'last_changed': 'last_changed':
'2015-01-12' '2016-05-10'
}; };
SnapTranslator.dict.ja = { SnapTranslator.dict.ja = {

Wyświetl plik

@ -1036,7 +1036,8 @@
I have originally written morphic.js in Florian Balmer's Notepad2 I have originally written morphic.js in Florian Balmer's Notepad2
editor for Windows, later switched to Apple's Dashcode and later editor for Windows, later switched to Apple's Dashcode and later
still to Apple's Xcode. I've also come to depend on both Douglas still to Apple's Xcode. I've also come to depend on both Douglas
Crockford's JSLint, Mozilla's Firebug and Google's Chrome to get Crockford's JSLint and later the JSHint project, as well as on
Mozilla's Firebug and Google's Chrome to get
it right. it right.
@ -1048,6 +1049,7 @@
Ian Reynolds contributed backspace key handling for Chrome. Ian Reynolds contributed backspace key handling for Chrome.
Davide Della Casa contributed performance optimizations for Firefox. Davide Della Casa contributed performance optimizations for Firefox.
Jason N (@cyderize) contributed native copy & paste for text editing. Jason N (@cyderize) contributed native copy & paste for text editing.
Bartosz Leper contributed retina display support.
- Jens Mönig - Jens Mönig
*/ */
@ -1056,7 +1058,7 @@
/*global window, HTMLCanvasElement, FileReader, Audio, FileList*/ /*global window, HTMLCanvasElement, FileReader, Audio, FileList*/
var morphicVersion = '2016-May-04'; var morphicVersion = '2016-May-10';
var modules = {}; // keep track of additional loaded modules var modules = {}; // keep track of additional loaded modules
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
@ -1102,6 +1104,8 @@ var touchScreenSettings = {
var MorphicPreferences = standardSettings; var MorphicPreferences = standardSettings;
enableRetinaSupport();
// Global Functions //////////////////////////////////////////////////// // Global Functions ////////////////////////////////////////////////////
function nop() { function nop() {
@ -1170,13 +1174,18 @@ function fontHeight(height) {
return minHeight * 1.2; // assuming 1/5 font size for ascenders return minHeight * 1.2; // assuming 1/5 font size for ascenders
} }
function newCanvas(extentPoint) { function newCanvas(extentPoint, nonRetina) {
// answer a new empty instance of Canvas, don't display anywhere // answer a new empty instance of Canvas, don't display anywhere
// nonRetina - optional Boolean "false"
// by default retina support is automatic
var canvas, ext; var canvas, ext;
ext = extentPoint || {x: 0, y: 0}; ext = extentPoint || {x: 0, y: 0};
canvas = document.createElement('canvas'); canvas = document.createElement('canvas');
canvas.width = ext.x; canvas.width = ext.x;
canvas.height = ext.y; canvas.height = ext.y;
if (nonRetina && canvas.isRetinaEnabled) {
canvas.isRetinaEnabled = false;
}
return canvas; return canvas;
} }
@ -1281,6 +1290,216 @@ function copy(target) {
return c; return c;
} }
// Retina Display Support //////////////////////////////////////////////
function enableRetinaSupport() {
/*
=== contributed by Bartosz Leper ===
This installs a series of utilities that allow using Canvas the same way
on retina and non-retina displays. If the display is a retina one, the
underlying dimensions of the Canvas elements are doubled, but this will
be transparent to the code that uses Canvas. All dimensions read or
written to the Canvas element will be scaled appropriately.
NOTE: This implementation is not exhaustive; it only implements what is
needed by the Snap! UI.
*/
// Get the window's pixel ratio for canvas elements.
// See: http://www.html5rocks.com/en/tutorials/canvas/hidpi/
var ctx = document.createElement("canvas").getContext("2d"),
backingStorePixelRatio = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1,
// Unfortunately, it's really hard to make this work well when changing
// zoom level, so let's leave it like this right now, and stick to
// whatever the ratio was in the beginning.
originalDevicePixelRatio = window.devicePixelRatio,
canvasProto = HTMLCanvasElement.prototype,
contextProto = CanvasRenderingContext2D.prototype,
uber = {
drawImage: contextProto.drawImage,
getImageData: contextProto.getImageData,
width: Object.getOwnPropertyDescriptor(
canvasProto,
'width'
),
height: Object.getOwnPropertyDescriptor(
canvasProto,
'height'
),
shadowOffsetX: Object.getOwnPropertyDescriptor(
contextProto,
'shadowOffsetX'
),
shadowOffsetY: Object.getOwnPropertyDescriptor(
contextProto,
'shadowOffsetY'
),
shadowBlur: Object.getOwnPropertyDescriptor(
contextProto,
'shadowBlur'
)
};
// check whether properties can be overridden, needed for Safari
if (Object.keys(uber).some(function (any) {
var prop = uber[any];
return prop.hasOwnProperty('configurable') && (!prop.configurable);
})) {return; }
function getPixelRatio(imageSource) {
return imageSource.isRetinaEnabled ?
(originalDevicePixelRatio || 1) / backingStorePixelRatio : 1;
}
canvasProto._isRetinaEnabled = true;
Object.defineProperty(canvasProto, 'isRetinaEnabled', {
get: function() {
return this._isRetinaEnabled;
},
set: function(enabled) {
var prevPixelRatio = getPixelRatio(this);
var prevWidth = this.width;
var prevHeight = this.height;
this._isRetinaEnabled = enabled;
if (getPixelRatio(this) != prevPixelRatio) {
this.width = prevWidth;
this.height = prevHeight;
}
}
});
Object.defineProperty(canvasProto, 'width', {
get: function() {
return uber.width.get.call(this) / getPixelRatio(this);
},
set: function(width) {
var pixelRatio = getPixelRatio(this);
uber.width.set.call(this, width * pixelRatio);
var context = this.getContext('2d');
context.restore();
context.save();
context.scale(pixelRatio, pixelRatio);
}
});
Object.defineProperty(canvasProto, 'height', {
get: function() {
return uber.height.get.call(this) / getPixelRatio(this);
},
set: function(height) {
var pixelRatio = getPixelRatio(this);
uber.height.set.call(this, height * pixelRatio);
var context = this.getContext('2d');
context.restore();
context.save();
context.scale(pixelRatio, pixelRatio);
}
});
contextProto.drawImage = function(image) {
var pixelRatio = getPixelRatio(image),
sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight;
// Different signatures of drawImage() method have different
// parameter assignments.
switch (arguments.length) {
case 9:
sx = arguments[1];
sy = arguments[2];
sWidth = arguments[3];
sHeight = arguments[4];
dx = arguments[5];
dy = arguments[6];
dWidth = arguments[7];
dHeight = arguments[8];
break;
case 5:
sx = 0;
sy = 0;
sWidth = image.width;
sHeight = image.height;
dx = arguments[1];
dy = arguments[2];
dWidth = arguments[3];
dHeight = arguments[4];
break;
case 3:
sx = 0;
sy = 0;
sWidth = image.width;
sHeight = image.height;
dx = arguments[1];
dy = arguments[2];
dWidth = image.width;
dHeight = image.height;
break;
default:
throw Error('Called drawImage() with ' + arguments.length +
' arguments');
}
uber.drawImage.call(
this, image,
sx * pixelRatio, sy * pixelRatio,
sWidth * pixelRatio, sHeight * pixelRatio,
dx, dy,
dWidth, dHeight);
};
contextProto.getImageData = function(sx, sy, sw, sh) {
var pixelRatio = getPixelRatio(this.canvas);
return uber.getImageData.call(
this,
sx * pixelRatio, sy * pixelRatio,
sw * pixelRatio, sh * pixelRatio);
};
Object.defineProperty(contextProto, 'shadowOffsetX', {
get: function() {
return uber.shadowOffsetX.get.call(this) /
getPixelRatio(this.canvas);
},
set: function(offset) {
var pixelRatio = getPixelRatio(this.canvas);
uber.shadowOffsetX.set.call(this, offset * pixelRatio);
}
});
Object.defineProperty(contextProto, 'shadowOffsetY', {
get: function() {
return uber.shadowOffsetY.get.call(this) /
getPixelRatio(this.canvas);
},
set: function(offset) {
var pixelRatio = getPixelRatio(this.canvas);
uber.shadowOffsetY.set.call(this, offset * pixelRatio);
}
});
Object.defineProperty(contextProto, 'shadowBlur', {
get: function() {
return uber.shadowBlur.get.call(this) /
getPixelRatio(this.canvas);
},
set: function(blur) {
var pixelRatio = getPixelRatio(this.canvas);
uber.shadowBlur.set.call(this, blur * pixelRatio);
}
});
}
// Colors ////////////////////////////////////////////////////////////// // Colors //////////////////////////////////////////////////////////////
// Color instance creation: // Color instance creation:
@ -9947,7 +10166,7 @@ HandMorph.prototype.processDrop = function (event) {
target = target.parent; target = target.parent;
} }
pic.onload = function () { pic.onload = function () {
canvas = newCanvas(new Point(pic.width, pic.height)); canvas = newCanvas(new Point(pic.width, pic.height), true);
canvas.getContext('2d').drawImage(pic, 0, 0); canvas.getContext('2d').drawImage(pic, 0, 0);
target.droppedImage(canvas, aFile.name); target.droppedImage(canvas, aFile.name);
}; };
@ -10038,7 +10257,7 @@ HandMorph.prototype.processDrop = function (event) {
} }
img = new Image(); img = new Image();
img.onload = function () { img.onload = function () {
canvas = newCanvas(new Point(img.width, img.height)); canvas = newCanvas(new Point(img.width, img.height), true);
canvas.getContext('2d').drawImage(img, 0, 0); canvas.getContext('2d').drawImage(img, 0, 0);
target.droppedImage(canvas); target.droppedImage(canvas);
}; };
@ -10050,7 +10269,7 @@ HandMorph.prototype.processDrop = function (event) {
} }
img = new Image(); img = new Image();
img.onload = function () { img.onload = function () {
canvas = newCanvas(new Point(img.width, img.height)); canvas = newCanvas(new Point(img.width, img.height), true);
canvas.getContext('2d').drawImage(img, 0, 0); canvas.getContext('2d').drawImage(img, 0, 0);
target.droppedImage(canvas); target.droppedImage(canvas);
}; };
@ -10190,22 +10409,16 @@ WorldMorph.prototype.doOneCycle = function () {
}; };
WorldMorph.prototype.fillPage = function () { WorldMorph.prototype.fillPage = function () {
var pos = getDocumentPositionOf(this.worldCanvas), var clientHeight = window.innerHeight,
clientHeight = window.innerHeight,
clientWidth = window.innerWidth, clientWidth = window.innerWidth,
myself = this; myself = this;
this.worldCanvas.style.position = "absolute";
this.worldCanvas.style.left = "0px";
this.worldCanvas.style.right = "0px";
this.worldCanvas.style.width = "100%";
this.worldCanvas.style.height = "100%";
if (pos.x > 0) {
this.worldCanvas.style.position = "absolute";
this.worldCanvas.style.left = "0px";
pos.x = 0;
}
if (pos.y > 0) {
this.worldCanvas.style.position = "absolute";
this.worldCanvas.style.top = "0px";
pos.y = 0;
}
if (document.documentElement.scrollTop) { if (document.documentElement.scrollTop) {
// scrolled down b/c of viewport scaling // scrolled down b/c of viewport scaling
clientHeight = document.documentElement.clientHeight; clientHeight = document.documentElement.clientHeight;

Wyświetl plik

@ -82,7 +82,7 @@ SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize, BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
TableMorph, TableFrameMorph*/ TableMorph, TableFrameMorph*/
modules.objects = '2016-May-04'; modules.objects = '2016-May-10';
var SpriteMorph; var SpriteMorph;
var StageMorph; var StageMorph;
@ -1498,7 +1498,7 @@ SpriteMorph.prototype.drawNew = function () {
// create a new, adequately dimensioned canvas // create a new, adequately dimensioned canvas
// and draw the costume on it // and draw the costume on it
this.image = newCanvas(costumeExtent); this.image = newCanvas(costumeExtent, true);
this.silentSetExtent(costumeExtent); this.silentSetExtent(costumeExtent);
ctx = this.image.getContext('2d'); ctx = this.image.getContext('2d');
ctx.scale(this.scale * stageScale, this.scale * stageScale); ctx.scale(this.scale * stageScale, this.scale * stageScale);
@ -1527,7 +1527,7 @@ SpriteMorph.prototype.drawNew = function () {
1000 1000
); );
this.silentSetExtent(new Point(newX, newX)); this.silentSetExtent(new Point(newX, newX));
this.image = newCanvas(this.extent()); this.image = newCanvas(this.extent(), true);
this.setCenter(currentCenter, true); // just me this.setCenter(currentCenter, true); // just me
SpriteMorph.uber.drawNew.call(this, facing); SpriteMorph.uber.drawNew.call(this, facing);
this.rotationOffset = this.extent().divideBy(2); this.rotationOffset = this.extent().divideBy(2);
@ -1576,7 +1576,7 @@ SpriteMorph.prototype.colorFiltered = function (aColor) {
dta; dta;
src = this.image.getContext('2d').getImageData(0, 0, ext.x, ext.y); src = this.image.getContext('2d').getImageData(0, 0, ext.x, ext.y);
morph.image = newCanvas(ext); morph.image = newCanvas(ext, true);
morph.bounds = this.bounds.copy(); morph.bounds = this.bounds.copy();
ctx = morph.image.getContext('2d'); ctx = morph.image.getContext('2d');
dta = ctx.createImageData(ext.x, ext.y); dta = ctx.createImageData(ext.x, ext.y);
@ -3005,11 +3005,11 @@ SpriteMorph.prototype.goBack = function (layers) {
SpriteMorph.prototype.overlappingImage = function (otherSprite) { SpriteMorph.prototype.overlappingImage = function (otherSprite) {
// overrides method from Morph because Sprites aren't nested Morphs // overrides method from Morph because Sprites aren't nested Morphs
var oRect = this.bounds.intersect(otherSprite.bounds), var oRect = this.bounds.intersect(otherSprite.bounds),
oImg = newCanvas(oRect.extent()), oImg = newCanvas(oRect.extent(), true),
ctx = oImg.getContext('2d'); ctx = oImg.getContext('2d');
if (oRect.width() < 1 || oRect.height() < 1) { if (oRect.width() < 1 || oRect.height() < 1) {
return newCanvas(new Point(1, 1)); return newCanvas(new Point(1, 1), true);
} }
ctx.drawImage( ctx.drawImage(
this.image, this.image,
@ -6522,7 +6522,7 @@ SpriteBubbleMorph.prototype.fixLayout = function () {
// Costume instance creation // Costume instance creation
function Costume(canvas, name, rotationCenter) { function Costume(canvas, name, rotationCenter) {
this.contents = canvas || newCanvas(); this.contents = canvas || newCanvas(null, true);
this.shrinkToFit(this.maxExtent()); this.shrinkToFit(this.maxExtent());
this.name = name || null; this.name = name || null;
this.rotationCenter = rotationCenter || this.center(); this.rotationCenter = rotationCenter || this.center();
@ -6566,7 +6566,7 @@ Costume.prototype.shrinkWrap = function () {
// adjust my contents' bounds to my visible bounding box // adjust my contents' bounds to my visible bounding box
var bb = this.boundingBox(), var bb = this.boundingBox(),
ext = bb.extent(), ext = bb.extent(),
pic = newCanvas(ext), pic = newCanvas(ext, true),
ctx = pic.getContext('2d'); ctx = pic.getContext('2d');
ctx.drawImage( ctx.drawImage(
@ -6652,7 +6652,7 @@ Costume.prototype.boundingBox = function () {
// Costume duplication // Costume duplication
Costume.prototype.copy = function () { Costume.prototype.copy = function () {
var canvas = newCanvas(this.extent()), var canvas = newCanvas(this.extent(), true),
cpy, cpy,
ctx; ctx;
ctx = canvas.getContext('2d'); ctx = canvas.getContext('2d');
@ -6670,7 +6670,7 @@ Costume.prototype.flipped = function () {
(mirrored along a vertical axis), used for (mirrored along a vertical axis), used for
SpriteMorph's rotation style type 2 SpriteMorph's rotation style type 2
*/ */
var canvas = newCanvas(this.extent()), var canvas = newCanvas(this.extent(), true),
ctx = canvas.getContext('2d'), ctx = canvas.getContext('2d'),
flipped; flipped;
@ -6696,7 +6696,7 @@ Costume.prototype.edit = function (aWorld, anIDE, isnew, oncancel, onsubmit) {
editor.openIn( editor.openIn(
aWorld, aWorld,
isnew ? isnew ?
newCanvas(StageMorph.prototype.dimensions) : newCanvas(StageMorph.prototype.dimensions, true) :
this.contents, this.contents,
isnew ? isnew ?
null : null :

Wyświetl plik

@ -62,6 +62,7 @@
Dec 15 - center rotation point on costume creating (Craxic) Dec 15 - center rotation point on costume creating (Craxic)
Jan 18 - avoid pixel collision detection in PaintCanvas (Jens) Jan 18 - avoid pixel collision detection in PaintCanvas (Jens)
Mar 22 - fixed automatic rotation center point mechanism (Jens) Mar 22 - fixed automatic rotation center point mechanism (Jens)
May 10 - retina display support adjustments (Jens)
*/ */
/*global Point, Rectangle, DialogBoxMorph, AlignmentMorph, PushButtonMorph, /*global Point, Rectangle, DialogBoxMorph, AlignmentMorph, PushButtonMorph,
@ -72,7 +73,7 @@ StageMorph, isNil*/
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.paint = '2016-May-02'; modules.paint = '2016-May-10';
// Declarations // Declarations
@ -572,9 +573,9 @@ PaintCanvasMorph.prototype.init = function (shift) {
this.dragRect = new Rectangle(); this.dragRect = new Rectangle();
// rectangle with origin being the starting drag position and // rectangle with origin being the starting drag position and
// corner being the current drag position // corner being the current drag position
this.mask = newCanvas(this.extent()); // Temporary canvas this.mask = newCanvas(this.extent(), true); // Temporary canvas
this.paper = newCanvas(this.extent()); // Actual canvas this.paper = newCanvas(this.extent(), true); // Actual canvas
this.erasermask = newCanvas(this.extent()); // eraser memory this.erasermask = newCanvas(this.extent(), true); // eraser memory
this.background = newCanvas(this.extent()); // checkers this.background = newCanvas(this.extent()); // checkers
this.settings = { this.settings = {
"primarycolor": new Color(0, 0, 0, 255), // usually fill color "primarycolor": new Color(0, 0, 0, 255), // usually fill color
@ -617,8 +618,8 @@ PaintCanvasMorph.prototype.updateAutomaticCenter = function () {
PaintCanvasMorph.prototype.scale = function (x, y) { PaintCanvasMorph.prototype.scale = function (x, y) {
this.updateAutomaticCenter(); this.updateAutomaticCenter();
this.mask = newCanvas(this.extent()); this.mask = newCanvas(this.extent(), true);
var c = newCanvas(this.extent()); var c = newCanvas(this.extent(), true);
c.getContext("2d").save(); c.getContext("2d").save();
c.getContext("2d").translate( c.getContext("2d").translate(
this.rotationCenter.x, this.rotationCenter.x,
@ -637,14 +638,14 @@ PaintCanvasMorph.prototype.scale = function (x, y) {
}; };
PaintCanvasMorph.prototype.cacheUndo = function () { PaintCanvasMorph.prototype.cacheUndo = function () {
var cachecan = newCanvas(this.extent()); var cachecan = newCanvas(this.extent(), true);
this.merge(this.paper, cachecan); this.merge(this.paper, cachecan);
this.undoBuffer.push(cachecan); this.undoBuffer.push(cachecan);
}; };
PaintCanvasMorph.prototype.undo = function () { PaintCanvasMorph.prototype.undo = function () {
if (this.undoBuffer.length > 0) { if (this.undoBuffer.length > 0) {
this.paper = newCanvas(this.extent()); this.paper = newCanvas(this.extent(), true);
this.mask.width = this.mask.width + 1 - 1; this.mask.width = this.mask.width + 1 - 1;
this.merge(this.undoBuffer.pop(), this.paper); this.merge(this.undoBuffer.pop(), this.paper);
this.drawNew(); this.drawNew();
@ -671,7 +672,7 @@ PaintCanvasMorph.prototype.clearCanvas = function () {
}; };
PaintCanvasMorph.prototype.toolChanged = function (tool) { PaintCanvasMorph.prototype.toolChanged = function (tool) {
this.mask = newCanvas(this.extent()); this.mask = newCanvas(this.extent(), true);
if (tool === "crosshairs") { if (tool === "crosshairs") {
this.updateAutomaticCenter(); this.updateAutomaticCenter();
this.drawcrosshair(); this.drawcrosshair();
@ -812,7 +813,7 @@ PaintCanvasMorph.prototype.mouseDownLeft = function (pos) {
} }
if (this.settings.primarycolor === "transparent" && if (this.settings.primarycolor === "transparent" &&
this.currentTool !== "crosshairs") { this.currentTool !== "crosshairs") {
this.erasermask = newCanvas(this.extent()); this.erasermask = newCanvas(this.extent(), true);
this.merge(this.paper, this.erasermask); this.merge(this.paper, this.erasermask);
} }
}; };
@ -953,7 +954,7 @@ PaintCanvasMorph.prototype.mouseMove = function (pos) {
} }
mctx.stroke(); mctx.stroke();
mctx.restore(); mctx.restore();
this.paper = newCanvas(this.extent()); this.paper = newCanvas(this.extent(), true);
this.merge(this.mask, this.paper); this.merge(this.mask, this.paper);
break; break;
default: default:
@ -977,9 +978,9 @@ PaintCanvasMorph.prototype.mouseLeaveDragging
PaintCanvasMorph.prototype.buildContents = function () { PaintCanvasMorph.prototype.buildContents = function () {
this.background = newCanvas(this.extent()); this.background = newCanvas(this.extent());
this.paper = newCanvas(this.extent()); this.paper = newCanvas(this.extent(), true);
this.mask = newCanvas(this.extent()); this.mask = newCanvas(this.extent(), true);
this.erasermask = newCanvas(this.extent()); this.erasermask = newCanvas(this.extent(), true);
var i, j, bkctx = this.background.getContext("2d"); var i, j, bkctx = this.background.getContext("2d");
for (i = 0; i < this.background.width; i += 5) { for (i = 0; i < this.background.width; i += 5) {
for (j = 0; j < this.background.height; j += 5) { for (j = 0; j < this.background.height; j += 5) {
@ -994,7 +995,7 @@ PaintCanvasMorph.prototype.buildContents = function () {
}; };
PaintCanvasMorph.prototype.drawNew = function () { PaintCanvasMorph.prototype.drawNew = function () {
var can = newCanvas(this.extent()); var can = newCanvas(this.extent(), true);
this.merge(this.background, can); this.merge(this.background, can);
this.merge(this.paper, can); this.merge(this.paper, can);
this.merge(this.mask, can); this.merge(this.mask, can);

Wyświetl plik

@ -60,7 +60,7 @@ SyntaxElementMorph, Variable, isSnapObject, console*/
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.store = '2016-May-02'; modules.store = '2016-May-10';
// XML_Serializer /////////////////////////////////////////////////////// // XML_Serializer ///////////////////////////////////////////////////////
@ -1321,7 +1321,8 @@ SnapSerializer.prototype.loadValue = function (model) {
v = new Costume(null, name, center); v = new Costume(null, name, center);
image.onload = function () { image.onload = function () {
var canvas = newCanvas( var canvas = newCanvas(
new Point(image.width, image.height) new Point(image.width, image.height),
true // nonRetina
), ),
context = canvas.getContext('2d'); context = canvas.getContext('2d');
context.drawImage(image, 0, 0); context.drawImage(image, 0, 0);