write_xlsx 1.12.1 → 1.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.rubocop.yml +12 -0
 - data/Changes +6 -0
 - data/LICENSE.txt +1 -1
 - data/examples/autofilter.rb +1 -2
 - data/examples/colors.rb +4 -4
 - data/examples/formats.rb +14 -14
 - data/lib/write_xlsx/chart/area.rb +1 -1
 - data/lib/write_xlsx/chart/axis.rb +4 -4
 - data/lib/write_xlsx/chart/bar.rb +1 -1
 - data/lib/write_xlsx/chart/caption.rb +8 -4
 - data/lib/write_xlsx/chart/column.rb +1 -1
 - data/lib/write_xlsx/chart/doughnut.rb +2 -2
 - data/lib/write_xlsx/chart/line.rb +1 -1
 - data/lib/write_xlsx/chart/pie.rb +2 -2
 - data/lib/write_xlsx/chart/radar.rb +1 -1
 - data/lib/write_xlsx/chart/scatter.rb +1 -1
 - data/lib/write_xlsx/chart/series.rb +10 -20
 - data/lib/write_xlsx/chart/stock.rb +1 -1
 - data/lib/write_xlsx/chart.rb +14 -21
 - data/lib/write_xlsx/chartsheet.rb +3 -3
 - data/lib/write_xlsx/drawing.rb +108 -114
 - data/lib/write_xlsx/format.rb +20 -24
 - data/lib/write_xlsx/image.rb +89 -0
 - data/lib/write_xlsx/image_property.rb +163 -0
 - data/lib/write_xlsx/inserted_chart.rb +42 -0
 - data/lib/write_xlsx/package/app.rb +1 -0
 - data/lib/write_xlsx/package/button.rb +58 -5
 - data/lib/write_xlsx/package/conditional_format.rb +4 -4
 - data/lib/write_xlsx/package/packager.rb +22 -27
 - data/lib/write_xlsx/package/rich_value.rb +1 -1
 - data/lib/write_xlsx/package/styles.rb +1 -1
 - data/lib/write_xlsx/package/vml.rb +10 -19
 - data/lib/write_xlsx/shape.rb +3 -2
 - data/lib/write_xlsx/sparkline.rb +1 -1
 - data/lib/write_xlsx/utility.rb +8 -203
 - data/lib/write_xlsx/version.rb +1 -1
 - data/lib/write_xlsx/workbook.rb +87 -175
 - data/lib/write_xlsx/worksheet/data_validation.rb +1 -1
 - data/lib/write_xlsx/worksheet/hyperlink.rb +2 -2
 - data/lib/write_xlsx/worksheet.rb +478 -484
 - data/lib/write_xlsx/zip_file_utils.rb +2 -2
 - data/write_xlsx.gemspec +3 -3
 - metadata +15 -9
 
    
        data/lib/write_xlsx/drawing.rb
    CHANGED
    
    | 
         @@ -6,8 +6,11 @@ require 'write_xlsx/utility' 
     | 
|
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            module Writexlsx
         
     | 
| 
       8 
8 
     | 
    
         
             
              class Drawing
         
     | 
| 
      
 9 
     | 
    
         
            +
                include Writexlsx::Utility
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       9 
11 
     | 
    
         
             
                attr_accessor :type, :dimensions, :width, :height, :shape, :anchor, :rel_index, :url_rel_index, :name, :description
         
     | 
| 
       10 
12 
     | 
    
         
             
                attr_reader :tip, :decorative
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_writer :writer, :embedded, :orientation
         
     | 
| 
       11 
14 
     | 
    
         | 
| 
       12 
15 
     | 
    
         
             
                def initialize(type, dimensions, width, height, shape, anchor, rel_index = nil, url_rel_index = nil, tip = nil, name = nil, description = nil, decorative = nil)
         
     | 
| 
       13 
16 
     | 
    
         
             
                  @type = type
         
     | 
| 
         @@ -23,93 +26,11 @@ module Writexlsx 
     | 
|
| 
       23 
26 
     | 
    
         
             
                  @description = description
         
     | 
| 
       24 
27 
     | 
    
         
             
                  @decorative = decorative
         
     | 
| 
       25 
28 
     | 
    
         
             
                end
         
     | 
| 
       26 
     | 
    
         
            -
              end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
              class Drawings
         
     | 
| 
       29 
     | 
    
         
            -
                include Writexlsx::Utility
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                attr_writer :embedded, :orientation
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                def initialize
         
     | 
| 
       34 
     | 
    
         
            -
                  @writer = Package::XMLWriterSimple.new
         
     | 
| 
       35 
     | 
    
         
            -
                  @drawings    = []
         
     | 
| 
       36 
     | 
    
         
            -
                  @embedded    = false
         
     | 
| 
       37 
     | 
    
         
            -
                  @orientation = false
         
     | 
| 
       38 
     | 
    
         
            -
                end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                def xml_str
         
     | 
| 
       41 
     | 
    
         
            -
                  @writer.string
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                def set_xml_writer(filename)
         
     | 
| 
       45 
     | 
    
         
            -
                  @writer.set_xml_writer(filename)
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                #
         
     | 
| 
       49 
     | 
    
         
            -
                # Assemble and write the XML file.
         
     | 
| 
       50 
     | 
    
         
            -
                #
         
     | 
| 
       51 
     | 
    
         
            -
                def assemble_xml_file
         
     | 
| 
       52 
     | 
    
         
            -
                  write_xml_declaration do
         
     | 
| 
       53 
     | 
    
         
            -
                    # Write the xdr:wsDr element.
         
     | 
| 
       54 
     | 
    
         
            -
                    write_drawing_workspace do
         
     | 
| 
       55 
     | 
    
         
            -
                      if @embedded
         
     | 
| 
       56 
     | 
    
         
            -
                        index = 0
         
     | 
| 
       57 
     | 
    
         
            -
                        @drawings.each do |drawing|
         
     | 
| 
       58 
     | 
    
         
            -
                          # Write the xdr:twoCellAnchor element.
         
     | 
| 
       59 
     | 
    
         
            -
                          index += 1
         
     | 
| 
       60 
     | 
    
         
            -
                          write_two_cell_anchor(index, drawing)
         
     | 
| 
       61 
     | 
    
         
            -
                        end
         
     | 
| 
       62 
     | 
    
         
            -
                      else
         
     | 
| 
       63 
     | 
    
         
            -
                        # Write the xdr:absoluteAnchor element.
         
     | 
| 
       64 
     | 
    
         
            -
                        write_absolute_anchor(1)
         
     | 
| 
       65 
     | 
    
         
            -
                      end
         
     | 
| 
       66 
     | 
    
         
            -
                    end
         
     | 
| 
       67 
     | 
    
         
            -
                  end
         
     | 
| 
       68 
     | 
    
         
            -
                end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                #
         
     | 
| 
       71 
     | 
    
         
            -
                # Add a chart, image or shape sub object to the drawing.
         
     | 
| 
       72 
     | 
    
         
            -
                #
         
     | 
| 
       73 
     | 
    
         
            -
                def add_drawing_object(drawing)
         
     | 
| 
       74 
     | 
    
         
            -
                  @drawings << drawing
         
     | 
| 
       75 
     | 
    
         
            -
                end
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                private
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                #
         
     | 
| 
       80 
     | 
    
         
            -
                # Write the <xdr:wsDr> element.
         
     | 
| 
       81 
     | 
    
         
            -
                #
         
     | 
| 
       82 
     | 
    
         
            -
                def write_drawing_workspace(&block)
         
     | 
| 
       83 
     | 
    
         
            -
                  schema = 'http://schemas.openxmlformats.org/drawingml/'
         
     | 
| 
       84 
     | 
    
         
            -
                  attributes = [
         
     | 
| 
       85 
     | 
    
         
            -
                    ['xmlns:xdr', "#{schema}2006/spreadsheetDrawing"],
         
     | 
| 
       86 
     | 
    
         
            -
                    ['xmlns:a',    "#{schema}2006/main"]
         
     | 
| 
       87 
     | 
    
         
            -
                  ]
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                  @writer.tag_elements('xdr:wsDr', attributes, &block)
         
     | 
| 
       90 
     | 
    
         
            -
                end
         
     | 
| 
       91 
29 
     | 
    
         | 
| 
       92 
30 
     | 
    
         
             
                #
         
     | 
| 
       93 
31 
     | 
    
         
             
                # Write the <xdr:twoCellAnchor> element.
         
     | 
| 
       94 
32 
     | 
    
         
             
                #
         
     | 
