Commit 4245363c authored by Joel Martin's avatar Joel Martin

Add a viewport example/test.

Tested with an iPad 2.

This example shows a 400x200 viewport of an 800x400 display.

It tries to be intelligent about how much it redraws. It copies what
it can, and then when the user releases the mouse, it redraws the
"dirty" areas that were newly revealed.
parent ce3bdbcc
<!DOCTYPE html>
<html>
<head><title>Viewport Test</title></head>
<body>
<br><br>
Canvas:
<input id="move-selector" type="button" value="Move"
onclick="toggleMove();">
<br>
<canvas id="canvas" width="640" height="20"
style="border-style: dotted; border-width: 1px;">
Canvas not supported.
</canvas>
<br>
Results:<br>
<textarea id="messages" style="font-size: 9;" cols=80 rows=25></textarea>
</body>
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
<script src="../include/util.js"></script>
<script src="../include/webutil.js"></script>
<script src="../include/base64.js"></script>
<script src="../include/input.js"></script>
<script src="../include/display.js"></script>
<script>
var msg_cnt = 0, iterations,
fb_width = 800,
fb_height = 600,
viewport = {
'x': 0, 'y': 0,
'w' : 400, 'h' : 200 },
cleanRect = {},
penDown = false, doMove = false,
inMove = false, lastPos = {},
canvas, ctx, keyboard, mouse;
var newline = "\n";
if (Util.Engine.trident) {
var newline = "<br>\n";
}
function message(str) {
console.log(str);
cell = $D('messages');
cell.innerHTML += msg_cnt + ": " + str + newline;
cell.scrollTop = cell.scrollHeight;
msg_cnt++;
}
function mouseButton(x, y, down, bmask) {
//msg = 'mouse x,y: ' + x + ',' + y + ' down: ' + down;
//msg += ' bmask: ' + bmask;
//message(msg);
if (doMove) {
if (down && !inMove) {
inMove = true;
lastPos = {'x': x, 'y': y};
cleanRect = {
'x1': viewport.x,
'y1': viewport.y,
'x2': viewport.x + viewport.w - 1,
'y2': viewport.y + viewport.h - 1};
} else if (!down && inMove) {
inMove = false;
dirtyRedraw();
}
return;
}
if (down && ! penDown) {
penDown = true;
ctx.beginPath();
ctx.moveTo(x, y);
} else if (!down && penDown) {
penDown = false;
ctx.closePath();
}
}
function mouseMove(x, y) {
var deltaX, deltaY, x1, y1;
if (inMove) {
viewportMove(x, y);
return;
}
if (penDown) {
ctx.lineTo(x, y);
ctx.stroke();
}
}
function viewportMove(x, y) {
var v = viewport, c = cleanRect,
vx2 = v.x + v.w - 1, vy2 = v.y + v.h - 1,
deltaX, deltaY, w, h;
//deltaX = x - lastPos.x; // drag viewport
deltaX = lastPos.x - x; // drag frame buffer
//deltaY = y - lastPos.y; // drag viewport
deltaY = lastPos.y - y; // drag frame buffer
lastPos = {'x': x, 'y': y};
if ((deltaX < 0) && ((v.x + deltaX) < 0)) {
deltaX = - v.x;
}
if ((vx2 + deltaX) >= fb_width) {
deltaX -= ((vx2 + deltaX) - fb_width);
}
v.x += deltaX;
vx2 += deltaX;
if ((v.y + deltaY) < 0) {
deltaY = - v.y;
}
if ((vy2 + deltaY) >= fb_height) {
deltaY -= ((vy2 + deltaY) - fb_height);
}
v.y += deltaY;
vy2 += deltaY;
// Update the clean rectangle
if (v.x > c.x1) {
c.x1 = v.x;
}
if (vx2 < c.x2) {
c.x2 = vx2;
}
if (v.y > c.y1) {
c.y1 = v.y;
}
if (vy2 < c.y2) {
c.y2 = vy2;
}
if (deltaX < 0) {
// Shift viewport left, redraw left section
x1 = 0;
w = - deltaX;
} else {
// Shift viewport right, redraw right section
x1 = v.w - deltaX;
w = deltaX;
}
if (deltaY < 0) {
// Shift viewport up, redraw top section
y1 = 0;
h = - deltaY;
} else {
// Shift viewport down, redraw bottom section
y1 = v.h - deltaY;
h = deltaY;
}
if (deltaX !== 0) {
canvas.copyImage(0, 0, -deltaX, 0, v.w, v.h);
canvas.fillRect(x1, 0, w, v.h, [255,255,255]);
}
if (deltaY !== 0) {
canvas.copyImage(0, 0, 0, -deltaY, v.w, v.h);
canvas.fillRect(0, y1, v.w, h, [255,255,255]);
}
}
function dirtyRedraw() {
var v = viewport, c = cleanRect,
vx2 = v.x + v.w - 1, vy2 = v.y + v.h - 1;
if ((c.x1 >= c.x2) || (c.y1 >= c.y2)) {
// Nothing clean, redraw everything
drawArea(0, 0, v.w, v.h);
} else {
// Redraw dirty regions
if (v.x < c.x1) {
// redraw left side dirty region
drawArea(0, 0, c.x1 - v.x, v.h);
}
if (vx2 > c.x2) {
// redraw right side dirty region
drawArea(v.w - (vx2 - c.x2), 0, vx2 - c.x2, v.h);
}
if (v.y < c.y1) {
// redraw top/middle dirty region
drawArea(c.x1 - v.x, 0, c.x2 - c.x1 + 1, c.y1 - v.y);
}
if (vy2 > c.y2) {
// redraw bottom/middle dirty region
drawArea(c.x1 - v.x, c.y2 - v.y, c.x2 - c.x1 + 1, v.h - (c.y2 - v.y));
}
}
}
function drawArea(x, y, w, h) {
var imgData = ctx.createImageData(w, h),
data = imgData.data, pixel, realX, realY;
for (var i = 0; i < w; i++) {
realX = viewport.x + x + i;
for (var j = 0; j < h; j++) {
realY = viewport.y + y + j;
pixel = (j * w * 4 + i * 4);
data[pixel + 0] = ((realX * realY) / 13) % 256;
data[pixel + 1] = ((realX * realY) + 392) % 256;
data[pixel + 2] = ((realX + realY) + 256) % 256;
data[pixel + 3] = 255;
}
}
//message("i: " + i + ", j: " + j + ", pixel: " + pixel);
ctx.putImageData(imgData, x, y);
}
function toggleMove() {
if (doMove) {
doMove = false;
$D('move-selector').style.backgroundColor = "";
$D('move-selector').style.color = "";
} else {
doMove = true;
$D('move-selector').style.backgroundColor = "black";
$D('move-selector').style.color = "lightgray";
}
}
window.onload = function() {
canvas = new Display({'target' : $D('canvas')});
ctx = canvas.get_context();
mouse = new Mouse({'target': $D('canvas'),
'onMouseButton': mouseButton,
'onMouseMove': mouseMove});
canvas.resize(viewport.w, viewport.h, true);
mouse.grab();
message("Display initialized");
drawArea(0, 0, viewport.w, viewport.h);
}
</script>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment