diff --git a/src/components/mode-tools/mode-tools.jsx b/src/components/mode-tools/mode-tools.jsx
index aa1d8040..c9d4d1b4 100644
--- a/src/components/mode-tools/mode-tools.jsx
+++ b/src/components/mode-tools/mode-tools.jsx
@@ -12,7 +12,6 @@ import {defineMessages, injectIntl, intlShape} from 'react-intl';
 import Input from '../forms/input.jsx';
 import InputGroup from '../input-group/input-group.jsx';
 import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
-// import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
 import Modes from '../../lib/modes';
 import styles from './mode-tools.css';
 
@@ -20,11 +19,11 @@ import copyIcon from './icons/copy.svg';
 import pasteIcon from './icons/paste.svg';
 
 import brushIcon from '../brush-mode/brush.svg';
-// import curvedPointIcon from './curved-point.svg';
+import curvedPointIcon from './icons/curved-point.svg';
 import eraserIcon from '../eraser-mode/eraser.svg';
 // import flipHorizontalIcon from './icons/flip-horizontal.svg';
 // import flipVerticalIcon from './icons/flip-vertical.svg';
-// import straightPointIcon from './straight-point.svg';
+import straightPointIcon from './icons/straight-point.svg';
 
 import {MAX_STROKE_WIDTH} from '../../reducers/stroke-width';
 
@@ -50,6 +49,16 @@ const ModeToolsComponent = props => {
             defaultMessage: 'Paste',
             description: 'Label for the paste button',
             id: 'paint.modeTools.paste'
+        },
+        curved: {
+            defaultMessage: 'Curved',
+            description: 'Label for the button that converts selected points to curves',
+            id: 'paint.modeTools.curved'
+        },
+        pointed: {
+            defaultMessage: 'Pointed',
+            description: 'Label for the button that converts selected points to sharp points',
+            id: 'paint.modeTools.pointed'
         }
     });
 
