diff --git a/src/drawer.js b/src/drawer.js
index a53d0d3b..27f0cdd7 100644
--- a/src/drawer.js
+++ b/src/drawer.js
@@ -87,8 +87,7 @@ $.Drawer = function( options ) {
 
 
         //internal state / configurable settings
-        overlays:           [], // An unordered list of Overlays added.
-        collectionOverlays: {},
+        collectionOverlays: {}, // For collection mode. Here an overlay is actually a viewer.
 
         //configurable settings
         maxImageCacheCount: $.DEFAULT_SETTINGS.maxImageCacheCount,
@@ -148,199 +147,11 @@ $.Drawer = function( options ) {
     this.container.style.textAlign = "left";
     this.container.appendChild( this.canvas );
 
-    //create the correct type of overlay by convention if the overlays
-    //are not already OpenSeadragon.Overlays
-    for( i = 0; i < this.overlays.length; i++ ){
-        if( $.isPlainObject( this.overlays[ i ] ) ){
-
-            this.overlays[ i ] = addOverlayFromConfiguration( this, this.overlays[ i ]);
-
-        } else if ( $.isFunction( this.overlays[ i ] ) ){
-            //TODO
-        }
-    }
-
     //this.profiler    = new $.Profiler();
 };
 
 $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
 
-    /**
-     * Adds an html element as an overlay to the current viewport.  Useful for
-     * highlighting words or areas of interest on an image or other zoomable
-     * interface.
-     * @method
-     * @param {Element|String|Object} element - A reference to an element or an id for
-     *      the element which will overlayed. Or an Object specifying the configuration for the overlay
-     * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
-     *      rectangle which will be overlayed.
-     * @param {OpenSeadragon.OverlayPlacement} placement - The position of the
-     *      viewport which the location coordinates will be treated as relative
-     *      to.
-     * @param {function} onDraw - If supplied the callback is called when the overlay 
-     *      needs to be drawn. It it the responsibility of the callback to do any drawing/positioning.
-     *      It is passed position, size and element.
-     * @fires OpenSeadragon.Viewer.event:add-overlay
-     */
-    addOverlay: function( element, location, placement, onDraw ) {
-        var options;
-        if( $.isPlainObject( element ) ){
-            options = element;
-        } else {
-            options = {
-                element: element,
-                location: location,
-                placement: placement,
-                onDraw: onDraw
-            };
-        }
-
-        element = $.getElement(options.element);
-
-        if ( getOverlayIndex( this.overlays, element ) >= 0 ) {
-            // they're trying to add a duplicate overlay
-            return;
-        }
-
-        this.overlays.push( new $.Overlay({
-            element: element,
-            location: options.location,
-            placement: options.placement,
-            onDraw: options.onDraw
-        }) );
-        this.updateAgain = true;
-        if( this.viewer ){
-            /**
-             * Raised when an overlay is added to the viewer (see {@link OpenSeadragon.Drawer#addOverlay}).
-             *
-             * @event add-overlay
-             * @memberof OpenSeadragon.Viewer
-             * @type {object}
-             * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
-             * @property {Element} element - The overlay element.
-             * @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
-             * @property {OpenSeadragon.OverlayPlacement} placement
-             * @property {?Object} userData - Arbitrary subscriber-defined object.
-             */
-            this.viewer.raiseEvent( 'add-overlay', {
-                element: element,
-                location: options.location,
-                placement: options.placement
-            });
-        }
-        return this;
-    },
-
-    /**
-     * Updates the overlay represented by the reference to the element or
-     * element id moving it to the new location, relative to the new placement.
-     * @method
-     * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
-     *      rectangle which will be overlayed.
-     * @param {OpenSeadragon.OverlayPlacement} placement - The position of the
-     *      viewport which the location coordinates will be treated as relative
-     *      to.
-     * @return {OpenSeadragon.Drawer} Chainable.
-     * @fires OpenSeadragon.Viewer.event:update-overlay
-     */
-    updateOverlay: function( element, location, placement ) {
-        var i;
-
-        element = $.getElement( element );
-        i = getOverlayIndex( this.overlays, element );
-
-        if ( i >= 0 ) {
-            this.overlays[ i ].update( location, placement );
-            this.updateAgain = true;
-        }
-        if( this.viewer ){
-            /**
-             * Raised when an overlay's location or placement changes (see {@link OpenSeadragon.Drawer#updateOverlay}).
-             *
-             * @event update-overlay
-             * @memberof OpenSeadragon.Viewer
-             * @type {object}
-             * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
-             * @property {Element} element
-             * @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
-             * @property {OpenSeadragon.OverlayPlacement} placement
-             * @property {?Object} userData - Arbitrary subscriber-defined object.
-             */
-            this.viewer.raiseEvent( 'update-overlay', {
-                element: element,
-                location: location,
-                placement: placement
-            });
-        }
-        return this;
-    },
-
-    /**
-     * Removes and overlay identified by the reference element or element id
-     *      and schedules and update.
-     * @method
-     * @param {Element|String} element - A reference to the element or an
-     *      element id which represent the ovelay content to be removed.
-     * @return {OpenSeadragon.Drawer} Chainable.
-     * @fires OpenSeadragon.Viewer.event:remove-overlay
-     */
-    removeOverlay: function( element ) {
-        var i;
-
-        element = $.getElement( element );
-        i = getOverlayIndex( this.overlays, element );
-
-        if ( i >= 0 ) {
-            this.overlays[ i ].destroy();
-            this.overlays.splice( i, 1 );
-            this.updateAgain = true;
-        }
-        if( this.viewer ){
-            /**
-             * Raised when an overlay is removed from the viewer (see {@link OpenSeadragon.Drawer#removeOverlay}).
-             *
-             * @event remove-overlay
-             * @memberof OpenSeadragon.Viewer
-             * @type {object}
-             * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
-             * @property {Element} element - The overlay element.
-             * @property {?Object} userData - Arbitrary subscriber-defined object.
-             */
-            this.viewer.raiseEvent( 'remove-overlay', {
-                element: element
-            });
-        }
-        return this;
-    },
-
-    /**
-     * Removes all currently configured Overlays from this Drawer and schedules
-     *      and update.
-     * @method
-     * @return {OpenSeadragon.Drawer} Chainable.
-     * @fires OpenSeadragon.Viewer.event:clear-overlay
-     */
-    clearOverlays: function() {
-        while ( this.overlays.length > 0 ) {
-            this.overlays.pop().destroy();
-            this.updateAgain = true;
-        }
-        if( this.viewer ){
-            /**
-             * Raised when all overlays are removed from the viewer (see {@link OpenSeadragon.Drawer#clearOverlays}).
-             *
-             * @event clear-overlay
-             * @memberof OpenSeadragon.Viewer
-             * @type {object}
-             * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
-             * @property {?Object} userData - Arbitrary subscriber-defined object.
-             */
-            this.viewer.raiseEvent( 'clear-overlay', {} );
-        }
-        return this;
-    },
-
-
     /**
      * Returns whether the Drawer is scheduled for an update at the
      *      soonest possible opportunity.
@@ -467,61 +278,6 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
     }
 };
 
-/**
- * @private
- * @inner
- */
- function addOverlayFromConfiguration( drawer, overlay ){
-
-    var element  = null,
-        rect = ( overlay.height && overlay.width ) ? new $.Rect(
-            overlay.x || overlay.px,
-            overlay.y || overlay.py,
-            overlay.width,
-            overlay.height
-        ) : new $.Point(
-            overlay.x || overlay.px,
-            overlay.y || overlay.py
-        ),
-        id = overlay.id ?
-            overlay.id :
-            "openseadragon-overlay-"+Math.floor(Math.random()*10000000);
-
-    element = $.getElement(overlay.id);
-    if( !element ){
-        element         = document.createElement("a");
-        element.href    = "#/overlay/"+id;
-    }
-    element.id        = id;
-    $.addClass( element, overlay.className ?
-        overlay.className :
-        "openseadragon-overlay"
-    );
-
-
-    if(overlay.px !== undefined){
-        //if they specified 'px' so it's in pixel coordinates so
-        //we need to translate to viewport coordinates
-        rect = drawer.viewport.imageToViewportRectangle( rect );
-    }
-    
-    if( overlay.placement ){
-        return new $.Overlay({
-            element: element,
-            location: drawer.viewport.pointFromPixel(rect),
-            placement: $.OverlayPlacement[overlay.placement.toUpperCase()],
-            onDraw: overlay.onDraw
-        });
-    }else{
-        return new $.Overlay({
-            element: element,
-            location: rect,
-            onDraw: overlay.onDraw
-        });
-    }
-
-}
-
 /**
  * @private
  * @inner
@@ -695,7 +451,6 @@ function updateViewport( drawer ) {
 
     //TODO
     drawTiles( drawer, drawer.lastDrawn );
-    drawOverlays( drawer.viewport, drawer.overlays, drawer.container );
 
     //TODO
     if ( best ) {
@@ -1142,23 +897,6 @@ function resetCoverage( coverage, level ) {
     coverage[ level ] = {};
 }
 
-/**
- * @private
- * @inner
- * Determines the 'z-index' of the given overlay.  Overlays are ordered in
- * a z-index based on the order they are added to the Drawer.
- */
-function getOverlayIndex( overlays, element ) {
-    var i;
-    for ( i = overlays.length - 1; i >= 0; i-- ) {
-        if ( overlays[ i ].element == element ) {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
 /**
  * @private
  * @inner
@@ -1196,28 +934,6 @@ function finishLoadingImage( image, callback, successful, jobid ){
 
 }
 
-
-function drawOverlays( viewport, overlays, container ){
-    var i,
-        length = overlays.length;
-    for ( i = 0; i < length; i++ ) {
-        drawOverlay( viewport, overlays[ i ], container );
-    }
-}
-
-function drawOverlay( viewport, overlay, container ){
-
-    overlay.position = viewport.pixelFromPoint(
-        overlay.bounds.getTopLeft(),
-        true
-    );
-    overlay.size     = viewport.deltaPixelsFromPoints(
-        overlay.bounds.getSize(),
-        true
-    );
-    overlay.drawHTML( container, viewport );
-}
-
 function drawTiles( drawer, lastDrawn ){
     var i,
         tile,
diff --git a/src/overlay.js b/src/overlay.js
index 29445389..c87c84e1 100644
--- a/src/overlay.js
+++ b/src/overlay.js
@@ -174,7 +174,7 @@
                 element.parentNode.removeChild( element );
                 //this should allow us to preserve overlays when required between
                 //pages
-                if( element.prevElementParent ){
+                if ( element.prevElementParent ) {
                     style.display = 'none';
                     //element.prevElementParent.insertBefore(
                     //    element,
@@ -208,10 +208,16 @@
                 drawerCenter = new $.Point(
                     viewport.viewer.drawer.canvas.width / 2,
                     viewport.viewer.drawer.canvas.height / 2
-                ),
-                degrees = viewport.degrees,
-                position,
-                size,
+                    ),
+                degrees  = viewport.degrees,
+                position = viewport.pixelFromPoint(
+                    this.bounds.getTopLeft(),
+                    true
+                    ),
+                size     = viewport.deltaPixelsFromPoints(
+                    this.bounds.getSize(),
+                    true
+                    ),
                 overlayCenter;
 
             if ( element.parentNode != container ) {
@@ -225,8 +231,8 @@
                 this.size = $.getElementSize( element );
             }
 
-            position = this.position;
-            size     = this.size;
+            this.position = position;
+            this.size     = size;
 
             this.adjust( position, size );
 
diff --git a/src/viewer.js b/src/viewer.js
index 11a96691..f9eb1242 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -126,7 +126,7 @@ $.Viewer = function( options ) {
          */
         canvas:         null,
 
-        //TODO: not sure how to best describe these
+        // Overlays list. An overlay allows to add html on top of the viewer.
         overlays:       [],
 
         //private state properties
@@ -570,9 +570,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
             this.navigator.close();
         }
 
-        if ( this.drawer ) {
-            this.drawer.clearOverlays();
-        }
+        this.clearOverlays();
 
         this.source     = null;
         this.drawer     = null;
@@ -1299,6 +1297,178 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
         return this;
     },
 
+   /**
+     * Adds an html element as an overlay to the current viewport.  Useful for
+     * highlighting words or areas of interest on an image or other zoomable
+     * interface.
+     * @method
+     * @param {Element|String|Object} element - A reference to an element or an id for
+     *      the element which will overlayed. Or an Object specifying the configuration for the overlay
+     * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
+     *      rectangle which will be overlayed.
+     * @param {OpenSeadragon.OverlayPlacement} placement - The position of the
+     *      viewport which the location coordinates will be treated as relative
+     *      to.
+     * @param {function} onDraw - If supplied the callback is called when the overlay
+     *      needs to be drawn. It it the responsibility of the callback to do any drawing/positioning.
+     *      It is passed position, size and element.
+     * @return {OpenSeadragon.Viewer} Chainable.
+     * @fires OpenSeadragon.Viewer.event:add-overlay
+     */
+    addOverlay: function( element, location, placement, onDraw ) {
+        var options;
+        if( $.isPlainObject( element ) ){
+            options = element;
+        } else {
+            options = {
+                element: element,
+                location: location,
+                placement: placement,
+                onDraw: onDraw
+            };
+        }
+
+        element = $.getElement(options.element);
+
+        if ( getOverlayIndex( this.currentOverlays, element ) >= 0 ) {
+            // they're trying to add a duplicate overlay
+            return this;
+        }
+
+        this.currentOverlays.push( new $.Overlay({
+            element: element,
+            location: options.location,
+            placement: options.placement,
+            onDraw: options.onDraw
+        }) );
+        THIS[ this.hash ].forceRedraw = true;
+        /**
+         * Raised when an overlay is added to the viewer (see {@link OpenSeadragon.Viewer#addOverlay}).
+         *
+         * @event add-overlay
+         * @memberof OpenSeadragon.Viewer
+         * @type {object}
+         * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
+         * @property {Element} element - The overlay element.
+         * @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
+         * @property {OpenSeadragon.OverlayPlacement} placement
+         * @property {?Object} userData - Arbitrary subscriber-defined object.
+         */
+        this.raiseEvent( 'add-overlay', {
+            element: element,
+            location: options.location,
+            placement: options.placement
+        });
+        return this;
+    },
+
+    /**
+     * Updates the overlay represented by the reference to the element or
+     * element id moving it to the new location, relative to the new placement.
+     * @method
+     * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
+     *      rectangle which will be overlayed.
+     * @param {OpenSeadragon.OverlayPlacement} placement - The position of the
+     *      viewport which the location coordinates will be treated as relative
+     *      to.
+     * @return {OpenSeadragon.Viewer} Chainable.
+     * @fires OpenSeadragon.Viewer.event:update-overlay
+     */
+    updateOverlay: function( element, location, placement ) {
+        var i;
+
+        element = $.getElement( element );
+        i = getOverlayIndex( this.currentOverlays, element );
+
+        if ( i >= 0 ) {
+            this.currentOverlays[ i ].update( location, placement );
+            THIS[ this.hash ].forceRedraw = true;
+            /**
+             * Raised when an overlay's location or placement changes
+             * (see {@link OpenSeadragon.Viewer#updateOverlay}).
+             *
+             * @event update-overlay
+             * @memberof OpenSeadragon.Viewer
+             * @type {object}
+             * @property {OpenSeadragon.Viewer} eventSource - A reference to the
+             * Viewer which raised the event.
+             * @property {Element} element
+             * @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
+             * @property {OpenSeadragon.OverlayPlacement} placement
+             * @property {?Object} userData - Arbitrary subscriber-defined object.
+             */
+            this.raiseEvent( 'update-overlay', {
+                element: element,
+                location: location,
+                placement: placement
+            });
+        }
+        return this;
+    },
+
+    /**
+     * Removes an overlay identified by the reference element or element id
+     * and schedules an update.
+     * @method
+     * @param {Element|String} element - A reference to the element or an
+     *      element id which represent the ovelay content to be removed.
+     * @return {OpenSeadragon.Viewer} Chainable.
+     * @fires OpenSeadragon.Viewer.event:remove-overlay
+     */
+    removeOverlay: function( element ) {
+        var i;
+
+        element = $.getElement( element );
+        i = getOverlayIndex( this.currentOverlays, element );
+
+        if ( i >= 0 ) {
+            this.currentOverlays[ i ].destroy();
+            this.currentOverlays.splice( i, 1 );
+            THIS[ this.hash ].forceRedraw = true;
+            /**
+             * Raised when an overlay is removed from the viewer
+             * (see {@link OpenSeadragon.Viewer#removeOverlay}).
+             *
+             * @event remove-overlay
+             * @memberof OpenSeadragon.Viewer
+             * @type {object}
+             * @property {OpenSeadragon.Viewer} eventSource - A reference to the
+             * Viewer which raised the event.
+             * @property {Element} element - The overlay element.
+             * @property {?Object} userData - Arbitrary subscriber-defined object.
+             */
+            this.raiseEvent( 'remove-overlay', {
+                element: element
+            });
+        }
+        return this;
+    },
+
+    /**
+     * Removes all currently configured Overlays from this Viewer and schedules
+     * an update.
+     * @method
+     * @return {OpenSeadragon.Viewer} Chainable.
+     * @fires OpenSeadragon.Viewer.event:clear-overlay
+     */
+    clearOverlays: function() {
+        while ( this.currentOverlays.length > 0 ) {
+            this.currentOverlays.pop().destroy();
+        }
+        THIS[ this.hash ].forceRedraw = true;
+        /**
+         * Raised when all overlays are removed from the viewer (see {@link OpenSeadragon.Drawer#clearOverlays}).
+         *
+         * @event clear-overlay
+         * @memberof OpenSeadragon.Viewer
+         * @type {object}
+         * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
+         * @property {?Object} userData - Arbitrary subscriber-defined object.
+         */
+        this.raiseEvent( 'clear-overlay', {} );
+        return this;
+    },
+
     /**
      * Updates the sequence buttons.
      * @function OpenSeadragon.Viewer.prototype._updateSequenceButtons
@@ -1417,7 +1587,7 @@ function openTileSource( viewer, source ) {
             //minZoomLevel:           this.minZoomLevel,
             //maxZoomLevel:           this.maxZoomLevel
         });
-    }else{
+    } else {
         if( source ){
             _this.source = source;
         }
@@ -1515,6 +1685,16 @@ function openTileSource( viewer, source ) {
 
     VIEWERS[ _this.hash ] = _this;
 
+    _this.currentOverlays = [];
+    var i;
+    for ( i = 0; i < _this.overlays.length; i++ ) {
+        _this.currentOverlays[ i ] = getOverlayObject( _this, _this.overlays[ i ] );
+    }
+    for ( var j = 0; j < _this.source.overlays.length; j++ ) {
+        _this.currentOverlays[ i + j ] =
+            getOverlayObject( _this, _this.source.overlays[ j ] );
+    }
+
     /**
      * Raised when the viewer has opened and loaded one or more TileSources.
      *
@@ -1530,8 +1710,82 @@ function openTileSource( viewer, source ) {
     return _this;
 }
 
+function getOverlayObject( viewer, overlay ) {
+    if ( !$.isPlainObject( overlay ) ) {
+        return overlay;
+    }
 
+    var element  = null,
+    rect = ( overlay.height && overlay.width ) ? new $.Rect(
+        overlay.x || overlay.px,
+        overlay.y || overlay.py,
+        overlay.width,
+        overlay.height
+    ) : new $.Point(
+        overlay.x || overlay.px,
+        overlay.y || overlay.py
+    ),
+    id = overlay.id ?
+        overlay.id :
+        "openseadragon-overlay-" + Math.floor( Math.random() * 10000000 );
 
+    element = $.getElement(overlay.id);
+    if ( !element ) {
+        element         = document.createElement("a");
+        element.href    = "#/overlay/" + id;
+    }
+    element.id = id;
+    $.addClass( element, overlay.className ?
+        overlay.className :
+        "openseadragon-overlay"
+    );
+
+    if( overlay.px !== undefined ) {
+        //if they specified 'px' so it's in pixel coordinates so
+        //we need to translate to viewport coordinates
+        rect = viewer.viewport.imageToViewportRectangle( rect );
+    }
+
+    if( overlay.placement ){
+        return new $.Overlay({
+            element: element,
+            location: viewer.viewport.pointFromPixel( rect ),
+            placement: $.OverlayPlacement[ overlay.placement.toUpperCase() ],
+            onDraw: overlay.onDraw
+        });
+    } else {
+        return new $.Overlay({
+            element: element,
+            location: rect,
+            onDraw: overlay.onDraw
+        });
+    }
+}
+
+/**
+ * @private
+ * @inner
+ * Determines the 'z-index' of the given overlay.  Overlays are ordered in
+ * a z-index based on the order they are added to the Drawer.
+ */
+function getOverlayIndex( overlays, element ) {
+    var i;
+    for ( i = overlays.length - 1; i >= 0; i-- ) {
+        if ( overlays[ i ].element == element ) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+function drawOverlays( viewport, overlays, container ){
+    var i,
+        length = overlays.length;
+    for ( i = 0; i < length; i++ ) {
+        overlays[ i ].drawHTML( container, viewport );
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 // Schedulers provide the general engine for animation
@@ -1905,6 +2159,7 @@ function updateOnce( viewer ) {
 
     if ( animated ) {
         viewer.drawer.update();
+        drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.canvas );
         if( viewer.navigator ){
             viewer.navigator.update( viewer.viewport );
         }
@@ -1920,6 +2175,7 @@ function updateOnce( viewer ) {
         viewer.raiseEvent( "animation" );
     } else if ( THIS[ viewer.hash ].forceRedraw || viewer.drawer.needsUpdate() ) {
         viewer.drawer.update();
+        drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.canvas );
         if( viewer.navigator ){
             viewer.navigator.update( viewer.viewport );
         }