test/hexapdf/layout/test_style.rb in hexapdf-0.5.0 vs test/hexapdf/layout/test_style.rb in hexapdf-0.6.0
- old
+ new
@@ -1,10 +1,13 @@
# -*- encoding: utf-8 -*-
require 'test_helper'
+require_relative '../content/common'
+require 'hexapdf/document'
require 'hexapdf/layout/style'
-require 'hexapdf/layout/text_box'
+require 'hexapdf/layout/text_layouter'
+require 'hexapdf/layout/box'
describe HexaPDF::Layout::Style::LineSpacing do
before do
@line1 = Object.new
@line1.define_singleton_method(:y_min) { - 1}
@@ -45,11 +48,11 @@
it "allows fixed line spacing" do
obj = line_spacing(:fixed, 7)
assert_equal(:fixed, obj.type)
assert_equal(7, obj.value)
assert_equal(7, obj.baseline_distance(@line1, @line2))
- assert_equal(7 - 1 - 4, obj.gap(@line1, @line2))
+ assert_equal(7 - 1 - 4, obj.gap(@line1, @line2))
end
it "allows line spacing using a leading value" do
obj = line_spacing(:leading, 3)
assert_equal(:leading, obj.type)
@@ -70,68 +73,553 @@
it "raises an error if an invalid type is provided" do
assert_raises(ArgumentError) { line_spacing(:invalid) }
end
end
+describe HexaPDF::Layout::Style::Quad do
+ def create_quad(val)
+ HexaPDF::Layout::Style::Quad.new(val)
+ end
+
+ describe "initialize" do
+ it "works with a single value" do
+ quad = create_quad(5)
+ assert_equal(5, quad.top)
+ assert_equal(5, quad.right)
+ assert_equal(5, quad.bottom)
+ assert_equal(5, quad.left)
+ end
+
+ it "works with two values" do
+ quad = create_quad([5, 2])
+ assert_equal(5, quad.top)
+ assert_equal(2, quad.right)
+ assert_equal(5, quad.bottom)
+ assert_equal(2, quad.left)
+ end
+
+ it "works with three values" do
+ quad = create_quad([5, 2, 7])
+ assert_equal(5, quad.top)
+ assert_equal(2, quad.right)
+ assert_equal(7, quad.bottom)
+ assert_equal(2, quad.left)
+ end
+
+ it "works with four or more values" do
+ quad = create_quad([5, 2, 7, 1, 9])
+ assert_equal(5, quad.top)
+ assert_equal(2, quad.right)
+ assert_equal(7, quad.bottom)
+ assert_equal(1, quad.left)
+ end
+
+ it "works with a Quad as value" do
+ quad = create_quad([5, 2, 7, 1])
+ new_quad = create_quad(quad)
+ assert_equal(new_quad.top, quad.top)
+ assert_equal(new_quad.right, quad.right)
+ assert_equal(new_quad.bottom, quad.bottom)
+ assert_equal(new_quad.left, quad.left)
+ end
+ end
+
+ it "can be asked if it contains only a single value" do
+ assert(create_quad(5).simple?)
+ refute(create_quad([5, 2]).simple?)
+ end
+end
+
+describe HexaPDF::Layout::Style::Border do
+ def create_border(*args)
+ HexaPDF::Layout::Style::Border.new(*args)
+ end
+
+ it "has accessors for with, color and style that return Quads" do
+ border = create_border
+ assert_kind_of(HexaPDF::Layout::Style::Quad, border.width)
+ assert_kind_of(HexaPDF::Layout::Style::Quad, border.color)
+ assert_kind_of(HexaPDF::Layout::Style::Quad, border.style)
+ end
+
+ it "can be asked whether a border is defined" do
+ assert(create_border.none?)
+ refute(create_border(width: 5).none?)
+ end
+
+ describe "draw" do
+ before do
+ @canvas = HexaPDF::Document.new.pages.add.canvas
+ end
+
+ describe "simple - same width, color and style on all sides" do
+ it "works with style solid" do
+ border = create_border(width: 10, color: 0.5, style: :solid)
+ border.draw(@canvas, 0, 0, 100, 100)
+ assert_operators(@canvas.contents, [[:save_graphics_state],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:append_rectangle, [5, 5, 90, 90]],
+ [:stroke_path],
+ [:restore_graphics_state]])
+ end
+
+ it "works with style dashed" do
+ border = create_border(width: 10, color: 0.5, style: :dashed)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [2]],
+ [:append_rectangle, [0, 0, 200, 300]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_line_dash_pattern, [[10, 20], 25]],
+ [:move_to, [0, 295]], [:line_to, [200, 295]],
+ [:move_to, [200, 5]], [:line_to, [0, 5]],
+ [:stroke_path],
+ [:set_line_dash_pattern, [[10, 18], 23]],
+ [:move_to, [195, 300]], [:line_to, [195, 0]],
+ [:move_to, [5, 0]], [:line_to, [5, 300]],
+ [:stroke_path],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works with style dashed_round" do
+ border = create_border(width: 10, color: 0.5, style: :dashed_round)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [1]],
+ [:append_rectangle, [0, 0, 200, 300]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_line_dash_pattern, [[10, 20], 25]],
+ [:move_to, [0, 295]], [:line_to, [200, 295]],
+ [:move_to, [200, 5]], [:line_to, [0, 5]],
+ [:stroke_path],
+ [:set_line_dash_pattern, [[10, 18], 23]],
+ [:move_to, [195, 300]], [:line_to, [195, 0]],
+ [:move_to, [5, 0]], [:line_to, [5, 300]],
+ [:stroke_path],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works with style dotted" do
+ border = create_border(width: 10, color: 0.5, style: :dotted)
+ border.draw(@canvas, 0, 0, 100, 200)
+ ops = [[:save_graphics_state],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [1]],
+ [:append_rectangle, [0, 0, 100, 200]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_line_dash_pattern, [[0, 18], 13]],
+ [:move_to, [0, 195]], [:line_to, [100, 195]],
+ [:move_to, [100, 5]], [:line_to, [0, 5]],
+ [:stroke_path],
+ [:set_line_dash_pattern, [[0, 19], 14]],
+ [:move_to, [95, 200]], [:line_to, [95, 0]],
+ [:move_to, [5, 0]], [:line_to, [5, 200]],
+ [:stroke_path],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+ end
+
+ describe "complex borders where edges have different width/color/style values" do
+ it "works correctly for the top border" do
+ border = create_border(width: [10, 0, 0, 0], color: 0.5, style: :dashed)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:save_graphics_state],
+ [:move_to, [0, 300]], [:line_to, [200, 300]],
+ [:line_to, [200, 290]], [:line_to, [0, 290]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [2]],
+ [:set_line_dash_pattern, [[10, 20], 25]],
+ [:move_to, [0, 295]], [:line_to, [200, 295]],
+ [:stroke_path],
+ [:restore_graphics_state],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works correctly for the right border" do
+ border = create_border(width: [0, 10, 0, 0], color: 0.5, style: :dashed)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:save_graphics_state],
+ [:move_to, [200, 300]], [:line_to, [200, 0]],
+ [:line_to, [190, 0]], [:line_to, [190, 300]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [2]],
+ [:set_line_dash_pattern, [[10, 18], 23]],
+ [:move_to, [195, 300]], [:line_to, [195, 0]],
+ [:stroke_path],
+ [:restore_graphics_state],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works correctly for the bottom border" do
+ border = create_border(width: [0, 0, 10, 0], color: 0.5, style: :dashed)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:save_graphics_state],
+ [:move_to, [200, 0]], [:line_to, [0, 0]],
+ [:line_to, [0, 10]], [:line_to, [200, 10]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [2]],
+ [:set_line_dash_pattern, [[10, 20], 25]],
+ [:move_to, [200, 5]], [:line_to, [0, 5]],
+ [:stroke_path],
+ [:restore_graphics_state],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works correctly for the left border" do
+ border = create_border(width: [0, 0, 0, 10], color: 0.5, style: :dashed)
+ border.draw(@canvas, 0, 0, 200, 300)
+ ops = [[:save_graphics_state],
+ [:save_graphics_state],
+ [:move_to, [0, 0]], [:line_to, [0, 300]],
+ [:line_to, [10, 300]], [:line_to, [10, 0]],
+ [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.5]],
+ [:set_line_width, [10]],
+ [:set_line_cap_style, [2]],
+ [:set_line_dash_pattern, [[10, 18], 23]],
+ [:move_to, [5, 0]], [:line_to, [5, 300]],
+ [:stroke_path],
+ [:restore_graphics_state],
+ [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+
+ it "works with all values combined" do
+ border = create_border(width: [20, 10, 40, 30], color: [0, 0.25, 0.5, 0.75],
+ style: [:solid, :dashed, :dashed_round, :dotted])
+ border.draw(@canvas, 0, 0, 100, 200)
+ ops = [[:save_graphics_state],
+ [:save_graphics_state],
+ [:move_to, [0, 200]], [:line_to, [100, 200]],
+ [:line_to, [90, 180]], [:line_to, [30, 180]], [:clip_path_non_zero], [:end_path],
+ [:set_line_width, [20]],
+ [:move_to, [0, 190]], [:line_to, [100, 190]], [:stroke_path],
+ [:restore_graphics_state], [:save_graphics_state],
+ [:move_to, [100, 200]], [:line_to, [100, 0]],
+ [:line_to, [90, 40]], [:line_to, [90, 180]], [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.25]], [:set_line_width, [10]],
+ [:set_line_cap_style, [2]], [:set_line_dash_pattern, [[10, 20], 25]],
+ [:move_to, [95, 200]], [:line_to, [95, 0]], [:stroke_path],
+ [:restore_graphics_state], [:save_graphics_state],
+ [:move_to, [100, 0]], [:line_to, [0, 0]],
+ [:line_to, [30, 40]], [:line_to, [90, 40]], [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.5]], [:set_line_width, [40]],
+ [:set_line_cap_style, [1]], [:set_line_dash_pattern, [[40, 0], 20]],
+ [:move_to, [100, 20]], [:line_to, [0, 20]], [:stroke_path],
+ [:restore_graphics_state], [:save_graphics_state],
+ [:move_to, [0, 0]], [:line_to, [0, 200]],
+ [:line_to, [30, 180]], [:line_to, [30, 40]], [:clip_path_non_zero], [:end_path],
+ [:set_device_gray_stroking_color, [0.75]], [:set_line_width, [30]],
+ [:set_line_cap_style, [1]], [:set_line_dash_pattern, [[0, 42.5], 27.5]],
+ [:move_to, [15, 0]], [:line_to, [15, 200]], [:stroke_path],
+ [:restore_graphics_state], [:restore_graphics_state]]
+ assert_operators(@canvas.contents, ops)
+ end
+ end
+
+ it "raises an error if an invalid style is provided" do
+ assert_raises(ArgumentError) do
+ create_border(width: 1, color: 0, style: :unknown).draw(@canvas, 0, 0, 10, 10)
+ end
+ end
+ end
+end
+
+describe HexaPDF::Layout::Style::Layers do
+ before do
+ @layers = HexaPDF::Layout::Style::Layers.new
+ end
+
+ it "can be initialized with an array of layers" do
+ data = [-> {}]
+ layers = HexaPDF::Layout::Style::Layers.new(data)
+ assert_equal(data, layers.enum_for(:each, {}).to_a)
+ end
+
+ describe "add and each" do
+ it "can use a given block" do
+ block = proc { true}
+ @layers.add(&block)
+ assert_equal([block], @layers.enum_for(:each, {}).to_a)
+ end
+
+ it "can store a reference" do
+ @layers.add(:link, option: :value)
+ value = Object.new
+ value.define_singleton_method(:new) {|*args| :new }
+ config = Object.new
+ config.define_singleton_method(:constantize) {|*args| value }
+ assert_equal([:new], @layers.enum_for(:each, config).to_a)
+ end
+
+ it "fails if neither a block nor a name is given when adding a layer" do
+ assert_raises(ArgumentError) { @layers.add }
+ end
+ end
+
+ it "can determine whether layers are defined" do
+ assert(@layers.none?)
+ @layers.add {}
+ refute(@layers.none?)
+ end
+
+ it "draws the layers onto a canvas" do
+ box = Object.new
+ value = nil
+ klass = Class.new
+ klass.send(:define_method, :initialize) {|**args| @args = args }
+ klass.send(:define_method, :call) do |canvas, _|
+ value = @args
+ canvas.line_width(5)
+ end
+ canvas = HexaPDF::Document.new.pages.add.canvas
+ canvas.context.document.config['style.layers_map'][:test] = klass
+
+ @layers.add {|canv, ibox| assert_equal(box, ibox); canv.line_width(10)}
+ @layers.add(:test, option: :value)
+ @layers.draw(canvas, 10, 15, box)
+ ops = [[:save_graphics_state],
+ [:concatenate_matrix, [1, 0, 0, 1, 10, 15]],
+ [:save_graphics_state],
+ [:set_line_width, [10]],
+ [:restore_graphics_state],
+ [:save_graphics_state],
+ [:set_line_width, [5]],
+ [:restore_graphics_state],
+ [:restore_graphics_state]]
+ assert_operators(canvas.contents, ops)
+ assert_equal({option: :value}, value)
+ end
+end
+
+describe HexaPDF::Layout::Style::LinkLayer do
+ describe "initialize" do
+ it "fails if more than one possible target is chosen" do
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, uri: true) }
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, file: true) }
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(uri: true, file: true) }
+ end
+
+ it "fails if an invalid border is provided" do
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(border: 5) }
+ end
+ end
+
+ describe "call" do
+ before do
+ @canvas = HexaPDF::Document.new.pages.add.canvas
+ @canvas.translate(10, 10)
+ @box = HexaPDF::Layout::Box.new(width: 15, height: 10)
+ end
+
+ def call_link(hash)
+ link = HexaPDF::Layout::Style::LinkLayer.new(hash)
+ link.call(@canvas, @box)
+ @canvas.context[:Annots][0]
+ end
+
+ it "sets general values like /Rect and /QuadPoints" do
+ annot = call_link(dest: true)
+ assert_equal(:Link, annot[:Subtype])
+ assert_equal([10, 10, 25, 20], annot[:Rect].value)
+ assert_equal([10, 10, 25, 10, 25, 20, 10, 20], annot[:QuadPoints])
+ end
+
+ it "removes the border by default" do
+ annot = call_link(dest: true)
+ assert_equal([0, 0, 0], annot[:Border])
+ end
+
+ it "uses a default border if no specific border style is specified" do
+ annot = call_link(dest: true, border: true)
+ assert_equal([0, 0, 1], annot[:Border])
+ end
+
+ it "uses the specified border and border color" do
+ annot = call_link(dest: true, border: [10, 10, 2], border_color: [255])
+ assert_equal([10, 10, 2], annot[:Border])
+ assert_equal([1.0], annot[:C])
+ end
+
+ it "works for simple destinations" do
+ annot = call_link(dest: [@canvas.context, :FitH])
+ assert_equal([@canvas.context, :FitH], annot[:Dest])
+ assert_nil(annot[:A])
+ end
+
+ it "works for URIs" do
+ annot = call_link(uri: "test.html")
+ assert_equal({S: :URI, URI: "test.html"}, annot[:A].value)
+ assert_nil(annot[:Dest])
+ end
+
+ it "works for files" do
+ annot = call_link(file: "local-file.pdf")
+ assert_equal({S: :Launch, F: "local-file.pdf", NewWindow: true}, annot[:A].value)
+ assert_nil(annot[:Dest])
+ end
+ end
+end
+
describe HexaPDF::Layout::Style do
before do
@style = HexaPDF::Layout::Style.new
end
it "can assign values on initialization" do
style = HexaPDF::Layout::Style.new(font_size: 10)
assert_equal(10, style.font_size)
end
- it "has several dynamically generated properties with default values" do
+ it "has several simple and dynamically generated properties with default values" do
assert_raises(HexaPDF::Error) { @style.font }
assert_equal(10, @style.font_size)
assert_equal(0, @style.character_spacing)
assert_equal(0, @style.word_spacing)
assert_equal(100, @style.horizontal_scaling)
assert_equal(0, @style.text_rise)
assert_equal({}, @style.font_features)
+ assert_equal(:fill, @style.text_rendering_mode)
+ assert_equal([0], @style.fill_color.components)
+ assert_equal(1, @style.fill_alpha)
+ assert_equal([0], @style.stroke_color.components)
+ assert_equal(1, @style.stroke_alpha)
+ assert_equal(1, @style.stroke_width)
+ assert_equal(:butt, @style.stroke_cap_style)
+ assert_equal(:miter, @style.stroke_join_style)
+ assert_equal(10.0, @style.stroke_miter_limit)
assert_equal(:left, @style.align)
assert_equal(:top, @style.valign)
+ assert_equal(0, @style.text_indent)
+ assert_nil(@style.background_color)
+ assert(@style.padding.simple?)
+ assert_equal(0, @style.padding.top)
+ assert(@style.margin.simple?)
+ assert_equal(0, @style.margin.top)
+ assert(@style.border.none?)
+ assert_equal([[], 0], @style.stroke_dash_pattern.to_operands)
+ assert_equal([:proportional, 1], [@style.line_spacing.type, @style.line_spacing.value])
+ refute(@style.subscript)
+ refute(@style.superscript)
+ assert_kind_of(HexaPDF::Layout::Style::Layers, @style.underlays)
+ assert_kind_of(HexaPDF::Layout::Style::Layers, @style.overlays)
end
- it "can set and retrieve line spacing objects" do
- assert_equal([:proportional, 1], [@style.line_spacing.type, @style.line_spacing.value])
- @style.line_spacing = :double
- assert_equal([:proportional, 2], [@style.line_spacing.type, @style.line_spacing.value])
+ it "allows using a non-standard setter for generated properties" do
+ @style.padding = [5, 3]
+ assert_equal(5, @style.padding.top)
+ assert_equal(3, @style.padding.left)
+
+ @style.stroke_dash_pattern(5, 2)
+ assert_equal([[5], 2], @style.stroke_dash_pattern.to_operands)
end
- it "can set and retrieve text segmentation algorithms" do
- assert_equal(HexaPDF::Layout::TextBox::SimpleTextSegmentation,
+ it "allows checking whether a property has been set or accessed" do
+ refute(@style.align?)
+ assert_equal(:left, @style.align)
+ assert(@style.align?)
+
+ refute(@style.valign?)
+ @style.valign = :bottom
+ assert(@style.valign?)
+ end
+
+ it "has several dynamically generated properties with default values that take blocks" do
+ assert_equal(HexaPDF::Layout::TextLayouter::SimpleTextSegmentation,
@style.text_segmentation_algorithm)
+ assert_equal(HexaPDF::Layout::TextLayouter::SimpleLineWrapping,
+ @style.text_line_wrapping_algorithm)
+
block = proc { :y }
@style.text_segmentation_algorithm(&block)
assert_equal(block, @style.text_segmentation_algorithm)
- end
- it "can set and retrieve line wrapping algorithms" do
- assert_equal(HexaPDF::Layout::TextBox::SimpleLineWrapping,
- @style.text_line_wrapping_algorithm)
- @style.text_line_wrapping_algorithm(:callable)
- assert_equal(:callable, @style.text_line_wrapping_algorithm)
+ @style.text_segmentation_algorithm(:callable)
+ assert_equal(:callable, @style.text_segmentation_algorithm)
end
- it "has methods for some derived and cached values" do
- assert_equal(0.01, @style.scaled_font_size)
- assert_equal(0, @style.scaled_character_spacing)
- assert_equal(0, @style.scaled_word_spacing)
- assert_equal(1, @style.scaled_horizontal_scaling)
+ describe "methods for some derived and cached values" do
+ before do
+ wrapped_font = Object.new
+ wrapped_font.define_singleton_method(:ascender) { 600 }
+ wrapped_font.define_singleton_method(:descender) { -100 }
+ font = Object.new
+ font.define_singleton_method(:scaling_factor) { 1 }
+ font.define_singleton_method(:wrapped_font) { wrapped_font }
+ @style.font = font
+ end
- wrapped_font = Object.new
- wrapped_font.define_singleton_method(:ascender) { 600 }
- wrapped_font.define_singleton_method(:descender) { -100 }
- font = Object.new
- font.define_singleton_method(:scaling_factor) { 1 }
- font.define_singleton_method(:wrapped_font) { wrapped_font }
- @style.font = font
+ it "computes them correctly" do
+ @style.horizontal_scaling(200).character_spacing(1).word_spacing(2)
+ assert_equal(0.02, @style.scaled_font_size)
+ assert_equal(2, @style.scaled_character_spacing)
+ assert_equal(4, @style.scaled_word_spacing)
+ assert_equal(2, @style.scaled_horizontal_scaling)
- assert_equal(6, @style.scaled_font_ascender)
- assert_equal(-1, @style.scaled_font_descender)
+ assert_equal(6, @style.scaled_font_ascender)
+ assert_equal(-1, @style.scaled_font_descender)
+ end
+
+ it "computes item widths correctly" do
+ @style.horizontal_scaling(200).character_spacing(1).word_spacing(2)
+
+ assert_equal(-1.0, @style.scaled_item_width(50))
+
+ obj = Object.new
+ obj.define_singleton_method(:width) { 100 }
+ obj.define_singleton_method(:apply_word_spacing?) { true }
+ assert_equal(8, @style.scaled_item_width(obj))
+ end
+
+ it "handles subscript" do
+ @style.subscript = true
+ assert_in_delta(5.83, @style.calculated_font_size)
+ assert_in_delta(0.00583, @style.scaled_font_size, 0.000001)
+ assert_in_delta(-2.00, @style.calculated_text_rise)
+ end
+
+ it "handles superscript" do
+ @style.superscript = true
+ assert_in_delta(5.83, @style.calculated_font_size)
+ assert_in_delta(3.30, @style.calculated_text_rise)
+ end
+
+ it "handles underline" do
+ @style.font.wrapped_font.define_singleton_method(:underline_position) { -100 }
+ @style.font.wrapped_font.define_singleton_method(:underline_thickness) { 10 }
+ @style.text_rise = 10
+ assert_in_delta(-1.05 + 10, @style.calculated_underline_position)
+ assert_equal(0.1, @style.calculated_underline_thickness)
+ end
+
+ it "handles strikeout" do
+ @style.font.wrapped_font.define_singleton_method(:strikeout_position) { 300 }
+ @style.font.wrapped_font.define_singleton_method(:strikeout_thickness) { 10 }
+ @style.text_rise = 10
+ assert_in_delta(2.95 + 10, @style.calculated_strikeout_position)
+ assert_equal(0.1, @style.calculated_strikeout_thickness)
+ end
end
it "can clear cached values" do
assert_equal(0.01, @style.scaled_font_size)
@style.font_size = 20