Class: OoxmlParser::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/ooxml_parser/common_parser/common_data/color.rb

Constant Summary collapse

COLOR_INDEXED =

List of color duplicated from ‘OpenXML Sdk IndexedColors` class See msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.indexedcolors.aspx

Returns:

  • (Array)

    Deprecated Indexed colors

%w(
  000000
  FFFFFF
  FF0000
  00FF00
  0000FF
  FFFF00
  FF00FF
  00FFFF
  000000
  FFFFFF
  FF0000
  00FF00
  0000FF
  FFFF00
  FF00FF
  00FFFF
  800000
  008000
  000080
  808000
  800080
  008080
  C0C0C0
  808080
  9999FF
  993366
  FFFFCC
  CCFFFF
  660066
  FF8080
  0066CC
  CCCCFF
  000080
  FF00FF
  FFFF00
  00FFFF
  800080
  800000
  008080
  0000FF
  00CCFF
  CCFFFF
  CCFFCC
  FFFF99
  99CCFF
  FF99CC
  CC99FF
  FFCC99
  3366FF
  33CCCC
  99CC00
  FFCC00
  FF9900
  FF6600
  666699
  969696
  003366
  339966
  003300
  333300
  993300
  993366
  333399
  333333
  n/a
  n/a
).freeze
VALUE_FOR_NONE_COLOR =

Value of color if non selected

nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(new_red = VALUE_FOR_NONE_COLOR, new_green = VALUE_FOR_NONE_COLOR, new_blue = VALUE_FOR_NONE_COLOR) ⇒ Color

Returns a new instance of Color.



103
104
105
106
107
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 103

def initialize(new_red = VALUE_FOR_NONE_COLOR, new_green = VALUE_FOR_NONE_COLOR, new_blue = VALUE_FOR_NONE_COLOR)
  @red = new_red
  @green = new_green
  @blue = new_blue
end

Instance Attribute Details

#alpha_channelInteger

Returns Value of alpha-channel.

Returns:

  • (Integer)

    Value of alpha-channel



94
95
96
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 94

def alpha_channel
  @alpha_channel
end

#blueInteger

Returns Value of Blue Part.

Returns:

  • (Integer)

    Value of Blue Part



88
89
90
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 88

def blue
  @blue
end

#greenInteger

Returns Value of Green Part.

Returns:

  • (Integer)

    Value of Green Part



86
87
88
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 86

def green
  @green
end

#positionObject

Returns the value of attribute position.



97
98
99
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 97

def position
  @position
end

#propertiesObject

Returns the value of attribute properties.



98
99
100
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 98

def properties
  @properties
end

#redInteger

Returns Value of Red Part.

Returns:

  • (Integer)

    Value of Red Part



84
85
86
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 84

def red
  @red
end

#styleString

Returns Value of Color Style.

Returns:

  • (String)

    Value of Color Style



90
91
92
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 90

def style
  @style
end

Class Method Details

.array_from_const(const_array_name) ⇒ Array, Color

Read array of color from the AllTestData’s constant

Parameters:

  • const_array_name (Array)
    • array of the string

Returns:

  • (Array, Color)

    array of color



291
292
293
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 291

def array_from_const(const_array_name)
  const_array_name.map { |current_color| Color.parse_string(current_color) }
end

.from_int16(color) ⇒ Object



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 263

def from_int16(color)
  return nil unless color
  return Color.new(nil, nil, nil) if color == 'auto' || color == 'null'

  char_array = color.split(//)
  alpha_channel, red, green, blue = nil
  if char_array.length == 6
    red = (char_array[0] + char_array[1]).hex
    green = (char_array[2] + char_array[3]).hex
    blue = (char_array[4] + char_array[5]).hex
  elsif char_array.length == 8
    alpha_channel = (char_array[0] + char_array[1]).hex
    red = (char_array[2] + char_array[3]).hex
    green = (char_array[4] + char_array[5]).hex
    blue = (char_array[6] + char_array[7]).hex
  end
  font_color = Color.new(red, green, blue)
  font_color.set_alpha_channel(alpha_channel) if alpha_channel
  font_color
end

.generate_random_colorObject Also known as: random



257
258
259
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 257

def generate_random_color
  Color.new(rand(256), rand(256), rand(256))
end

.get_rgb_by_color_index(index) ⇒ Object



295
296
297
298
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 295

def get_rgb_by_color_index(index)
  color_by_index = COLOR_INDEXED[index]
  color_by_index == 'n/a' ? Color.new : Color.from_int16(color_by_index)
end

.parse_color(color_node) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 455

def parse_color(color_node)
  case color_node.name
  when 'srgbClr'
    color = Color.from_int16(color_node.attribute('val').value)
    color.properties = ColorProperties.parse(color_node)
    color
  when 'schemeClr'
    color = SchemeColor.new
    color.value = ThemeColors.list[color_node.attribute('val').value.to_sym]
    color.properties = ColorProperties.parse(color_node)
    color.converted_color = HSLColor.calculate_with_luminance color.value,
                                                              color.properties.luminance_modulation,
                                                              color.properties.luminance_offset
    color
  end
end

.parse_color_hash(hash) ⇒ Object



284
285
286
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 284

def parse_color_hash(hash)
  Color.new(hash['red'], hash['green'], hash['blue'])
end

.parse_color_model(color_model_parent_node) ⇒ Object



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 429

def parse_color_model(color_model_parent_node)
  color = nil
  tint = nil
  color_model_parent_node.xpath('*').each do |color_model_node|
    color_model_node.xpath('*').each do |color_mode_node_child|
      case color_mode_node_child.name
      when 'tint'
        tint = color_mode_node_child.attribute('val').value.to_f / 100_000.0
      end
    end
    case color_model_node.name
    when 'scrgbClr'
      color = Color.new(color_model_node.attribute('r').value.to_i, color_model_node.attribute('g').value.to_i, color_model_node.attribute('b').value.to_i)
      color.alpha_channel = ColorAlphaChannel.parse(color_model_node)
    when 'srgbClr'
      color = Color.from_int16(color_model_node.attribute('val').value)
      color.alpha_channel = ColorAlphaChannel.parse(color_model_node)
    when 'schemeClr'
      color = parse_scheme_color(color_model_node)
    end
  end
  return nil unless color
  color.calculate_with_tint!(1.0 - tint) if tint
  color
end

.parse_color_tag(color_tag) ⇒ Object



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 394

def parse_color_tag(color_tag)
  unless color_tag.nil?
    if color_tag.attribute('indexed').nil? && !color_tag.attribute('rgb').nil?
      if color_tag.attribute('rgb').value.is_a?(String)
        return Color.from_int16(color_tag.attribute('rgb').value.to_s)
      end
      return Color.from_int16(color_tag.attribute('rgb').value.value.to_s)
    elsif color_tag.attribute('rgb').nil? && !color_tag.attribute('indexed').nil?
      if color_tag.attribute('indexed').value.is_a?(String)
        return Color.get_rgb_by_color_index(color_tag.attribute('indexed').value.to_i)
      end
      return Color.get_rgb_by_color_index(color_tag.attribute('indexed').value.value.to_i)
    elsif !color_tag.attribute('theme').nil?
      return ThemeColors.parse_color_theme(color_tag)
    end
  end
  nil
end

.parse_int16_string(color) ⇒ Object



316
317
318
319
320
321
322
323
324
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 316

def parse_int16_string(color)
  return nil if color.nil?

  char_array = color.split(//)
  red = (char_array[0] + char_array[1]).hex
  green = (char_array[2] + char_array[3]).hex
  blue = (char_array[4] + char_array[5]).hex
  Color.new(red, green, blue)
end

.parse_scheme_color(scheme_color_node) ⇒ Object



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 413

def parse_scheme_color(scheme_color_node)
  color = ThemeColors.list[scheme_color_node.attribute('val').value.to_sym]
  hls = HSLColor.rgb_to_hsl(color)
  scheme_color_node.xpath('*').each do |scheme_color_node_child|
    case scheme_color_node_child.name
    when 'lumMod'
      hls.l = hls.l * (scheme_color_node_child.attribute('val').value.to_f / 100_000.0)
    when 'lumOff'
      hls.l = hls.l + (scheme_color_node_child.attribute('val').value.to_f / 100_000.0)
    end
  end
  color = hls.to_rgb
  color.alpha_channel = ColorAlphaChannel.parse(scheme_color_node)
  color
end

.parse_string(str) ⇒ Object Also known as: parse



300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 300

def parse_string(str)
  return str if str.is_a?(Color)
  return Color.new(VALUE_FOR_NONE_COLOR, VALUE_FOR_NONE_COLOR, VALUE_FOR_NONE_COLOR) if str == 'none' || str == '' || str == 'transparent' || str.nil?
  split = if str.include?('RGB (') || str.include?('rgb(')
            str.gsub(/[(RGBrgb\(\) )]/, '').split(',')
          elsif str.include?('RGB ') || str.include?('rgb')
            str.gsub(/RGB |rgb/, '').split(', ')
          else
            raise "Incorrect data for color to parse: '#{str}'"
          end

  Color.new(split[0].to_i, split[1].to_i, split[2].to_i)
end

.scrgb_to_srgb(color) ⇒ Object



340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 340

def scrgb_to_srgb(color)
  result_color = if color < 0
                   0
                 elsif color <= 0.0031308
                   color * 12.92
                 elsif color < 1
                   1.055 * (color**(1.0 / 2.4)) - 0.055
                 else
                   1
                 end
  (result_color * 255.0).to_i
end

.shade_for_component(color_component, shade_value) ⇒ Object



353
354
355
356
357
358
359
360
361
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 353

def shade_for_component(color_component, shade_value)
  if color_component * shade_value < 0
    0
  elsif color_component * shade_value > 1
    1
  else
    color_component * shade_value
  end
end

.srgb_to_scrgb(color) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 326

def srgb_to_scrgb(color)
  lineal_value = color.to_f / 255.0
  result_color = if lineal_value < 0
                   0
                 elsif lineal_value <= 0.04045
                   lineal_value / 12.92
                 elsif lineal_value <= 1
                   ((lineal_value + 0.055) / 1.055)**2.4
                 else
                   1
                 end
  result_color
end

.tint_for_component(color_component, tint) ⇒ Object



363
364
365
366
367
368
369
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 363

def tint_for_component(color_component, tint)
  if tint > 0
    color_component * (1 - tint) + tint
  else
    color_component * (1 + tint)
  end
end

.to_color(something) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 371

def to_color(something)
  case something
  when SchemeColor
    something.converted_color
  when ForegroundColor, DocxColorScheme
    something.color
  when PresentationFill
    if something.color.respond_to? :converted_color
      something.color.converted_color
    else
      something.color
    end
  when String
    Color.parse(something)
  when Symbol
    Color.parse(something.to_s)
  when DocxColor
    Color.parse(something.value)
  else
    something
  end
end

Instance Method Details

#==(other) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 135

def ==(other)
  if other.is_a?(Color)
    if nil?
      false
    elsif (@red == other.red) && (@green == other.green) && (@blue == other.blue)
      true
    elsif (none? && other.white?) || (white? && other.none?)
      true
    else
      false
    end
  else
    false
  end
end

#calculate_with_shade!(shade) ⇒ Object



176
177
178
179
180
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 176

def calculate_with_shade!(shade)
  @red = (@red * shade.to_f).to_i
  @green = (@green * shade.to_f).to_i
  @blue = (@blue * shade.to_f).to_i
end

#calculate_with_tint!(tint) ⇒ Object



170
171
172
173
174
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 170

def calculate_with_tint!(tint)
  @red += (tint.to_f * (255 - @red)).to_i
  @green += (tint.to_f * (255 - @green)).to_i
  @blue += (tint.to_f * (255 - @blue)).to_i
end

#copyObject



131
132
133
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 131

def copy
  Color.new(@red, @green, @blue)
end

#looks_like?(color_to_check = nil, delta = 8) ⇒ Boolean

To compare color, which look alike

Parameters:

  • color_to_check (String or Color) (defaults to: nil)

    color to compare

  • delta (Integer) (defaults to: 8)

    max delta for each of specters

Returns:

  • (Boolean)


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 154

def looks_like?(color_to_check = nil, delta = 8)
  color_to_check = color_to_check.converted_color if color_to_check.is_a?(SchemeColor)
  color_to_check = color_to_check.color if color_to_check.is_a?(ForegroundColor)
  color_to_check = color_to_check.color.converted_color if color_to_check.is_a?(PresentationFill)
  color_to_check = Color.parse(color_to_check) if color_to_check.is_a?(String)
  color_to_check = Color.parse(color_to_check.to_s) if color_to_check.is_a?(Symbol)
  color_to_check = Color.parse(color_to_check.value) if color_to_check.is_a?(DocxColor)
  return false if none? && !color_to_check.none?
  return false if !none? && color_to_check.none?
  return true if self == color_to_check
  red = color_to_check.red
  green = color_to_check.green
  blue = color_to_check.blue
  ((self.red - red).abs < delta && (self.green - green).abs < delta && (self.blue - blue).abs < delta) ? true : false
end

#none?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 123

def none?
  (@red == VALUE_FOR_NONE_COLOR) && (@green == VALUE_FOR_NONE_COLOR) && (@blue == VALUE_FOR_NONE_COLOR)
end

#shade(shade_value) ⇒ Object



182
183
184
185
186
187
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 182

def shade(shade_value)
  red = Color.scrgb_to_srgb(Color.shade_for_component(Color.srgb_to_scrgb(@red), shade_value))
  green = Color.scrgb_to_srgb(Color.shade_for_component(Color.srgb_to_scrgb(@green), shade_value))
  blue = Color.scrgb_to_srgb(Color.shade_for_component(Color.srgb_to_scrgb(@blue), shade_value))
  Color.new(red, green, blue)
end

#tint(shade_value) ⇒ Object



189
190
191
192
193
194
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 189

def tint(shade_value)
  red = Color.scrgb_to_srgb(Color.tint_for_component(Color.srgb_to_scrgb(@red), shade_value))
  green = Color.scrgb_to_srgb(Color.tint_for_component(Color.srgb_to_scrgb(@green), shade_value))
  blue = Color.scrgb_to_srgb(Color.tint_for_component(Color.srgb_to_scrgb(@blue), shade_value))
  Color.new(red, green, blue)
end

#to_hexObject Also known as: to_int16



117
118
119
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 117

def to_hex
  (@red.to_s(16).rjust(2, '0') + @green.to_s(16).rjust(2, '0') + @blue.to_s(16).rjust(2, '0')).upcase
end

#to_hslObject



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 198

def to_hsl
  max_hls = 255.0
  cd13 = 1.0 / 3.0
  cd23 = 2.0 / 3.0
  hls_color = HSLColor.new
  min = [@red, @green, @blue].min.to_f
  max = [@red, @green, @blue].max.to_f
  delta = (max - min).to_f
  dmax = (max + min) / 255.0
  ddelta = delta / 255.0
  hls_color.l = dmax / 2.0

  if delta != 0
    hls_color.s = if hls_color.l < 0.5
                    ddelta / dmax
                  else
                    ddelta / (2.0 - dmax)
                  end
    ddelta *= 1_530.0
    d_r = (max - @red) / ddelta
    d_g = (max - @green) / ddelta
    d_b = (max - @blue) / ddelta

    if @red == max
      hls_color.h = d_b - d_r
    elsif @green == max
      hls_color.h = cd13 + d_r - d_b
    elsif @blue == max
      hls_color.h = cd23 + d_g - d_r
    end

    hls_color.h += 1 if hls_color.h < 0
    hls_color.h -= 1 if hls_color.h < 1
  end
  hls_color.h = ((hls_color.h * max_hls).round >> 0) & 0xFF
  hls_color.h = 0 if hls_color.h < 0
  hls_color.h = 255 if hls_color.h > 255

  hls_color.l = ((hls_color.l * max_hls).round >> 0) & 0xFF
  hls_color.l = 0 if hls_color.l < 0
  hls_color.l = 255 if hls_color.l > 255

  hls_color.s = ((hls_color.s * max_hls).round >> 0) & 0xFF
  hls_color.s = 0 if hls_color.s < 0
  hls_color.s = 255 if hls_color.s > 255

  hls_color
end

#to_hsl_standardisedObject

redefine code from our to_hsl realisation to standartised way for services like serennu.com/colour/hsltorgb.php



248
249
250
251
252
253
254
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 248

def to_hsl_standardised
  hsl = to_hsl
  hsl.h = hsl.h * 360 / 256
  hsl.l = (hsl.l * 100.0 / 255.0).round
  hsl.s = (hsl.s * 100.0 / 255.0).round
  hsl
end

#to_sObject



109
110
111
112
113
114
115
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 109

def to_s
  if @red == VALUE_FOR_NONE_COLOR && @green == VALUE_FOR_NONE_COLOR && @blue == VALUE_FOR_NONE_COLOR
    'none'
  else
    "RGB (#{@red}, #{@green}, #{@blue})"
  end
end

#white?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/ooxml_parser/common_parser/common_data/color.rb', line 127

def white?
  (@red == 255) && (@green == 255) && (@blue == 255)
end