// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; base.require('base.range'); base.require('base.events'); base.exportTo('ui', function() { // FIXME(pdr): Replace this padding with just what's necessary for // drawing borders / highlights. // https://code.google.com/p/trace-viewer/issues/detail?id=228 var DEFAULT_PAD_PERCENTAGE = 0.75; function QuadViewViewport(worldRect, opt_quad_stack_scale, opt_padding, opt_devicePixelRatio) { base.EventTarget.call(this); if (!worldRect) throw new Error('Cannot initialize a viewport with an empty worldRect'); // Physical pixels / device-independent pixels; // 1 is normal; higher for eg Retina this.devicePixelRatio = opt_devicePixelRatio || window.devicePixelRatio || 1; this.layoutRect_ = undefined; this.setWorldRect_(worldRect, opt_padding); var scale; if (opt_quad_stack_scale) { scale = opt_quad_stack_scale; } else { scale = 0.125; if (this.devicePixelRatio > 1) scale = scale * this.devicePixelRatio; } this.worldPixelsPerDevicePixel_ = scale; this.updateScale_(); } QuadViewViewport.prototype = { __proto__: base.EventTarget.prototype, // The pixels in the original, traced browser are // represented in a canvas 'world', scaled by a // this 'scale' value. set scale(scale) { this.worldPixelsPerDevicePixel_ = scale; this.updateScale_(); this.didChange_(); }, get scale() { return this.worldPixelsPerDevicePixel_; }, get worldRect() { return this.worldRect_; }, get unpaddedWorldRect() { return this.unpaddedWorldRect_; }, updateBoxSize: function(canvas) { var resizedCanvas = false; if (canvas.width !== this.worldWidthInDevicePixels_) { canvas.width = this.worldWidthInDevicePixels_ * ui.RASTER_SCALE; canvas.style.width = this.layoutRect_.width + 'px'; resizedCanvas = true; } if (canvas.height !== this.worldHeightInDevicePixels_) { canvas.height = this.worldHeightInDevicePixels_ * ui.RASTER_SCALE; canvas.style.height = this.layoutRect_.height + 'px'; resizedCanvas = true; } return resizedCanvas; }, layoutPixelsToWorldPixels: function(v) { var tmp = this.layoutPixelsToDevicePixels(v); return this.devicePixelsToWorldPixels(tmp); }, layoutPixelsToDevicePixels: function(v) { var res = vec2.create(); return vec2.scale(res, v, this.devicePixelRatio); }, devicePixelsToWorldPixels: function(v) { var res = vec2.create(); vec2.transformMat2d(res, v, this.transformDevicePixelsToWorld_); return res; }, getWorldToDevicePixelsTransform: function() { return this.transformWorldToDevicePixels_; }, getDeviceLineWidthAssumingTransformIsApplied: function( desiredDeviceLineWidth) { return desiredDeviceLineWidth / this.worldPixelsPerDevicePixel_; }, applyTransformToContext: function(ctx) { var transform = this.transformWorldToDevicePixels_; ctx.transform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]); }, forceRedrawAll: function() { this.didChange_(); }, //------------------------------------------- updateScale_: function() { this.worldWidthInDevicePixels_ = this.worldRect_.width * this.worldPixelsPerDevicePixel_; this.worldHeightInDevicePixels_ = this.worldRect_.height * this.worldPixelsPerDevicePixel_; this.updateLayoutRect_(); this.transformWorldToDevicePixels_ = mat2d.create(); this.transformDevicePixelsToWorld_ = mat2d.create(); this.updateTransform_(); }, /** Adjust the scaled world box for Retina-like displays */ updateLayoutRect_: function() { var devicePixelsPerLayoutPixel = this.worldPixelsPerDevicePixel_ / this.devicePixelRatio; this.layoutRect_ = this.worldRect.scale(devicePixelsPerLayoutPixel); }, setWorldRect_: function(worldRect, opt_padding) { var worldPad; var padding; if (opt_padding !== undefined) { padding = opt_padding; } else { padding = DEFAULT_PAD_PERCENTAGE; } worldPad = Math.min(worldRect.width, worldRect.height) * padding; this.unpaddedWorldRect_ = worldRect; this.worldRect_ = worldRect.clone().enlarge(worldPad); }, updateTransform_: function() { if (!this.transformWorldToDevicePixels_) return; mat2d.identity(this.transformWorldToDevicePixels_); mat2d.translateXY( this.transformWorldToDevicePixels_, -this.worldRect_.x, -this.worldRect_.y); mat2d.scaleXY(this.transformWorldToDevicePixels_, this.worldPixelsPerDevicePixel_, this.worldPixelsPerDevicePixel_); mat2d.invert(this.transformDevicePixelsToWorld_, this.transformWorldToDevicePixels_); }, didChange_: function() { base.dispatchSimpleEvent(this, 'change', false, false); } }; return { QuadViewViewport: QuadViewViewport }; });