@@ -95,18 +104,18 @@ const ModeToolsComponent = props => {
     case Modes.RESHAPE:
         return (
             <div className={classNames(props.className, styles.modeTools)}>
-                {/* <LabeledIconButton
-                    imgAlt="Curved Point Icon"
+                <LabeledIconButton
+                    disabled={!props.hasSelectedUncurvedPoints}
                     imgSrc={curvedPointIcon}
-                    title="Curved"
-                    onClick={function () {}}
+                    title={props.intl.formatMessage(messages.curved)}
+                    onClick={props.onCurvePoints}
                 />
                 <LabeledIconButton
-                    imgAlt="Straight Point Icon"
+                    disabled={!props.hasSelectedUnpointedPoints}
                     imgSrc={straightPointIcon}
-                    title="Pointed"
-                    onClick={function () {}}
-                /> */}
+                    title={props.intl.formatMessage(messages.pointed)}
+                    onClick={props.onPointPoints}
+                />
             </div>
         );
     case Modes.SELECT:
@@ -153,12 +162,16 @@ ModeToolsComponent.propTypes = {
     className: PropTypes.string,
     clipboardItems: PropTypes.arrayOf(PropTypes.array),
     eraserValue: PropTypes.number,
+    hasSelectedUncurvedPoints: PropTypes.bool,
+    hasSelectedUnpointedPoints: PropTypes.bool,
     intl: intlShape.isRequired,
     mode: PropTypes.string.isRequired,
     onBrushSliderChange: PropTypes.func,
     onCopyToClipboard: PropTypes.func.isRequired,
+    onCurvePoints: PropTypes.func.isRequired,
     onEraserSliderChange: PropTypes.func,
     onPasteFromClipboard: PropTypes.func.isRequired,
+    onPointPoints: PropTypes.func.isRequired,
     selectedItems: PropTypes.arrayOf(PropTypes.instanceOf(paper.Item))
 };
 
diff --git a/src/containers/mode-tools.jsx b/src/containers/mode-tools.jsx
index 830083af..7b06fd71 100644
--- a/src/containers/mode-tools.jsx
+++ b/src/containers/mode-tools.jsx
@@ -8,15 +8,132 @@ import ModeToolsComponent from '../components/mode-tools/mode-tools.jsx';
 import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
 import {incrementPasteOffset, setClipboardItems} from '../reducers/clipboard';
 import {clearSelection, getSelectedLeafItems, getSelectedRootItems} from '../helper/selection';
+import {HANDLE_RATIO} from '../helper/math';
 
 class ModeTools extends React.Component {
     constructor (props) {
         super(props);
         bindAll(this, [
+            '_getSelectedUncurvedPoints',
+            '_getSelectedUnpointedPoints',
+            'hasSelectedUncurvedPoints',
+            'hasSelectedUnpointedPoints',
             'handleCopyToClipboard',
-            'handlePasteFromClipboard'
+            'handleCurvePoints',
+            'handlePasteFromClipboard',
+            'handlePointPoints'
         ]);
     }
+    _getSelectedUncurvedPoints () {
+        const items = [];
+        const selectedItems = getSelectedLeafItems();
+        for (const item of selectedItems) {
+            if (!item.segments) continue;
+            for (const seg of item.segments) {
+                if (seg.selected) {
+                    const prev = seg.getPrevious();
+                    const next = seg.getNext();
+                    const isCurved =
+                        (!prev || seg.handleIn.length > 0) &&
+                        (!next || seg.handleOut.length > 0) &&
+                        (prev && next ? seg.handleOut.isColinear(seg.handleIn) : true);
+                    if (!isCurved) items.push(seg);
+                }
+            }
+        }
+        return items;
+    }
+    _getSelectedUnpointedPoints () {
+        const points = [];
+        const selectedItems = getSelectedLeafItems();
+        for (const item of selectedItems) {
+            if (!item.segments) continue;
+            for (const seg of item.segments) {
+                if (seg.selected) {
+                    if (seg.handleIn.length > 0 || seg.handleOut.length > 0) {
+                        points.push(seg);
+                    }
+                }
+            }
+        }
+        return points;
+    }
+    hasSelectedUncurvedPoints () {
+        const points = this._getSelectedUncurvedPoints();
+        return points.length > 0;
+    }
+    hasSelectedUnpointedPoints () {
+        const points = this._getSelectedUnpointedPoints();
+        return points.length > 0;
+    }
+    handleCurvePoints () {
+        let changed;
+        const points = this._getSelectedUncurvedPoints();
+        for (const point of points) {
+            const prev = point.getPrevious();
+            const next = point.getNext();
+            const noHandles = point.handleIn.length === 0 && point.handleOut.length === 0;
+            if (!prev && !next) {
+                continue;
+            } else if (prev && next && noHandles) {
+                // Handles are parallel to the line from prev to next
+                point.handleIn = prev.point.subtract(next.point)
+                    .normalize()
+                    .multiply(prev.getCurve().length * HANDLE_RATIO);
+            } else if (prev && !next && point.handleIn.length === 0) {
+                // Point is end point
+                // Direction is average of normal at the point and direction to prev point, using the
+                // normal that points out from the convex side
+                // Lenth is curve length * HANDLE_RATIO
+                const convexity = prev.getCurve().getCurvatureAtTime(.5) < 0 ? -1 : 1;
+                point.handleIn = (prev.getCurve().getNormalAtTime(1)
+                    .multiply(convexity)
+                    .add(prev.point.subtract(point.point).normalize()))
+                    .normalize()
+                    .multiply(prev.getCurve().length * HANDLE_RATIO);
+            } else if (next && !prev && point.handleOut.length === 0) {
+                // Point is start point
+                // Direction is average of normal at the point and direction to prev point, using the
+                // normal that points out from the convex side
+                // Lenth is curve length * HANDLE_RATIO
+                const convexity = point.getCurve().getCurvatureAtTime(.5) < 0 ? -1 : 1;
+                point.handleOut = (point.getCurve().getNormalAtTime(0)
+                    .multiply(convexity)
+                    .add(next.point.subtract(point.point).normalize()))
+                    .normalize()
+                    .multiply(point.getCurve().length * HANDLE_RATIO);
+            }
+
+            // Point guaranteed to have a handle now. Make the second handle match the length and direction of first.
+            // This defines a curved point.
+            if (point.handleIn.length > 0 && next) {
+                point.handleOut = point.handleIn.multiply(-1);
+            } else if (point.handleOut.length > 0 && prev) {
+                point.handleIn = point.handleOut.multiply(-1);
+            }
+            changed = true;
+        }
+        if (changed) {
+            this.props.setSelectedItems();
+            this.props.onUpdateSvg();
+        }
+    }
+    handlePointPoints () {
+        let changed;
+        const points = this._getSelectedUnpointedPoints();
+        for (const point of points) {
+            const noHandles = point.handleIn.length === 0 && point.handleOut.length === 0;
+            if (!noHandles) {
+                point.handleIn = null;
+                point.handleOut = null;
+                changed = true;
+            }
+        }
+        if (changed) {
+            this.props.setSelectedItems();
+            this.props.onUpdateSvg();
+        }
+    }
     handleCopyToClipboard () {
         const selectedItems = getSelectedRootItems();
         if (selectedItems.length > 0) {
@@ -50,8 +167,12 @@ class ModeTools extends React.Component {
     render () {
         return (
             <ModeToolsComponent
+                hasSelectedUncurvedPoints={this.hasSelectedUncurvedPoints()}
+                hasSelectedUnpointedPoints={this.hasSelectedUnpointedPoints()}
                 onCopyToClipboard={this.handleCopyToClipboard}
+                onCurvePoints={this.handleCurvePoints}
                 onPasteFromClipboard={this.handlePasteFromClipboard}
+                onPointPoints={this.handlePointPoints}
             />
         );
     }
@@ -63,13 +184,17 @@ ModeTools.propTypes = {
     incrementPasteOffset: PropTypes.func.isRequired,
     onUpdateSvg: PropTypes.func.isRequired,
     pasteOffset: PropTypes.number,
+    // Listen on selected items to update hasSelectedPoints
+    selectedItems:
+        PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)), // eslint-disable-line react/no-unused-prop-types
     setClipboardItems: PropTypes.func.isRequired,
     setSelectedItems: PropTypes.func.isRequired
 };
 
 const mapStateToProps = state => ({
     clipboardItems: state.scratchPaint.clipboard.items,
-    pasteOffset: state.scratchPaint.clipboard.pasteOffset
+    pasteOffset: state.scratchPaint.clipboard.pasteOffset,
+    selectedItems: state.scratchPaint.selectedItems
 });
 const mapDispatchToProps = dispatch => ({
     setClipboardItems: items => {
diff --git a/src/helper/math.js b/src/helper/math.js
index 5c74c740..cab99242 100644
--- a/src/helper/math.js
+++ b/src/helper/math.js
@@ -1,5 +1,8 @@
 import paper from '@scratch/paper';
 
+/** The ratio of the curve length to use for the handle length to convert squares into approximately circles. */
+const HANDLE_RATIO = 0.3902628565;
+
 const checkPointsClose = function (startPos, eventPoint, threshold) {
     const xOff = Math.abs(startPos.x - eventPoint.x);
     const yOff = Math.abs(startPos.y - eventPoint.y);
@@ -95,6 +98,7 @@ const expandByOne = function (path) {
 };
 
 export {
+    HANDLE_RATIO,
     checkPointsClose,
     expandByOne,
     getRandomInt,
diff --git a/src/helper/selection-tools/handle-tool.js b/src/helper/selection-tools/handle-tool.js
index cbf78770..305681fd 100644
--- a/src/helper/selection-tools/handle-tool.js
+++ b/src/helper/selection-tools/handle-tool.js
@@ -79,6 +79,7 @@ class HandleTool {
             }
         }
         if (moved) {
+            this.setSelectedItems();
             this.onUpdateSvg();
         }
         this.selectedItems = [];
diff --git a/src/helper/selection-tools/point-tool.js b/src/helper/selection-tools/point-tool.js
index 0c88d2f9..9a9ddd4b 100644
--- a/src/helper/selection-tools/point-tool.js
+++ b/src/helper/selection-tools/point-tool.js
@@ -1,6 +1,7 @@
 import paper from '@scratch/paper';
 import {snapDeltaToAngle} from '../math';
 import {clearSelection, getSelectedLeafItems} from '../selection';
+import {HANDLE_RATIO} from '../math';
 
 /** Subtool of ReshapeTool for moving control points. */
 class PointTool {
@@ -72,8 +73,8 @@ class PointTool {
             hitProperties.hitResult.location.curve.length - hitProperties.hitResult.location.curveOffset;
 
         // Handle length based on curve length until next point
-        let handleIn = hitProperties.hitResult.location.tangent.multiply(-beforeCurveLength / 2);
-        let handleOut = hitProperties.hitResult.location.tangent.multiply(afterCurveLength / 2);
+        let handleIn = hitProperties.hitResult.location.tangent.multiply(-beforeCurveLength * HANDLE_RATIO);
+        let handleOut = hitProperties.hitResult.location.tangent.multiply(afterCurveLength * HANDLE_RATIO);
         // Don't let one handle overwhelm the other (results in path doubling back on itself weirdly)
         if (handleIn.length > 3 * handleOut.length) {
             handleIn = handleIn.multiply(3 * handleOut.length / handleIn.length);
@@ -98,7 +99,7 @@ class PointTool {
         if (beforeSegment && beforeSegment.handleOut) {
             if (afterSegment) {
                 beforeSegment.handleOut =
-                    beforeSegment.handleOut.multiply(beforeCurveLength / 2 / beforeSegment.handleOut.length);
+                    beforeSegment.handleOut.multiply(beforeCurveLength * HANDLE_RATIO / beforeSegment.handleOut.length);
             } else {
                 beforeSegment.handleOut = null;
             }
@@ -106,7 +107,7 @@ class PointTool {
         if (afterSegment && afterSegment.handleIn) {
             if (beforeSegment) {
                 afterSegment.handleIn =
-                    afterSegment.handleIn.multiply(afterCurveLength / 2 / afterSegment.handleIn.length);
+                    afterSegment.handleIn.multiply(afterCurveLength * HANDLE_RATIO / afterSegment.handleIn.length);
             } else {
                 afterSegment.handleIn = null;
             }
@@ -123,14 +124,15 @@ class PointTool {
         if (beforeSegment && beforeSegment.handleOut) {
             if (afterSegment) {
                 beforeSegment.handleOut =
-                    beforeSegment.handleOut.multiply(curveLength / 2 / beforeSegment.handleOut.length);
+                    beforeSegment.handleOut.multiply(curveLength * HANDLE_RATIO / beforeSegment.handleOut.length);
             } else {
                 beforeSegment.handleOut = null;
             }
         }
         if (afterSegment && afterSegment.handleIn) {
             if (beforeSegment) {
-                afterSegment.handleIn = afterSegment.handleIn.multiply(curveLength / 2 / afterSegment.handleIn.length);
+                afterSegment.handleIn =
+                    afterSegment.handleIn.multiply(curveLength * HANDLE_RATIO / afterSegment.handleIn.length);
             } else {
                 afterSegment.handleIn = null;
             }
diff --git a/src/reducers/selected-items.js b/src/reducers/selected-items.js
index 67a2d147..c68dece7 100644
--- a/src/reducers/selected-items.js
+++ b/src/reducers/selected-items.js
@@ -10,17 +10,11 @@ const reducer = function (state, action) {
             log.warn(`No selected items or wrong format provided: ${action.selectedItems}`);
             return state;
         }
-        // If they are not equal, return the new list of items. Else return old list
-        if (action.selectedItems.length !== state.length) {
-            return action.selectedItems;
+        // If they are both empty, no change
+        if (action.selectedItems.length === 0 && state.length === 0) {
+            return state;
         }
-        // Shallow equality check (we may need to update this later for more granularity)
-        for (let i = 0; i < action.selectedItems.length; i++) {
-            if (action.selectedItems[i] !== state[i]) {
-                return action.selectedItems;
-            }
-        }
-        return state;
+        return action.selectedItems;
     default:
         return state;
     }