| 
       95 
     | 
    
         
            -
                def write_two_cell_anchor( 
     | 
| 
       96 
     | 
    
         
            -
                  index, drawing = args
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                  type          = drawing.type
         
     | 
| 
       99 
     | 
    
         
            -
                  width         = drawing.width
         
     | 
| 
       100 
     | 
    
         
            -
                  height        = drawing.height
         
     | 
| 
       101 
     | 
    
         
            -
                  shape         = drawing.shape
         
     | 
| 
       102 
     | 
    
         
            -
                  anchor        = drawing.anchor
         
     | 
| 
       103 
     | 
    
         
            -
                  rel_index     = drawing.rel_index
         
     | 
| 
       104 
     | 
    
         
            -
                  url_rel_index = drawing.url_rel_index
         
     | 
| 
       105 
     | 
    
         
            -
                  tip           = drawing.tip
         
     | 
| 
       106 
     | 
    
         
            -
                  name          = drawing.name
         
     | 
| 
       107 
     | 
    
         
            -
                  description   = drawing.description
         
     | 
| 
       108 
     | 
    
         
            -
                  decorative    = drawing.decorative
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                  col_from, row_from, col_from_offset, row_from_offset,
         
     | 
| 
       111 
     | 
    
         
            -
                  col_to, row_to, col_to_offset, row_to_offset, col_absolute, row_absolute = drawing.dimensions
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
      
 33 
     | 
    
         
            +
                def write_two_cell_anchor(index)
         
     | 
| 
       113 
34 
     | 
    
         
             
                  attributes      = []
         
     | 
| 
       114 
35 
     | 
    
         | 
| 
       115 
36 
     | 
    
         
             
                  # Add attribute for images.
         
     | 
| 
         @@ -124,9 +45,9 @@ module Writexlsx 
     | 
|
| 
       124 
45 
     | 
    
         | 
| 
       125 
46 
     | 
    
         
             
                  @writer.tag_elements('xdr:twoCellAnchor', attributes) do
         
     | 
| 
       126 
47 
     | 
    
         
             
                    # Write the xdr:from element.
         
     | 
| 
       127 
     | 
    
         
            -
                    write_from 
     | 
| 
      
 48 
     | 
    
         
            +
                    write_from
         
     | 
| 
       128 
49 
     | 
    
         
             
                    # Write the xdr:to element.
         
     | 
| 
       129 
     | 
    
         
            -
                    write_to 
     | 
| 
      
 50 
     | 
    
         
            +
                    write_to
         
     | 
| 
       130 
51 
     | 
    
         | 
| 
       131 
52 
     | 
    
         
             
                    if type == 1
         
     | 
| 
       132 
53 
     | 
    
         
             
                      # Graphic frame.
         
     | 
| 
         @@ -135,14 +56,10 @@ module Writexlsx 
     | 
|
| 
       135 
56 
     | 
    
         
             
                      write_graphic_frame(index, rel_index, name, description, decorative)
         
     | 
| 
       136 
57 
     | 
    
         
             
                    elsif type == 2
         
     | 
| 
       137 
58 
     | 
    
         
             
                      # Write the xdr:pic element.
         
     | 
| 
       138 
     | 
    
         
            -
                      write_pic(
         
     | 
| 
       139 
     | 
    
         
            -
                        index,        rel_index,      col_absolute,
         
     | 
| 
       140 
     | 
    
         
            -
                        row_absolute, width,          height,
         
     | 
| 
       141 
     | 
    
         
            -
                        description,  url_rel_index, tip, decorative
         
     | 
| 
       142 
     | 
    
         
            -
                      )
         
     | 
| 
      
 59 
     | 
    
         
            +
                      write_pic(index)
         
     | 
| 
       143 
60 
     | 
    
         
             
                    else
         
     | 
| 
       144 
61 
     | 
    
         
             
                      # Write the xdr:sp element for shapes.
         
     | 
| 
       145 
     | 
    
         
            -
                      write_sp(index,  
     | 
| 
      
 62 
     | 
    
         
            +
                      write_sp(index, shape)
         
     | 
| 
       146 
63 
     | 
    
         
             
                    end
         
     | 
| 
       147 
64 
     | 
    
         | 
| 
       148 
65 
     | 
    
         
             
                    # Write the xdr:clientData element.
         
     | 
| 
         @@ -182,7 +99,9 @@ module Writexlsx 
     | 
|
| 
       182 
99 
     | 
    
         
             
                #
         
     | 
| 
       183 
100 
     | 
    
         
             
                # Write the <xdr:from> element.
         
     | 
| 
       184 
101 
     | 
    
         
             
                #
         
     | 
| 
       185 
     | 
    
         
            -
                def write_from 
     | 
| 
      
 102 
     | 
    
         
            +
                def write_from
         
     | 
| 
      
 103 
     | 
    
         
            +
                  col, row, col_offset, row_offset = dimensions
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
       186 
105 
     | 
    
         
             
                  @writer.tag_elements('xdr:from') do
         
     | 
| 
       187 
106 
     | 
    
         
             
                    # Write the xdr:col element.
         
     | 
| 
       188 
107 
     | 
    
         
             
                    write_col(col)
         
     | 
| 
         @@ -198,7 +117,9 @@ module Writexlsx 
     | 
|
| 
       198 
117 
     | 
    
         
             
                #
         
     | 
| 
       199 
118 
     | 
    
         
             
                # Write the <xdr:to> element.
         
     | 
| 
       200 
119 
     | 
    
         
             
                #
         
     | 
| 
       201 
     | 
    
         
            -
                def write_to 
     | 
| 
      
 120 
     | 
    
         
            +
                def write_to
         
     | 
| 
      
 121 
     | 
    
         
            +
                  col, row, col_offset, row_offset = dimensions[4, 4]
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
       202 
123 
     | 
    
         
             
                  @writer.tag_elements('xdr:to') do
         
     | 
| 
       203 
124 
     | 
    
         
             
                    # Write the xdr:col element.
         
     | 
| 
       204 
125 
     | 
    
         
             
                    write_col(col)
         
     | 
| 
         @@ -290,7 +211,6 @@ module Writexlsx 
     | 
|
| 
       290 
211 
     | 
    
         
             
                def write_nv_graphic_frame_pr(
         
     | 
| 
       291 
212 
     | 
    
         
             
                      index, name = nil, description = nil, decorative = nil
         
     | 
| 
       292 
213 
     | 
    
         
             
                    )
         
     | 
| 
       293 
     | 
    
         
            -
             
     | 
| 
       294 
214 
     | 
    
         
             
                  name = "Chart #{index}" unless ptrue?(name)
         
     | 
| 
       295 
215 
     | 
    
         | 
| 
       296 
216 
     | 
    
         
             
                  @writer.tag_elements('xdr:nvGraphicFramePr') do
         
     | 
| 
         @@ -522,7 +442,7 @@ module Writexlsx 
     | 
|
| 
       522 
442 
     | 
    
         
             
                #
         
     | 
| 
       523 
443 
     | 
    
         
             
                # Write the <xdr:sp> element.
         
     | 
| 
       524 
444 
     | 
    
         
             
                #
         
     | 
| 
       525 
     | 
    
         
            -
                def write_sp(index,  
     | 
| 
      
 445 
     | 
    
         
            +
                def write_sp(index, shape)
         
     | 
| 
       526 
446 
     | 
    
         
             
                  if shape.connect == 0
         
     | 
| 
       527 
447 
     | 
    
         
             
                    # Add attribute for shapes.
         
     | 
| 
       528 
448 
     | 
    
         
             
                    attributes = [
         
     | 
| 
         @@ -534,7 +454,7 @@ module Writexlsx 
     | 
|
| 
       534 
454 
     | 
    
         
             
                      write_nv_sp_pr(index, shape)
         
     | 
| 
       535 
455 
     | 
    
         | 
| 
       536 
456 
     | 
    
         
             
                      # Write the xdr:spPr element.
         
     | 
| 
       537 
     | 
    
         
            -
                      write_xdr_sp_pr( 
     | 
| 
      
 457 
     | 
    
         
            +
                      write_xdr_sp_pr(shape)
         
     | 
| 
       538 
458 
     | 
    
         | 
| 
       539 
459 
     | 
    
         
             
                      # Write the xdr:txBody element.
         
     | 
| 
       540 
460 
     | 
    
         
             
                      write_tx_body(shape) if shape.text != 0
         
     | 
| 
         @@ -546,7 +466,7 @@ module Writexlsx 
     | 
|
| 
       546 
466 
     | 
    
         
             
                      write_nv_cxn_sp_pr(index, shape)
         
     | 
| 
       547 
467 
     | 
    
         | 
| 
       548 
468 
     | 
    
         
             
                      # Write the xdr:spPr element.
         
     | 
| 
       549 
     | 
    
         
            -
                      write_xdr_sp_pr( 
     | 
| 
      
 469 
     | 
    
         
            +
                      write_xdr_sp_pr(shape)
         
     | 
| 
       550 
470 
     | 
    
         
             
                    end
         
     | 
| 
       551 
471 
     | 
    
         
             
                  end
         
     | 
| 
       552 
472 
     | 
    
         
             
                end
         
     | 
| 
         @@ -601,26 +521,29 @@ module Writexlsx 
     | 
|
| 
       601 
521 
     | 
    
         
             
                #
         
     | 
| 
       602 
522 
     | 
    
         
             
                # Write the <xdr:pic> element.
         
     | 
| 
       603 
523 
     | 
    
         
             
                #
         
     | 
| 
       604 
     | 
    
         
            -
                def write_pic(index 
     | 
| 
      
 524 
     | 
    
         
            +
                def write_pic(index)
         
     | 
| 
      
 525 
     | 
    
         
            +
                  col_absolute, row_absolute = dimensions[8, 2]
         
     | 
| 
      
 526 
     | 
    
         
            +
             
     | 
| 
       605 
527 
     | 
    
         
             
                  @writer.tag_elements('xdr:pic') do
         
     | 
| 
       606 
528 
     | 
    
         
             
                    # Write the xdr:nvPicPr element.
         
     | 
| 
       607 
     | 
    
         
            -
                    write_nv_pic_pr(index 
     | 
| 
      
 529 
     | 
    
         
            +
                    write_nv_pic_pr(index)
         
     | 
| 
       608 
530 
     | 
    
         
             
                    # Write the xdr:blipFill element.
         
     | 
| 
       609 
     | 
    
         
            -
                    write_blip_fill 
     | 
| 
      
 531 
     | 
    
         
            +
                    write_blip_fill
         
     | 
| 
       610 
532 
     | 
    
         | 
| 
       611 
533 
     | 
    
         
             
                    # Pictures are rectangle shapes by default.
         
     | 
| 
       612 
     | 
    
         
            -
                     
     | 
| 
       613 
     | 
    
         
            -
                     
     | 
| 
      
 534 
     | 
    
         
            +
                    pic_shape = Shape.new
         
     | 
| 
      
 535 
     | 
    
         
            +
                    pic_shape.type = 'rect'
         
     | 
| 
       614 
536 
     | 
    
         | 
| 
       615 
537 
     | 
    
         
             
                    # Write the xdr:spPr element.
         
     | 
| 
       616 
     | 
    
         
            -
                    write_sp_pr( 
     | 
| 
      
 538 
     | 
    
         
            +
                    write_sp_pr(pic_shape)
         
     | 
| 
       617 
539 
     | 
    
         
             
                  end
         
     | 
| 
       618 
540 
     | 
    
         
             
                end
         
     | 
| 
       619 
541 
     | 
    
         | 
| 
       620 
542 
     | 
    
         
             
                #
         
     | 
| 
       621 
543 
     | 
    
         
             
                # Write the <xdr:nvPicPr> element.
         
     | 
| 
       622 
544 
     | 
    
         
             
                #
         
     | 
| 
       623 
     | 
    
         
            -
                def write_nv_pic_pr(index, _rel_index, description, url_rel_index, tip, decorative)
         
     | 
| 
      
 545 
     | 
    
         
            +
                # def write_nv_pic_pr(index, _rel_index, description, url_rel_index, tip, decorative)
         
     | 
| 
      
 546 
     | 
    
         
            +
                def write_nv_pic_pr(index)
         
     | 
| 
       624 
547 
     | 
    
         
             
                  @writer.tag_elements('xdr:nvPicPr') do
         
     | 
| 
       625 
548 
     | 
    
         
             
                    # Write the xdr:cNvPr element.
         
     | 
| 
       626 
549 
     | 
    
         
             
                    write_c_nv_pr(
         
     | 
| 
         @@ -656,10 +579,10 @@ module Writexlsx 
     | 
|
| 
       656 
579 
     | 
    
         
             
                #
         
     | 
| 
       657 
580 
     | 
    
         
             
                # Write the <xdr:blipFill> element.
         
     | 
| 
       658 
581 
     | 
    
         
             
                #
         
     | 
| 
       659 
     | 
    
         
            -
                def write_blip_fill 
     | 
| 
      
 582 
     | 
    
         
            +
                def write_blip_fill
         
     | 
| 
       660 
583 
     | 
    
         
             
                  @writer.tag_elements('xdr:blipFill') do
         
     | 
| 
       661 
584 
     | 
    
         
             
                    # Write the a:blip element.
         
     | 
| 
       662 
     | 
    
         
            -
                    write_a_blip( 
     | 
| 
      
 585 
     | 
    
         
            +
                    write_a_blip(rel_index)
         
     | 
| 
       663 
586 
     | 
    
         
             
                    # Write the a:stretch element.
         
     | 
| 
       664 
587 
     | 
    
         
             
                    write_a_stretch
         
     | 
| 
       665 
588 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -701,10 +624,10 @@ module Writexlsx 
     | 
|
| 
       701 
624 
     | 
    
         
             
                #
         
     | 
| 
       702 
625 
     | 
    
         
             
                # Write the <xdr:spPr> element, for charts.
         
     | 
| 
       703 
626 
     | 
    
         
             
                #
         
     | 
| 
       704 
     | 
    
         
            -
                def write_sp_pr( 
     | 
| 
      
 627 
     | 
    
         
            +
                def write_sp_pr(shape)
         
     | 
| 
       705 
628 
     | 
    
         
             
                  @writer.tag_elements('xdr:spPr') do
         
     | 
| 
       706 
629 
     | 
    
         
             
                    # Write the a:xfrm element.
         
     | 
| 
       707 
     | 
    
         
            -
                    write_a_xfrm 
     | 
| 
      
 630 
     | 
    
         
            +
                    write_a_xfrm
         
     | 
| 
       708 
631 
     | 
    
         
             
                    # Write the a:prstGeom element.
         
     | 
| 
       709 
632 
     | 
    
         
             
                    write_a_prst_geom(shape)
         
     | 
| 
       710 
633 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -713,12 +636,12 @@ module Writexlsx 
     | 
|
| 
       713 
636 
     | 
    
         
             
                #
         
     | 
| 
       714 
637 
     | 
    
         
             
                # Write the <xdr:spPr> element for shapes.
         
     | 
| 
       715 
638 
     | 
    
         
             
                #
         
     | 
| 
       716 
     | 
    
         
            -
                def write_xdr_sp_pr( 
     | 
| 
      
 639 
     | 
    
         
            +
                def write_xdr_sp_pr(shape)
         
     | 
| 
       717 
640 
     | 
    
         
             
                  attributes = [%w[bwMode auto]]
         
     | 
| 
       718 
641 
     | 
    
         | 
| 
       719 
642 
     | 
    
         
             
                  @writer.tag_elements('xdr:spPr', attributes) do
         
     | 
| 
       720 
643 
     | 
    
         
             
                    # Write the a:xfrm element.
         
     | 
| 
       721 
     | 
    
         
            -
                    write_a_xfrm( 
     | 
| 
      
 644 
     | 
    
         
            +
                    write_a_xfrm(shape)
         
     | 
| 
       722 
645 
     | 
    
         | 
| 
       723 
646 
     | 
    
         
             
                    # Write the a:prstGeom element.
         
     | 
| 
       724 
647 
     | 
    
         
             
                    write_a_prst_geom(shape)
         
     | 
| 
         @@ -738,7 +661,7 @@ module Writexlsx 
     | 
|
| 
       738 
661 
     | 
    
         
             
                #
         
     | 
| 
       739 
662 
     | 
    
         
             
                # Write the <a:xfrm> element.
         
     | 
| 
       740 
663 
     | 
    
         
             
                #
         
     | 
| 
       741 
     | 
    
         
            -
                def write_a_xfrm( 
     | 
| 
      
 664 
     | 
    
         
            +
                def write_a_xfrm(shape = nil)
         
     | 
| 
       742 
665 
     | 
    
         
             
                  attributes = []
         
     | 
| 
       743 
666 
     | 
    
         | 
| 
       744 
667 
     | 
    
         
             
                  rotation = shape ? shape.rotation : 0
         
     | 
| 
         @@ -750,7 +673,7 @@ module Writexlsx 
     | 
|
| 
       750 
673 
     | 
    
         | 
| 
       751 
674 
     | 
    
         
             
                  @writer.tag_elements('a:xfrm', attributes) do
         
     | 
| 
       752 
675 
     | 
    
         
             
                    # Write the a:off element.
         
     | 
| 
       753 
     | 
    
         
            -
                    write_a_off 
     | 
| 
      
 676 
     | 
    
         
            +
                    write_a_off
         
     | 
| 
       754 
677 
     | 
    
         
             
                    # Write the a:ext element.
         
     | 
| 
       755 
678 
     | 
    
         
             
                    write_a_ext(width, height)
         
     | 
| 
       756 
679 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -759,7 +682,9 @@ module Writexlsx 
     | 
|
| 
       759 
682 
     | 
    
         
             
                #
         
     | 
| 
       760 
683 
     | 
    
         
             
                # Write the <a:off> element.
         
     | 
| 
       761 
684 
     | 
    
         
             
                #
         
     | 
| 
       762 
     | 
    
         
            -
                def write_a_off 
     | 
| 
      
 685 
     | 
    
         
            +
                def write_a_off
         
     | 
| 
      
 686 
     | 
    
         
            +
                  x, y = dimensions[8, 2]
         
     | 
| 
      
 687 
     | 
    
         
            +
             
     | 
| 
       763 
688 
     | 
    
         
             
                  attributes = [
         
     | 
| 
       764 
689 
     | 
    
         
             
                    ['x', x],
         
     | 
| 
       765 
690 
     | 
    
         
             
                    ['y', y]
         
     | 
| 
         @@ -923,7 +848,7 @@ module Writexlsx 
     | 
|
| 
       923 
848 
     | 
    
         
             
                        @writer.tag_elements('a:rPr', attributes) do
         
     | 
| 
       924 
849 
     | 
    
         
             
                          color = shape.format[:color]
         
     | 
| 
       925 
850 
     | 
    
         
             
                          if color
         
     | 
| 
       926 
     | 
    
         
            -
                            color = shape. 
     | 
| 
      
 851 
     | 
    
         
            +
                            color = shape.palette_color_from_index(color)
         
     | 
| 
       927 
852 
     | 
    
         
             
                            color = color.sub(/^FF/, '')  # Remove leading FF from rgb for shape color.
         
     | 
| 
       928 
853 
     | 
    
         
             
                          else
         
     | 
| 
       929 
854 
     | 
    
         
             
                            color = '000000'
         
     | 
| 
         @@ -944,4 +869,73 @@ module Writexlsx 
     | 
|
| 
       944 
869 
     | 
    
         
             
                  end
         
     | 
| 
       945 
870 
     | 
    
         
             
                end
         
     | 
| 
       946 
871 
     | 
    
         
             
              end
         
     | 
| 
      
 872 
     | 
    
         
            +
             
     | 
| 
      
 873 
     | 
    
         
            +
              class Drawings
         
     | 
| 
      
 874 
     | 
    
         
            +
                include Writexlsx::Utility
         
     | 
| 
      
 875 
     | 
    
         
            +
             
     | 
| 
      
 876 
     | 
    
         
            +
                attr_writer :embedded, :orientation
         
     | 
| 
      
 877 
     | 
    
         
            +
             
     | 
| 
      
 878 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 879 
     | 
    
         
            +
                  @writer = Package::XMLWriterSimple.new
         
     | 
| 
      
 880 
     | 
    
         
            +
                  @drawings    = []
         
     | 
| 
      
 881 
     | 
    
         
            +
                  @embedded    = false
         
     | 
| 
      
 882 
     | 
    
         
            +
                  @orientation = false
         
     | 
| 
      
 883 
     | 
    
         
            +
                end
         
     | 
| 
      
 884 
     | 
    
         
            +
             
     | 
| 
      
 885 
     | 
    
         
            +
                def xml_str
         
     | 
| 
      
 886 
     | 
    
         
            +
                  @writer.string
         
     | 
| 
      
 887 
     | 
    
         
            +
                end
         
     | 
| 
      
 888 
     | 
    
         
            +
             
     | 
| 
      
 889 
     | 
    
         
            +
                def set_xml_writer(filename)
         
     | 
| 
      
 890 
     | 
    
         
            +
                  @writer.set_xml_writer(filename)
         
     | 
| 
      
 891 
     | 
    
         
            +
                end
         
     | 
| 
      
 892 
     | 
    
         
            +
             
     | 
| 
      
 893 
     | 
    
         
            +
                #
         
     | 
| 
      
 894 
     | 
    
         
            +
                # Assemble and write the XML file.
         
     | 
| 
      
 895 
     | 
    
         
            +
                #
         
     | 
| 
      
 896 
     | 
    
         
            +
                def assemble_xml_file
         
     | 
| 
      
 897 
     | 
    
         
            +
                  write_xml_declaration do
         
     | 
| 
      
 898 
     | 
    
         
            +
                    # Write the xdr:wsDr element.
         
     | 
| 
      
 899 
     | 
    
         
            +
                    write_drawing_workspace do
         
     | 
| 
      
 900 
     | 
    
         
            +
                      if @embedded
         
     | 
| 
      
 901 
     | 
    
         
            +
                        @drawings.each_with_index do |drawing, index|
         
     | 
| 
      
 902 
     | 
    
         
            +
                          # Write the xdr:twoCellAnchor element.
         
     | 
| 
      
 903 
     | 
    
         
            +
                          drawing.writer = @writer
         
     | 
| 
      
 904 
     | 
    
         
            +
                          drawing.embedded = @embedded
         
     | 
| 
      
 905 
     | 
    
         
            +
                          drawing.write_two_cell_anchor(index + 1)
         
     | 
| 
      
 906 
     | 
    
         
            +
                        end
         
     | 
| 
      
 907 
     | 
    
         
            +
                      else
         
     | 
| 
      
 908 
     | 
    
         
            +
                        # Write the xdr:absoluteAnchor element.
         
     | 
| 
      
 909 
     | 
    
         
            +
                        drawing = Drawing.new(nil, nil, nil, nil, nil, nil)
         
     | 
| 
      
 910 
     | 
    
         
            +
                        drawing.writer = @writer
         
     | 
| 
      
 911 
     | 
    
         
            +
                        drawing.embedded = @embedded
         
     | 
| 
      
 912 
     | 
    
         
            +
                        drawing.orientation = @orientation
         
     | 
| 
      
 913 
     | 
    
         
            +
                        drawing.write_absolute_anchor(1)
         
     | 
| 
      
 914 
     | 
    
         
            +
                      end
         
     | 
| 
      
 915 
     | 
    
         
            +
                    end
         
     | 
| 
      
 916 
     | 
    
         
            +
                  end
         
     | 
| 
      
 917 
     | 
    
         
            +
                end
         
     | 
| 
      
 918 
     | 
    
         
            +
             
     | 
| 
      
 919 
     | 
    
         
            +
                #
         
     | 
| 
      
 920 
     | 
    
         
            +
                # Add a chart, image or shape sub object to the drawing.
         
     | 
| 
      
 921 
     | 
    
         
            +
                #
         
     | 
| 
      
 922 
     | 
    
         
            +
                def add_drawing_object(drawing)
         
     | 
| 
      
 923 
     | 
    
         
            +
                  @drawings << drawing
         
     | 
| 
      
 924 
     | 
    
         
            +
                end
         
     | 
| 
      
 925 
     | 
    
         
            +
             
     | 
| 
      
 926 
     | 
    
         
            +
                private
         
     | 
| 
      
 927 
     | 
    
         
            +
             
     | 
| 
      
 928 
     | 
    
         
            +
                #
         
     | 
| 
      
 929 
     | 
    
         
            +
                # Write the <xdr:wsDr> element.
         
     | 
| 
      
 930 
     | 
    
         
            +
                #
         
     | 
| 
      
 931 
     | 
    
         
            +
                def write_drawing_workspace(&block)
         
     | 
| 
      
 932 
     | 
    
         
            +
                  schema = 'http://schemas.openxmlformats.org/drawingml/'
         
     | 
| 
      
 933 
     | 
    
         
            +
                  attributes = [
         
     | 
| 
      
 934 
     | 
    
         
            +
                    ['xmlns:xdr', "#{schema}2006/spreadsheetDrawing"],
         
     | 
| 
      
 935 
     | 
    
         
            +
                    ['xmlns:a',    "#{schema}2006/main"]
         
     | 
| 
      
 936 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 937 
     | 
    
         
            +
             
     | 
| 
      
 938 
     | 
    
         
            +
                  @writer.tag_elements('xdr:wsDr', attributes, &block)
         
     | 
| 
      
 939 
     | 
    
         
            +
                end
         
     | 
| 
      
 940 
     | 
    
         
            +
              end
         
     | 
| 
       947 
941 
     | 
    
         
             
            end
         
     | 
    
        data/lib/write_xlsx/format.rb
    CHANGED
    
    | 
         @@ -9,10 +9,10 @@ module Writexlsx 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                attr_reader :xf_index, :dxf_index, :num_format                                                 # :nodoc:
         
     | 
| 
       11 
11 
     | 
    
         
             
                attr_reader :underline, :font_script, :size, :theme, :font, :font_family, :hyperlink, :xf_id   # :nodoc:
         
     | 
| 
       12 
     | 
    
         
            -
                attr_reader :diag_type, :diag_color, :font_only, :color_indexed 
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :diag_type, :diag_color, :font_only, :color_indexed                                # :nodoc:
         
     | 
| 
       13 
13 
     | 
    
         
             
                attr_reader :left, :left_color, :right, :right_color, :top, :top_color, :bottom, :bottom_color # :nodoc:
         
     | 
| 
       14 
14 
     | 
    
         
             
                attr_reader :font_scheme                                                                       # :nodoc:
         
     | 
| 
       15 
     | 
    
         
            -
                attr_accessor :quote_prefix, :num_format_index, :border_index, :font_index 
     | 
| 
      
 15 
     | 
    
         
            +
                attr_accessor :quote_prefix, :num_format_index, :border_index, :font_index                     # :nodoc:
         
     | 
| 
       16 
16 
     | 
    
         
             
                attr_accessor :fill_index, :font_condense, :font_extend, :diag_border                          # :nodoc:
         
     | 
| 
       17 
17 
     | 
    
         
             
                attr_accessor :bg_color, :fg_color, :pattern                                                   # :nodoc:
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
         @@ -166,7 +166,7 @@ module Writexlsx 
     | 
|
| 
       166 
166 
     | 
    
         
             
                  align << %w[horizontal right]       if @text_h_align == 3
         
     | 
| 
       167 
167 
     | 
    
         
             
                  align << %w[horizontal fill]        if @text_h_align == 4
         
     | 
| 
       168 
168 
     | 
    
         
             
                  align << %w[horizontal justify]     if @text_h_align == 5
         
     | 
| 
       169 
     | 
    
         
            -
                  align << ['horizontal', continuous] 
     | 
| 
      
 169 
     | 
    
         
            +
                  align << ['horizontal', continuous] if @text_h_align == 6
         
     | 
| 
       170 
170 
     | 
    
         
             
                  align << %w[horizontal distributed] if @text_h_align == 7
         
     | 
| 
       171 
171 
     | 
    
         | 
| 
       172 
172 
     | 
    
         
             
                  align << ['justifyLastLine', 1] if @just_distrib != 0
         
     | 
| 
         @@ -345,28 +345,24 @@ module Writexlsx 
     | 
|
| 
       345 
345 
     | 
    
         | 
| 
       346 
346 
     | 
    
         
             
                  location = location.downcase
         
     | 
| 
       347 
347 
     | 
    
         | 
| 
       348 
     | 
    
         
            -
                   
     | 
| 
       349 
     | 
    
         
            -
                  set_text_h_align( 
     | 
| 
       350 
     | 
    
         
            -
                   
     | 
| 
       351 
     | 
    
         
            -
                  set_text_h_align(3) 
     | 
| 
       352 
     | 
    
         
            -
                  set_text_h_align(4) 
     | 
| 
       353 
     | 
    
         
            -
                  set_text_h_align(5) 
     | 
| 
       354 
     | 
    
         
            -
                   
     | 
| 
       355 
     | 
    
         
            -
             
     | 
| 
       356 
     | 
    
         
            -
                   
     | 
| 
       357 
     | 
    
         
            -
             
     | 
| 
       358 
     | 
    
         
            -
                   
     | 
| 
       359 
     | 
    
         
            -
                   
     | 
| 
      
 348 
     | 
    
         
            +
                  case location
         
     | 
| 
      
 349 
     | 
    
         
            +
                  when 'left'                         then set_text_h_align(1)
         
     | 
| 
      
 350 
     | 
    
         
            +
                  when 'centre', 'center'             then set_text_h_align(2)
         
     | 
| 
      
 351 
     | 
    
         
            +
                  when 'right'                        then set_text_h_align(3)
         
     | 
| 
      
 352 
     | 
    
         
            +
                  when 'fill'                         then set_text_h_align(4)
         
     | 
| 
      
 353 
     | 
    
         
            +
                  when 'justify'                      then set_text_h_align(5)
         
     | 
| 
      
 354 
     | 
    
         
            +
                  when 'center_across', 'centre_across', 'merge'
         
     | 
| 
      
 355 
     | 
    
         
            +
                    set_text_h_align(6)
         
     | 
| 
      
 356 
     | 
    
         
            +
                  when 'distributed', 'equal_space', 'justify_distributed'
         
     | 
| 
      
 357 
     | 
    
         
            +
                    set_text_h_align(7)
         
     | 
| 
      
 358 
     | 
    
         
            +
                  when 'top'                          then set_text_v_align(1)
         
     | 
| 
      
 359 
     | 
    
         
            +
                  when 'vcentre', 'vcenter'           then set_text_v_align(2)
         
     | 
| 
      
 360 
     | 
    
         
            +
                  when 'bottom'                       then set_text_v_align(3)
         
     | 
| 
      
 361 
     | 
    
         
            +
                  when 'vjustify'                     then set_text_v_align(4)
         
     | 
| 
      
 362 
     | 
    
         
            +
                  when 'vdistributed', 'vequal_space' then set_text_v_align(5)
         
     | 
| 
      
 363 
     | 
    
         
            +
                  end
         
     | 
| 
       360 
364 
     | 
    
         | 
| 
       361 
365 
     | 
    
         
             
                  @just_distrib = 1 if location == 'justify_distributed'
         
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
       363 
     | 
    
         
            -
                  set_text_v_align(1) if location == 'top'
         
     | 
| 
       364 
     | 
    
         
            -
                  set_text_v_align(2) if location == 'vcentre'
         
     | 
| 
       365 
     | 
    
         
            -
                  set_text_v_align(2) if location == 'vcenter'
         
     | 
| 
       366 
     | 
    
         
            -
                  set_text_v_align(3) if location == 'bottom'
         
     | 
| 
       367 
     | 
    
         
            -
                  set_text_v_align(4) if location == 'vjustify'
         
     | 
| 
       368 
     | 
    
         
            -
                  set_text_v_align(5) if location == 'vdistributed'
         
     | 
| 
       369 
     | 
    
         
            -
                  set_text_v_align(5) if location == 'vequal_space'    # S::PE.
         
     | 
| 
       370 
366 
     | 
    
         
             
                end
         
     | 
| 
       371 
367 
     | 
    
         | 
| 
       372 
368 
     | 
    
         
             
                #
         
     | 
| 
         @@ -419,7 +415,7 @@ module Writexlsx 
     | 
|
| 
       419 
415 
     | 
    
         
             
                def set_rotation(rotation)
         
     | 
| 
       420 
416 
     | 
    
         
             
                  if rotation == 270
         
     | 
| 
       421 
417 
     | 
    
         
             
                    rotation = 255
         
     | 
| 
       422 
     | 
    
         
            -
                  elsif rotation 
     | 
| 
      
 418 
     | 
    
         
            +
                  elsif rotation.between?(-90, 90)
         
     | 
| 
       423 
419 
     | 
    
         
             
                    rotation = -rotation + 90 if rotation < 0
         
     | 
| 
       424 
420 
     | 
    
         
             
                  else
         
     | 
| 
       425 
421 
     | 
    
         
             
                    raise "Rotation #{rotation} outside range: -90 <= angle <= 90"
         
     | 
| 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'write_xlsx/image_property'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Writexlsx
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Image
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :row, :col, :x_offset, :y_offset, :x_scale, :y_scale
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :url, :tip, :anchor, :description, :decorative
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(
         
     | 
| 
      
 12 
     | 
    
         
            +
                      row, col, image, x_offset, y_offset, x_scale, y_scale,
         
     | 
| 
      
 13 
     | 
    
         
            +
                      url, tip, anchor, description, decorative
         
     | 
| 
      
 14 
     | 
    
         
            +
                    )
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @row         = row
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @col         = col
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @image       = ImageProperty.new(image)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @x_offset    = x_offset
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @y_offset    = y_offset
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @x_scale     = x_scale
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @y_scale     = y_scale
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @url         = url
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @tip         = tip
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @anchor      = anchor
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @description = description
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @decorative  = decorative
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def scaled_width
         
     | 
| 
      
 30 
     | 
    
         
            +
                  width * x_scale * 96.0 / x_dpi
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def scaled_height
         
     | 
| 
      
 34 
     | 
    
         
            +
                  height * y_scale * 96.0 / y_dpi
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def width_emus
         
     | 
| 
      
 38 
     | 
    
         
            +
                  (0.5 + (scaled_width * 9_525)).to_i
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def height_emus
         
     | 
| 
      
 42 
     | 
    
         
            +
                  (0.5 + (scaled_height * 9_525)).to_i
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def image
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @image.filename
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def type
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @image.type
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def width
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @image.width
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def height
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @image.height
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def name
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @image.name
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def x_dpi
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @image.x_dpi
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def y_dpi
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @image.y_dpi
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def md5
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @image.md5
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def filename
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @image.filename
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def position
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @image.position
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def ref_id
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @image.ref_id
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'digest/md5'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Writexlsx
         
     | 
| 
      
 7 
     | 
    
         
            +
              class ImageProperty
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :type, :width, :height, :name, :x_dpi, :y_dpi, :md5
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :filename, :description, :decorative
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_accessor :ref_id, :body, :position
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(filename, options = {})
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @filename    = filename
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @description = options[:description]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @decorative  = options[:decorative]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @position    = options[:position]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @name        = File.basename(filename)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  # Open the image file and import the data.
         
     | 
| 
      
 20 
     | 
    
         
            +
                  data = File.binread(filename)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @md5  = Digest::MD5.hexdigest(data)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if data.unpack1('x A3') == 'PNG'
         
     | 
| 
      
 23 
     | 
    
         
            +
                    process_png(data)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  elsif data.unpack1('n') == 0xFFD8
         
     | 
| 
      
 25 
     | 
    
         
            +
                    process_jpg(data)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  elsif data.unpack1('A4') == 'GIF8'
         
     | 
| 
      
 27 
     | 
    
         
            +
                    process_gif(data)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  elsif data.unpack1('A2') == 'BM'
         
     | 
| 
      
 29 
     | 
    
         
            +
                    process_bmp(data)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  else
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # TODO. Add Image::Size to support other types.
         
     | 
| 
      
 32 
     | 
    
         
            +
                    raise "Unsupported image format for file: #{filename}\n"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  # Set a default dpi for images with 0 dpi.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @x_dpi = 96 if @x_dpi == 0
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @y_dpi = 96 if @y_dpi == 0
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                #
         
     | 
| 
      
 41 
     | 
    
         
            +
                # Extract width and height information from a PNG file.
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                def process_png(data)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @type   = 'png'
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @width  = 0
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @height = 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @x_dpi  = 96
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @y_dpi  = 96
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  offset = 8
         
     | 
| 
      
 51 
     | 
    
         
            +
                  data_length = data.size
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  # Search through the image data to read the height and width in th the
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # IHDR element. Also read the DPI in the pHYs element.
         
     | 
| 
      
 55 
     | 
    
         
            +
                  while offset < data_length
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    length = data[offset + 0, 4].unpack1("N")
         
     | 
| 
      
 58 
     | 
    
         
            +
                    png_type   = data[offset + 4, 4].unpack1("A4")
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    case png_type
         
     | 
| 
      
 61 
     | 
    
         
            +
                    when "IHDR"
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @width  = data[offset + 8, 4].unpack1("N")
         
     | 
| 
      
 63 
     | 
    
         
            +
                      @height = data[offset + 12, 4].unpack1("N")
         
     | 
| 
      
 64 
     | 
    
         
            +
                    when "pHYs"
         
     | 
| 
      
 65 
     | 
    
         
            +
                      x_ppu = data[offset + 8,  4].unpack1("N")
         
     | 
| 
      
 66 
     | 
    
         
            +
                      y_ppu = data[offset + 12, 4].unpack1("N")
         
     | 
| 
      
 67 
     | 
    
         
            +
                      units = data[offset + 16, 1].unpack1("C")
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                      if units == 1
         
     | 
| 
      
 70 
     | 
    
         
            +
                        @x_dpi = x_ppu * 0.0254
         
     | 
| 
      
 71 
     | 
    
         
            +
                        @y_dpi = y_ppu * 0.0254
         
     | 
| 
      
 72 
     | 
    
         
            +
                      end
         
     | 
| 
      
 73 
     | 
    
         
            +
                    end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    offset = offset + length + 12
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    break if png_type == "IEND"
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  raise "#{@filename}: no size data found in png image.\n" unless @height
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def process_jpg(data)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  @type  = 'jpeg'
         
     | 
| 
      
 84 
     | 
    
         
            +
                  @x_dpi = 96
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @y_dpi = 96
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  offset = 2
         
     | 
| 
      
 88 
     | 
    
         
            +
                  data_length = data.bytesize
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  # Search through the image data to read the JPEG markers.
         
     | 
| 
      
 91 
     | 
    
         
            +
                  while offset < data_length
         
     | 
| 
      
 92 
     | 
    
         
            +
                    marker  = data[offset + 0, 2].unpack1("n")
         
     | 
| 
      
 93 
     | 
    
         
            +
                    length  = data[offset + 2, 2].unpack1("n")
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    # Read the height and width in the 0xFFCn elements
         
     | 
| 
      
 96 
     | 
    
         
            +
                    # (Except C4, C8 and CC which aren't SOF markers).
         
     | 
| 
      
 97 
     | 
    
         
            +
                    if (marker & 0xFFF0) == 0xFFC0 &&
         
     | 
| 
      
 98 
     | 
    
         
            +
                       marker != 0xFFC4 && marker != 0xFFCC
         
     | 
| 
      
 99 
     | 
    
         
            +
                      @height = data[offset + 5, 2].unpack1("n")
         
     | 
| 
      
 100 
     | 
    
         
            +
                      @width  = data[offset + 7, 2].unpack1("n")
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    # Read the DPI in the 0xFFE0 element.
         
     | 
| 
      
 104 
     | 
    
         
            +
                    if marker == 0xFFE0
         
     | 
| 
      
 105 
     | 
    
         
            +
                      units     = data[offset + 11, 1].unpack1("C")
         
     | 
| 
      
 106 
     | 
    
         
            +
                      x_density = data[offset + 12, 2].unpack1("n")
         
     | 
| 
      
 107 
     | 
    
         
            +
                      y_density = data[offset + 14, 2].unpack1("n")
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                      if units == 1
         
     | 
| 
      
 110 
     | 
    
         
            +
                        @x_dpi = x_density
         
     | 
| 
      
 111 
     | 
    
         
            +
                        @y_dpi = y_density
         
     | 
| 
      
 112 
     | 
    
         
            +
                      elsif units == 2
         
     | 
| 
      
 113 
     | 
    
         
            +
                        @x_dpi = x_density * 2.54
         
     | 
| 
      
 114 
     | 
    
         
            +
                        @y_dpi = y_density * 2.54
         
     | 
| 
      
 115 
     | 
    
         
            +
                      end
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    offset += length + 2
         
     | 
| 
      
 119 
     | 
    
         
            +
                    break if marker == 0xFFDA
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  raise "#{@filename}: no size data found in jpeg image.\n" unless @height
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                #
         
     | 
| 
      
 126 
     | 
    
         
            +
                # Extract width and height information from a GIF file.
         
     | 
| 
      
 127 
     | 
    
         
            +
                #
         
     | 
| 
      
 128 
     | 
    
         
            +
                def process_gif(data)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  @type  = 'gif'
         
     | 
| 
      
 130 
     | 
    
         
            +
                  @x_dpi = 96
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @y_dpi = 96
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  @width  = data[6, 2].unpack1("v")
         
     | 
| 
      
 134 
     | 
    
         
            +
                  @height = data[8, 2].unpack1("v")
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  raise "#{@filename}: no size data found in gif image.\n" if @height.nil?
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                # Extract width and height information from a BMP file.
         
     | 
| 
      
 140 
     | 
    
         
            +
                def process_bmp(data)       # :nodoc:
         
     | 
| 
      
 141 
     | 
    
         
            +
                  @type = 'bmp'
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  # Check that the file is big enough to be a bitmap.
         
     | 
| 
      
 144 
     | 
    
         
            +
                  raise "#{@filename} doesn't contain enough data." if data.bytesize <= 0x36
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  # Read the bitmap width and height. Verify the sizes.
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @width, @height = data.unpack("x18 V2")
         
     | 
| 
      
 148 
     | 
    
         
            +
                  raise "#{@filename}: largest image width #{width} supported is 65k." if width > 0xFFFF
         
     | 
| 
      
 149 
     | 
    
         
            +
                  raise "#{@filename}: largest image height supported is 65k." if @height > 0xFFFF
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                  # Read the bitmap planes and bpp data. Verify them.
         
     | 
| 
      
 152 
     | 
    
         
            +
                  planes, bitcount = data.unpack("x26 v2")
         
     | 
| 
      
 153 
     | 
    
         
            +
                  raise "#{@filename} isn't a 24bit true color bitmap." unless bitcount == 24
         
     | 
| 
      
 154 
     | 
    
         
            +
                  raise "#{@filename}: only 1 plane supported in bitmap image." unless planes == 1
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  # Read the bitmap compression. Verify compression.
         
     | 
| 
      
 157 
     | 
    
         
            +
                  compression = data.unpack1("x30 V")
         
     | 
| 
      
 158 
     | 
    
         
            +
                  raise "#{@filename}: compression not supported in bitmap image." unless compression == 0
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                  @x_dpi = @y_dpi = 96
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     |