diff options
Diffstat (limited to 'chromium/third_party/trace-viewer/src/ui/quad_stack_view.js')
-rw-r--r-- | chromium/third_party/trace-viewer/src/ui/quad_stack_view.js | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/chromium/third_party/trace-viewer/src/ui/quad_stack_view.js b/chromium/third_party/trace-viewer/src/ui/quad_stack_view.js deleted file mode 100644 index fdd185547ef..00000000000 --- a/chromium/third_party/trace-viewer/src/ui/quad_stack_view.js +++ /dev/null @@ -1,603 +0,0 @@ -// Copyright (c) 2013 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'; - -/** - * @fileoverview QuadStackView controls the content and viewing angle a - * QuadStack. - */ -base.requireStylesheet('ui.quad_stack_view'); - -base.requireTemplate('ui.quad_stack_view'); - -base.require('base.bbox2'); -base.require('base.gl_matrix'); -base.require('base.quad'); -base.require('base.raf'); -base.require('base.rect'); -base.require('base.settings'); -base.require('ui.camera'); -base.require('ui.mouse_mode_selector'); -base.require('ui.mouse_tracker'); - -base.exportTo('ui', function() { - var constants = {}; - constants.IMAGE_LOAD_RETRY_TIME_MS = 500; - constants.SUBDIVISION_MINIMUM = 1; - constants.SUBDIVISION_RECURSION_DEPTH = 3; - constants.SUBDIVISION_DEPTH_THRESHOLD = 100; - constants.FAR_PLANE_DISTANCE = 10000; - - // Care of bckenney@ via - // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 - function drawTexturedTriangle(ctx, img, p0, p1, p2, t0, t1, t2) { - var tmp_p0 = [p0[0], p0[1]]; - var tmp_p1 = [p1[0], p1[1]]; - var tmp_p2 = [p2[0], p2[1]]; - var tmp_t0 = [t0[0], t0[1]]; - var tmp_t1 = [t1[0], t1[1]]; - var tmp_t2 = [t2[0], t2[1]]; - - ctx.beginPath(); - ctx.moveTo(tmp_p0[0], tmp_p0[1]); - ctx.lineTo(tmp_p1[0], tmp_p1[1]); - ctx.lineTo(tmp_p2[0], tmp_p2[1]); - ctx.closePath(); - - tmp_p1[0] -= tmp_p0[0]; - tmp_p1[1] -= tmp_p0[1]; - tmp_p2[0] -= tmp_p0[0]; - tmp_p2[1] -= tmp_p0[1]; - - tmp_t1[0] -= tmp_t0[0]; - tmp_t1[1] -= tmp_t0[1]; - tmp_t2[0] -= tmp_t0[0]; - tmp_t2[1] -= tmp_t0[1]; - - var det = 1 / (tmp_t1[0] * tmp_t2[1] - tmp_t2[0] * tmp_t1[1]), - - // linear transformation - a = (tmp_t2[1] * tmp_p1[0] - tmp_t1[1] * tmp_p2[0]) * det, - b = (tmp_t2[1] * tmp_p1[1] - tmp_t1[1] * tmp_p2[1]) * det, - c = (tmp_t1[0] * tmp_p2[0] - tmp_t2[0] * tmp_p1[0]) * det, - d = (tmp_t1[0] * tmp_p2[1] - tmp_t2[0] * tmp_p1[1]) * det, - - // translation - e = tmp_p0[0] - a * tmp_t0[0] - c * tmp_t0[1], - f = tmp_p0[1] - b * tmp_t0[0] - d * tmp_t0[1]; - - ctx.save(); - ctx.transform(a, b, c, d, e, f); - ctx.clip(); - ctx.drawImage(img, 0, 0); - ctx.restore(); - } - - function drawTriangleSub( - ctx, img, p0, p1, p2, t0, t1, t2, opt_recursion_depth) { - var depth = opt_recursion_depth || 0; - - // We may subdivide if we are not at the limit of recursion. - var subdivisionIndex = 0; - if (depth < constants.SUBDIVISION_MINIMUM) { - subdivisionIndex = 7; - } else if (depth < constants.SUBDIVISION_RECURSION_DEPTH) { - if (Math.abs(p0[2] - p1[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) - subdivisionIndex += 1; - if (Math.abs(p0[2] - p2[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) - subdivisionIndex += 2; - if (Math.abs(p1[2] - p2[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) - subdivisionIndex += 4; - } - - // These need to be created every time, since temporaries - // outside of the scope will be rewritten in recursion. - var p01 = vec4.create(); - var p02 = vec4.create(); - var p12 = vec4.create(); - var t01 = vec2.create(); - var t02 = vec2.create(); - var t12 = vec2.create(); - - // Calculate the position before w-divide. - for (var i = 0; i < 2; ++i) { - p0[i] *= p0[2]; - p1[i] *= p1[2]; - p2[i] *= p2[2]; - } - - // Interpolate the 3d position. - for (var i = 0; i < 4; ++i) { - p01[i] = (p0[i] + p1[i]) / 2; - p02[i] = (p0[i] + p2[i]) / 2; - p12[i] = (p1[i] + p2[i]) / 2; - } - - // Re-apply w-divide to the original points and the interpolated ones. - for (var i = 0; i < 2; ++i) { - p0[i] /= p0[2]; - p1[i] /= p1[2]; - p2[i] /= p2[2]; - - p01[i] /= p01[2]; - p02[i] /= p02[2]; - p12[i] /= p12[2]; - } - - // Interpolate the texture coordinates. - for (var i = 0; i < 2; ++i) { - t01[i] = (t0[i] + t1[i]) / 2; - t02[i] = (t0[i] + t2[i]) / 2; - t12[i] = (t1[i] + t2[i]) / 2; - } - - // Based on the index, we subdivide the triangle differently. - // Assuming the triangle is p0, p1, p2 and points between i j - // are represented as pij (that is, a point between p2 and p0 - // is p02, etc), then the new triangles are defined by - // the 3rd 4th and 5th arguments into the function. - switch (subdivisionIndex) { - case 1: - drawTriangleSub(ctx, img, p0, p01, p2, t0, t01, t2, depth + 1); - drawTriangleSub(ctx, img, p01, p1, p2, t01, t1, t2, depth + 1); - break; - case 2: - drawTriangleSub(ctx, img, p0, p1, p02, t0, t1, t02, depth + 1); - drawTriangleSub(ctx, img, p1, p02, p2, t1, t02, t2, depth + 1); - break; - case 3: - drawTriangleSub(ctx, img, p0, p01, p02, t0, t01, t02, depth + 1); - drawTriangleSub(ctx, img, p02, p01, p2, t02, t01, t2, depth + 1); - drawTriangleSub(ctx, img, p01, p1, p2, t01, t1, t2, depth + 1); - break; - case 4: - drawTriangleSub(ctx, img, p0, p12, p2, t0, t12, t2, depth + 1); - drawTriangleSub(ctx, img, p0, p1, p12, t0, t1, t12, depth + 1); - break; - case 5: - drawTriangleSub(ctx, img, p0, p01, p2, t0, t01, t2, depth + 1); - drawTriangleSub(ctx, img, p2, p01, p12, t2, t01, t12, depth + 1); - drawTriangleSub(ctx, img, p01, p1, p12, t01, t1, t12, depth + 1); - break; - case 6: - drawTriangleSub(ctx, img, p0, p12, p02, t0, t12, t02, depth + 1); - drawTriangleSub(ctx, img, p0, p1, p12, t0, t1, t12, depth + 1); - drawTriangleSub(ctx, img, p02, p12, p2, t02, t12, t2, depth + 1); - break; - case 7: - drawTriangleSub(ctx, img, p0, p01, p02, t0, t01, t02, depth + 1); - drawTriangleSub(ctx, img, p01, p12, p02, t01, t12, t02, depth + 1); - drawTriangleSub(ctx, img, p01, p1, p12, t01, t1, t12, depth + 1); - drawTriangleSub(ctx, img, p02, p12, p2, t02, t12, t2, depth + 1); - break; - default: - // In the 0 case and all other cases, we simply draw the triangle. - drawTexturedTriangle(ctx, img, p0, p1, p2, t0, t1, t2); - break; - } - } - - // Created to avoid creating garbage when doing bulk transforms. - var tmp_vec4 = vec4.create(); - function transform(transformed, point, matrix, viewport) { - vec4.set(tmp_vec4, point[0], point[1], 0, 1); - vec4.transformMat4(tmp_vec4, tmp_vec4, matrix); - - var w = tmp_vec4[3]; - if (w < 1e-6) w = 1e-6; - - transformed[0] = ((tmp_vec4[0] / w) + 1) * viewport.width / 2; - transformed[1] = ((tmp_vec4[1] / w) + 1) * viewport.height / 2; - transformed[2] = w; - } - - function drawProjectedQuadBackgroundToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas) { - if (quad.imageData) { - quadCanvas.width = quad.imageData.width; - quadCanvas.height = quad.imageData.height; - quadCanvas.getContext('2d').putImageData(quad.imageData, 0, 0); - var quadBBox = new base.BBox2(); - quadBBox.addQuad(quad); - var iw = quadCanvas.width; - var ih = quadCanvas.height; - drawTriangleSub( - ctx, quadCanvas, - p1, p2, p4, - [0, 0], [iw, 0], [0, ih]); - drawTriangleSub( - ctx, quadCanvas, - p2, p3, p4, - [iw, 0], [iw, ih], [0, ih]); - } - - if (quad.backgroundColor) { - ctx.fillStyle = quad.backgroundColor; - ctx.beginPath(); - ctx.moveTo(p1[0], p1[1]); - ctx.lineTo(p2[0], p2[1]); - ctx.lineTo(p3[0], p3[1]); - ctx.lineTo(p4[0], p4[1]); - ctx.closePath(); - ctx.fill(); - } - } - - function drawProjectedQuadOutlineToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas) { - ctx.beginPath(); - ctx.moveTo(p1[0], p1[1]); - ctx.lineTo(p2[0], p2[1]); - ctx.lineTo(p3[0], p3[1]); - ctx.lineTo(p4[0], p4[1]); - ctx.closePath(); - ctx.save(); - if (quad.borderColor) - ctx.strokeStyle = quad.borderColor; - else - ctx.strokeStyle = 'rgb(128,128,128)'; - - if (quad.shadowOffset) { - ctx.shadowColor = 'rgb(0, 0, 0)'; - ctx.shadowOffsetX = quad.shadowOffset[0]; - ctx.shadowOffsetY = quad.shadowOffset[1]; - if (quad.shadowBlur) - ctx.shadowBlur = quad.shadowBlur; - } - - if (quad.borderWidth) - ctx.lineWidth = quad.borderWidth; - else - ctx.lineWidth = 1; - - ctx.stroke(); - ctx.restore(); - } - - function drawProjectedQuadSelectionOutlineToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas) { - if (!quad.upperBorderColor) - return; - - ctx.lineWidth = 8; - ctx.strokeStyle = quad.upperBorderColor; - - ctx.beginPath(); - ctx.moveTo(p1[0], p1[1]); - ctx.lineTo(p2[0], p2[1]); - ctx.lineTo(p3[0], p3[1]); - ctx.lineTo(p4[0], p4[1]); - ctx.closePath(); - ctx.stroke(); - } - - function drawProjectedQuadToContext( - passNumber, quad, p1, p2, p3, p4, ctx, quadCanvas) { - if (passNumber === 0) { - drawProjectedQuadBackgroundToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas); - } else if (passNumber === 1) { - drawProjectedQuadOutlineToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas); - } else if (passNumber === 2) { - drawProjectedQuadSelectionOutlineToContext( - quad, p1, p2, p3, p4, ctx, quadCanvas); - } else { - throw new Error('Invalid pass number'); - } - } - - var tmp_p1 = vec3.create(); - var tmp_p2 = vec3.create(); - var tmp_p3 = vec3.create(); - var tmp_p4 = vec3.create(); - function transformAndProcessQuads( - matrix, viewport, quads, numPasses, handleQuadFunc, opt_arg1, opt_arg2) { - - for (var passNumber = 0; passNumber < numPasses; passNumber++) { - for (var i = 0; i < quads.length; i++) { - var quad = quads[i]; - transform(tmp_p1, quad.p1, matrix, viewport); - transform(tmp_p2, quad.p2, matrix, viewport); - transform(tmp_p3, quad.p3, matrix, viewport); - transform(tmp_p4, quad.p4, matrix, viewport); - handleQuadFunc(passNumber, quad, - tmp_p1, tmp_p2, tmp_p3, tmp_p4, - opt_arg1, opt_arg2); - } - } - } - - /** - * @constructor - */ - var QuadStackView = ui.define('quad-stack-view'); - - QuadStackView.prototype = { - __proto__: HTMLUnknownElement.prototype, - - decorate: function() { - this.className = 'quad-stack-view'; - - var node = base.instantiateTemplate('#quad-stack-view-template'); - this.appendChild(node); - - this.canvas_ = this.querySelector('#canvas'); - this.chromeImages_ = { - left: this.querySelector('#chrome-left'), - mid: this.querySelector('#chrome-mid'), - right: this.querySelector('#chrome-right') - }; - - this.trackMouse_(); - - this.camera_ = new ui.Camera(this.mouseModeSelector_); - this.camera_.addEventListener('renderrequired', - this.onRenderRequired_.bind(this)); - this.cameraWasReset_ = false; - this.camera_.canvas = this.canvas_; - - this.viewportRect_ = base.Rect.fromXYWH(0, 0, 0, 0); - - this.stackingDistance_ = 45; - this.pixelRatio_ = window.devicePixelRatio || 1; - }, - - onStackingDistanceChange: function(e) { - this.stackingDistance_ = parseInt(e.target.value); - this.scheduleRender(); - }, - - get mouseModeSelector() { - return this.mouseModeSelector_; - }, - - get camera() { - return this.camera_; - }, - - set quads(q) { - this.quads_ = q; - this.scheduleRender(); - }, - - set deviceRect(rect) { - if (!rect || rect.equalTo(this.deviceRect_)) - return; - - this.deviceRect_ = rect; - this.camera_.deviceRect = rect; - this.chromeQuad_ = undefined; - }, - - resize: function() { - if (!this.offsetParent) - return true; - - var width = parseInt(window.getComputedStyle(this.offsetParent).width); - var height = parseInt(window.getComputedStyle(this.offsetParent).height); - var rect = base.Rect.fromXYWH(0, 0, width, height); - - if (rect.equalTo(this.viewportRect_)) - return false; - - this.viewportRect_ = rect; - this.style.width = width + 'px'; - this.style.height = height + 'px'; - this.canvas_.style.width = width + 'px'; - this.canvas_.style.height = height + 'px'; - this.canvas_.width = this.pixelRatio_ * width; - this.canvas_.height = this.pixelRatio_ * height; - if (!this.cameraWasReset_) { - this.camera_.resetCamera(); - this.cameraWasReset_ = true; - } - return true; - }, - - readyToDraw: function() { - // If src isn't set yet, set it to ensure we can use - // the image to draw onto a canvas. - if (!this.chromeImages_.left.src) { - var leftContent = - window.getComputedStyle(this.chromeImages_.left).content; - leftContent = leftContent.replace(/url\((.*)\)/, '$1'); - - var midContent = - window.getComputedStyle(this.chromeImages_.mid).content; - midContent = midContent.replace(/url\((.*)\)/, '$1'); - - var rightContent = - window.getComputedStyle(this.chromeImages_.right).content; - rightContent = rightContent.replace(/url\((.*)\)/, '$1'); - - this.chromeImages_.left.src = leftContent; - this.chromeImages_.mid.src = midContent; - this.chromeImages_.right.src = rightContent; - } - - // If all of the images are loaded (height > 0), then - // we are ready to draw. - return (this.chromeImages_.left.height > 0) && - (this.chromeImages_.mid.height > 0) && - (this.chromeImages_.right.height > 0); - }, - - get chromeQuad() { - if (this.chromeQuad_) - return this.chromeQuad_; - - // Draw the chrome border into a separate canvas. - var chromeCanvas = document.createElement('canvas'); - var offsetY = this.chromeImages_.left.height; - - chromeCanvas.width = this.deviceRect_.width; - chromeCanvas.height = this.deviceRect_.height + offsetY; - - var leftWidth = this.chromeImages_.left.width; - var midWidth = this.chromeImages_.mid.width; - var rightWidth = this.chromeImages_.right.width; - - var chromeCtx = chromeCanvas.getContext('2d'); - chromeCtx.drawImage(this.chromeImages_.left, 0, 0); - - chromeCtx.save(); - chromeCtx.translate(leftWidth, 0); - - // Calculate the scale of the mid image. - var s = (this.deviceRect_.width - leftWidth - rightWidth) / midWidth; - chromeCtx.scale(s, 1); - - chromeCtx.drawImage(this.chromeImages_.mid, 0, 0); - chromeCtx.restore(); - - chromeCtx.drawImage( - this.chromeImages_.right, leftWidth + s * midWidth, 0); - - // Construct the quad. - var chromeRect = base.Rect.fromXYWH( - this.deviceRect_.x, - this.deviceRect_.y - offsetY, - this.deviceRect_.width, - this.deviceRect_.height + offsetY); - var chromeQuad = base.Quad.fromRect(chromeRect); - chromeQuad.stackingGroupId = this.maxStackingGroupId_ + 1; - chromeQuad.imageData = chromeCtx.getImageData( - 0, 0, chromeCanvas.width, chromeCanvas.height); - chromeQuad.shadowOffset = [0, 0]; - chromeQuad.shadowBlur = 5; - chromeQuad.borderWidth = 3; - this.chromeQuad_ = chromeQuad; - return this.chromeQuad_; - }, - - scheduleRender: function() { - if (this.redrawScheduled_) - return false; - this.redrawScheduled_ = true; - base.requestAnimationFrame(this.render, this); - }, - - onRenderRequired_: function(e) { - this.scheduleRender(); - }, - - stackTransformAndProcessQuads_: function( - numPasses, handleQuadFunc, includeChromeQuad, opt_arg1, opt_arg2) { - var mv = this.camera_.modelViewMatrix; - var p = this.camera_.projectionMatrix; - - var viewport = base.Rect.fromXYWH( - 0, 0, this.canvas_.width, this.canvas_.height); - - // Calculate the quad stacks. - var quadStacks = []; - for (var i = 0; i < this.quads_.length; ++i) { - var quad = this.quads_[i]; - var stackingId = quad.stackingGroupId || 0; - while (stackingId >= quadStacks.length) - quadStacks.push([]); - - quadStacks[stackingId].push(quad); - } - - var mvp = mat4.create(); - this.maxStackingGroupId_ = quadStacks.length; - var stackingDistance = - this.stackingDistance_ * this.camera_.stackingDistanceDampening; - - // Draw the quad stacks, raising each subsequent level. - mat4.multiply(mvp, p, mv); - for (var i = 0; i < quadStacks.length; ++i) { - transformAndProcessQuads(mvp, viewport, quadStacks[i], - numPasses, handleQuadFunc, - opt_arg1, opt_arg2); - - mat4.translate(mv, mv, [0, 0, stackingDistance]); - mat4.multiply(mvp, p, mv); - } - - if (includeChromeQuad && this.deviceRect_) { - transformAndProcessQuads(mvp, viewport, [this.chromeQuad], - numPasses, drawProjectedQuadToContext, - opt_arg1, opt_arg2); - } - }, - - render: function() { - this.redrawScheduled_ = false; - - if (!this.readyToDraw()) { - setTimeout(this.scheduleRender.bind(this), - constants.IMAGE_LOAD_RETRY_TIME_MS); - return; - } - - if (!this.quads_) - return; - - var canvasCtx = this.canvas_.getContext('2d'); - if (!this.resize()) - canvasCtx.clearRect(0, 0, this.canvas_.width, this.canvas_.height); - - var quadCanvas = document.createElement('canvas'); - this.stackTransformAndProcessQuads_( - 3, drawProjectedQuadToContext, true, - canvasCtx, quadCanvas); - quadCanvas.width = 0; // Hack: Frees the quadCanvas' resources. - }, - - trackMouse_: function() { - this.mouseModeSelector_ = new ui.MouseModeSelector(this); - this.mouseModeSelector_.supportedModeMask = - ui.MOUSE_SELECTOR_MODE.SELECTION | - ui.MOUSE_SELECTOR_MODE.PANSCAN | - ui.MOUSE_SELECTOR_MODE.ZOOM | - ui.MOUSE_SELECTOR_MODE.ROTATE; - this.mouseModeSelector_.mode = ui.MOUSE_SELECTOR_MODE.PANSCAN; - this.mouseModeSelector_.pos = {x: 0, y: 100}; - this.appendChild(this.mouseModeSelector_); - this.mouseModeSelector_.settingsKey = - 'quadStackView.mouseModeSelector'; - - this.mouseModeSelector_.setModifierForAlternateMode( - ui.MOUSE_SELECTOR_MODE.ROTATE, ui.MODIFIER.SHIFT); - this.mouseModeSelector_.setModifierForAlternateMode( - ui.MOUSE_SELECTOR_MODE.PANSCAN, ui.MODIFIER.SPACE); - this.mouseModeSelector_.setModifierForAlternateMode( - ui.MOUSE_SELECTOR_MODE.ZOOM, ui.MODIFIER.CMD_OR_CTRL); - - this.mouseModeSelector_.addEventListener('updateselection', - this.onSelectionUpdate_.bind(this)); - this.mouseModeSelector_.addEventListener('endselection', - this.onSelectionUpdate_.bind(this)); - }, - - extractRelativeMousePosition_: function(e) { - var br = this.canvas_.getBoundingClientRect(); - return [ - this.pixelRatio_ * (e.clientX - this.canvas_.offsetLeft - br.left), - this.pixelRatio_ * (e.clientY - this.canvas_.offsetTop - br.top) - ]; - }, - - onSelectionUpdate_: function(e) { - var mousePos = this.extractRelativeMousePosition_(e); - var res = []; - function handleQuad(passNumber, quad, p1, p2, p3, p4) { - if (base.pointInImplicitQuad(mousePos, p1, p2, p3, p4)) - res.push(quad); - } - this.stackTransformAndProcessQuads_(1, handleQuad, false); - var e = new Event('selectionchange', false, false); - e.quads = res; - this.dispatchEvent(e); - } - }; - - return { - QuadStackView: QuadStackView - }; -}); |