wmf: GraphViz block diagram (.dot) source

This page hosts a formal specification of wmf using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

wmf.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__wmf {
		label="Wmf";
		graph[style=dotted];

		wmf__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="special_header_pos">0</TD><TD PORT="special_header_size">22</TD><TD>SpecialHeader</TD><TD PORT="special_header_type">special_header</TD></TR>
			<TR><TD PORT="header_pos">22</TD><TD PORT="header_size">18</TD><TD>Header</TD><TD PORT="header_type">header</TD></TR>
			<TR><TD PORT="records_pos">40</TD><TD PORT="records_size">...</TD><TD>Record</TD><TD PORT="records_type">records</TD></TR>
			<TR><TD COLSPAN="4" PORT="records__repeat">repeat until _.function == :func_eof</TD></TR>
		</TABLE>>];
		subgraph cluster__params_setwindoworg {
			label="Wmf::ParamsSetwindoworg";
			graph[style=dotted];

			params_setwindoworg__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="y_pos">0</TD><TD PORT="y_size">2</TD><TD>s2le</TD><TD PORT="y_type">y</TD></TR>
				<TR><TD PORT="x_pos">2</TD><TD PORT="x_size">2</TD><TD>s2le</TD><TD PORT="x_type">x</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_setbkmode {
			label="Wmf::ParamsSetbkmode";
			graph[style=dotted];

			params_setbkmode__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="bk_mode_pos">0</TD><TD PORT="bk_mode_size">2</TD><TD>u2le→MixMode</TD><TD PORT="bk_mode_type">bk_mode</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__point_s {
			label="Wmf::PointS";
			graph[style=dotted];

			point_s__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="x_pos">0</TD><TD PORT="x_size">2</TD><TD>s2le</TD><TD PORT="x_type">x</TD></TR>
				<TR><TD PORT="y_pos">2</TD><TD PORT="y_size">2</TD><TD>s2le</TD><TD PORT="y_type">y</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_setwindowext {
			label="Wmf::ParamsSetwindowext";
			graph[style=dotted];

			params_setwindowext__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="y_pos">0</TD><TD PORT="y_size">2</TD><TD>s2le</TD><TD PORT="y_type">y</TD></TR>
				<TR><TD PORT="x_pos">2</TD><TD PORT="x_size">2</TD><TD>s2le</TD><TD PORT="x_type">x</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_polygon {
			label="Wmf::ParamsPolygon";
			graph[style=dotted];

			params_polygon__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="num_points_pos">0</TD><TD PORT="num_points_size">2</TD><TD>s2le</TD><TD PORT="num_points_type">num_points</TD></TR>
				<TR><TD PORT="points_pos">2</TD><TD PORT="points_size">4</TD><TD>PointS</TD><TD PORT="points_type">points</TD></TR>
				<TR><TD COLSPAN="4" PORT="points__repeat">repeat num_points times</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__header {
			label="Wmf::Header";
			graph[style=dotted];

			header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="metafile_type_pos">0</TD><TD PORT="metafile_type_size">2</TD><TD>u2le→MetafileType</TD><TD PORT="metafile_type_type">metafile_type</TD></TR>
				<TR><TD PORT="header_size_pos">2</TD><TD PORT="header_size_size">2</TD><TD>u2le</TD><TD PORT="header_size_type">header_size</TD></TR>
				<TR><TD PORT="version_pos">4</TD><TD PORT="version_size">2</TD><TD>u2le</TD><TD PORT="version_type">version</TD></TR>
				<TR><TD PORT="size_pos">6</TD><TD PORT="size_size">4</TD><TD>u4le</TD><TD PORT="size_type">size</TD></TR>
				<TR><TD PORT="number_of_objects_pos">10</TD><TD PORT="number_of_objects_size">2</TD><TD>u2le</TD><TD PORT="number_of_objects_type">number_of_objects</TD></TR>
				<TR><TD PORT="max_record_pos">12</TD><TD PORT="max_record_size">4</TD><TD>u4le</TD><TD PORT="max_record_type">max_record</TD></TR>
				<TR><TD PORT="number_of_members_pos">16</TD><TD PORT="number_of_members_size">2</TD><TD>u2le</TD><TD PORT="number_of_members_type">number_of_members</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__color_ref {
			label="Wmf::ColorRef";
			graph[style=dotted];

			color_ref__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="red_pos">0</TD><TD PORT="red_size">1</TD><TD>u1</TD><TD PORT="red_type">red</TD></TR>
				<TR><TD PORT="green_pos">1</TD><TD PORT="green_size">1</TD><TD>u1</TD><TD PORT="green_type">green</TD></TR>
				<TR><TD PORT="blue_pos">2</TD><TD PORT="blue_size">1</TD><TD>u1</TD><TD PORT="blue_type">blue</TD></TR>
				<TR><TD PORT="reserved_pos">3</TD><TD PORT="reserved_size">1</TD><TD>u1</TD><TD PORT="reserved_type">reserved</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_setrop2 {
			label="Wmf::ParamsSetrop2";
			graph[style=dotted];

			params_setrop2__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="draw_mode_pos">0</TD><TD PORT="draw_mode_size">2</TD><TD>u2le→BinRasterOp</TD><TD PORT="draw_mode_type">draw_mode</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_setpolyfillmode {
			label="Wmf::ParamsSetpolyfillmode";
			graph[style=dotted];

			params_setpolyfillmode__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="poly_fill_mode_pos">0</TD><TD PORT="poly_fill_mode_size">2</TD><TD>u2le→PolyFillMode</TD><TD PORT="poly_fill_mode_type">poly_fill_mode</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__params_polyline {
			label="Wmf::ParamsPolyline";
			graph[style=dotted];

			params_polyline__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="num_points_pos">0</TD><TD PORT="num_points_size">2</TD><TD>s2le</TD><TD PORT="num_points_type">num_points</TD></TR>
				<TR><TD PORT="points_pos">2</TD><TD PORT="points_size">4</TD><TD>PointS</TD><TD PORT="points_type">points</TD></TR>
				<TR><TD COLSPAN="4" PORT="points__repeat">repeat num_points times</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__special_header {
			label="Wmf::SpecialHeader";
			graph[style=dotted];

			special_header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="magic_pos">0</TD><TD PORT="magic_size">4</TD><TD>D7 CD C6 9A</TD><TD PORT="magic_type">magic</TD></TR>
				<TR><TD PORT="handle_pos">4</TD><TD PORT="handle_size">2</TD><TD>00 00</TD><TD PORT="handle_type">handle</TD></TR>
				<TR><TD PORT="left_pos">6</TD><TD PORT="left_size">2</TD><TD>s2le</TD><TD PORT="left_type">left</TD></TR>
				<TR><TD PORT="top_pos">8</TD><TD PORT="top_size">2</TD><TD>s2le</TD><TD PORT="top_type">top</TD></TR>
				<TR><TD PORT="right_pos">10</TD><TD PORT="right_size">2</TD><TD>s2le</TD><TD PORT="right_type">right</TD></TR>
				<TR><TD PORT="bottom_pos">12</TD><TD PORT="bottom_size">2</TD><TD>s2le</TD><TD PORT="bottom_type">bottom</TD></TR>
				<TR><TD PORT="inch_pos">14</TD><TD PORT="inch_size">2</TD><TD>u2le</TD><TD PORT="inch_type">inch</TD></TR>
				<TR><TD PORT="reserved_pos">16</TD><TD PORT="reserved_size">4</TD><TD>00 00 00 00</TD><TD PORT="reserved_type">reserved</TD></TR>
				<TR><TD PORT="checksum_pos">20</TD><TD PORT="checksum_size">2</TD><TD>u2le</TD><TD PORT="checksum_type">checksum</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__record {
			label="Wmf::Record";
			graph[style=dotted];

			record__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="size_pos">0</TD><TD PORT="size_size">4</TD><TD>u4le</TD><TD PORT="size_type">size</TD></TR>
				<TR><TD PORT="function_pos">4</TD><TD PORT="function_size">2</TD><TD>u2le→Func</TD><TD PORT="function_type">function</TD></TR>
				<TR><TD PORT="params_pos">6</TD><TD PORT="params_size">...</TD><TD>switch (function)</TD><TD PORT="params_type">params</TD></TR>
			</TABLE>>];
record__seq_params_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>:func_setbkmode</TD><TD PORT="case0">ParamsSetbkmode</TD></TR>
	<TR><TD>:func_setbkcolor</TD><TD PORT="case1">ColorRef</TD></TR>
	<TR><TD>:func_setrop2</TD><TD PORT="case2">ParamsSetrop2</TD></TR>
	<TR><TD>:func_polyline</TD><TD PORT="case3">ParamsPolyline</TD></TR>
	<TR><TD>:func_setwindoworg</TD><TD PORT="case4">ParamsSetwindoworg</TD></TR>
	<TR><TD>:func_polygon</TD><TD PORT="case5">ParamsPolygon</TD></TR>
	<TR><TD>:func_setwindowext</TD><TD PORT="case6">ParamsSetwindowext</TD></TR>
	<TR><TD>:func_setpolyfillmode</TD><TD PORT="case7">ParamsSetpolyfillmode</TD></TR>
</TABLE>>];
		}
	}
	wmf__seq:special_header_type -> special_header__seq [style=bold];
	wmf__seq:header_type -> header__seq [style=bold];
	wmf__seq:records_type -> record__seq [style=bold];
	record__seq:function_type -> wmf__seq:records__repeat [color="#404040"];
	params_polygon__seq:points_type -> point_s__seq [style=bold];
	params_polygon__seq:num_points_type -> params_polygon__seq:points__repeat [color="#404040"];
	params_polyline__seq:points_type -> point_s__seq [style=bold];
	params_polyline__seq:num_points_type -> params_polyline__seq:points__repeat [color="#404040"];
	record__seq:params_type -> record__seq_params_switch [style=bold];
	record__seq_params_switch:case0 -> params_setbkmode__seq [style=bold];
	record__seq_params_switch:case1 -> color_ref__seq [style=bold];
	record__seq_params_switch:case2 -> params_setrop2__seq [style=bold];
	record__seq_params_switch:case3 -> params_polyline__seq [style=bold];
	record__seq_params_switch:case4 -> params_setwindoworg__seq [style=bold];
	record__seq_params_switch:case5 -> params_polygon__seq [style=bold];
	record__seq_params_switch:case6 -> params_setwindowext__seq [style=bold];
	record__seq_params_switch:case7 -> params_setpolyfillmode__seq [style=bold];
	record__seq:function_type -> record__seq:params_type [color="#404040"];
}