このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
ラストは FixColourMapEntries メッセージだ。
これは種類 1 番のクライアントメッセージで、
クライアントが非 TrueColor の画素表現を使っている際に、
そのカラーテーブル(≒パレット)の一部または全部を、
特定の色に固定したい場合に送られる。
カラーテーブルを使った表現を使う場合、
常に最適な画面表示を行うためには、
状況に応じてカラーテーブルの内容を変更する必要がある。
画面を管理するのはサーバなので、
通常カラーテーブルの管理はサーバが行い、
クライアントに対して通知してくることになる。
しかしながら、クライアントの処理能力によっては、
パレットを固定した方がよい場合もある。
その際にこのメッセージが利用されるのだ。
このメッセージは可変長で、以下のような構造を持つ。
U8 messageType; // 常に 1
U8 reserved; // 1 バイトの詰め物
U16 firstColor; // 範囲の最初のインデックス
U16 count; // メッセージに含まれる色の数
ColorEntry colors[]; // カラーテーブル
firstColor と count は、カラーテーブルの
どの部分を固定するかどうかを示している。
firstIndex = 10, count = 4 ならば、
カラーテーブルの 10 番から 13 番までを示すことになる。
colors 配列には count の数の色情報が入る。
色情報は、RGB 各 U16 で構成される組み合わせだ。
ばらばらにすると面倒なので、
ColorEntry というクラスにしておこう。
========== ColorEntry.java ==========
package jp.loafer.rfb.message;
import java.io.IOException;
import jp.loafer.rfb.RFBContext;
import jp.loafer.rfb.io.RFBInputStream;
import jp.loafer.rfb.io.RFBOutputStream;
/**
* カラーテーブルの要素を表す不変クラス。
* @author kes
*/
public class ColorEntry implements Message {
/**
* 永続化用既定コンストラクタ。
*/
public ColorEntry() {
//
}
/**
* {@link ColorEntry} のインスタンスを作成。
* @param red 赤の値。
* @param green 緑の値。
* @param blue 青の値。
*/
public ColorEntry(int red, int green, int blue) {
if (red < 0 || red > 0xffff)
throw new IllegalArgumentException("bad red value.");
if (green < 0 || green > 0xffff)
throw new IllegalArgumentException("bad green value.");
if (blue < 0 || blue > 0xffff)
throw new IllegalArgumentException("bad blue value.");
this.red = red;
this.green = green;
this.blue = blue;
}
/**
* 赤の値を取得。
* @return 赤の値。
*/
public int getRed() {
return red;
}
/**
* 青の値を取得。
* @return 青の値。
*/
public int getBlue() {
return blue;
}
/**
* 緑の値を取得。
* @return 緑の値。
*/
public int getGreen() {
return green;
}
/**
* @see Message#read(RFBContext, RFBInputStream)
*/
public void read(RFBContext context, RFBInputStream in) throws IOException {
red = in.readU16();
green = in.readU16();
blue = in.readU16();
}
/**
* @see Message#write(RFBContext, RFBOutputStream)
*/
public void write(RFBContext context, RFBOutputStream out) throws IOException {
out.writeU16(red);
out.writeU16(green);
out.writeU16(blue);
}
protected int red;
protected int green;
protected int blue;
}
========== end of ColorEntry.java ==========
ColorEntry は、単に RGB を格納するだけのクラスだ。
PixelFormat と同じように、Message を実装させている。
では、肝心のメッセージクラスを作る。
========== FixColorMapEntriesMessage.java ==========
package jp.loafer.rfb.message.client;
import java.io.IOException;
import jp.loafer.rfb.RFBContext;
import jp.loafer.rfb.io.RFBInputStream;
import jp.loafer.rfb.io.RFBOutputStream;
import jp.loafer.rfb.message.ColorEntry;
/**
* FixColourMapEntries クライアントメッセージ。。
* @author kes
*/
public class FixColorMapEntriesMessage extends BaseClientMessage {
/**
* 永続化用既定コンストラクタ。
*/
public FixColorMapEntriesMessage() {
//
}
/**
* FixColourMapEntries メッセージを作成。
* @param firstIndex カラーテーブルが示す色の最初のインデックス。
* @param colors カラーテーブルの配列。
*/
public FixColorMapEntriesMessage(int firstIndex, ColorEntry[] colors) {
if (firstIndex < 0) throw new IndexOutOfBoundsException();
if (colors == null) throw new NullPointerException();
this.firstIndex = firstIndex;
this.colors = colors;
}
/**
* カラーテーブルが示す色の最初のインデックスを取得。
* @return 最初のインデックス。
*/
public int getFirstIndex() {
return firstIndex;
}
/**
* カラーテーブルの配列を取得。
* @return カラーテーブルの配列。
*/
public ColorEntry[] getColors() {
return colors.clone();
}
/**
* カラーテーブルの要素を取得。
* インデックスは {@link #getFirstIndex()} の値に関係なく 0 を基準とする。
* @param index 0 ベースのインデックス。
* @return カラーテーブルの要素。
*/
public ColorEntry getColors(int index) {
return colors[index];
}
/**
* @see ClientMessage#getType()
*/
public int getType() {
return ClientMessage.FIX_COLOR_MAP_ENTRIES;
}
/**
* @see ClientMessage#read(RFBContext, RFBInputStream)
*/
@Override
public void read(RFBContext context, RFBInputStream in) throws IOException {
super.read(context, in);
in.readU8();
int length = in.readU16();
colors = new ColorEntry[length];
for (int i = 0; i < length; ++i) {
colors[i] = in.readMessage(context, ColorEntry.class);
}
}
/**
* @see ClientMessage#write(RFBContext, RFBOutputStream)
*/
@Override
public void write(RFBContext context, RFBOutputStream out) throws IOException {
super.write(context, out);
out.writeU8(0);
out.writeU16(colors.length);
for (int i = 0; i < colors.length; ++i) {
out.writeMessage(context, colors[i]);
}
}
private int firstIndex;
private ColorEntry[] colors;
}
========== end of FixColorMapEntriesMessage.java ==========
SetEncodingsMessage クラスと同様、
配列をフィールドとしているので、
複数の getter を用意している。
ColorEntry クラスは(ほぼ)不変クラスなので、
単に配列を clone するだけで特に問題はない。
なお、このメッセージは RFB 3.3 の初期には存在したが、
3.3 の改訂版以降は非推奨となっている。
そのため最近のクライアントはこのメッセージを使わないが、
3.3 をサポートするサーバであれば、
このメッセージを読み出せるようにしておく必要がある。