From 8d55265de1da652654ca76bf39eb2e7305bbd558 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Mon, 16 Apr 2018 18:08:17 -0400 Subject: [PATCH 1/4] Double resolution on import and halve on export --- src/containers/paint-editor.jsx | 14 +++++++++++--- src/containers/paper-canvas.jsx | 22 ++++++++++++++++++---- src/helper/layer.js | 9 ++++++--- src/helper/math.js | 30 +++++++++++++++++++++++++----- src/helper/transparent.png | Bin 414 -> 0 bytes src/helper/view.js | 16 +++++++++++----- 6 files changed, 71 insertions(+), 20 deletions(-) delete mode 100644 src/helper/transparent.png diff --git a/src/containers/paint-editor.jsx b/src/containers/paint-editor.jsx index 93a24104..fec95385 100644 --- a/src/containers/paint-editor.jsx +++ b/src/containers/paint-editor.jsx @@ -17,6 +17,7 @@ import {trim} from '../helper/bitmap'; import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo'; import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order'; import {groupSelection, ungroupSelection} from '../helper/group'; +import {scaleWithStrokes} from '../helper/math'; import {getSelectedLeafItems} from '../helper/selection'; import {resetZoom, zoomOnSelection} from '../helper/view'; import EyeDropperTool from '../helper/tools/eye-dropper'; @@ -112,6 +113,9 @@ class PaintEditor extends React.Component { } const guideLayers = hideGuideLayers(true /* includeRaster */); + + // Export at 0.5x + scaleWithStrokes(paper.project.activeLayer, .5, new paper.Point()); const bounds = paper.project.activeLayer.bounds; this.props.onUpdateSvg( @@ -120,8 +124,11 @@ class PaintEditor extends React.Component { bounds: 'content', matrix: new paper.Matrix().translate(-bounds.x, -bounds.y) }), - paper.project.view.center.x - bounds.x, - paper.project.view.center.y - bounds.y); + (paper.project.view.center.x / 2) - bounds.x, + (paper.project.view.center.y / 2) - bounds.y); + + scaleWithStrokes(paper.project.activeLayer, 2, new paper.Point()); + paper.project.activeLayer.applyMatrix = true; showGuideLayers(guideLayers); if (raster) raster.remove(); @@ -221,7 +228,8 @@ class PaintEditor extends React.Component { paper.project.view.pixelRatio, paper.view.zoom, paper.project.view.bounds.x, - paper.project.view.bounds.y + paper.project.view.bounds.y, + isBitmap(this.props.format) ); this.eyeDropper.pickX = -1; this.eyeDropper.pickY = -1; diff --git a/src/containers/paper-canvas.jsx b/src/containers/paper-canvas.jsx index c3d36a91..a64ed9f6 100644 --- a/src/containers/paper-canvas.jsx +++ b/src/containers/paper-canvas.jsx @@ -14,8 +14,8 @@ import {isGroup, ungroupItems} from '../helper/group'; import {clearRaster, getRaster, setupLayers, hideGuideLayers, showGuideLayers} from '../helper/layer'; import {deleteSelection, getSelectedLeafItems} from '../helper/selection'; import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items'; -import {pan, resetZoom, zoomOnFixedPoint} from '../helper/view'; -import {ensureClockwise} from '../helper/math'; +import {clampViewBounds, pan, resetZoom, zoomOnFixedPoint} from '../helper/view'; +import {ensureClockwise, scaleWithStrokes} from '../helper/math'; import {clearHoveredItem} from '../reducers/hover'; import {clearPasteOffset} from '../reducers/clipboard'; import {updateViewBounds} from '../reducers/view-bounds'; @@ -41,6 +41,8 @@ class PaperCanvas extends React.Component { componentDidMount () { document.addEventListener('keydown', this.handleKeyDown); paper.setup(this.canvas); + paper.view.zoom = .5; + clampViewBounds(); const context = this.canvas.getContext('2d'); context.webkitImageSmoothingEnabled = false; @@ -85,6 +87,12 @@ class PaperCanvas extends React.Component { // @todo if the active layer contains only rasters, drawing them directly to the raster layer // would be more efficient. // Export svg + + // Store the zoom/pan and restore it after snapshotting + const oldZoom = paper.project.view.zoom; + const oldCenter = paper.project.view.center.clone(); + paper.project.view.zoom = 1; + const guideLayers = hideGuideLayers(true /* includeRaster */); const bounds = paper.project.activeLayer.bounds; const svg = paper.project.exportSVG({ @@ -104,6 +112,7 @@ class PaperCanvas extends React.Component { const raster = new paper.Raster(img); raster.onLoad = () => { const subCanvas = raster.canvas; + document.body.appendChild(subCanvas); getRaster().drawImage( subCanvas, new paper.Point(Math.floor(bounds.topLeft.x), Math.floor(bounds.topLeft.y))); @@ -112,6 +121,10 @@ class PaperCanvas extends React.Component { }; }; img.src = `data:image/svg+xml;charset=utf-8,${svgString}`; + + // Restore old zoom + paper.project.view.zoom = oldZoom; + paper.project.view.center = oldCenter; } convertToVector () { this.props.clearSelectedItems(); @@ -207,14 +220,15 @@ class PaperCanvas extends React.Component { } ensureClockwise(item); - + scaleWithStrokes(item, 2, new paper.Point()); // Import at 2x + if (typeof rotationCenterX !== 'undefined' && typeof rotationCenterY !== 'undefined') { let rotationPoint = new paper.Point(rotationCenterX, rotationCenterY); if (viewBox && viewBox.length >= 2 && !isNaN(viewBox[0]) && !isNaN(viewBox[1])) { rotationPoint = rotationPoint.subtract(viewBox[0], viewBox[1]); } item.translate(paper.project.view.center - .subtract(rotationPoint)); + .subtract(rotationPoint.multiply(2))); } else { // Center item.translate(paper.project.view.center diff --git a/src/helper/layer.js b/src/helper/layer.js index d6d9b7d6..b1448fa6 100644 --- a/src/helper/layer.js +++ b/src/helper/layer.js @@ -1,6 +1,6 @@ import paper from '@scratch/paper'; -import rasterSrc from './transparent.png'; import log from '../log/log'; +import {ART_BOARD_WIDTH, ART_BOARD_HEIGHT} from './view'; const _getLayer = function (layerString) { for (const layer of paper.project.layers) { @@ -19,7 +19,10 @@ const clearRaster = function () { layer.removeChildren(); // Generate blank raster - const raster = new paper.Raster(rasterSrc); + const tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = ART_BOARD_WIDTH; + tmpCanvas.height = ART_BOARD_HEIGHT; + const raster = new paper.Raster(tmpCanvas); raster.parent = layer; raster.guide = true; raster.locked = true; @@ -158,7 +161,7 @@ const _makeBackgroundGuideLayer = function () { const vBackground = _makeBackgroundPaper(120, 90, '#E5E5E5'); vBackground.position = paper.view.center; - vBackground.scaling = new paper.Point(4, 4); + vBackground.scaling = new paper.Point(8, 8); vBackground.guide = true; vBackground.locked = true; diff --git a/src/helper/math.js b/src/helper/math.js index 2da863a5..69856b17 100644 --- a/src/helper/math.js +++ b/src/helper/math.js @@ -97,17 +97,36 @@ const expandBy = function (path, amount) { } }; -// Make item clockwise. Drill down into groups. -const ensureClockwise = function (item) { +// Do for all nested items in groups +const _doRecursively = function (item, func) { if (item instanceof paper.Group) { for (const child of item.children) { - ensureClockwise(child); + _doRecursively(child, func); } - } else if (item instanceof paper.PathItem) { - item.clockwise = true; + } else { + func(item); } }; +// Make item clockwise. Drill down into groups. +const ensureClockwise = function (root) { + _doRecursively(root, item => { + if (item instanceof paper.PathItem) { + item.clockwise = true; + } + }); +}; + +// Scale item and its strokes by factor +const scaleWithStrokes = function (root, factor, pivot) { + _doRecursively(root, item => { + if (item.strokeWidth) { + item.strokeWidth = item.strokeWidth * factor; + } + }); + root.scale(factor, pivot); +}; + export { HANDLE_RATIO, checkPointsClose, @@ -115,6 +134,7 @@ export { expandBy, getRandomInt, getRandomBoolean, + scaleWithStrokes, snapDeltaToAngle, sortItemsByZIndex }; diff --git a/src/helper/transparent.png b/src/helper/transparent.png deleted file mode 100644 index ebfbd78d7bb185a8b821b5242930fcff0712ca04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 414 zcmeAS@N?(olHy`uVBq!ia0y~yV0-|?85}G?5mmbftAU(UPZ!6Kid%0FGBN@Mn-u=9 j&+~8qF-HN_LZC*{eKP~&`EKLuAR|3p{an^LB{Ts54Luau diff --git a/src/helper/view.js b/src/helper/view.js index ab4d30f3..eda11aff 100644 --- a/src/helper/view.js +++ b/src/helper/view.js @@ -1,6 +1,9 @@ import paper from '@scratch/paper'; import {getSelectedRootItems} from './selection'; +const ART_BOARD_WIDTH = 480 * 2; +const ART_BOARD_HEIGHT = 360 * 2; + const clampViewBounds = () => { const {left, right, top, bottom} = paper.project.view.bounds; if (left < 0) { @@ -9,11 +12,11 @@ const clampViewBounds = () => { if (top < 0) { paper.project.view.scrollBy(new paper.Point(0, -top)); } - if (bottom > 360) { - paper.project.view.scrollBy(new paper.Point(0, 360 - bottom)); + if (bottom > ART_BOARD_HEIGHT) { + paper.project.view.scrollBy(new paper.Point(0, ART_BOARD_HEIGHT - bottom)); } - if (right > 480) { - paper.project.view.scrollBy(new paper.Point(480 - right, 0)); + if (right > ART_BOARD_WIDTH) { + paper.project.view.scrollBy(new paper.Point(ART_BOARD_WIDTH - right, 0)); } }; @@ -53,7 +56,7 @@ const zoomOnSelection = deltaZoom => { }; const resetZoom = () => { - paper.project.view.zoom = 1; + paper.project.view.zoom = .5; clampViewBounds(); }; @@ -63,6 +66,9 @@ const pan = (dx, dy) => { }; export { + ART_BOARD_HEIGHT, + ART_BOARD_WIDTH, + clampViewBounds, pan, resetZoom, zoomOnSelection, From b93f902827c1ab4b598be7d4cc9ef3ea31dc902b Mon Sep 17 00:00:00 2001 From: DD Liu Date: Mon, 16 Apr 2018 19:27:11 -0400 Subject: [PATCH 2/4] double defaults --- src/reducers/brush-mode.js | 2 +- src/reducers/eraser-mode.js | 2 +- src/reducers/stroke-width.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/reducers/brush-mode.js b/src/reducers/brush-mode.js index 16315bef..b92707a6 100644 --- a/src/reducers/brush-mode.js +++ b/src/reducers/brush-mode.js @@ -1,7 +1,7 @@ import log from '../log/log'; const CHANGE_BRUSH_SIZE = 'scratch-paint/brush-mode/CHANGE_BRUSH_SIZE'; -const initialState = {brushSize: 5}; +const initialState = {brushSize: 10}; const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; diff --git a/src/reducers/eraser-mode.js b/src/reducers/eraser-mode.js index 28b19e10..c307aa3f 100644 --- a/src/reducers/eraser-mode.js +++ b/src/reducers/eraser-mode.js @@ -1,7 +1,7 @@ import log from '../log/log'; const CHANGE_ERASER_SIZE = 'scratch-paint/eraser-mode/CHANGE_ERASER_SIZE'; -const initialState = {brushSize: 20}; +const initialState = {brushSize: 40}; const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; diff --git a/src/reducers/stroke-width.js b/src/reducers/stroke-width.js index 43213b8d..19564d2c 100644 --- a/src/reducers/stroke-width.js +++ b/src/reducers/stroke-width.js @@ -3,8 +3,8 @@ import {CHANGE_SELECTED_ITEMS} from './selected-items'; import {getColorsFromSelection} from '../helper/style-path'; const CHANGE_STROKE_WIDTH = 'scratch-paint/stroke-width/CHANGE_STROKE_WIDTH'; -const MAX_STROKE_WIDTH = 400; -const initialState = 2; +const MAX_STROKE_WIDTH = 800; +const initialState = 4; const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; From bec01149ea5b6ba8dd9eb8f0e0800ac8b7856e78 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 20 Apr 2018 11:20:38 -0400 Subject: [PATCH 3/4] Fix review comments --- src/containers/paint-editor.jsx | 3 +-- src/containers/paper-canvas.jsx | 1 - src/helper/view.js | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/containers/paint-editor.jsx b/src/containers/paint-editor.jsx index fec95385..07354966 100644 --- a/src/containers/paint-editor.jsx +++ b/src/containers/paint-editor.jsx @@ -228,8 +228,7 @@ class PaintEditor extends React.Component { paper.project.view.pixelRatio, paper.view.zoom, paper.project.view.bounds.x, - paper.project.view.bounds.y, - isBitmap(this.props.format) + paper.project.view.bounds.y ); this.eyeDropper.pickX = -1; this.eyeDropper.pickY = -1; diff --git a/src/containers/paper-canvas.jsx b/src/containers/paper-canvas.jsx index a64ed9f6..b11ba7d5 100644 --- a/src/containers/paper-canvas.jsx +++ b/src/containers/paper-canvas.jsx @@ -112,7 +112,6 @@ class PaperCanvas extends React.Component { const raster = new paper.Raster(img); raster.onLoad = () => { const subCanvas = raster.canvas; - document.body.appendChild(subCanvas); getRaster().drawImage( subCanvas, new paper.Point(Math.floor(bounds.topLeft.x), Math.floor(bounds.topLeft.y))); diff --git a/src/helper/view.js b/src/helper/view.js index eda11aff..b220115e 100644 --- a/src/helper/view.js +++ b/src/helper/view.js @@ -25,7 +25,7 @@ const clampViewBounds = () => { const zoomOnFixedPoint = (deltaZoom, fixedPoint) => { const {view} = paper.project; const preZoomCenter = view.center; - const newZoom = Math.max(1, view.zoom + deltaZoom); + const newZoom = Math.max(0.5, view.zoom + deltaZoom); const scaling = view.zoom / newZoom; const preZoomOffset = fixedPoint.subtract(preZoomCenter); const postZoomOffset = fixedPoint.subtract(preZoomOffset.multiply(scaling)) From f08c3e140feb108f3ab80fdae69fb1fb82a2281f Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 20 Apr 2018 11:27:09 -0400 Subject: [PATCH 4/4] Fix merge --- src/helper/layer.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/helper/layer.js b/src/helper/layer.js index b1448fa6..a905172e 100644 --- a/src/helper/layer.js +++ b/src/helper/layer.js @@ -33,7 +33,10 @@ const getRaster = function () { const layer = _getLayer('isRasterLayer'); // Generate blank raster if (layer.children.length === 0) { - const raster = new paper.Raster(rasterSrc); + const tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = ART_BOARD_WIDTH; + tmpCanvas.height = ART_BOARD_HEIGHT; + const raster = new paper.Raster(tmpCanvas); raster.parent = layer; raster.guide = true; raster.locked = true;