# 2.44

## 练习 2.44 请定义出corner-split里使用的过程up-split，它与right-split类似，除在其中交换了below和beside的角色之外。

### the Jeff Tian painter

img = document.querySelector('#jeff-tian');

const framedPainter = (frameX, frameY, frameWidth, frameHeight) => (painter) => {
painter(frameX, frameY, frameWidth, frameHeight);
};

drawToFrame = (frame, width, height) => (framedPainter) => {
const canvas = document.querySelector(frame);
canvas.width = width;
canvas.height = height;

const ctx = canvas.getContext('2d');
framedPainter(ctx);
};

const createPainter = (image, sourceX, sourceY, sourceWidth, sourceHeight) => (frameX, frameY, frameWidth, frameHeight) => (ctx) => {
ctx.drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, frameX, frameY, frameWidth, frameHeight);
};

// (x, y, w, h) -> ctx -> void
jeffTianPainter = createPainter(img, 0, 0, img.naturalWidth, img.naturalHeight);

if(img.complete) {
handler();
}

};

img.onerror = () => {
};

### beside

// ((x, y, w, h) -> ctx -> void,
// (x, y, w, h) -> ctx -> void) ->
// (x, y, w, h) -> ctx -> void
beside = (painter1, painter2) => (x, y, w, h) => (ctx) => {
ctx.save();
painter1(x, y, Math.floor(w/2), h)(ctx);
ctx.restore();
ctx.save();
painter2(x + Math.floor(w/2) + 1, y, Math.ceil(w/2), h)(ctx);
ctx.restore();
};

// (x, y, w, h) -> ctx -> void
const besidePainter = beside(jeffTianPainter, jeffTianPainter);

### below

below = (painter1, painter2) => (x, y, w, h) => (ctx) => {
ctx.save();
painter2(x, y, w, Math.floor(h/2))(ctx);
ctx.restore();
ctx.save();
painter1(x, y + Math.floor(h/2)+1, w, Math.ceil(h/2))(ctx);
ctx.restore();
};

const belowPainter = below(jeffTianPainter, jeffTianPainter);

### flip-vert

// painter -> ctx -> void
flipVert = (painter) => (x, y, w, h) => (ctx) => {
ctx.save();
ctx.scale(1, -1);
painter(x, -y, w, -h)(ctx);
ctx.restore();
}

const flipVertPainter = flipVert(jeffTianPainter);

### flip-horiz

flipHoriz = (painter) => (x, y, w, h) => (ctx) => {
ctx.save();
ctx.scale(-1, 1);
painter(-x, y, -w, h)(ctx);
ctx.restore();
};
const flipHorizPainter = flipHoriz(jeffTianPainter);

### wave2 with Jeff Tian Painter

wave2 = beside(jeffTianPainter, flipVert(jeffTianPainter));

### wave4 with Jeff Tian Painter

const wave4 = below(wave2, wave2);

### flipped-pairs with jeffTianPainter

const flippedPairs = (painter) => {
const painter2 = beside(painter, flipVert(painter));

return below(painter2, painter2);
}

const wave4 = flippedPairs(jeffTianPainter);

### 通过递归在图形的右边做分割和分支

/**

/------------------------\
|           |            |
|           |  rightSplit|
|           |     n-1    |
|  identity |------------|
|           |            |
|           |  rightSplit|
|           |     n-1    |
\-----------|------------/

*/

rightSplit = (painter, n) => {
if (n === 0) {
return painter;
}

const smaller = rightSplit(painter, n - 1);
return beside(painter, below(smaller, smaller));
};

const rightSplit1 = rightSplit(jeffTianPainter, 1);

const rightSplit1 = rightSplit(jeffTianPainter, 4);

### 向上分割

upSplit = (painter, n) => {
if (n === 0) {
return painter;
}

const smaller = upSplit(painter, n - 1);
return below(beside(smaller, smaller), painter);
};

const upSplit4 = upSplit(jeffTianPainter, 4);

### 通过同时在图形中向上和向右分支，产生出一种平衡模式

cornerSplit = (painter, n) => {
if (n === 0) {
return painter;
}

const up = upSplit(painter, n - 1);
const right = rightSplit(painter, n - 1);
const topLeft = beside(up, up);
const bottomRight = below(right, right);
const corner  = cornerSplit(painter, n - 1);

return beside(below(topLeft, painter), below(corner, bottomRight));
}

const cornerSplit4 = cornerSplit(jeffTianPainter, 4);

### square-limit 模式

const squareLimit = (painter, n) => {
const quarter = cornerSplit(painter, n);
const half = beside(flipHoriz(quarter), quarter);
return below(flipVert(half), half);
};

const squareLimit4 = squareLimit(jeffTianPainter, 4);

(define (up-split painter n)
(if (= n 0)
painter
(let ((smaller (up-split painter (- n 1))))
(below (beside smaller smaller) painter)
)
)
)

// placeholder, nothing here