lib/origami/graphics/text.rb in origami-1.2.7 vs lib/origami/graphics/text.rb in origami-2.0.0

- old
+ new

@@ -1,242 +1,225 @@ =begin -= File - graphics/text.rb + This file is part of Origami, PDF manipulation framework for Ruby + Copyright (C) 2016 Guillaume Delugré. -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org> - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + Origami is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. + Origami is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU Lesser General Public License + along with Origami. If not, see <http://www.gnu.org/licenses/>. =end module Origami - - module Text - OPERATORS = - [ - 'Tc', 'Tw', 'Tz', 'TL', 'Tf', 'Tr', 'Ts', # Text state - 'BT', 'ET', # Text objects - 'Td', 'TD', 'Tm', 'T*', # Positioning - 'Tj', "'", '"', 'TJ' # Showing - ] - - module Rendering - FILL = 0 - STROKE = 1 - FILL_AND_STROKE = 2 - INVISIBLE = 3 - FILL_AND_CLIP = 4 - STROKE_AND_CLIP = 5 - FILL_AND_STROKE_AND_CLIP = 6 - CLIP = 7 - end + module Text - class TextStateError < Exception #:nodoc: - end + OPERATORS = + [ + 'Tc', 'Tw', 'Tz', 'TL', 'Tf', 'Tr', 'Ts', # Text state + 'BT', 'ET', # Text objects + 'Td', 'TD', 'Tm', 'T*', # Positioning + 'Tj', "'", '"', 'TJ' # Showing + ] - class State + module Rendering + FILL = 0 + STROKE = 1 + FILL_AND_STROKE = 2 + INVISIBLE = 3 + FILL_AND_CLIP = 4 + STROKE_AND_CLIP = 5 + FILL_AND_STROKE_AND_CLIP = 6 + CLIP = 7 + end - attr_accessor :char_spacing, :word_spacing, :scaling, :leading - attr_accessor :font, :font_size - attr_accessor :rendering_mode - attr_accessor :text_rise, :text_knockout + class TextStateError < Error #:nodoc: + end - attr_accessor :text_matrix, :text_line_matrix, :text_rendering_matrix + class State + attr_accessor :char_spacing, :word_spacing, :scaling, :leading + attr_accessor :font, :font_size + attr_accessor :rendering_mode + attr_accessor :text_rise, :text_knockout - def initialize - self.reset - end + attr_accessor :text_matrix, :text_line_matrix, :text_rendering_matrix - def reset - - @char_spacing = 0 - @word_spacing = 0 - @scaling = 100 - @leading = 0 - @font = nil - @font_size = nil - @rendering_mode = Rendering::FILL - @text_rise = 0 - @text_knockout = true + def initialize + self.reset + end - # - # Text objects - # + def reset + @char_spacing = 0 + @word_spacing = 0 + @scaling = 100 + @leading = 0 + @font = nil + @font_size = nil + @rendering_mode = Rendering::FILL + @text_rise = 0 + @text_knockout = true - @text_object = false - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = nil + # + # Text objects + # - end + @text_object = false + @text_matrix = + @text_line_matrix = + @text_rendering_matrix = nil + end - def is_in_text_object? - @text_object - end + def is_in_text_object? + @text_object + end - def begin_text_object - if is_in_text_object? - raise TextStateError, - "Cannot start a text object within an existing text object." - end + def begin_text_object + if is_in_text_object? + raise TextStateError, "Cannot start a text object within an existing text object." + end - @text_object = true - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = Matrix.identity(3) - end + @text_object = true + @text_matrix = + @text_line_matrix = + @text_rendering_matrix = Matrix.identity(3) + end - def end_text_object - unless is_in_text_object? - raise TextStateError, - "Cannot end text object : no previous text object has begun." + def end_text_object + unless is_in_text_object? + raise TextStateError, "Cannot end text object : no previous text object has begun." + end + + @text_object = false + @text_matrix = + @text_line_matrix = + @text_rendering_matrix = nil + end + end #class State + end #module Text + + class PDF::Instruction + # + # Text instructions definitions + # + insn 'Tc', Real do |canvas, cS| canvas.gs.text_state.char_spacing = cS end + insn 'Tw', Real do |canvas, wS| canvas.gs.text_state.word_spacing = wS end + insn 'Tz', Real do |canvas, s| canvas.gs.text_state.scaling = s end + insn 'TL', Real do |canvas, l| canvas.gs.text_state.leading = l end + + insn 'Tf', Name, Real do |canvas, font, size| + canvas.gs.text_state.font = font + canvas.gs.text_state.font_size = size end - @text_object = false - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = nil - end + insn 'Tr', Integer do |canvas, r| canvas.gs.text_state.rendering_mode = r end + insn 'Ts', Real do |canvas, s| canvas.gs.text_state.text_rise = s end + insn 'BT' do |canvas| canvas.gs.text_state.begin_text_object end + insn 'ET' do |canvas| canvas.gs.text_state.end_text_object end - end #class State - - end #module Text + insn 'Td', Real, Real do |canvas, tx, ty| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : Td" + end - class PDF::Instruction - # Text instructions definitions - insn 'Tc', Real do |canvas, cS| canvas.gs.text_state.char_spacing = cS end - insn 'Tw', Real do |canvas, wS| canvas.gs.text_state.word_spacing = wS end - insn 'Tz', Real do |canvas, s| canvas.gs.text_state.scaling = s end - insn 'TL', Real do |canvas, l| canvas.gs.text_state.leading = l end - - insn 'Tf', Name, Real do |canvas, font, size| - canvas.gs.text_state.font = font - canvas.gs.text_state.font_size = size - end + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix + end - insn 'Tr', Integer do |canvas, r| canvas.gs.text_state.rendering_mode = r end - insn 'Ts', Real do |canvas, s| canvas.gs.text_state.text_rise = s end - insn 'BT' do |canvas| canvas.gs.text_state.begin_text_object end - insn 'ET' do |canvas| canvas.gs.text_state.end_text_object end - - insn 'Td', Real, Real do |canvas, tx, ty| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Td" - end + insn 'TD', Real, Real do |canvas, tx, ty| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : TD" + end - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - end + canvas.gs.text_state.leading = -ty - insn 'TD', Real, Real do |canvas, tx, ty| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : TD" - end + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * canvas.gs.text_state.text_line_matrix + end - canvas.gs.text_state.leading = -ty + insn 'Tm', Real, Real, Real, Real, Real, Real do |canvas, a,b,c,d,e,f,g| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : Tm" + end - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * canvas.gs.text_state.text_line_matrix - end + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[a,b,0],[c,d,0],[e,f,1]]) + end - insn 'Tm', Real, Real, Real, Real, Real, Real do |canvas, a,b,c,d,e,f,g| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Tm" - end + insn 'T*' do |canvas| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : T*" + end - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[a,b,0],[c,d,0],[e,f,1]]) - end + tx, ty = 0, -canvas.gs.text_state.leading - insn 'T*' do |canvas| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : T*" - end + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix + end - tx, ty = 0, -canvas.gs.text_state.leading + insn 'Tj', String do |canvas, s| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : Tj" + end - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - end + canvas.write_text(s) + end - insn 'Tj', String do |canvas, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Tj" - end + insn "'", String do |canvas, s| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : '" + end - canvas.write_text(s) - end + tx, ty = 0, -canvas.gs.text_state.leading - insn "'", String do |canvas, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : '" - end - - tx, ty = 0, -canvas.gs.text_state.leading + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix + canvas.write_text(s) + end - canvas.write_text(s) - end + insn '"', Real, Real, String do |canvas, w, c, s| + unless canvas.gs.text_state.is_in_text_object? + raise TextStateError, "Must be in a text object to use operator : \"" + end - insn '"', Real, Real, String do |canvas, w, c, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : \"" - end - - canvas.gs.text_state.word_spacing = w - canvas.gs.text_state.char_spacing = c + canvas.gs.text_state.word_spacing = w + canvas.gs.text_state.char_spacing = c - tx, ty = 0, -gs.text_state.leading + tx, ty = 0, -gs.text_state.leading - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix + canvas.gs.text_state.text_matrix = + canvas.gs.text_state.text_line_matrix = + Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - canvas.write_text(s) - end - - insn 'TJ', Array do |canvas, arr| - arr.each do |g| - case g - when Fixnum,Float then - # XXX: handle this in text space ? - when ::String then - canvas.write_text(g) - else - raise InvalidPDFInstructionError, - "Invalid component type `#{g.class}` in TJ operand" + canvas.write_text(s) end - end + + insn 'TJ', Array do |canvas, arr| + arr.each do |g| + case g + when Fixnum,Float then + # XXX: handle this in text space ? + when ::String then + canvas.write_text(g) + else + raise InvalidPDFInstructionError, + "Invalid component type `#{g.class}` in TJ operand" + end + end + end end - end end