このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
画素データの送信用メッセージクラスが用意できたので、
RFBCanvas#sendFramebuffer の実装が可能となった。
========== RFBCanvas#sendFramebuffer ==========
// 必要に応じて画面の変更を送信
void sendFramebuffer() throws IOException {
synchronized (paintingSystem) {
// 送信が可能なのは、未送信でかつクライアントが要求した範囲
Shape s = intersectShapes(unsentRegion, requestedRegion);
if (s == null) return;
// 領域含む矩形を取得し
Rectangle r = s.getBounds();
// 領域のデータを符号化
byte[] data = encodeRawPixels(r);
// 画面送信サーバメッセージを作成し
UpdateRectangle[] rects =
new UpdateRectangle[] { new UpdateRectangle(r.x, r.y,
r.width, r.height, Encoding.RAW, data) };
FramebufferUpdateMessage m = new FramebufferUpdateMessage(rects);
// 送信!
out.writeMessage(context, m);
out.flush();
// データを送信した場合、未送信領域から除いておく
unsentRegion = subtractShapes(unsentRegion, r);
// 次の RequestFramebufferUpdate を
// 受信するまでは送信できない
requestedRegion = null;
}
}
========== end of RFBCanvas#sendFramebuffer ==========
sendFramebuffer では、未送信領域をクライアントに送る。
クライアントが要求した領域 requestRegion と、
更新があった範囲である unsentRegion の重なる部分が、
実際に送られるべき画面の範囲である。
範囲が決まったら、範囲の画素データを符号化し、
FramebufferUpdateMessage メッセージを作成して送信する。
最後に、送信した範囲を未送信領域から除いて完了となる。
subtractShapes は、領域の減算を行うためのメソッドだ。
========== RFBCanvas#subtractShapes ==========
// Shape から Shape を減算する
static private Shape subtractShapes(Shape minuend, Shape subtrahend) {
if (subtrahend == null) return minuend;
if (minuend == null) return null;
Area a = new Area(minuend);
a.subtract(new Area(subtrahend));
if (a.isEmpty()) return null;
return a;
}
========== end of RFBCanvas#subtractShapes ==========
また、intersectShapes は、
領域の重なった範囲を取得するメソッドだ。
========== RFBCanvas#intersectShapes ==========
// Shape 2 つの重なった領域を得る
static private Shape intersectShapes(Shape intersectand, Shape intersector) {
if (intersectand == null || intersector == null) return null;
// 両方とも Rectangle の場合高速な演算を行う
if (intersectand instanceof Rectangle && intersector instanceof Rectangle) {
Rectangle r = ((Rectangle)intersectand)
.intersection((Rectangle)intersector);
if (r.isEmpty()) return null;
return r;
}
Area a = new Area(intersectand);
a.intersect(new Area(intersector));
if (a.isEmpty()) return null;
return a;
}
========== end of RFBCanvas#intersectShapes ==========
重なった範囲の計算は頻繁に行われるので、
intersectShapes は矩形の範囲を特別に扱い、
より高速な演算が行われるように配慮している。
そして encodeRawPixels は、指定した範囲の画素データを、
byte 配列に符号化するメソッドである。
通常、符号化にはややこしい処理が伴うのだが、
RAW 符号化(Encoding.RAW)であれば、
加工なしの画素データそのままの表現を使えるので、
簡単に実装することができるのである。
encodeRawPixels は明日にしよう。