jan_flanders

Untitled

Dec 17th, 2012
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 34.34 KB | None | 0 0
  1. open Swf
  2.  
  3. (* DATA *)
  4.  
  5. type header = {
  6.     hd_major_version : int;
  7.     hd_minor_version : int;
  8.     hd_num_tables : int;
  9.     hd_search_range : int;
  10.     hd_entry_selector : int;
  11.     hd_range_shift : int;
  12. }
  13.  
  14. type entry = {
  15.     entry_table_name : string;
  16.     entry_checksum : int32;
  17.     entry_offset : int32;
  18.     entry_length: int32;
  19. }
  20.  
  21. (* GLYF *)
  22.  
  23. type glyf_header = {
  24.     gh_num_contours : int;
  25.     gh_xmin : int;
  26.     gh_ymin : int;
  27.     gh_xmax : int;
  28.     gh_ymax : int;
  29. }
  30.  
  31. type glyf_simple = {
  32.     gs_end_pts_of_contours : int array;
  33.     gs_instruction_length : int;
  34.     gs_instructions : char array;
  35.     gs_flags : int array;
  36.     gs_x_coordinates : int array;
  37.     gs_y_coordinates : int array;
  38. }
  39.  
  40. type transformation_option =
  41.     | Scale of float
  42.     | ScaleXY of float * float
  43.     | ScaleMatrix of float * float * float * float
  44.  
  45. type glyf_component = {
  46.     gc_flags : int;
  47.     gc_glyf_index : int;
  48.     gc_arg1 : int;
  49.     gc_arg2 : int;
  50.     gc_transformations : transformation_option list;
  51. }
  52.  
  53. type glyf_def =
  54.     | TglyfSimple of glyf_simple
  55.     | TglyfComposite of glyf_component list
  56.  
  57. type glyf = {
  58.     glyf_header : glyf_header;
  59.     glyf_def : glyf_def;
  60. }
  61.  
  62. (* HMTX *)
  63.  
  64. type hmtx = {
  65.     advance_width : int;
  66.     left_side_bearing : int;
  67. }
  68.  
  69. (* CMAP *)
  70.  
  71. type cmap_subtable_header = {
  72.     csh_platform_id : int;
  73.     csh_platform_specific_id : int;
  74.     csh_offset : int32;
  75. }
  76.  
  77. type cmap_format_0 = {
  78.     c0_format : int;
  79.     c0_length : int;
  80.     c0_language : int;
  81.     c0_glyph_index_array : char array;
  82. }
  83.  
  84. type cmap_format_4 = {
  85.     c4_format : int;
  86.     c4_length : int;
  87.     c4_language : int;
  88.     c4_seg_count_x2 : int;
  89.     c4_search_range : int;
  90.     c4_entry_selector : int;
  91.     c4_range_shift : int;
  92.     c4_end_code : int array;
  93.     c4_reserved_pad : int;
  94.     c4_start_code : int array;
  95.     c4_id_delta : int array;
  96.     c4_id_range_offset : int array;
  97.     c4_glyph_index_array : int array;
  98. }
  99.  
  100. type cmap_format_6 = {
  101.     c6_format : int;
  102.     c6_length : int;
  103.     c6_language : int;
  104.     c6_first_code : int;
  105.     c6_entry_count : int;
  106.     c6_glyph_index_array : int array;
  107. }
  108.  
  109. type cmap_subtable_def =
  110.     | Cmap0 of cmap_format_0
  111.     | Cmap4 of cmap_format_4
  112.     | Cmap6 of cmap_format_6
  113.     | CmapUnk of string
  114.  
  115. type cmap_subtable = {
  116.     cs_header : cmap_subtable_header;
  117.     cs_def : cmap_subtable_def;
  118. }
  119.  
  120. type cmap = {
  121.     cmap_version : int;
  122.     cmap_num_subtables : int;
  123.     cmap_subtables : cmap_subtable list;
  124. }
  125.  
  126. (* KERN *)
  127.  
  128. type kern_subtable_header = {
  129.     ksh_length : int32;
  130.     ksh_coverage : int;
  131.     ksh_tuple_index : int;
  132. }
  133.  
  134. type kern_pair = {
  135.     left : int;
  136.     right : int;
  137.     value : int;
  138. }
  139.  
  140. type kern_format_0 = {
  141.     k0_num_pairs : int;
  142.     k0_search_range : int;
  143.     k0_entry_selector : int;
  144.     k0_range_shift : int;
  145.     k0_pairs : kern_pair list;
  146. }
  147.  
  148. type kern_format_2 = {
  149.     k2_row_width : int;
  150.     k2_left_offset_table : int;
  151.     k2_right_offset_table : int;
  152.     k2_array : int;
  153.     k2_first_glyph : int;
  154.     k2_num_glyphs : int;
  155.     k2_offsets : int list;
  156. }
  157.  
  158. type kern_subtable_def =
  159.     | Kern0 of kern_format_0
  160.     | Kern2 of kern_format_2
  161.  
  162. type kern_subtable = {
  163.     ks_header : kern_subtable_header;
  164.     ks_def : kern_subtable_def;
  165. }
  166.  
  167. type kern = {
  168.     kern_version : int32;
  169.     kern_num_tables : int32;
  170.     kern_subtables : kern_subtable list;
  171. }
  172.  
  173. (* NAME *)
  174.  
  175. type name_record = {
  176.     nr_platform_id : int;
  177.     nr_platform_specific_id : int;
  178.     nr_language_id : int;
  179.     nr_name_id : int;
  180.     nr_length : int;
  181.     nr_offset : int;
  182.     mutable nr_value : string;
  183. }
  184.  
  185. type name = {
  186.     name_format : int;
  187.     name_num_records : int;
  188.     name_offset : int;
  189.     name_records : name_record array;
  190. }
  191.  
  192. (* HEAD *)
  193.  
  194. type head = {
  195.     hd_version : int32;
  196.     hd_font_revision : int32;
  197.     hd_checksum_adjustment : int32;
  198.     hd_magic_number : int32;
  199.     hd_flags : int;
  200.     hd_units_per_em : int;
  201.     hd_created : float;
  202.     hd_modified : float;
  203.     hd_xmin : int;
  204.     hd_ymin : int;
  205.     hd_xmax : int;
  206.     hd_ymax : int;
  207.     hd_mac_style : int;
  208.     hd_lowest_rec_ppem : int;
  209.     hd_font_direction_hint : int;
  210.     hd_index_to_loc_format : int;
  211.     hd_glyph_data_format : int;
  212. }
  213.  
  214. (* HHEA *)
  215.  
  216. type hhea = {
  217.     hhea_version : int32;
  218.     hhea_ascent : int;
  219.     hhea_descent : int;
  220.     hhea_line_gap : int;
  221.     hhea_advance_width_max : int;
  222.     hhea_min_left_side_bearing : int;
  223.     hhea_min_right_side_bearing : int;
  224.     hhea_x_max_extent : int;
  225.     hhea_caret_slope_rise : int;
  226.     hhea_caret_slope_run : int;
  227.     hhea_caret_offset : int;
  228.     hhea_reserved : string;
  229.     hhea_metric_data_format : int;
  230.     hhea_number_of_hmetrics :int;
  231. }
  232.  
  233. (* LOCA *)
  234.  
  235. type loca = int32 array
  236.  
  237. (* MAXP *)
  238.  
  239. type maxp = {
  240.     maxp_version_number : int32;
  241.     maxp_num_glyphs : int;
  242.     maxp_max_points : int;
  243.     maxp_max_contours : int;
  244.     maxp_max_component_points : int;
  245.     maxp_max_component_contours : int;
  246.     maxp_max_zones : int;
  247.     maxp_max_twilight_points : int;
  248.     maxp_max_storage : int;
  249.     maxp_max_function_defs : int;
  250.     maxp_max_instruction_defs :int;
  251.     maxp_max_stack_elements : int;
  252.     maxp_max_size_of_instructions :int;
  253.     maxp_max_component_elements :int;
  254.     maxp_max_component_depth :int;
  255. }
  256.  
  257. (* OS2 *)
  258.  
  259. type os2 = {
  260.     os2_version : int;
  261.     os2_x_avg_char_width : int;
  262.     os2_us_weight_class : int;
  263.     os2_us_width_class : int;
  264.     os2_fs_type : int;
  265.     os2_y_subscript_x_size : int;
  266.     os2_y_subscript_y_size : int;
  267.     os2_y_subscript_x_offset : int;
  268.     os2_y_subscript_y_offset : int;
  269.     os2_y_superscript_x_size : int;
  270.     os2_y_superscript_y_size : int;
  271.     os2_y_superscript_x_offset : int;
  272.     os2_y_superscript_y_offset : int;
  273.     os2_y_strikeout_size : int;
  274.     os2_y_strikeout_position : int;
  275.     os2_s_family_class : int;
  276.     os2_b_family_type : int;
  277.     os2_b_serif_style : int;
  278.     os2_b_weight : int;
  279.     os2_b_proportion : int;
  280.     os2_b_contrast : int;
  281.     os2_b_stroke_variation : int;
  282.     os2_b_arm_style : int;
  283.     os2_b_letterform : int;
  284.     os2_b_midline : int;
  285.     os2_b_x_height : int;
  286.     os2_ul_unicode_range_1 : int32;
  287.     os2_ul_unicode_range_2 : int32;
  288.     os2_ul_unicode_range_3 : int32;
  289.     os2_ul_unicode_range_4 : int32;
  290.     os2_ach_vendor_id : int32;
  291.     os2_fs_selection : int;
  292.     os2_us_first_char_index : int;
  293.     os2_us_last_char_index : int;
  294.     os2_s_typo_ascender : int;
  295.     os2_s_typo_descender : int;
  296.     os2_us_win_ascent : int;
  297.     os2_us_win_descent : int;
  298. }
  299.  
  300. type table =
  301.     | TGlyf of glyf array
  302.     | THmtx of hmtx list
  303.     | TCmap of cmap
  304.     | TKern of kern
  305.     | TName of name
  306.     | THead of head
  307.     | THhea of hhea
  308.     | TLoca of loca
  309.     | TMaxp of maxp
  310.     | TOS2 of os2
  311.     | TUnk of string
  312.  
  313. type ttf = {
  314.     ttf_header : header;
  315.     ttf_name : string;
  316.     ttf_directory: (string,entry) Hashtbl.t;
  317.     ttf_tables : (string * table) list;
  318. }
  319.  
  320. type ctx = {
  321.     file : in_channel;
  322.     ch : IO.input;
  323.     mutable entry : entry;
  324. }
  325.  
  326. let rd16 = IO.BigEndian.read_i16
  327. let rdu16 = IO.BigEndian.read_ui16
  328. let rd32 = IO.BigEndian.read_i32
  329. let rd32r = IO.BigEndian.read_real_i32
  330. let rdd = IO.BigEndian.read_double
  331. let rbti ch = int_of_char (IO.read ch)
  332. let ti32 = Int32.of_int
  333. let ti = Int32.to_int
  334.  
  335. (* PARSING *)
  336.  
  337. let parse_header ctx =
  338.     let ch = ctx.ch in
  339.     let major_version = rdu16 ch in
  340.     let minor_version = rdu16 ch in
  341.     let num_tables = rdu16 ch in
  342.     let search_range = rdu16 ch in
  343.     let entry_selector = rdu16 ch in
  344.     let range_shift = rdu16 ch in
  345.     {
  346.         hd_major_version = major_version;
  347.         hd_minor_version = minor_version;
  348.         hd_num_tables = num_tables;
  349.         hd_search_range = search_range;
  350.         hd_entry_selector = entry_selector;
  351.         hd_range_shift = range_shift;
  352.     }
  353.  
  354. let parse_directory ctx header =
  355.     let ch = ctx.ch in
  356.     let directory = Hashtbl.create 0 in
  357.     for i = 0 to header.hd_num_tables - 1 do
  358.         let name = IO.nread ch 4 in
  359.         let cs = rd32r ch in
  360.         let off = rd32r ch in
  361.         let length = rd32r ch in
  362.         Hashtbl.add directory name {
  363.             entry_table_name = name;
  364.             entry_checksum = cs;
  365.             entry_offset = off;
  366.             entry_length = length;
  367.         }
  368.     done;
  369.     directory
  370.  
  371. let parse_head_table ctx =
  372.     let ch = ctx.ch in
  373.     let version = rd32r ch in
  374.     let font_revision = rd32r ch in
  375.     let checksum_adjustment = rd32r ch in
  376.     let magic_number = rd32r ch in
  377.     let flags = rdu16 ch in
  378.     let units_per_em = rdu16 ch in
  379.     let created = rdd ch in
  380.     let modified = rdd ch in
  381.     let xmin = rd16 ch in
  382.     let ymin = rd16 ch in
  383.     let xmax = rd16 ch in
  384.     let ymax = rd16 ch in
  385.     let mac_style = rdu16 ch in
  386.     let lowest_rec_ppem = rdu16 ch in
  387.     let font_direction_hint = rd16 ch in
  388.     let index_to_loc_format = rd16 ch in
  389.     let glyph_data_format = rd16 ch in
  390.     {
  391.         hd_version = version;
  392.         hd_font_revision = font_revision;
  393.         hd_checksum_adjustment = checksum_adjustment;
  394.         hd_magic_number = magic_number;
  395.         hd_flags = flags;
  396.         hd_units_per_em = units_per_em;
  397.         hd_created = created;
  398.         hd_modified = modified;
  399.         hd_xmin = xmin;
  400.         hd_ymin = ymin;
  401.         hd_xmax = xmax;
  402.         hd_ymax = ymax;
  403.         hd_mac_style = mac_style;
  404.         hd_lowest_rec_ppem = lowest_rec_ppem;
  405.         hd_font_direction_hint = font_direction_hint;
  406.         hd_index_to_loc_format = index_to_loc_format;
  407.         hd_glyph_data_format = glyph_data_format;
  408.     }
  409.  
  410. let parse_hhea_table ctx =
  411.     let ch = ctx.ch in
  412.     let version = rd32r ch in
  413.     let ascender = rd16 ch in
  414.     let descender = rd16 ch in
  415.     let line_gap = rd16 ch in
  416.     let advance_width_max = rdu16 ch in
  417.     let min_left_side_bearing = rd16 ch in
  418.     let min_right_side_bearing = rd16 ch in
  419.     let x_max_extent = rd16 ch in
  420.     let caret_slope_rise = rd16 ch in
  421.     let caret_slope_run = rd16 ch in
  422.     let caret_offset = rd16 ch in
  423.     let reserved = IO.nread ch 8 in
  424.     let metric_data_format = rd16 ch in
  425.     let number_of_hmetrics = rdu16 ch in
  426.     {
  427.         hhea_version = version;
  428.         hhea_ascent = ascender;
  429.         hhea_descent = descender;
  430.         hhea_line_gap = line_gap;
  431.         hhea_advance_width_max = advance_width_max;
  432.         hhea_min_left_side_bearing = min_left_side_bearing;
  433.         hhea_min_right_side_bearing = min_right_side_bearing;
  434.         hhea_x_max_extent = x_max_extent;
  435.         hhea_caret_slope_rise = caret_slope_rise;
  436.         hhea_caret_slope_run = caret_slope_run;
  437.         hhea_caret_offset = caret_offset;
  438.         hhea_reserved = reserved;
  439.         hhea_metric_data_format = metric_data_format;
  440.         hhea_number_of_hmetrics = number_of_hmetrics;
  441.     }
  442.  
  443. let parse_maxp_table ctx =
  444.     let ch = ctx.ch in
  445.     let version_number = rd32r ch in
  446.     let num_glyphs = rdu16 ch in
  447.     let max_points = rdu16 ch in
  448.     let max_contours = rdu16 ch in
  449.     let max_component_points = rdu16 ch in
  450.     let max_component_contours = rdu16 ch in
  451.     let max_zones = rdu16 ch in
  452.     let max_twilight_points = rdu16 ch in
  453.     let max_storage = rdu16 ch in
  454.     let max_function_defs = rdu16 ch in
  455.     let max_instruction_defs = rdu16 ch in
  456.     let max_stack_elements = rdu16 ch in
  457.     let max_size_of_instructions = rdu16 ch in
  458.     let max_component_elements = rdu16 ch in
  459.     let max_component_depth = rdu16 ch in
  460.     {
  461.         maxp_version_number = version_number;
  462.         maxp_num_glyphs = num_glyphs;
  463.         maxp_max_points = max_points;
  464.         maxp_max_contours = max_contours;
  465.         maxp_max_component_points = max_component_points;
  466.         maxp_max_component_contours = max_component_contours;
  467.         maxp_max_zones = max_zones;
  468.         maxp_max_twilight_points = max_twilight_points;
  469.         maxp_max_storage = max_storage;
  470.         maxp_max_function_defs = max_function_defs;
  471.         maxp_max_instruction_defs = max_instruction_defs;
  472.         maxp_max_stack_elements = max_stack_elements;
  473.         maxp_max_size_of_instructions = max_size_of_instructions;
  474.         maxp_max_component_elements = max_component_elements;
  475.         maxp_max_component_depth = max_component_depth;
  476.     }
  477.  
  478. let parse_loca_table head maxp ctx =
  479.     let ch = ctx.ch in
  480.     if head.hd_index_to_loc_format = 0 then
  481.         Array.init (maxp.maxp_num_glyphs + 1) (fun _ -> ti32 ((rdu16 ch) * 2))
  482.     else
  483.         Array.init (maxp.maxp_num_glyphs + 1) (fun _ -> rd32r ch)
  484.  
  485. let parse_hmtx_table maxp hhea ctx =
  486.     let ch = ctx.ch in
  487.     let last_advance_width = ref 0 in
  488.     ExtList.List.init maxp.maxp_num_glyphs (fun i ->
  489.         let advance_width = if i > hhea.hhea_number_of_hmetrics then
  490.             !last_advance_width
  491.         else
  492.             rdu16 ch
  493.         in
  494.         last_advance_width := advance_width;
  495.         let left_side_bearing = rd16 ch in
  496.         {
  497.             advance_width = advance_width;
  498.             left_side_bearing = left_side_bearing;
  499.         }
  500.     )
  501.  
  502. let parse_cmap_table ctx =
  503.     let ch = ctx.ch in
  504.     let version = rdu16 ch in
  505.     let num_subtables = rdu16 ch in
  506.     let dir = ExtList.List.init num_subtables (fun _ ->
  507.         let platform_id = rdu16 ch in
  508.         let platform_specific_id = rdu16 ch in
  509.         let offset = rd32r ch in
  510.         {
  511.             csh_platform_id = platform_id;
  512.             csh_platform_specific_id = platform_specific_id;
  513.             csh_offset = offset;
  514.         }
  515.     ) in
  516.     let parse_sub entry =
  517.         seek_in ctx.file ((ti ctx.entry.entry_offset) + (ti entry.csh_offset));
  518.         let format = rdu16 ch in
  519.         let length = rdu16 ch in
  520.         let language = rdu16 ch in
  521.         let def = match format with
  522.             | 0 ->
  523.                 let glyph_index = Array.init 256 (fun _ -> IO.read ch) in
  524.                 Cmap0 {
  525.                     c0_format = 0;
  526.                     c0_length = length;
  527.                     c0_language = language;
  528.                     c0_glyph_index_array = glyph_index;
  529.                 }
  530.             | 4 ->
  531.                 let seg_count_x2 = rdu16 ch in
  532.                 let seg_count = seg_count_x2 / 2 in
  533.                 let search_range = rdu16 ch in
  534.                 let entry_selector = rdu16 ch in
  535.                 let range_shift = rdu16 ch in
  536.                 let end_code = Array.init seg_count (fun _ -> rdu16 ch) in
  537.                 let reserved = rdu16 ch in
  538.                 assert (reserved = 0);
  539.                 let start_code = Array.init seg_count (fun _ -> rdu16 ch) in
  540.                 let id_delta = Array.init seg_count (fun _ -> rdu16 ch) in
  541.                 let id_range_offset = Array.init seg_count (fun _ -> rdu16 ch) in
  542.                 let count = length - (8 * seg_count + 16) / 2 in
  543.                 let glyph_index = Array.init count (fun _ -> rdu16 ch) in
  544.                 (* TODO: whatever Reader.hx does here *)
  545.                 Cmap4 {
  546.                     c4_format = format;
  547.                     c4_length = length;
  548.                     c4_language = language;
  549.                     c4_seg_count_x2 = seg_count;
  550.                     c4_search_range = search_range;
  551.                     c4_entry_selector = entry_selector;
  552.                     c4_range_shift = range_shift;
  553.                     c4_end_code = end_code;
  554.                     c4_reserved_pad = reserved;
  555.                     c4_start_code = start_code;
  556.                     c4_id_delta = id_delta;
  557.                     c4_id_range_offset = id_range_offset;
  558.                     c4_glyph_index_array = glyph_index;
  559.                 }
  560.             | 6 ->
  561.                 let first_code = rdu16 ch in
  562.                 let entry_count = rdu16 ch in
  563.                 let glyph_index = Array.init entry_count (fun _ -> rdu16 ch) in
  564.                 Cmap6 {
  565.                     c6_format = format;
  566.                     c6_length = length;
  567.                     c6_language = language;
  568.                     c6_first_code = first_code;
  569.                     c6_entry_count = entry_count;
  570.                     c6_glyph_index_array = glyph_index;
  571.                 }
  572.             | x ->
  573.                 failwith ("Not implemented format: " ^ (string_of_int x));
  574.         in
  575.         {
  576.             cs_def = def;
  577.             cs_header = entry;
  578.         }
  579.  
  580.     in
  581.     {
  582.         cmap_version = version;
  583.         cmap_num_subtables = num_subtables;
  584.         cmap_subtables = List.rev_map parse_sub dir;
  585.     }
  586.  
  587. let parse_glyf_table maxp loca cmap hmtx ctx =
  588.     let ch = ctx.ch in
  589.     let parse_glyf i =
  590.         seek_in ctx.file ((ti ctx.entry.entry_offset) + (ti loca.(i)));
  591.         let num_contours = rd16 ch in
  592.         let xmin = rd16 ch in
  593.         let ymin = rd16 ch in
  594.         let xmax = rd16 ch in
  595.         let ymax = rd16 ch in
  596.         let header = {
  597.             gh_num_contours = num_contours;
  598.             gh_xmin = xmin;
  599.             gh_ymin = ymin;
  600.             gh_xmax = xmax;
  601.             gh_ymax = ymax;
  602.         } in
  603.         let def = if num_contours >= 0 then begin
  604.             let num_points = ref 0 in
  605.             let end_pts_of_contours = Array.init num_contours (fun i ->
  606.                 let v = rdu16 ch in
  607.                 if i = num_contours - 1 then num_points := v + 1;
  608.                 v
  609.             ) in
  610.             let instruction_length = rdu16 ch in
  611.             let instructions = Array.init instruction_length (fun _ ->
  612.                 IO.read ch
  613.             ) in
  614.             let flags = DynArray.create () in
  615.             let rec loop index =
  616.                 if index >= !num_points then () else begin
  617.                     let v = rbti ch in
  618.                     let incr = if (v land 8) == 0 then begin
  619.                         DynArray.add flags v;
  620.                         1
  621.                     end else begin
  622.                         let r = (int_of_char (IO.read ch)) in
  623.                         for i = 0 to r - 1 do DynArray.add flags v done;
  624.                         r
  625.                     end in
  626.                     loop (index + incr)
  627.                 end
  628.             in
  629.             loop 0;
  630.             let x_coordinates = Array.init !num_points (fun i ->
  631.                 let flag = DynArray.get flags i in
  632.                 if flag land 0x10 <> 0 then begin
  633.                     if flag land 0x02 <> 0 then rbti ch
  634.                     else 0
  635.                 end else begin
  636.                     if flag land 0x02 <> 0 then -rbti ch
  637.                     else rd16 ch
  638.                 end;
  639.             ) in
  640.             let y_coordinates = Array.init !num_points (fun i ->
  641.                 let flag = DynArray.get flags i in
  642.                 if flag land 0x20 <> 0 then begin
  643.                     if flag land 0x04 <> 0 then rbti ch
  644.                     else 0
  645.                 end else begin
  646.                     if flag land 0x04 <> 0 then -rbti ch
  647.                     else rd16 ch
  648.                 end;
  649.             ) in
  650.             TglyfSimple {
  651.                 gs_end_pts_of_contours = end_pts_of_contours;
  652.                 gs_instruction_length = instruction_length;
  653.                 gs_instructions = instructions;
  654.                 gs_flags = DynArray.to_array flags;
  655.                 gs_x_coordinates = x_coordinates;
  656.                 gs_y_coordinates = y_coordinates;
  657.             }
  658.         end else if num_contours = -1 then begin
  659.             let acc = DynArray.create () in
  660.             let rec loop () =
  661.                 let flags = rdu16 ch in
  662.                 let glyph_index = rdu16 ch in
  663.                 let arg1,arg2 = if flags land 1 <> 0 then begin
  664.                     let arg1 = rd16 ch in
  665.                     let arg2 = rd16 ch in
  666.                     arg1,arg2
  667.                 end else begin
  668.                     let arg1 = rbti ch in
  669.                     let arg2 = rbti ch in
  670.                     arg1,arg2
  671.                 end in
  672.                 let fmt214 i = (float_of_int i) /. (float_of_int 0x4000) in
  673.                 let tmodes = DynArray.create () in
  674.                 if flags land 8 <> 0 then DynArray.add tmodes (Scale (fmt214 (rd16 ch)));
  675.                 if flags land 64 <> 0 then begin
  676.                     let s1 = fmt214 (rd16 ch) in
  677.                     let s2 = fmt214 (rd16 ch) in
  678.                     DynArray.add tmodes (ScaleXY (s1,s2))
  679.                 end;
  680.                 if flags land 128 <> 0 then begin
  681.                     let a = fmt214 (rd16 ch) in
  682.                     let b = fmt214 (rd16 ch) in
  683.                     let c = fmt214 (rd16 ch) in
  684.                     let d = fmt214 (rd16 ch) in
  685.                     DynArray.add tmodes (ScaleMatrix (a,b,c,d))
  686.                 end;
  687.                 DynArray.add acc {
  688.                     gc_flags = flags;
  689.                     gc_glyf_index = glyph_index;
  690.                     gc_arg1 = arg1;
  691.                     gc_arg2 = arg2;
  692.                     gc_transformations = DynArray.to_list tmodes;
  693.                 }
  694.             in
  695.             loop ();
  696.             TglyfComposite (DynArray.to_list acc)
  697.         end else
  698.             failwith "Unknown Glyf"
  699.         in
  700.         {
  701.             glyf_header = header;
  702.             glyf_def = def;
  703.         }
  704.     in
  705.     Array.init maxp.maxp_num_glyphs (fun i -> parse_glyf i)
  706.  
  707. let parse_kern_table ctx =
  708.     let ch = ctx.ch in
  709.     let version = ti32 (rd16 ch) in
  710.     let num_tables = ti32 (rd16 ch) in
  711.     let tables = ExtList.List.init (ti num_tables) (fun _ ->
  712.         let length = ti32 (rdu16 ch) in
  713.         let tuple_index = rdu16 ch in
  714.         let coverage = rdu16 ch in
  715.         let def = match coverage lsr 8 with
  716.         | 0 ->
  717.             let num_pairs = rdu16 ch in
  718.             let search_range = rdu16 ch in
  719.             let entry_selector = rdu16 ch in
  720.             let range_shift = rdu16 ch in
  721.             let kerning_pairs = ExtList.List.init num_pairs (fun _ ->
  722.                 let left = rdu16 ch in
  723.                 let right = rdu16 ch in
  724.                 let value = rd16 ch in
  725.                 {
  726.                     left = left;
  727.                     right = right;
  728.                     value = value;
  729.                 }
  730.             ) in
  731.             Kern0 {
  732.                 k0_num_pairs = num_pairs;
  733.                 k0_search_range = search_range;
  734.                 k0_entry_selector = entry_selector;
  735.                 k0_range_shift = range_shift;
  736.                 k0_pairs = kerning_pairs;
  737.             }
  738.         | 2 ->
  739.             let row_width = rdu16 ch in
  740.             let left_offset_table = rdu16 ch in
  741.             let right_offset_table = rdu16 ch in
  742.             let array_offset = rdu16 ch in
  743.             let first_glyph = rdu16 ch in
  744.             let num_glyphs = rdu16 ch in
  745.             let offsets = ExtList.List.init num_glyphs (fun _ ->
  746.                 rdu16 ch
  747.             ) in
  748.             Kern2 {
  749.                 k2_row_width = row_width;
  750.                 k2_left_offset_table = left_offset_table;
  751.                 k2_right_offset_table = right_offset_table;
  752.                 k2_array = array_offset;
  753.                 k2_first_glyph = first_glyph;
  754.                 k2_num_glyphs = num_glyphs;
  755.                 k2_offsets = offsets;
  756.             }
  757.         | i ->
  758.             failwith ("Unknown kerning: " ^ (string_of_int i));
  759.         in
  760.         {
  761.             ks_def = def;
  762.             ks_header = {
  763.                 ksh_length = length;
  764.                 ksh_coverage = coverage;
  765.                 ksh_tuple_index = tuple_index;
  766.             }
  767.         }
  768.     ) in
  769.     {
  770.         kern_version = version;
  771.         kern_num_tables = num_tables;
  772.         kern_subtables = tables;
  773.     }
  774.  
  775. let parse_name_table ctx =
  776.     let ch = ctx.ch in
  777.     let format = rdu16 ch in
  778.     let num_records = rdu16 ch in
  779.     let offset = rdu16 ch in
  780.     let records = Array.init num_records (fun _ ->
  781.         let platform_id = rdu16 ch in
  782.         let platform_specific_id = rdu16 ch in
  783.         let language_id = rdu16 ch in
  784.         let name_id = rdu16 ch in
  785.         let length = rdu16 ch in
  786.         let offset = rdu16 ch in
  787.         {
  788.             nr_platform_id = platform_id;
  789.             nr_platform_specific_id = platform_specific_id;
  790.             nr_language_id = language_id;
  791.             nr_name_id = name_id;
  792.             nr_length = length;
  793.             nr_offset = offset;
  794.             nr_value = "";
  795.         }
  796.     ) in
  797.     let ttf_name = ref "" in
  798.     let records = Array.map (fun r ->
  799.         seek_in ctx.file ((ti ctx.entry.entry_offset) + offset + r.nr_offset);
  800.         r.nr_value <- IO.nread ch r.nr_length;
  801.         if r.nr_name_id = 4 && r.nr_platform_id = 3 || r.nr_platform_id = 0 then ttf_name := r.nr_value;
  802.         r
  803.     ) records in
  804.     {
  805.         name_format = format;
  806.         name_num_records = num_records;
  807.         name_offset = offset;
  808.         name_records = records;
  809.     },!ttf_name
  810.  
  811. let parse_os2_table ctx =
  812.     let ch = ctx.ch in
  813.     let version = rdu16 ch in
  814.     let x_avg_char_width = rd16 ch in
  815.     let us_weight_class = rdu16 ch in
  816.     let us_width_class = rdu16 ch in
  817.     let fs_type = rd16 ch in
  818.     let y_subscript_x_size = rd16 ch in
  819.     let y_subscript_y_size = rd16 ch in
  820.     let y_subscript_x_offset = rd16 ch in
  821.     let y_subscript_y_offset = rd16 ch in
  822.     let y_superscript_x_size = rd16 ch in
  823.     let y_superscript_y_size = rd16 ch in
  824.     let y_superscript_x_offset = rd16 ch in
  825.     let y_superscript_y_offset = rd16 ch in
  826.     let y_strikeout_size = rd16 ch in
  827.     let y_strikeout_position = rd16 ch in
  828.     let s_family_class = rd16 ch in
  829.     let b_family_type = rbti ch in
  830.     let b_serif_style = rbti ch in
  831.     let b_weight = rbti ch in
  832.     let b_proportion = rbti ch in
  833.     let b_contrast = rbti ch in
  834.     let b_stroke_variation = rbti ch in
  835.     let b_arm_style = rbti ch in
  836.     let b_letterform = rbti ch in
  837.     let b_midline = rbti ch in
  838.     let b_x_height = rbti ch in
  839.     let ul_unicode_range_1 = rd32r ch in
  840.     let ul_unicode_range_2 = rd32r ch in
  841.     let ul_unicode_range_3 = rd32r ch in
  842.     let ul_unicode_range_4 = rd32r ch in
  843.     let ach_vendor_id = rd32r ch in
  844.     let fs_selection = rd16 ch in
  845.     let us_first_char_index = rdu16 ch in
  846.     let us_last_char_index = rdu16 ch in
  847.     let s_typo_ascender = rd16 ch in
  848.     let s_typo_descender = rd16 ch in
  849.     let us_win_ascent = rdu16 ch in
  850.     let us_win_descent = rdu16 ch in
  851.     {
  852.         os2_version = version;
  853.         os2_x_avg_char_width = x_avg_char_width;
  854.         os2_us_weight_class = us_weight_class;
  855.         os2_us_width_class = us_width_class;
  856.         os2_fs_type = fs_type;
  857.         os2_y_subscript_x_size = y_subscript_x_size;
  858.         os2_y_subscript_y_size = y_subscript_y_size;
  859.         os2_y_subscript_x_offset = y_subscript_x_offset;
  860.         os2_y_subscript_y_offset = y_subscript_y_offset;
  861.         os2_y_superscript_x_size = y_superscript_x_size;
  862.         os2_y_superscript_y_size = y_superscript_y_size;
  863.         os2_y_superscript_x_offset = y_superscript_x_offset;
  864.         os2_y_superscript_y_offset = y_superscript_y_offset;
  865.         os2_y_strikeout_size = y_strikeout_size;
  866.         os2_y_strikeout_position = y_strikeout_position;
  867.         os2_s_family_class = s_family_class;
  868.         os2_b_family_type = b_family_type;
  869.         os2_b_serif_style = b_serif_style;
  870.         os2_b_weight = b_weight;
  871.         os2_b_proportion = b_proportion;
  872.         os2_b_contrast = b_contrast;
  873.         os2_b_stroke_variation = b_stroke_variation;
  874.         os2_b_arm_style = b_arm_style;
  875.         os2_b_letterform = b_letterform;
  876.         os2_b_midline = b_midline;
  877.         os2_b_x_height = b_x_height;
  878.         os2_ul_unicode_range_1 = ul_unicode_range_1;
  879.         os2_ul_unicode_range_2 = ul_unicode_range_2;
  880.         os2_ul_unicode_range_3 = ul_unicode_range_3;
  881.         os2_ul_unicode_range_4 = ul_unicode_range_4;
  882.         os2_ach_vendor_id = ach_vendor_id;
  883.         os2_fs_selection = fs_selection;
  884.         os2_us_first_char_index = us_first_char_index;
  885.         os2_us_last_char_index = us_last_char_index;
  886.         os2_s_typo_ascender = s_typo_ascender;
  887.         os2_s_typo_descender = s_typo_descender;
  888.         os2_us_win_ascent = us_win_ascent;
  889.         os2_us_win_descent = us_win_descent;
  890.     }
  891.  
  892. let parse file : ttf =
  893.     let ctx = {
  894.         file = file;
  895.         ch = IO.input_channel file;
  896.         entry = {
  897.             entry_table_name = "";
  898.             entry_offset = ti32 0;
  899.             entry_length = ti32 0;
  900.             entry_checksum = ti32 0;
  901.         }
  902.     } in
  903.     let header = parse_header ctx in
  904.     let directory = parse_directory ctx header in
  905.     let parse_table entry f =
  906.         seek_in file (ti entry.entry_offset);
  907.         ctx.entry <- entry;
  908.         f ctx
  909.     in
  910.     let head = parse_table (Hashtbl.find directory "head") parse_head_table in
  911.     let hhea = parse_table (Hashtbl.find directory "hhea") parse_hhea_table in
  912.     let maxp = parse_table (Hashtbl.find directory "maxp") parse_maxp_table in
  913.     let loca = parse_table (Hashtbl.find directory "loca") (parse_loca_table head maxp) in
  914.     let hmtx = parse_table (Hashtbl.find directory "hmtx") (parse_hmtx_table maxp hhea) in
  915.     let cmap = parse_table (Hashtbl.find directory "cmap") (parse_cmap_table) in
  916.     let glyf = parse_table (Hashtbl.find directory "glyf") (parse_glyf_table maxp loca cmap hmtx) in
  917.     (* let kern = parse_table (Hashtbl.find directory "kern") (parse_kern_table) in *)
  918.     let name,ttf_name = parse_table (Hashtbl.find directory "name") (parse_name_table) in
  919.     let os2 = parse_table (Hashtbl.find directory "OS/2") (parse_os2_table) in
  920.     let tables = ("head", (THead head)) :: ("hhea", (THhea hhea)) :: ("maxp", (TMaxp maxp))
  921.               :: ("loca", (TLoca loca)) :: ("hmtx", (THmtx hmtx)) :: ("cmap", (TCmap cmap))
  922.               :: ("glyf", (TGlyf glyf)) :: ("name", (TName name))
  923.               :: ("OS/2", (TOS2 os2)) :: []
  924.     in
  925.     {
  926.         ttf_header = header;
  927.         ttf_name = ttf_name;
  928.         ttf_directory = directory;
  929.         ttf_tables = tables;
  930.     }
  931.  
  932. (* WRITING *)
  933.  
  934. (* TODO: move this to swf.ml *)
  935.  
  936. type font_language_code =
  937.     | LCNone (*0*)
  938.     | LCLatin (*1*)
  939.     | LCJapanese (*2*)
  940.     | LCKorean (*3*)
  941.     | LCSimplifiedChinese (*4*)
  942.     | LCTraditionalChinese (*5*)
  943.  
  944. type font_glyph_data = {
  945.     font_char_code: int;
  946.     font_shape: shape_records;
  947. }
  948.  
  949. type font_layout_glyph_data = {
  950.     font_advance: int;
  951.     font_bounds: rect;
  952. }
  953.  
  954. type font_kerning_data = {
  955.     font_char_code1: int;
  956.     font_char_code2: int;
  957.     font_adjust: int;
  958. }
  959.  
  960. type font_layout_data = {
  961.     font_ascent: int;
  962.     font_descent: int;
  963.     font_leading: int;
  964.     font_glyphs: font_layout_glyph_data list;
  965.     font_kerning: font_kerning_data list;
  966. }
  967.  
  968. type font2_data = {
  969.     font_shift_jis: bool;
  970.     font_is_small: bool;
  971.     font_is_ansi: bool;
  972.     font_is_italic: bool;
  973.     font_is_bold: bool;
  974.     font_language: font_language_code;
  975.     font_name: string;
  976.     font_glyphs: font_glyph_data array;
  977.     font_layout: font_layout_data option;
  978. }
  979.  
  980. (* This can stay *)
  981.  
  982. type write_ctx = {
  983.     head : head;
  984.     cmap : cmap;
  985.     glyf : glyf array;
  986. }
  987.  
  988. type glyf_path = {
  989.     gp_type : int;
  990.     gp_x : float;
  991.     gp_y : float;
  992.     gp_cx : float;
  993.     gp_cy : float;
  994. }
  995.  
  996. let mk_path t x y cx cy = {
  997.     gp_type = t;
  998.     gp_x = x;
  999.     gp_y = y;
  1000.     gp_cx = cx;
  1001.     gp_cy = cy;
  1002. }
  1003.  
  1004. let make_path ctx pq p1 p2 arr g =
  1005.     let p1_on_curve = g.gs_flags.(p1) land 0x01 <> 0 in
  1006.     let p2_on_curve = g.gs_flags.(p2) land 0x01 <> 0 in
  1007.     match p1_on_curve, p2_on_curve with
  1008.     | true, true ->
  1009.         let path = mk_path 1 (float_of_int g.gs_x_coordinates.(p2)) (float_of_int g.gs_y_coordinates.(p2)) 0.0 0.0 in
  1010.         DynArray.add arr path;
  1011.     | false, false ->
  1012.         let path = mk_path 2 !pq.gp_x !pq.gp_y (float_of_int g.gs_x_coordinates.(p1)) (float_of_int g.gs_y_coordinates.(p1)) in
  1013.         DynArray.add arr path;
  1014.         pq := (mk_path (-1) (float_of_int g.gs_x_coordinates.(p2)) (float_of_int g.gs_y_coordinates.(p2)) 0.0 0.0)
  1015.     | true, false ->
  1016.         pq := (mk_path (-1) (float_of_int g.gs_x_coordinates.(p2)) (float_of_int g.gs_y_coordinates.(p2)) 0.0 0.0)
  1017.     | false, true ->
  1018.         let path = mk_path 2 (float_of_int g.gs_x_coordinates.(p2)) (float_of_int g.gs_y_coordinates.(p2)) !pq.gp_x !pq.gp_y in
  1019.         DynArray.add arr path
  1020.  
  1021. let build_paths ctx g =
  1022.     let len = Array.length g.gs_end_pts_of_contours in
  1023.     let arr = DynArray.create () in
  1024.     let cp = ref 0 in
  1025.     let start = ref 0 in
  1026.     let stop = ref 0 in
  1027.     let pq = ref (mk_path (-1) 0.0 0.0 0.0 0.0) in
  1028.     for i = 0 to len - 1 do
  1029.         start := !cp;
  1030.         stop := g.gs_end_pts_of_contours.(i);
  1031.         let path = mk_path 0 (float_of_int g.gs_x_coordinates.(!start)) (float_of_int g.gs_y_coordinates.(!start)) 0.0 0.0 in
  1032.         DynArray.add arr path;
  1033.         for j = 0 to !stop - !start - 1 do
  1034.             make_path ctx pq !cp (!cp + 1) arr g;
  1035.             incr cp;
  1036.         done;
  1037.         make_path ctx pq !stop !start arr g;
  1038.         incr cp;
  1039.     done;
  1040.     DynArray.to_list arr
  1041.  
  1042. let begin_fill ctx c a =
  1043.     SRStyleChange {
  1044.         scsr_move = None;
  1045.         scsr_fs0 = None;
  1046.         scsr_fs1 = Some(1); (* Some (c lor (a lsl 24));*) (* CHECK *)
  1047.         scsr_ls = None; (* CHECK *)
  1048.         scsr_new_styles = None;
  1049.     }
  1050.  
  1051. let move_to ctx x y =
  1052.     SRStyleChange {
  1053.         scsr_move = Some (0,int_of_float x, int_of_float y); (* TODO *)
  1054.         scsr_fs0 = None;
  1055.         scsr_fs1 = None; (* TODO *)
  1056.         scsr_ls = None;
  1057.         scsr_new_styles = None;
  1058.     }
  1059.  
  1060. let line_to ctx x y =
  1061.     SRStraightEdge {
  1062.         sser_nbits = max (SwfParser._nbits (abs(int_of_float x))) (SwfParser._nbits (abs(int_of_float y))); (* TODO ? *)
  1063.         sser_line = Some (int_of_float x), Some (int_of_float y);
  1064.     }
  1065.  
  1066. let curve_to ctx cx cy x y =
  1067.     SRCurvedEdge {
  1068.         scer_nbits = 2 + (max
  1069.             (max (SwfParser._nbits (abs(int_of_float x))) (SwfParser._nbits (abs(int_of_float y))))
  1070.             (max (SwfParser._nbits (abs(int_of_float cx))) (SwfParser._nbits (abs(int_of_float cy))))); (* TODO ? *)
  1071.         scer_cx = int_of_float cx;
  1072.         scer_cy = int_of_float cy;
  1073.         scer_ax = int_of_float x;
  1074.         scer_ay = int_of_float y;
  1075.     }
  1076.  
  1077. let write_paths ctx paths =
  1078.     let scale = 100. /. (float_of_int ctx.head.hd_units_per_em) in
  1079.     let srl = DynArray.create () in
  1080.     DynArray.add srl (begin_fill ctx 0 1);
  1081.     List.iter (fun path ->
  1082.         DynArray.add srl (match path.gp_type with
  1083.         | 0 -> move_to ctx (path.gp_x *. scale) ((-1.) *. path.gp_y *. scale);
  1084.         | 1 -> line_to ctx (path.gp_x *. scale) ((-1.) *. path.gp_y *. scale);
  1085.         | 2 -> curve_to ctx (path.gp_cx *. scale) ((-1.) *. path.gp_cy *. scale) (path.gp_x *. scale) ((-1.) *. path.gp_y *. scale);
  1086.         | _ -> assert false)
  1087.     ) paths;
  1088.     {
  1089.         srs_nfbits = 2; (* TODO *)
  1090.         srs_nlbits = 0; (* TODO *)
  1091.         srs_records = DynArray.to_list srl;
  1092.     }
  1093.  
  1094. let write_glyph ctx glyf =
  1095.     match glyf.glyf_def with
  1096.     | TglyfSimple g ->
  1097.         let path = build_paths ctx g in
  1098.         {
  1099.             font_char_code = 0; (* TODO *)
  1100.             font_shape = write_paths ctx path;
  1101.         }
  1102.     | TglyfComposite g ->
  1103.         {
  1104.             font_char_code = 0; (* TODO *)
  1105.             font_shape = write_paths ctx []; (* TODO *)
  1106.         }
  1107.  
  1108. let map_char_code cc c4 =
  1109.     (* TODO: well yeah... *)
  1110.     0
  1111.  
  1112. let make_cmap4_map ctx c4 =
  1113.     let lut = Hashtbl.create 0 in
  1114.     let seg_count = c4.c4_seg_count_x2 / 2 in
  1115.     for i = 0 to seg_count - 1 do
  1116.         for j = c4.c4_start_code.(i) to c4.c4_end_code.(i) do
  1117.             let index = map_char_code j c4 in
  1118.             Hashtbl.add lut j index
  1119.         done;
  1120.     done;
  1121.     lut
  1122.  
  1123. let bi v = if v then 1 else 0
  1124.  
  1125. let write_font2 ch b f2 =
  1126.     IO.write_byte ch 255; (* 48 DefineFont 1/2 *)
  1127.     IO.write_byte ch 18; (* 48 DefineFont 2/2 *)
  1128.     IO.write_i32 ch 16777215; (* TODO: tag body size/length *)
  1129.     IO.write_ui16 ch 1; (*TODO: Char id *)
  1130.    
  1131.     IO.write_bits b 1 (bi (f2.font_layout <> None));
  1132.     IO.write_bits b 1 (bi f2.font_shift_jis);
  1133.     IO.write_bits b 1 (bi f2.font_is_small);
  1134.     IO.write_bits b 1 (bi f2.font_is_ansi);
  1135.     IO.write_bits b 1 (bi false); (* TODO: wide offsets *)
  1136.     IO.write_bits b 1 (bi true); (* TODO: wide codes *)
  1137.     IO.write_bits b 1 (bi f2.font_is_italic);
  1138.     IO.write_bits b 1 (bi f2.font_is_bold);
  1139.    
  1140.     IO.write_byte ch 0; (* TODO: f2.font_language; LCNone *)
  1141.    
  1142.     IO.write_byte ch (String.length f2.font_name);
  1143.     IO.nwrite ch f2.font_name;
  1144.     IO.write_ui16 ch (Array.length f2.font_glyphs); (* numglyps *)
  1145.     Array.iter (fun _ -> IO.write_ui16 ch 0) f2.font_glyphs; (* TODO: offsetTable *)
  1146.     IO.write_ui16 ch (2 * Array.length f2.font_glyphs); (* TODO: offset to codeTable depends on 16 or 32 bit *)
  1147.    
  1148.     Array.iter (fun g ->
  1149.         (* let b = IO.output_bits ch in *)
  1150.         print_string "===========================================================================\n";
  1151.         let nlbits = ref g.font_shape.srs_nlbits in
  1152.         let nfbits = ref g.font_shape.srs_nfbits in
  1153.         List.iter (fun r ->
  1154.             match r with
  1155.             | SRStyleChange s ->
  1156.                 print_string "SRStyleChange\n";
  1157.                 (match s.scsr_move with
  1158.                 |None -> ();
  1159.                     print_string "s.scsr_move 0: 0"; print_string "\n";
  1160.                     print_string "s.scsr_move x: 0"; print_string "\n";
  1161.                     print_string "s.scsr_move y: 0"; print_string "\n\n";
  1162.                 |Some (w , x, y) ->
  1163.                     print_string "s.scsr_move 0: "; print_int w; print_string "\n";
  1164.                     print_string "s.scsr_move x: "; print_int x; print_string "\n";
  1165.                     print_string "s.scsr_move y: "; print_int y; print_string "\n\n";);
  1166.             | SRStraightEdge s->
  1167.                 print_string "SRStraightEdge\n";
  1168.                 print_string "s.sser_nbits: "; print_int s.sser_nbits; print_string "\n";
  1169.                 (match s.sser_line with
  1170.                 |None, None ->
  1171.                     print_string "s.sser_line x: None";
  1172.                     print_string "s.sser_line y: None\n\n";
  1173.                 |Some (x), None ->
  1174.                     print_string "s.sser_line x: "; print_int x; print_string "\n";
  1175.                     print_string "s.sser_line y: None\n\n";
  1176.                 |None, Some (y) ->
  1177.                     print_string "s.sser_line x: None\n";  
  1178.                     print_string "s.sser_line y: "; print_int y; print_string "\n\n";
  1179.                 |Some (x), Some (y) ->
  1180.                     print_string "s.sser_line x: "; print_int x; print_string "\n";
  1181.                     print_string "s.sser_line y: "; print_int y; print_string "\n\n";);
  1182.             | SRCurvedEdge s ->
  1183.                 print_string "SRCurvedEdge\n";
  1184.                 print_string "s.scer_nbits: "; print_int s.scer_nbits; print_string "\n";
  1185.                 print_string "s.scer_cx: "; print_int s.scer_cx; print_string "\n";
  1186.                 print_string "s.scer_cy: "; print_int s.scer_cy; print_string "\n";
  1187.                 print_string "s.scer_ax: "; print_int s.scer_ax; print_string "\n";
  1188.                 print_string "s.scer_ay: "; print_int s.scer_ay; print_string "\n\n";
  1189.  
  1190.             (* try *)
  1191.                 SwfParser.write_shape_record ch b nlbits nfbits r;
  1192.             (* with _ -> print_string "----------^^ FAILURE!"; print_string "\n\n"; *)
  1193.            
  1194.         ) g.font_shape.srs_records
  1195.     ) f2.font_glyphs
  1196.     (* TODO: rest *)
  1197.  
  1198. let write_swf ttf range_str =
  1199.     let ctx = {
  1200.         head = (match List.assoc "head" ttf.ttf_tables with THead head -> head | _ -> assert false);
  1201.         cmap = (match List.assoc "cmap" ttf.ttf_tables with TCmap cmap -> cmap | _ -> assert false);
  1202.         glyf = (match List.assoc "glyf" ttf.ttf_tables with TGlyf glyf -> glyf | _ -> assert false);
  1203.     } in
  1204.     let rec loop cl = match cl with
  1205.         | [] -> failwith "Cmap4 table not found"
  1206.         | {cs_def = Cmap4 c4} :: _ ->
  1207.             make_cmap4_map ctx c4
  1208.         | _ :: cl ->
  1209.             loop cl
  1210.     in
  1211.     let glyph_lut = loop ctx.cmap.cmap_subtables in
  1212.     ignore(glyph_lut);
  1213.     (* TODO: check range, perform lookup *)
  1214.     {
  1215.         font_shift_jis = false;
  1216.         font_is_small = false;
  1217.         font_is_ansi = false;
  1218.         font_is_italic = false;
  1219.         font_is_bold = false;
  1220.         font_language = LCNone;
  1221.         font_name = "chopin"; (* ttf.ttf_name; *)
  1222.         font_glyphs = Array.map (write_glyph ctx) ctx.glyf;
  1223.         font_layout = None;
  1224.     }
  1225. ;;
  1226. let f2 = write_swf (parse (open_in_bin "chopin.ttf")) "" in
  1227. let ch = (IO.output_channel (open_out_bin "chopin_test.dat")) in
  1228. let b = IO.output_bits ch in
  1229. write_font2 ch b f2
  1230.  
  1231. (* ocamlopt -I ../extlib -I ../extc enum.cmx extlist.cmx extstring.cmx io.cmx dynarray.cmx multiarray.cmx swf.cmx as3code.cmx as3parse.cmx actionscript.cmx swfparser.cmx ttf.ml -o run.exe *)
Advertisement
Add Comment
Please, Sign In to add comment