rbpdf 1.18.7 → 1.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +12 -0
- data/Gemfile +3 -0
- data/README.md +1 -5
- data/Rakefile +10 -0
- data/lib/rbpdf.rb +715 -222
- data/lib/rbpdf/version.rb +1 -1
- data/rbpdf.gemspec +3 -3
- data/test/err_font1.rb +3 -0
- data/test/err_font2.rb +4 -0
- data/test/rbpdf_bidi_test.rb +85 -14
- data/test/rbpdf_bookmark_test.rb +1 -2
- data/test/rbpdf_cell_test.rb +1 -2
- data/test/rbpdf_content_test.rb +1 -1
- data/test/rbpdf_css_test.rb +1 -1
- data/test/rbpdf_dom_test.rb +1 -1
- data/test/rbpdf_font_func_test.rb +1 -1
- data/test/rbpdf_font_style_test.rb +1 -2
- data/test/rbpdf_font_test.rb +111 -1
- data/test/rbpdf_format_test.rb +1 -2
- data/test/rbpdf_func_test.rb +1 -1
- data/test/rbpdf_html_anchor_test.rb +107 -0
- data/test/rbpdf_html_func_test.rb +1 -1
- data/test/rbpdf_html_test.rb +196 -349
- data/test/rbpdf_htmlcell_test.rb +1 -1
- data/test/rbpdf_image_rmagick_test.rb +1 -2
- data/test/rbpdf_image_test.rb +1 -2
- data/test/rbpdf_test.rb +1 -1
- data/test/rbpdf_transaction_test.rb +1 -1
- data/test/rbpdf_viewerpreferences_test.rb +1 -1
- data/test/rbpdf_write_test.rb +1 -2
- data/test/test_helper.rb +2 -0
- metadata +38 -89
- data/lib/fonts/README.z +0 -2
- data/lib/fonts/arialunicid0_cw.rb +0 -1738
- data/lib/fonts/cid0cs.rb +0 -21
- data/lib/fonts/cid0ct.rb +0 -21
- data/lib/fonts/cid0jp.rb +0 -21
- data/lib/fonts/cid0kr.rb +0 -21
- data/lib/fonts/courier.rb +0 -37
- data/lib/fonts/dejavu-fonts-ttf-2.33/AUTHORS +0 -53
- data/lib/fonts/dejavu-fonts-ttf-2.33/BUGS +0 -3
- data/lib/fonts/dejavu-fonts-ttf-2.33/LICENSE +0 -99
- data/lib/fonts/dejavu-fonts-ttf-2.33/NEWS +0 -1315
- data/lib/fonts/dejavu-fonts-ttf-2.33/README +0 -59
- data/lib/fonts/dejavusans.ctg.z +0 -0
- data/lib/fonts/dejavusans.rb +0 -338
- data/lib/fonts/dejavusans.z +0 -0
- data/lib/fonts/dejavusansb.ctg.z +0 -0
- data/lib/fonts/dejavusansb.rb +0 -330
- data/lib/fonts/dejavusansb.z +0 -0
- data/lib/fonts/dejavusansbi.ctg.z +0 -0
- data/lib/fonts/dejavusansbi.rb +0 -297
- data/lib/fonts/dejavusansbi.z +0 -0
- data/lib/fonts/dejavusansi.ctg.z +0 -0
- data/lib/fonts/dejavusansi.rb +0 -305
- data/lib/fonts/dejavusansi.z +0 -0
- data/lib/fonts/freefont-20080912/AUTHORS +0 -191
- data/lib/fonts/freefont-20080912/COPYING +0 -341
- data/lib/fonts/freefont-20080912/CREDITS +0 -506
- data/lib/fonts/freefont-20080912/ChangeLog +0 -3320
- data/lib/fonts/freefont-20080912/INSTALL +0 -81
- data/lib/fonts/freefont-20080912/README +0 -108
- data/lib/fonts/freemono.ctg.z +0 -0
- data/lib/fonts/freemono.rb +0 -203
- data/lib/fonts/freemono.z +0 -0
- data/lib/fonts/freemonob.ctg.z +0 -0
- data/lib/fonts/freemonob.rb +0 -120
- data/lib/fonts/freemonob.z +0 -0
- data/lib/fonts/freemonobi.ctg.z +0 -0
- data/lib/fonts/freemonobi.rb +0 -84
- data/lib/fonts/freemonobi.z +0 -0
- data/lib/fonts/freemonoi.ctg.z +0 -0
- data/lib/fonts/freemonoi.rb +0 -136
- data/lib/fonts/freemonoi.z +0 -0
- data/lib/fonts/freesans.ctg.z +0 -0
- data/lib/fonts/freesans.rb +0 -196
- data/lib/fonts/freesans.z +0 -0
- data/lib/fonts/freesansb.ctg.z +0 -0
- data/lib/fonts/freesansb.rb +0 -136
- data/lib/fonts/freesansb.z +0 -0
- data/lib/fonts/freesansbi.ctg.z +0 -0
- data/lib/fonts/freesansbi.rb +0 -108
- data/lib/fonts/freesansbi.z +0 -0
- data/lib/fonts/freesansi.ctg.z +0 -0
- data/lib/fonts/freesansi.rb +0 -136
- data/lib/fonts/freesansi.z +0 -0
- data/lib/fonts/freeserif.ctg.z +0 -0
- data/lib/fonts/freeserif.rb +0 -285
- data/lib/fonts/freeserif.z +0 -0
- data/lib/fonts/freeserifb.ctg.z +0 -0
- data/lib/fonts/freeserifb.rb +0 -164
- data/lib/fonts/freeserifb.z +0 -0
- data/lib/fonts/freeserifbi.ctg.z +0 -0
- data/lib/fonts/freeserifbi.rb +0 -130
- data/lib/fonts/freeserifbi.z +0 -0
- data/lib/fonts/freeserifi.ctg.z +0 -0
- data/lib/fonts/freeserifi.rb +0 -151
- data/lib/fonts/freeserifi.z +0 -0
- data/lib/fonts/helvetica.rb +0 -34
- data/lib/fonts/helveticab.rb +0 -34
- data/lib/fonts/helveticabi.rb +0 -34
- data/lib/fonts/helveticai.rb +0 -34
- data/lib/fonts/hysmyeongjostdmedium.rb +0 -31
- data/lib/fonts/kozgopromedium.rb +0 -47
- data/lib/fonts/kozminproregular.rb +0 -46
- data/lib/fonts/msungstdlight.rb +0 -23
- data/lib/fonts/sjis.rb +0 -834
- data/lib/fonts/stsongstdlight.rb +0 -23
- data/lib/fonts/symbol.rb +0 -33
- data/lib/fonts/times.rb +0 -34
- data/lib/fonts/timesb.rb +0 -34
- data/lib/fonts/timesbi.rb +0 -34
- data/lib/fonts/timesi.rb +0 -34
- data/lib/fonts/uni2cid_ac15.rb +0 -23613
- data/lib/fonts/uni2cid_ag15.rb +0 -30222
- data/lib/fonts/uni2cid_aj16.rb +0 -15705
- data/lib/fonts/uni2cid_ak12.rb +0 -17530
- data/lib/fonts/zapfdingbats.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6206e410a85c6ea47f3464985c9a4a8c6673974
|
4
|
+
data.tar.gz: 43b4d2ce869cdab5244ed41582fcdcaaf269aa15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65e07e6d1a6a72cf760a6bf5492db77b08cd0ffa9dd32de92b65bb8ec5fff85b457c1c20ec28b4bce91a1b0216efa4f49292889995242cebf7bb6be16cbdeda6
|
7
|
+
data.tar.gz: c77b80be9193f445da757904c8937f01714aea5be51f82156af113c1e521128cbb413b8533e9a52027b0b16444e59ebec473ec7d73c01d5f6f22da1fe2bad54b
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
1.19.0 2015-11-20
|
2
|
+
- Update base version to TCPDF 5.2.000.
|
3
|
+
- IMPORTANT: Support for font subsetting was added by default to reduce the size of documents using large unicode font files.
|
4
|
+
If you embed the whole font in the PDF, the person on the other end can make changes to it even if he didn't have your font.
|
5
|
+
If you subset the font, file size of the PDF will be smaller but the person who receives your PDF would need to have your same font in order to make changes to your PDF.
|
6
|
+
- The signature of the SetFont() and AddFont() methods were changed to include the font subsetting option (subsetting is applied by default).
|
7
|
+
- html anchors support. (by Oleg German)
|
8
|
+
- Test framework is changed to test-unit.
|
9
|
+
This particular error will occur when the test suite is run from outside a Rails environment.
|
10
|
+
Support the test suite is run from outside a Rails environment.
|
11
|
+
- Fonts file was separated in rbpdf-font.gem.
|
12
|
+
|
1
13
|
1.18.7 2015-10-18
|
2
14
|
- Fixed case of missing HTML <pre> tag texts with whitespace. (use htmlentities gem liblary.)
|
3
15
|
- Fixed HTML Image function y position problem with png alpha image.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/naitoh/rbpdf.svg?branch=master)](https://travis-ci.org/naitoh/rbpdf)
|
1
2
|
|
2
3
|
# RBPDF Template Plugin
|
3
4
|
|
@@ -26,11 +27,6 @@ RBPDF is distributed via RubyGems, and can be installed the usual way that you i
|
|
26
27
|
|
27
28
|
==
|
28
29
|
|
29
|
-
If you are using HTML, it is recommended you install:
|
30
|
-
```
|
31
|
-
gem install htmlentities
|
32
|
-
```
|
33
|
-
|
34
30
|
If you are using image file, it is recommended you install:
|
35
31
|
```
|
36
32
|
gem install rmagick
|
data/Rakefile
CHANGED
@@ -1,2 +1,12 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
desc 'Run test_unit based test'
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
# To run test for only one file (or file path pattern)
|
7
|
+
# $ bundle exec rake test TEST=test/test_specified_path.rb
|
8
|
+
t.libs << "test"
|
9
|
+
t.test_files = Dir["test/rbpdf_*.rb"]
|
10
|
+
t.verbose = true
|
11
|
+
end
|
2
12
|
|
data/lib/rbpdf.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
#============================================================+
|
3
3
|
# File name : rbpdf.rb
|
4
4
|
# Begin : 2002-08-03
|
5
|
-
# Last Update : 2010-
|
5
|
+
# Last Update : 2010-06-02
|
6
6
|
# Author : Nicola Asuni
|
7
|
-
# Version : 5.
|
7
|
+
# Version : 5.2.000
|
8
8
|
# License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
|
9
9
|
# ----------------------------------------------------------------------------
|
10
10
|
# This program is free software: you can redistribute it and/or modify
|
@@ -48,11 +48,8 @@
|
|
48
48
|
|
49
49
|
require "rbpdf/version"
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
rescue LoadError
|
54
|
-
# This gem is not required - just nice to have.
|
55
|
-
end
|
51
|
+
require 'htmlentities'
|
52
|
+
require 'rbpdf-font'
|
56
53
|
|
57
54
|
begin
|
58
55
|
# RMagick 2.14.0
|
@@ -72,6 +69,7 @@ end
|
|
72
69
|
require 'core/rmagick'
|
73
70
|
|
74
71
|
# Needed to run the test suite outside of a Rails environment.
|
72
|
+
require 'rubygems' if RUBY_VERSION < '1.9' # Ruby 1.8.7
|
75
73
|
require 'action_view'
|
76
74
|
require 'tempfile'
|
77
75
|
require 'uri'
|
@@ -81,21 +79,7 @@ require 'uri'
|
|
81
79
|
#
|
82
80
|
|
83
81
|
|
84
|
-
PDF_PRODUCER = 'RBPDF 5.
|
85
|
-
|
86
|
-
module RBPDFFontDescriptor
|
87
|
-
@@descriptors = { 'freesans' => {} }
|
88
|
-
@@font_name = 'freesans'
|
89
|
-
|
90
|
-
def self.font(font_name)
|
91
|
-
@@descriptors[font_name.gsub(".rb", "")]
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.define(font_name = 'freesans')
|
95
|
-
@@descriptors[font_name] ||= {}
|
96
|
-
yield @@descriptors[font_name]
|
97
|
-
end
|
98
|
-
end
|
82
|
+
PDF_PRODUCER = 'RBPDF 5.2.000'
|
99
83
|
|
100
84
|
# == This is a Ruby class for generating PDF files on-the-fly without requiring external extensions.
|
101
85
|
# * This class is a Ruby port of the TCPDF class by Nicola Asuni (http://www.tcpdf.org).
|
@@ -285,6 +269,8 @@ class RBPDF
|
|
285
269
|
@@k_path_url = Dir.tmpdir
|
286
270
|
end
|
287
271
|
|
272
|
+
@@k_path_fonts = RBPDFFontDescriptor.getfontpath
|
273
|
+
|
288
274
|
# set disk caching
|
289
275
|
@diskcache = diskcache ? true : false
|
290
276
|
|
@@ -447,12 +433,15 @@ class RBPDF
|
|
447
433
|
@diffs ||= []
|
448
434
|
@images ||= {}
|
449
435
|
@links ||= []
|
436
|
+
@html_anchors ||= {}
|
437
|
+
@html_anchor_links ||= {}
|
450
438
|
@gradients ||= []
|
451
439
|
@in_footer ||= false
|
452
440
|
@lasth ||= 0
|
453
441
|
@font_family ||= 'helvetica'
|
454
442
|
@font_style ||= ''
|
455
443
|
@font_size_pt ||= 12
|
444
|
+
@font_subsetting ||= true
|
456
445
|
@underline ||= false
|
457
446
|
@overline ||= false
|
458
447
|
@linethrough ||= false
|
@@ -1540,6 +1529,8 @@ class RBPDF
|
|
1540
1529
|
# close page
|
1541
1530
|
endPage()
|
1542
1531
|
lastPage()
|
1532
|
+
resetLinksAfterCurrentPage()
|
1533
|
+
|
1543
1534
|
@state = 2
|
1544
1535
|
SetAutoPageBreak(false)
|
1545
1536
|
@y = @h - (1 / @k)
|
@@ -2612,11 +2603,12 @@ class RBPDF
|
|
2612
2603
|
# * BI or IB: bold italic
|
2613
2604
|
# [@param string :fontfile] The font definition file. By default, the name is built from the family and style, in lower case with no space.
|
2614
2605
|
# [@return array] containing the font data, or false in case of error.
|
2606
|
+
# [@param boolean :subset] if true embedd only a subset of the font (stores only the information related to the used characters); this option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font.
|
2615
2607
|
# [@access public]
|
2616
2608
|
# [@since 1.5]
|
2617
2609
|
# [@see] SetFont()
|
2618
2610
|
#
|
2619
|
-
def AddFont(family, style='', fontfile='')
|
2611
|
+
def AddFont(family, style='', fontfile='', subset=nil)
|
2620
2612
|
if empty_string(family)
|
2621
2613
|
if !empty_string(@font_family)
|
2622
2614
|
family = @font_family
|
@@ -2624,6 +2616,7 @@ class RBPDF
|
|
2624
2616
|
Error('Empty font family')
|
2625
2617
|
end
|
2626
2618
|
end
|
2619
|
+
subset = @font_subsetting if subset.nil?
|
2627
2620
|
|
2628
2621
|
family = family.downcase
|
2629
2622
|
if ((!@is_unicode) and (family == 'arial'))
|
@@ -2769,17 +2762,21 @@ class RBPDF
|
|
2769
2762
|
desc['ItalicAngle'] = -11
|
2770
2763
|
end
|
2771
2764
|
end
|
2772
|
-
setFontBuffer(fontkey, {'i' => @numfonts, 'type' => font_desc[:type], 'name' => sname, 'desc' => desc, 'cidinfo' => font_desc[:cidinfo], 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'dw' => font_desc[:dw], 'enc' => font_desc[:enc]})
|
2773
2765
|
elsif font_desc[:type] == 'core'
|
2774
2766
|
font_desc[:name] = @core_fonts[fontkey]
|
2767
|
+
subset = false
|
2775
2768
|
elsif (font_desc[:type] == 'TrueType') or (font_desc[:type] == 'Type1')
|
2776
2769
|
# ...
|
2770
|
+
subset = false
|
2777
2771
|
elsif font_desc[:type] == 'TrueTypeUnicode'
|
2778
2772
|
font_desc[:enc] = 'Identity-H'
|
2779
2773
|
else
|
2780
|
-
Error('Unknow font type: ' + type + '')
|
2774
|
+
Error('Unknow font type: ' + font_desc[:type] + '')
|
2781
2775
|
end
|
2782
|
-
|
2776
|
+
# initialize subsetchars to contain default ASCII values (0-255)
|
2777
|
+
subsetchars = Array.new(256, true)
|
2778
|
+
|
2779
|
+
setFontBuffer(fontkey, {'fontkey' => fontkey, 'i' => @numfonts, 'type' => font_desc[:type], 'name' => font_desc[:name], 'desc' => desc, 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'dw' => font_desc[:dw], 'enc' => font_desc[:enc], 'cidinfo' => font_desc[:cidinfo], 'file' => font_desc[:file], 'ctg' => font_desc[:ctg], 'subset' => subset, 'subsetchars' => subsetchars})
|
2783
2780
|
|
2784
2781
|
if (!font_desc[:diff].nil? and (!font_desc[:diff].empty?))
|
2785
2782
|
#Search existing encodings
|
@@ -2798,10 +2795,19 @@ class RBPDF
|
|
2798
2795
|
setFontSubBuffer(fontkey, 'diff', d)
|
2799
2796
|
end
|
2800
2797
|
if !empty_string(font_desc[:file])
|
2801
|
-
if
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2798
|
+
if @font_files[font_desc[:file]].nil?
|
2799
|
+
if (font_desc[:type] == 'TrueType') or (font_desc[:type] == 'TrueTypeUnicode')
|
2800
|
+
@font_files[font_desc[:file]] = {'length1' => font_desc[:originalsize], 'fontdir' => fontdir, 'subset' => subset, 'fontkeys' => [fontkey]}
|
2801
|
+
elsif font_desc[:type] != 'core'
|
2802
|
+
@font_files[font_desc[:file]] = {'length1' => font_desc[:size1], 'length2' => font_desc[:size2], 'fontdir' => fontdir, 'subset' => subset, 'fontkeys' => [fontkey]}
|
2803
|
+
end
|
2804
|
+
else
|
2805
|
+
# update fontkeys that are sharing this font file
|
2806
|
+
@font_files[font_desc[:file]]['subset'] = (@font_files[font_desc[:file]]['subset'] and subset)
|
2807
|
+
unless @font_files[font_desc[:file]]['fontkeys'].include? fontkey
|
2808
|
+
@font_files[font_desc[:file]]['fontkeys'] ||= []
|
2809
|
+
@font_files[font_desc[:file]]['fontkeys'].push fontkey
|
2810
|
+
end
|
2805
2811
|
end
|
2806
2812
|
end
|
2807
2813
|
return fontdata
|
@@ -2845,17 +2851,19 @@ class RBPDF
|
|
2845
2851
|
# or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined.
|
2846
2852
|
# [@param float :size] Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12
|
2847
2853
|
# [@param string :fontfile] The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
|
2854
|
+
# [@param boolean :subset] if true embedd only a subset of the font (stores only the information related to the used characters); this option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font.
|
2855
|
+
# [@author Nicola Asuni]
|
2848
2856
|
# [@access public]
|
2849
2857
|
# [@since 1.0]
|
2850
2858
|
# [@see] AddFont(), SetFontSize()
|
2851
2859
|
#
|
2852
|
-
def SetFont(family, style='', size=0, fontfile='')
|
2860
|
+
def SetFont(family, style='', size=0, fontfile='', subset=nil)
|
2853
2861
|
# Select a font; size given in points
|
2854
2862
|
if size == 0
|
2855
2863
|
size = @font_size_pt
|
2856
2864
|
end
|
2857
2865
|
# try to add font (if not already added)
|
2858
|
-
fontdata = AddFont(family, style, fontfile)
|
2866
|
+
fontdata = AddFont(family, style, fontfile, subset)
|
2859
2867
|
@font_family = fontdata['family']
|
2860
2868
|
@font_style = fontdata['style']
|
2861
2869
|
@current_font = getFontBuffer(fontdata['fontkey'])
|
@@ -3268,6 +3276,34 @@ class RBPDF
|
|
3268
3276
|
end
|
3269
3277
|
alias_method :break_the_page?, :BreakThePage?
|
3270
3278
|
|
3279
|
+
#
|
3280
|
+
# Removes SHY characters from text.
|
3281
|
+
# Unicode Data:
|
3282
|
+
# * Name : SOFT HYPHEN, commonly abbreviated as SHY
|
3283
|
+
# * HTML Entity (decimal): ­
|
3284
|
+
# * HTML Entity (hex): ­
|
3285
|
+
# * HTML Entity (named): ­
|
3286
|
+
# * How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]
|
3287
|
+
# * UTF-8 (hex): 0xC2 0xAD (c2ad)
|
3288
|
+
# * UTF-8 character: chr(194).chr(173)
|
3289
|
+
# [@param string :txt] input string
|
3290
|
+
# [@return string] without SHY characters.
|
3291
|
+
# [@access public]
|
3292
|
+
# [@since (4.5.019) 2009-02-28]
|
3293
|
+
#
|
3294
|
+
def removeSHY(txt='')
|
3295
|
+
txt = txt.dup
|
3296
|
+
txt.force_encoding('ASCII-8BIT') if txt.respond_to?(:force_encoding)
|
3297
|
+
txt.gsub!(/([\xc2]{1}[\xad]{1})/, '')
|
3298
|
+
if !@is_unicode
|
3299
|
+
txt.gsub!(/([\xad]{1})/, '')
|
3300
|
+
return txt
|
3301
|
+
end
|
3302
|
+
txt.force_encoding('UTF-8') if txt.respond_to?(:force_encoding)
|
3303
|
+
return txt
|
3304
|
+
end
|
3305
|
+
alias_method :remove_shy, :removeSHY
|
3306
|
+
|
3271
3307
|
#
|
3272
3308
|
# Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
|
3273
3309
|
# If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
|
@@ -3333,35 +3369,6 @@ class RBPDF
|
|
3333
3369
|
end
|
3334
3370
|
alias_method :cell, :Cell
|
3335
3371
|
|
3336
|
-
#
|
3337
|
-
# Removes SHY characters from text.
|
3338
|
-
# [@param string :txt] input string
|
3339
|
-
# [@return string] without SHY characters.
|
3340
|
-
# [@access public]
|
3341
|
-
# [@since (4.5.019) 2009-02-28]
|
3342
|
-
#
|
3343
|
-
def removeSHY(txt='')
|
3344
|
-
txt = txt.dup
|
3345
|
-
# Unicode Data
|
3346
|
-
# Name : SOFT HYPHEN, commonly abbreviated as SHY
|
3347
|
-
# HTML Entity (decimal): ­
|
3348
|
-
# HTML Entity (hex): ­
|
3349
|
-
# HTML Entity (named): ­
|
3350
|
-
# How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]
|
3351
|
-
# UTF-8 (hex): 0xC2 0xAD (c2ad)
|
3352
|
-
# UTF-8 character: chr(194).chr(173)
|
3353
|
-
|
3354
|
-
txt.force_encoding('ASCII-8BIT') if txt.respond_to?(:force_encoding)
|
3355
|
-
txt.gsub!(/([\xc2]{1}[\xad]{1})/, '')
|
3356
|
-
if !@is_unicode
|
3357
|
-
txt.gsub!(/([\xad]{1})/, '')
|
3358
|
-
return txt
|
3359
|
-
end
|
3360
|
-
txt.force_encoding('UTF-8') if txt.respond_to?(:force_encoding)
|
3361
|
-
return txt
|
3362
|
-
end
|
3363
|
-
alias_method :remove_shy, :removeSHY
|
3364
|
-
|
3365
3372
|
#
|
3366
3373
|
# Returns the PDF string code to print a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
|
3367
3374
|
# If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
|
@@ -5449,7 +5456,9 @@ class RBPDF
|
|
5449
5456
|
def Output(name='', dest='')
|
5450
5457
|
#Output PDF to some destination
|
5451
5458
|
#Finish document if necessary
|
5459
|
+
|
5452
5460
|
lastPage()
|
5461
|
+
|
5453
5462
|
if (@state < 3)
|
5454
5463
|
Close();
|
5455
5464
|
end
|
@@ -6446,8 +6455,521 @@ protected
|
|
6446
6455
|
return @apxo_obj_id
|
6447
6456
|
end
|
6448
6457
|
|
6458
|
+
#
|
6459
|
+
# Get ULONG from string (Big Endian 32-bit unsigned integer).
|
6460
|
+
# [@parameter string :str] string from where to extract value
|
6461
|
+
# [@parameter int :offset] point from where to read the data
|
6462
|
+
# [@return int] 32 bit value
|
6463
|
+
# [@author Nicola Asuni]
|
6464
|
+
# [@access protected]
|
6465
|
+
# [@since 5.2.000 (2010-06-02)]
|
6466
|
+
#
|
6467
|
+
def getULONG(str, offset)
|
6468
|
+
v = str[offset, 4].unpack('N')
|
6469
|
+
return v[0].to_i
|
6470
|
+
end
|
6471
|
+
|
6472
|
+
#
|
6473
|
+
# Get USHORT from string (Big Endian 16-bit unsigned integer).
|
6474
|
+
# [@parameter string :str] string from where to extract value
|
6475
|
+
# [@parameter int :offset] point from where to read the data
|
6476
|
+
# [@return int] 16 bit value
|
6477
|
+
# [@author Nicola Asuni]
|
6478
|
+
# [@access protected]
|
6479
|
+
# [@since 5.2.000 (2010-06-02)]
|
6480
|
+
#
|
6481
|
+
def getUSHORT(str, offset)
|
6482
|
+
v = str[offset, 2].unpack('n')
|
6483
|
+
return v[0].to_i
|
6484
|
+
end
|
6485
|
+
|
6486
|
+
#
|
6487
|
+
# Get SHORT from string (Big Endian 16-bit signed integer).
|
6488
|
+
# [@parameter string :str] string from where to extract value
|
6489
|
+
# [@parameter int :offset] point from where to read the data
|
6490
|
+
# [@return int] 16 bit value
|
6491
|
+
# [@author Nicola Asuni]
|
6492
|
+
# [@access protected]
|
6493
|
+
# [@since 5.2.000 (2010-06-02)]
|
6494
|
+
#
|
6495
|
+
def getSHORT(str, offset)
|
6496
|
+
v = str[offset, 2].unpack('s')
|
6497
|
+
return v[0].to_i
|
6498
|
+
end
|
6499
|
+
|
6500
|
+
#
|
6501
|
+
# Get BYTE from string (8-bit unsigned integer).
|
6502
|
+
# [@parameter string :str] string from where to extract value
|
6503
|
+
# [@parameter int :offset] point from where to read the data
|
6504
|
+
# [@return int] 8 bit value
|
6505
|
+
# [@author Nicola Asuni]
|
6506
|
+
# [@access protected]
|
6507
|
+
# [@since 5.2.000 (2010-06-02)]
|
6508
|
+
#
|
6509
|
+
def getBYTE(str, offset)
|
6510
|
+
v = str[offset, 1].unpack('C')
|
6511
|
+
return v[0].to_i
|
6512
|
+
end
|
6513
|
+
|
6514
|
+
#
|
6515
|
+
# Returns a subset of the TrueType font data without the unused glyphs.
|
6516
|
+
# [@parameter string :font] TrueType font data
|
6517
|
+
# [@parameter array :subsetchars] array of used characters (the glyphs to keep)
|
6518
|
+
# [@return string] a subset of TrueType font data without the unused glyphs
|
6519
|
+
# [@author Nicola Asuni]
|
6520
|
+
# [@access protected]
|
6521
|
+
# [@since 5.2.000 (2010-06-02)]
|
6522
|
+
#
|
6523
|
+
def getTrueTypeFontSubset(font, subsetchars)
|
6524
|
+
#ksort(subsetchars)
|
6525
|
+
offset = 0 # offset position of the font data
|
6526
|
+
if getULONG(font, offset) != 0x10000
|
6527
|
+
# sfnt version must be 0x00010000 for TrueType version 1.0.
|
6528
|
+
return font
|
6529
|
+
end
|
6530
|
+
offset += 4
|
6531
|
+
|
6532
|
+
# get number of tables
|
6533
|
+
numTables = getUSHORT(font, offset); offset += 2
|
6534
|
+
# skip searchRange, entrySelector and rangeShift
|
6535
|
+
offset += 6
|
6536
|
+
# tables array(Hash)
|
6537
|
+
table = {}
|
6538
|
+
# for each table
|
6539
|
+
numTables.times {
|
6540
|
+
# get table info
|
6541
|
+
tag = font[offset, 4]
|
6542
|
+
offset += 4
|
6543
|
+
|
6544
|
+
table[tag] = {}
|
6545
|
+
table[tag]['checkSum'] = getULONG(font, offset); offset += 4
|
6546
|
+
table[tag]['offset'] = getULONG(font, offset); offset += 4
|
6547
|
+
table[tag]['length'] = getULONG(font, offset); offset += 4
|
6548
|
+
}
|
6549
|
+
# check magicNumber
|
6550
|
+
offset = table['head']['offset'] + 12
|
6551
|
+
if getULONG(font, offset) != 0x5F0F3CF5
|
6552
|
+
# magicNumber must be 0x5F0F3CF5
|
6553
|
+
return font
|
6554
|
+
end
|
6555
|
+
offset += 4
|
6556
|
+
|
6557
|
+
# get offset mode (indexToLocFormat : 0 = short, 1 = long)
|
6558
|
+
offset = table['head']['offset'] + 50
|
6559
|
+
short_offset = (getSHORT(font, offset) == 0); offset += 2
|
6560
|
+
# get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table
|
6561
|
+
indexToLoc = []
|
6562
|
+
offset = table['loca']['offset']
|
6563
|
+
if short_offset
|
6564
|
+
# short version
|
6565
|
+
n = table['loca']['length'] / 2 # numGlyphs + 1
|
6566
|
+
n.times {|i|
|
6567
|
+
indexToLoc[i] = getUSHORT(font, offset) * 2; offset += 2
|
6568
|
+
}
|
6569
|
+
else
|
6570
|
+
# long version
|
6571
|
+
n = table['loca']['length'] / 4 # numGlyphs + 1
|
6572
|
+
n.times {|i|
|
6573
|
+
indexToLoc[i] = getULONG(font, offset); offset += 4
|
6574
|
+
}
|
6575
|
+
end
|
6576
|
+
# get glyphs indexes of chars from cmap table
|
6577
|
+
subsetglyphs = [] # glyph IDs on key
|
6578
|
+
subsetglyphs[0] = true # character codes that do not correspond to any glyph in the font should be mapped to glyph index 0
|
6579
|
+
offset = table['cmap']['offset'] + 2
|
6580
|
+
numEncodingTables = getUSHORT(font, offset); offset += 2
|
6581
|
+
encodingTables = []
|
6582
|
+
numEncodingTables.times {|i|
|
6583
|
+
encodingTables[i] ||= {}
|
6584
|
+
encodingTables[i]['platformID'] = getUSHORT(font, offset); offset += 2
|
6585
|
+
encodingTables[i]['encodingID'] = getUSHORT(font, offset); offset += 2
|
6586
|
+
encodingTables[i]['offset'] = getULONG(font, offset); offset += 4
|
6587
|
+
}
|
6588
|
+
encodingTables.each {|enctable|
|
6589
|
+
if (enctable['platformID'] == 3) and (enctable['encodingID'] == 0)
|
6590
|
+
modesymbol = true
|
6591
|
+
else
|
6592
|
+
modesymbol = false
|
6593
|
+
end
|
6594
|
+
offset = table['cmap']['offset'] + enctable['offset']
|
6595
|
+
format = getUSHORT(font, offset); offset += 2
|
6596
|
+
case format
|
6597
|
+
when 0 # Format 0: Byte encoding table
|
6598
|
+
offset += 4 # skip length and version/language
|
6599
|
+
256.times {|k|
|
6600
|
+
if subsetchars[k]
|
6601
|
+
g = getBYTE(font, offset); offset += 1
|
6602
|
+
subsetglyphs[g] = k
|
6603
|
+
else
|
6604
|
+
offset += 1
|
6605
|
+
end
|
6606
|
+
}
|
6607
|
+
when 2 # Format 2: High-byte mapping through table
|
6608
|
+
offset += 4 # skip length and version
|
6609
|
+
# to be implemented ...
|
6610
|
+
when 4 # Format 4: Segment mapping to delta values
|
6611
|
+
length = getUSHORT(font, offset); offset += 2
|
6612
|
+
offset += 2 # skip version/language
|
6613
|
+
segCount = getUSHORT(font, offset) / 2; offset += 2
|
6614
|
+
offset += 6 # skip searchRange, entrySelector, rangeShift
|
6615
|
+
endCount = [] # array of end character codes for each segment
|
6616
|
+
segCount.times {|k|
|
6617
|
+
endCount[k] = getUSHORT(font, offset); offset += 2
|
6618
|
+
}
|
6619
|
+
offset += 2 # skip reservedPad
|
6620
|
+
startCount = [] # array of start character codes for each segment
|
6621
|
+
segCount.times {|k|
|
6622
|
+
startCount[k] = getUSHORT(font, offset); offset += 2
|
6623
|
+
}
|
6624
|
+
idDelta = [] # delta for all character codes in segment
|
6625
|
+
segCount.times {|k|
|
6626
|
+
idDelta[k] = getUSHORT(font, offset); offset += 2
|
6627
|
+
}
|
6628
|
+
idRangeOffset = [] # Offsets into glyphIdArray or 0
|
6629
|
+
segCount.times {|k|
|
6630
|
+
idRangeOffset[k] = getUSHORT(font, offset); offset += 2
|
6631
|
+
}
|
6632
|
+
gidlen = (length / 2) - 8 - (4 * segCount)
|
6633
|
+
glyphIdArray = [] # glyph index array
|
6634
|
+
gidlen.times {|k|
|
6635
|
+
glyphIdArray[k] = getUSHORT(font, offset); offset += 2
|
6636
|
+
}
|
6637
|
+
segCount.times {|k|
|
6638
|
+
startCount[k].upto(endCount[k]) {|c|
|
6639
|
+
if subsetchars[c]
|
6640
|
+
if idRangeOffset[k] == 0
|
6641
|
+
g = c
|
6642
|
+
else
|
6643
|
+
gid = (idRangeOffset[k] / 2) + (c - startCount[k]) - (segCount - k)
|
6644
|
+
g = glyphIdArray[gid]
|
6645
|
+
end
|
6646
|
+
g += (idDelta[k] - 65536)
|
6647
|
+
if g < 0
|
6648
|
+
g = 0
|
6649
|
+
end
|
6650
|
+
subsetglyphs[g] = c
|
6651
|
+
end
|
6652
|
+
}
|
6653
|
+
}
|
6654
|
+
when 6 # Format 6: Trimmed table mapping
|
6655
|
+
offset += 4 # skip length and version/language
|
6656
|
+
firstCode = getUSHORT(font, offset); offset += 2
|
6657
|
+
entryCount = getUSHORT(font, offset); offset += 2
|
6658
|
+
entryCount.times {|k|
|
6659
|
+
c = k + firstCode
|
6660
|
+
if subsetchars[c]
|
6661
|
+
g = getUSHORT(font, offset); offset += 2
|
6662
|
+
subsetglyphs[g] = c
|
6663
|
+
else
|
6664
|
+
offset += 2
|
6665
|
+
end
|
6666
|
+
}
|
6667
|
+
when 8 # Format 8: Mixed 16-bit and 32-bit coverage
|
6668
|
+
offset += 10 # skip length and version
|
6669
|
+
# to be implemented ...
|
6670
|
+
when 10 # Format 10: Trimmed array
|
6671
|
+
offset += 10 # skip length and version/language
|
6672
|
+
startCharCode = getULONG(font, offset); offset += 4
|
6673
|
+
numChars = getULONG(font, offset); offset += 4
|
6674
|
+
numChars.times {|k|
|
6675
|
+
c = k + startCharCode
|
6676
|
+
if subsetchars[c]
|
6677
|
+
g = getUSHORT(font, offset); offset += 2
|
6678
|
+
subsetglyphs[g] = c
|
6679
|
+
else
|
6680
|
+
offset += 2
|
6681
|
+
end
|
6682
|
+
}
|
6683
|
+
when 12 # Format 12: Segmented coverage
|
6684
|
+
offset += 10 # skip length and version/language
|
6685
|
+
nGroups = getULONG(font, offset); offset += 4
|
6686
|
+
nGroups.times {|k|
|
6687
|
+
startCharCode = getULONG(font, offset); offset += 4
|
6688
|
+
endCharCode = getULONG(font, offset); offset += 4
|
6689
|
+
startGlyphCode = getULONG(font, offset); offset += 4
|
6690
|
+
startCharCode.upto(endCharCode) {|c|
|
6691
|
+
if subsetchars[c]
|
6692
|
+
subsetglyphs[startGlyphCode] = c
|
6693
|
+
end
|
6694
|
+
startGlyphCode += 1
|
6695
|
+
}
|
6696
|
+
}
|
6697
|
+
end
|
6698
|
+
}
|
6699
|
+
# sort glyphs by key
|
6700
|
+
#ksort(subsetglyphs)
|
6701
|
+
# add composite glyps to subsetglyphs and remove missing glyphs
|
6702
|
+
subsetglyphs.each_with_index {|val, key|
|
6703
|
+
next if val.nil?
|
6704
|
+
if indexToLoc[key]
|
6705
|
+
offset = table['glyf']['offset'] + indexToLoc[key]
|
6706
|
+
numberOfContours = getSHORT(font, offset); offset += 2
|
6707
|
+
if numberOfContours < 0 # composite glyph
|
6708
|
+
offset += 8 # skip xMin, yMin, xMax, yMax
|
6709
|
+
loop {
|
6710
|
+
flags = getUSHORT(font, offset); offset += 2
|
6711
|
+
glyphIndex = getUSHORT(font, offset); offset += 2
|
6712
|
+
if subsetglyphs[glyphIndex].nil? and indexToLoc[glyphIndex]
|
6713
|
+
# add missing glyphs
|
6714
|
+
subsetglyphs[glyphIndex] = true
|
6715
|
+
end
|
6716
|
+
# skip some bytes by case
|
6717
|
+
if (flags & 1) != 0
|
6718
|
+
offset += 4
|
6719
|
+
else
|
6720
|
+
offset += 2
|
6721
|
+
end
|
6722
|
+
if (flags & 8) != 0
|
6723
|
+
offset += 2
|
6724
|
+
elsif (flags & 64) != 0
|
6725
|
+
offset += 4
|
6726
|
+
elsif (flags & 128) != 0
|
6727
|
+
offset += 8
|
6728
|
+
end
|
6729
|
+
|
6730
|
+
break if (flags & 32) == 0
|
6731
|
+
}
|
6732
|
+
end
|
6733
|
+
else
|
6734
|
+
subsetglyphs.delete_at(key)
|
6735
|
+
end
|
6736
|
+
}
|
6737
|
+
# build new glyf table with only used glyphs
|
6738
|
+
glyf = ''
|
6739
|
+
glyfSize = 0
|
6740
|
+
# create new empty indexToLoc table
|
6741
|
+
newIndexToLoc = Array.new(indexToLoc.length, 0)
|
6742
|
+
goffset = 0
|
6743
|
+
subsetglyphs.each_with_index {|char, glyphID|
|
6744
|
+
next if char.nil?
|
6745
|
+
if indexToLoc[glyphID] and indexToLoc[glyphID + 1]
|
6746
|
+
start = indexToLoc[glyphID]
|
6747
|
+
length = indexToLoc[glyphID + 1] - start
|
6748
|
+
glyf << font[table['glyf']['offset'] + start, length]
|
6749
|
+
newIndexToLoc[glyphID] = goffset
|
6750
|
+
goffset += length
|
6751
|
+
end
|
6752
|
+
}
|
6753
|
+
# build new loca table
|
6754
|
+
loca = ''
|
6755
|
+
if short_offset
|
6756
|
+
newIndexToLoc.each {|offset|
|
6757
|
+
loca << [offset / 2].pack('n')
|
6758
|
+
}
|
6759
|
+
else
|
6760
|
+
newIndexToLoc.each {|offset|
|
6761
|
+
loca << [offset].pack('N')
|
6762
|
+
}
|
6763
|
+
end
|
6764
|
+
# array of table names to preserve (loca and glyf tables will be added later)
|
6765
|
+
# table_names = ['cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2', 'post', 'cvt ', 'fpgm', 'prep']
|
6766
|
+
table_names = ['head', 'hhea', 'hmtx', 'maxp', 'OS/2', 'cvt ', 'fpgm', 'prep']
|
6767
|
+
# get the tables to preserve
|
6768
|
+
offset = 12
|
6769
|
+
table.each {|tag, val|
|
6770
|
+
if table_names.include?(tag)
|
6771
|
+
table[tag]['data'] = font[table[tag]['offset'], table[tag]['length']]
|
6772
|
+
if tag == 'head'
|
6773
|
+
# set the checkSumAdjustment to 0
|
6774
|
+
table[tag]['data'] = table[tag]['data'][0, 8] + "\x0\x0\x0\x0" + table[tag]['data'][12..-1]
|
6775
|
+
end
|
6776
|
+
pad = 4 - (table[tag]['length'] % 4)
|
6777
|
+
if pad != 4
|
6778
|
+
# the length of a table must be a multiple of four bytes
|
6779
|
+
table[tag]['length'] += pad
|
6780
|
+
table[tag]['data'] << "\x0" * pad
|
6781
|
+
end
|
6782
|
+
table[tag]['offset'] = offset
|
6783
|
+
offset += table[tag]['length']
|
6784
|
+
# table[tag]['checkSum'] = getTTFtableChecksum(table[tag]['data'], table[tag]['length'])
|
6785
|
+
else
|
6786
|
+
table.delete(tag)
|
6787
|
+
end
|
6788
|
+
}
|
6789
|
+
# add loca
|
6790
|
+
|
6791
|
+
table['loca'] = {}
|
6792
|
+
table['loca']['data'] = loca
|
6793
|
+
table['loca']['length'] = loca.length
|
6794
|
+
pad = 4 - (table['loca']['length'] % 4)
|
6795
|
+
if pad != 4
|
6796
|
+
# the length of a table must be a multiple of four bytes
|
6797
|
+
table['loca']['length'] += pad
|
6798
|
+
table['loca']['data'] << "\x0" * pad
|
6799
|
+
end
|
6800
|
+
table['loca']['offset'] = offset
|
6801
|
+
table['loca']['checkSum'] = getTTFtableChecksum(table['loca']['data'], table['loca']['length'])
|
6802
|
+
offset += table['loca']['length']
|
6803
|
+
# add glyf
|
6804
|
+
table['glyf'] = {}
|
6805
|
+
table['glyf']['data'] = glyf
|
6806
|
+
table['glyf']['length'] = glyf.length
|
6807
|
+
pad = 4 - (table['glyf']['length'] % 4)
|
6808
|
+
if pad != 4
|
6809
|
+
# the length of a table must be a multiple of four bytes
|
6810
|
+
table['glyf']['length'] += pad
|
6811
|
+
table['glyf']['data'] << "\x0" * pad
|
6812
|
+
end
|
6813
|
+
table['glyf']['offset'] = offset
|
6814
|
+
table['glyf']['checkSum'] = getTTFtableChecksum(table['glyf']['data'], table['glyf']['length'])
|
6815
|
+
# rebuild font
|
6816
|
+
font = ''
|
6817
|
+
font << [0x10000].pack('N') # sfnt version
|
6818
|
+
numTables = table.length
|
6819
|
+
font << [numTables].pack('n') # numTables
|
6820
|
+
entrySelector = (Math.log(numTables) / Math.log(2.0)).floor
|
6821
|
+
|
6822
|
+
searchRange = 2 **entrySelector * 16
|
6823
|
+
rangeShift = numTables * 16 - searchRange
|
6824
|
+
font << [searchRange].pack('n') # searchRange
|
6825
|
+
font << [entrySelector].pack('n') # entrySelector
|
6826
|
+
font << [rangeShift].pack('n') # rangeShift
|
6827
|
+
offset = numTables * 16
|
6828
|
+
table.each{|tag, data|
|
6829
|
+
font << tag # tag
|
6830
|
+
font << [data['checkSum']].pack('N') # checkSum
|
6831
|
+
font << [data['offset'] + offset].pack('N') # offset
|
6832
|
+
font << [data['length']].pack('N') # length
|
6833
|
+
}
|
6834
|
+
table.each{|tag, data|
|
6835
|
+
font << data['data']
|
6836
|
+
}
|
6837
|
+
# set checkSumAdjustment on head table
|
6838
|
+
checkSumAdjustment = 0xB1B0AFBA - getTTFtableChecksum(font, font.length)
|
6839
|
+
font = font[0, table['head']['offset'] + 8] + [checkSumAdjustment].pack('N') + font[(table['head']['offset'] + 12)..-1]
|
6840
|
+
return font
|
6841
|
+
end
|
6842
|
+
|
6843
|
+
#
|
6844
|
+
# Returs the checksum of a TTF table.
|
6845
|
+
# [@parameter string :table] table to check
|
6846
|
+
# [@parameter int :length] lenght of table in bytes
|
6847
|
+
# [@return int] checksum
|
6848
|
+
# [@author Nicola Asuni]
|
6849
|
+
# [@access protected]
|
6850
|
+
# [@since 5.2.000 (2010-06-02)]
|
6851
|
+
#
|
6852
|
+
def getTTFtableChecksum(table, length)
|
6853
|
+
sum = 0
|
6854
|
+
tlen = length / 4
|
6855
|
+
offset = 0
|
6856
|
+
tlen.times {
|
6857
|
+
v = table[offset, 4].unpack('N')
|
6858
|
+
sum += v[0]
|
6859
|
+
offset += 4
|
6860
|
+
}
|
6861
|
+
sum %= 0x100000000
|
6862
|
+
sum = [sum].pack('N').unpack('N')
|
6863
|
+
return sum[0]
|
6864
|
+
end
|
6865
|
+
|
6866
|
+
#
|
6867
|
+
# Outputs font widths
|
6868
|
+
# [@parameter array :font] font data
|
6869
|
+
# [@parameter int :cidoffset] offset for CID values
|
6870
|
+
# [@return] PDF command string for font widths
|
6871
|
+
# [@author] Nicola Asuni
|
6872
|
+
# [@access protected]
|
6873
|
+
# [@since 4.4.000 (2008-12-07)]
|
6874
|
+
#
|
6875
|
+
def putfontwidths(font, cidoffset=0)
|
6876
|
+
font_cw = font['cw'].sort
|
6877
|
+
rangeid = 0
|
6878
|
+
range = []
|
6879
|
+
prevcid = -2
|
6880
|
+
prevwidth = -1
|
6881
|
+
interval = false
|
6882
|
+
range_interval = []
|
6883
|
+
# for each character
|
6884
|
+
font_cw.each {|cid, width|
|
6885
|
+
cid -= cidoffset
|
6886
|
+
if font['subset'] and (cid > 255) and font['subsetchars'][cid].nil?
|
6887
|
+
# ignore the unused characters (font subsetting)
|
6888
|
+
next
|
6889
|
+
end
|
6890
|
+
if width != font['dw']
|
6891
|
+
if cid == prevcid + 1
|
6892
|
+
# consecutive CID
|
6893
|
+
if width == prevwidth
|
6894
|
+
if width == range[rangeid][0]
|
6895
|
+
range[rangeid].push width
|
6896
|
+
else
|
6897
|
+
range[rangeid].pop
|
6898
|
+
# new range
|
6899
|
+
rangeid = prevcid
|
6900
|
+
range[rangeid] = []
|
6901
|
+
range[rangeid].push prevwidth
|
6902
|
+
range[rangeid].push width
|
6903
|
+
end
|
6904
|
+
interval = true
|
6905
|
+
range_interval[rangeid] = true
|
6906
|
+
else
|
6907
|
+
if interval
|
6908
|
+
# new range
|
6909
|
+
rangeid = cid
|
6910
|
+
range[rangeid] = []
|
6911
|
+
range[rangeid].push width
|
6912
|
+
else
|
6913
|
+
range[rangeid].push width
|
6914
|
+
end
|
6915
|
+
interval = false
|
6916
|
+
end
|
6917
|
+
else
|
6918
|
+
# new range
|
6919
|
+
rangeid = cid
|
6920
|
+
range[rangeid] = []
|
6921
|
+
range[rangeid].push width
|
6922
|
+
interval = false
|
6923
|
+
end
|
6924
|
+
prevcid = cid
|
6925
|
+
prevwidth = width
|
6926
|
+
end
|
6927
|
+
}
|
6928
|
+
# optimize ranges
|
6929
|
+
prevk = -1
|
6930
|
+
nextk = -1
|
6931
|
+
prevint = false
|
6932
|
+
range.each_with_index {|ws, k|
|
6933
|
+
cws = ws ? ws.length : 0
|
6934
|
+
if (k == nextk) and !prevint and (range_interval[k].nil? or (cws < 4))
|
6935
|
+
if !range_interval[k].nil?
|
6936
|
+
range_interval[k] = nil
|
6937
|
+
end
|
6938
|
+
range[prevk] = range[prevk].concat(range[k]) if range[k]
|
6939
|
+
range[k] = nil
|
6940
|
+
else
|
6941
|
+
prevk = k
|
6942
|
+
end
|
6943
|
+
nextk = k + cws
|
6944
|
+
if !range_interval[k].nil?
|
6945
|
+
if cws > 3
|
6946
|
+
prevint = true
|
6947
|
+
else
|
6948
|
+
prevint = false
|
6949
|
+
end
|
6950
|
+
range_interval[k] = nil
|
6951
|
+
nextk -= 1
|
6952
|
+
else
|
6953
|
+
prevint = false
|
6954
|
+
end
|
6955
|
+
}
|
6956
|
+
# output data
|
6957
|
+
w = ''
|
6958
|
+
range.each_with_index {|ws, k|
|
6959
|
+
if ws and ws.uniq.length == 1
|
6960
|
+
# interval mode is more compact
|
6961
|
+
w << ' ' + k.to_s + ' ' + (k + ws.length - 1).to_s + ' ' + ws[0].to_s
|
6962
|
+
elsif ws
|
6963
|
+
# range mode
|
6964
|
+
w << ' ' + k.to_s + ' [ ' + ws.join(' ') + ' ]'
|
6965
|
+
end
|
6966
|
+
}
|
6967
|
+
return ('/W [' + w + ' ]')
|
6968
|
+
end
|
6969
|
+
|
6449
6970
|
#
|
6450
6971
|
# Output fonts.
|
6972
|
+
# [@author Nicola Asuni]
|
6451
6973
|
# [@access protected]
|
6452
6974
|
#
|
6453
6975
|
def putfonts()
|
@@ -6455,7 +6977,7 @@ protected
|
|
6455
6977
|
@diffs.each do |diff|
|
6456
6978
|
#Encodings
|
6457
6979
|
newobj();
|
6458
|
-
out('
|
6980
|
+
out('<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' + diff + '] >> endobj')
|
6459
6981
|
end
|
6460
6982
|
@font_files.each do |file, info|
|
6461
6983
|
# search and get font file to embedd
|
@@ -6487,6 +7009,23 @@ protected
|
|
6487
7009
|
# Strip second binary header
|
6488
7010
|
font = font[0..info['length1']] + font[info['length1'] + 6]
|
6489
7011
|
end
|
7012
|
+
elsif info['subset'] and (!compressed or (compressed and Object.const_defined?(:Zlib)))
|
7013
|
+
|
7014
|
+
if compressed
|
7015
|
+
# uncompress font
|
7016
|
+
font = Zlib::Inflate.inflate(font)
|
7017
|
+
end
|
7018
|
+
# merge subset characters
|
7019
|
+
subsetchars = [] # used chars
|
7020
|
+
info['fontkeys'].each {|fontkey|
|
7021
|
+
fontinfo = getFontBuffer(fontkey)
|
7022
|
+
subsetchars += fontinfo['subsetchars']
|
7023
|
+
}
|
7024
|
+
font = getTrueTypeFontSubset(font, subsetchars)
|
7025
|
+
if compressed
|
7026
|
+
# recompress font
|
7027
|
+
font = Zlib::Deflate.deflate(font)
|
7028
|
+
end
|
6490
7029
|
end
|
6491
7030
|
newobj()
|
6492
7031
|
@font_files[file]['n'] = @n
|
@@ -6511,7 +7050,7 @@ protected
|
|
6511
7050
|
type = font['type'];
|
6512
7051
|
name = font['name'];
|
6513
7052
|
if (type=='core')
|
6514
|
-
#
|
7053
|
+
# standard core font
|
6515
7054
|
obj_id = newobj()
|
6516
7055
|
out = '<</Type /Font'
|
6517
7056
|
out << ' /Subtype /Type1'
|
@@ -6526,10 +7065,8 @@ protected
|
|
6526
7065
|
end
|
6527
7066
|
out << ' >> endobj'
|
6528
7067
|
out(out)
|
6529
|
-
elsif type == 'Type0'
|
6530
|
-
putType0(font)
|
6531
7068
|
elsif (type=='Type1' || type=='TrueType')
|
6532
|
-
#
|
7069
|
+
# additional Type1 or TrueType font
|
6533
7070
|
obj_id = newobj()
|
6534
7071
|
out = '<</Type /Font'
|
6535
7072
|
out << ' /Subtype /' + type
|
@@ -6569,7 +7106,7 @@ protected
|
|
6569
7106
|
end
|
6570
7107
|
out(s + '>> endobj')
|
6571
7108
|
else
|
6572
|
-
#
|
7109
|
+
# additional types
|
6573
7110
|
mtd='put' + type.downcase;
|
6574
7111
|
unless self.respond_to?(mtd, true)
|
6575
7112
|
Error('Unsupported font type: ' + type)
|
@@ -6581,145 +7118,6 @@ protected
|
|
6581
7118
|
end
|
6582
7119
|
end
|
6583
7120
|
|
6584
|
-
#
|
6585
|
-
# Outputs font widths
|
6586
|
-
# [@parameter array :font] font data
|
6587
|
-
# [@parameter int :cidoffset] offset for CID values
|
6588
|
-
# [@return] PDF command string for font widths
|
6589
|
-
# [@author] Nicola Asuni
|
6590
|
-
# [@access protected]
|
6591
|
-
# [@since 4.4.000 (2008-12-07)]
|
6592
|
-
#
|
6593
|
-
def putfontwidths(font, cidoffset=0)
|
6594
|
-
font_cw = font['cw'].sort
|
6595
|
-
rangeid = 0
|
6596
|
-
range = []
|
6597
|
-
prevcid = -2
|
6598
|
-
prevwidth = -1
|
6599
|
-
interval = false
|
6600
|
-
range_interval = []
|
6601
|
-
# for each character
|
6602
|
-
font_cw.each {|cid, width|
|
6603
|
-
cid -= cidoffset
|
6604
|
-
if width != font['dw']
|
6605
|
-
if cid == prevcid + 1
|
6606
|
-
# consecutive CID
|
6607
|
-
if width == prevwidth
|
6608
|
-
if width == range[rangeid][0]
|
6609
|
-
range[rangeid].push width
|
6610
|
-
else
|
6611
|
-
range[rangeid].pop
|
6612
|
-
# new range
|
6613
|
-
rangeid = prevcid
|
6614
|
-
range[rangeid] = []
|
6615
|
-
range[rangeid].push prevwidth
|
6616
|
-
range[rangeid].push width
|
6617
|
-
end
|
6618
|
-
interval = true
|
6619
|
-
range_interval[rangeid] = true
|
6620
|
-
else
|
6621
|
-
if interval
|
6622
|
-
# new range
|
6623
|
-
rangeid = cid
|
6624
|
-
range[rangeid] = []
|
6625
|
-
range[rangeid].push width
|
6626
|
-
else
|
6627
|
-
range[rangeid].push width
|
6628
|
-
end
|
6629
|
-
interval = false
|
6630
|
-
end
|
6631
|
-
else
|
6632
|
-
# new range
|
6633
|
-
rangeid = cid
|
6634
|
-
range[rangeid] = []
|
6635
|
-
range[rangeid].push width
|
6636
|
-
interval = false
|
6637
|
-
end
|
6638
|
-
prevcid = cid
|
6639
|
-
prevwidth = width
|
6640
|
-
end
|
6641
|
-
}
|
6642
|
-
# optimize ranges
|
6643
|
-
prevk = -1
|
6644
|
-
nextk = -1
|
6645
|
-
prevint = false
|
6646
|
-
range.each_with_index {|ws, k|
|
6647
|
-
cws = ws ? ws.length : 0
|
6648
|
-
if (k == nextk) and !prevint and (range_interval[k].nil? or (cws < 4))
|
6649
|
-
if !range_interval[k].nil?
|
6650
|
-
range_interval[k] = nil
|
6651
|
-
end
|
6652
|
-
range[prevk] = range[prevk].concat(range[k]) if range[k]
|
6653
|
-
range[k] = nil
|
6654
|
-
else
|
6655
|
-
prevk = k
|
6656
|
-
end
|
6657
|
-
nextk = k + cws
|
6658
|
-
if !range_interval[k].nil?
|
6659
|
-
if cws > 3
|
6660
|
-
prevint = true
|
6661
|
-
else
|
6662
|
-
prevint = false
|
6663
|
-
end
|
6664
|
-
range_interval[k] = nil
|
6665
|
-
nextk -= 1
|
6666
|
-
else
|
6667
|
-
prevint = false
|
6668
|
-
end
|
6669
|
-
}
|
6670
|
-
# output data
|
6671
|
-
w = ''
|
6672
|
-
range.each_with_index {|ws, k|
|
6673
|
-
if ws and ws.uniq.length == 1
|
6674
|
-
# interval mode is more compact
|
6675
|
-
w << ' ' + k.to_s + ' ' + (k + ws.length - 1).to_s + ' ' + ws[0].to_s
|
6676
|
-
elsif ws
|
6677
|
-
# range mode
|
6678
|
-
w << ' ' + k.to_s + ' [ ' + ws.join(' ') + ' ]'
|
6679
|
-
end
|
6680
|
-
}
|
6681
|
-
return ('/W [' + w + ' ]')
|
6682
|
-
end
|
6683
|
-
|
6684
|
-
def putType0(font)
|
6685
|
-
# Type0
|
6686
|
-
newobj()
|
6687
|
-
out('<</Type /Font')
|
6688
|
-
out('/Subtype /Type0')
|
6689
|
-
out('/BaseFont /'+font['name']+'-'+font['cMap'])
|
6690
|
-
out('/Encoding /'+font['cMap'])
|
6691
|
-
out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
|
6692
|
-
out('>>')
|
6693
|
-
out('endobj')
|
6694
|
-
# CIDFont
|
6695
|
-
newobj()
|
6696
|
-
out('<</Type /Font')
|
6697
|
-
out('/Subtype /CIDFontType0')
|
6698
|
-
out('/BaseFont /'+font['name'])
|
6699
|
-
out('/CIDSystemInfo <</Registry (Adobe) /Ordering ('+font['registry']['ordering']+') /Supplement '+font['registry']['supplement'].to_s+'>>')
|
6700
|
-
out('/FontDescriptor '+(@n+1).to_s+' 0 R')
|
6701
|
-
w='/W [1 ['
|
6702
|
-
font['cw'].keys.sort.each {|key|
|
6703
|
-
w+=font['cw'][key].to_s + " "
|
6704
|
-
}
|
6705
|
-
out(w+'] 231 325 500 631 [500] 326 389 500]')
|
6706
|
-
out('>>')
|
6707
|
-
out('endobj')
|
6708
|
-
# Font descriptor
|
6709
|
-
newobj()
|
6710
|
-
out('<</Type /FontDescriptor')
|
6711
|
-
out('/FontName /'+font['name'])
|
6712
|
-
out('/Flags 6')
|
6713
|
-
out('/FontBBox [0 -200 1000 900]')
|
6714
|
-
out('/ItalicAngle 0')
|
6715
|
-
out('/Ascent 800')
|
6716
|
-
out('/Descent -200')
|
6717
|
-
out('/CapHeight 800')
|
6718
|
-
out('/StemV 60')
|
6719
|
-
out('>>')
|
6720
|
-
out('endobj')
|
6721
|
-
end
|
6722
|
-
|
6723
7121
|
#
|
6724
7122
|
# Adds unicode fonts.
|
6725
7123
|
# Based on PDF Reference 1.3 (section 5)
|
@@ -6730,12 +7128,20 @@ protected
|
|
6730
7128
|
# [@since 1.52.0.TC005 (2005-01-05)]
|
6731
7129
|
#
|
6732
7130
|
def puttruetypeunicode(font)
|
7131
|
+
fontname = ''
|
7132
|
+
if font['subset']
|
7133
|
+
# change name for font subsetting
|
7134
|
+
subtag = sprintf('%06u', font['i'])
|
7135
|
+
subtag = subtag.gsub('0123456789', 'ABCDEFGHIJ')
|
7136
|
+
fontname << subtag + '+'
|
7137
|
+
end
|
7138
|
+
fontname << font['name']
|
6733
7139
|
# Type0 Font
|
6734
7140
|
# A composite font composed of other fonts, organized hierarchically
|
6735
7141
|
obj_id = newobj()
|
6736
7142
|
out = '<</Type /Font'
|
6737
7143
|
out << ' /Subtype /Type0'
|
6738
|
-
out << ' /BaseFont /' +
|
7144
|
+
out << ' /BaseFont /' + fontname + ''
|
6739
7145
|
out << ' /Name /F' + font['i'].to_s
|
6740
7146
|
out << ' /Encoding /' + font['enc']
|
6741
7147
|
out << ' /ToUnicode /Identity-H'
|
@@ -6749,7 +7155,7 @@ protected
|
|
6749
7155
|
newobj();
|
6750
7156
|
out = '<</Type /Font'
|
6751
7157
|
out << ' /Subtype /CIDFontType2'
|
6752
|
-
out << ' /BaseFont /' +
|
7158
|
+
out << ' /BaseFont /' + fontname
|
6753
7159
|
|
6754
7160
|
# A dictionary containing entries that define the character collection of the CIDFont.
|
6755
7161
|
|
@@ -6761,14 +7167,15 @@ protected
|
|
6761
7167
|
out << ' /FontDescriptor ' + (@n + 1).to_s + ' 0 R'
|
6762
7168
|
out << ' /DW ' + font['dw'].to_s + '' # default width
|
6763
7169
|
out << "\n" + putfontwidths(font, 0)
|
6764
|
-
out << ' /CIDToGIDMap ' + (@n + 2).to_s + ' 0 R
|
7170
|
+
out << ' /CIDToGIDMap ' + (@n + 2).to_s + ' 0 R'
|
7171
|
+
out << ' >> endobj'
|
6765
7172
|
out(out)
|
6766
7173
|
|
6767
7174
|
# Font descriptor
|
6768
7175
|
# A font descriptor describing the CIDFont default metrics other than its glyph widths
|
6769
7176
|
newobj();
|
6770
7177
|
out = '<</Type /FontDescriptor'
|
6771
|
-
out << ' /FontName /' +
|
7178
|
+
out << ' /FontName /' + fontname
|
6772
7179
|
font['desc'].each do |key, value|
|
6773
7180
|
if value.is_a? Float
|
6774
7181
|
value = sprintf('%.3f', value)
|
@@ -6949,6 +7356,17 @@ protected
|
|
6949
7356
|
end
|
6950
7357
|
end
|
6951
7358
|
|
7359
|
+
#
|
7360
|
+
# Maps HTML anchor links to anchors.
|
7361
|
+
# [@access protected]
|
7362
|
+
#
|
7363
|
+
def mapLinksToHtmlAnchors
|
7364
|
+
@html_anchors.each do |anchor, positon|
|
7365
|
+
links = @html_anchor_links.find_all { |url, link_anchor| link_anchor == anchor}
|
7366
|
+
links.each {|url, link_anchor| @links[url] = positon }
|
7367
|
+
end
|
7368
|
+
end
|
7369
|
+
|
6952
7370
|
#
|
6953
7371
|
# Output Spot Colors Resources.
|
6954
7372
|
# [@access protected[
|
@@ -7037,11 +7455,13 @@ protected
|
|
7037
7455
|
# [@access protected]
|
7038
7456
|
#
|
7039
7457
|
def putresources()
|
7458
|
+
mapLinksToHtmlAnchors()
|
7040
7459
|
putextgstates()
|
7041
7460
|
putocg()
|
7042
7461
|
putfonts();
|
7043
7462
|
putimages();
|
7044
7463
|
putspotcolors()
|
7464
|
+
|
7045
7465
|
#Resource dictionary
|
7046
7466
|
@offsets[2]=@bufferlen
|
7047
7467
|
putresourcedict();
|
@@ -7461,7 +7881,7 @@ protected
|
|
7461
7881
|
end
|
7462
7882
|
|
7463
7883
|
#
|
7464
|
-
# Read a 4-byte integer from file
|
7884
|
+
# Read a 4-byte (32 bit) integer from file
|
7465
7885
|
# [@param string :f] file name.
|
7466
7886
|
# [@return] 4-byte integer
|
7467
7887
|
# [@access protected]
|
@@ -7665,6 +8085,7 @@ protected
|
|
7665
8085
|
return strarr
|
7666
8086
|
end
|
7667
8087
|
|
8088
|
+
unichar = -1 # last unicode char
|
7668
8089
|
unicode = [] # array containing unicode values
|
7669
8090
|
bytes = [] # array containing single character byte sequences
|
7670
8091
|
numbytes = 1; # number of octetc needed to represent the UTF-8 character
|
@@ -7674,7 +8095,7 @@ protected
|
|
7674
8095
|
str.each_byte do |char|
|
7675
8096
|
if (bytes.length == 0) # get starting octect
|
7676
8097
|
if (char <= 0x7F)
|
7677
|
-
|
8098
|
+
unichar = char # use the character "as is" because is ASCII
|
7678
8099
|
numbytes = 1
|
7679
8100
|
elsif ((char >> 0x05) == 0x06) # 2 bytes character (0x06 = 110 BIN)
|
7680
8101
|
bytes << ((char - 0xC0) << 0x06)
|
@@ -7687,7 +8108,7 @@ protected
|
|
7687
8108
|
numbytes = 4
|
7688
8109
|
else
|
7689
8110
|
# use replacement character for other invalid sequences
|
7690
|
-
|
8111
|
+
unichar = 0xFFFD
|
7691
8112
|
bytes = []
|
7692
8113
|
numbytes = 1
|
7693
8114
|
end
|
@@ -7704,9 +8125,9 @@ protected
|
|
7704
8125
|
# U+D800 and U+DFFF, which are reserved for use with the UTF-16
|
7705
8126
|
# encoding form (as surrogate pairs) and do not directly represent
|
7706
8127
|
# characters
|
7707
|
-
|
8128
|
+
unichar = 0xFFFD # use replacement character
|
7708
8129
|
else
|
7709
|
-
|
8130
|
+
unichar = char # add char to array
|
7710
8131
|
end
|
7711
8132
|
# reset data for next char
|
7712
8133
|
bytes = []
|
@@ -7714,11 +8135,20 @@ protected
|
|
7714
8135
|
end
|
7715
8136
|
else
|
7716
8137
|
# use replacement character for other invalid sequences
|
7717
|
-
|
8138
|
+
unichar = 0xFFFD
|
7718
8139
|
bytes = []
|
7719
8140
|
numbytes = 1;
|
7720
8141
|
end
|
8142
|
+
if unichar >= 0
|
8143
|
+
# insert unicode value into array
|
8144
|
+
unicode.push unichar
|
8145
|
+
# store this char for font subsetting
|
8146
|
+
@current_font['subsetchars'][unichar] = true
|
8147
|
+
unichar = -1
|
8148
|
+
end
|
7721
8149
|
end
|
8150
|
+
# update font subsetchars
|
8151
|
+
setFontSubBuffer(@current_font['fontkey'], 'subsetchars', @current_font['subsetchars'])
|
7722
8152
|
# insert new value on cache
|
7723
8153
|
@cache_utf8_string_to_array[str] = unicode.dup
|
7724
8154
|
return unicode;
|
@@ -7864,6 +8294,26 @@ protected
|
|
7864
8294
|
# ====================================================
|
7865
8295
|
public
|
7866
8296
|
|
8297
|
+
#
|
8298
|
+
# Set Font Subsetting.
|
8299
|
+
# [@param boolean :subset] subset of the font default setting.
|
8300
|
+
# [@access public]
|
8301
|
+
#
|
8302
|
+
def setFontSubsetting(subset)
|
8303
|
+
@font_subsetting = (subset == true ? true : false)
|
8304
|
+
end
|
8305
|
+
alias_method :set_font_subsetting, :setFontSubsetting
|
8306
|
+
|
8307
|
+
#
|
8308
|
+
# Get Font Subsetting.
|
8309
|
+
# [@return boolean]
|
8310
|
+
# [@access public]
|
8311
|
+
#
|
8312
|
+
def getFontSubsetting()
|
8313
|
+
return @font_subsetting
|
8314
|
+
end
|
8315
|
+
alias_method :get_font_subsetting, :getFontSubsetting
|
8316
|
+
|
7867
8317
|
#
|
7868
8318
|
# Set header font.
|
7869
8319
|
# [@param array :font] font
|
@@ -7970,8 +8420,10 @@ public
|
|
7970
8420
|
def addHtmlLink(url, name, fill=0, firstline=false, color='', style=-1, firstblock=false)
|
7971
8421
|
if !empty_string(url) and (url[0, 1] == '#')
|
7972
8422
|
# convert url to internal link
|
7973
|
-
|
8423
|
+
anchor = url.sub(/^#/, "")
|
8424
|
+
page = anchor.to_i
|
7974
8425
|
url = AddLink()
|
8426
|
+
@html_anchor_links[url] = anchor
|
7975
8427
|
SetLink(url, 0, page)
|
7976
8428
|
end
|
7977
8429
|
# store current settings
|
@@ -7995,6 +8447,27 @@ public
|
|
7995
8447
|
end
|
7996
8448
|
alias_method :add_html_link, :addHtmlLink
|
7997
8449
|
|
8450
|
+
#
|
8451
|
+
# Adds HTML anchor and remembers it's position
|
8452
|
+
# [@param string :anchor] html anchor id
|
8453
|
+
# [@access public]
|
8454
|
+
#
|
8455
|
+
def addHtmlAnchor(anchor)
|
8456
|
+
@html_anchors[anchor] = [@page, @y]
|
8457
|
+
end
|
8458
|
+
alias_method :add_html_anchor, :addHtmlAnchor
|
8459
|
+
|
8460
|
+
#
|
8461
|
+
# Outputs HTML anchor position
|
8462
|
+
# [@param string :anchor] html anchor id
|
8463
|
+
# [@return array] [Page, Y] of anchor
|
8464
|
+
# [@access public]
|
8465
|
+
#
|
8466
|
+
def getHtmlAnchorPosition(anchor)
|
8467
|
+
@html_anchors[anchor]
|
8468
|
+
end
|
8469
|
+
alias_method :get_html_anchor_position, :getHtmlAnchorPosition
|
8470
|
+
|
7998
8471
|
#
|
7999
8472
|
# Returns an associative array (keys: R,G,B) from an html color name or a six-digit or three-digit hexadecimal color representation (i.e. #3FE5AA or #7FF).
|
8000
8473
|
# [@param string :color] html color
|
@@ -9476,7 +9949,7 @@ public
|
|
9476
9949
|
if arabic
|
9477
9950
|
endedletter = [1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688]
|
9478
9951
|
alfletter = [1570,1571,1573,1575]
|
9479
|
-
chardata2 = chardata
|
9952
|
+
chardata2 = chardata.dup
|
9480
9953
|
laaletter = false
|
9481
9954
|
charAL = []
|
9482
9955
|
x = 0
|
@@ -9492,7 +9965,7 @@ public
|
|
9492
9965
|
numAL = x
|
9493
9966
|
reg_AL_NSM = /^(AL|NSM)$/
|
9494
9967
|
numchars.times do |i|
|
9495
|
-
thischar = chardata[i]
|
9968
|
+
thischar = chardata[i].dup
|
9496
9969
|
if i > 0
|
9497
9970
|
prevchar = chardata[i-1]
|
9498
9971
|
else
|
@@ -9653,8 +10126,12 @@ public
|
|
9653
10126
|
ordarray = []
|
9654
10127
|
numchars.times do |i|
|
9655
10128
|
ordarray.push chardata[i][:char]
|
10129
|
+
# store char values for subsetting
|
10130
|
+
@current_font['subsetchars'][chardata[i][:char]] = true
|
9656
10131
|
end
|
9657
10132
|
|
10133
|
+
# update font subsetchars
|
10134
|
+
setFontSubBuffer(@current_font['fontkey'], 'subsetchars', @current_font['subsetchars'])
|
9658
10135
|
return ordarray
|
9659
10136
|
end
|
9660
10137
|
protected :utf8Bidi
|
@@ -10774,7 +11251,8 @@ protected
|
|
10774
11251
|
# create an array of elements
|
10775
11252
|
dom = []
|
10776
11253
|
dom[key] = {}
|
10777
|
-
# set first void element
|
11254
|
+
# set inheritable properties fot the first void element
|
11255
|
+
# possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing
|
10778
11256
|
dom[key]['tag'] = false
|
10779
11257
|
dom[key]['block'] = false
|
10780
11258
|
dom[key]['value'] = ''
|
@@ -10787,7 +11265,7 @@ protected
|
|
10787
11265
|
dom[key]['clip'] = (@textrendermode > 3)
|
10788
11266
|
dom[key]['line-height'] = @cell_height_ratio
|
10789
11267
|
dom[key]['bgcolor'] = ActiveSupport::OrderedHash.new
|
10790
|
-
dom[key]['fgcolor'] = @fgcolor.dup
|
11268
|
+
dom[key]['fgcolor'] = @fgcolor.dup # color
|
10791
11269
|
dom[key]['strokecolor'] = @strokecolor.dup
|
10792
11270
|
|
10793
11271
|
dom[key]['align'] = ''
|
@@ -11328,7 +11806,7 @@ public
|
|
11328
11806
|
# Escape '<' character for not tag case.
|
11329
11807
|
html = html.gsub(%r{(<+)([^/a-zA-Z])}){CGI.escapeHTML($1) + $2}.gsub(%r{</([^a-zA-Z])}){'</' + $1}
|
11330
11808
|
|
11331
|
-
html = "%s" % sanitize(html, :tags=> %w(a b blockquote body br dd del div dl dt em font h1 h2 h3 h4 h5 h6 hr i img li ol p pre small span strong sub sup table td th thead tr tt u ins ul), :attributes => %w(cellspacing cellpadding bgcolor color value width height src size colspan rowspan style align border face href dir class id nobr stroke strokecolor fill nested tablehead))
|
11809
|
+
html = "%s" % sanitize(html, :tags=> %w(a b blockquote body br dd del div dl dt em font h1 h2 h3 h4 h5 h6 hr i img li ol p pre small span strong sub sup table td th thead tr tt u ins ul), :attributes => %w(cellspacing cellpadding bgcolor color value width height src size colspan rowspan style align border face href name dir class id nobr stroke strokecolor fill nested tablehead))
|
11332
11810
|
end
|
11333
11811
|
protected :sanitize_html
|
11334
11812
|
|
@@ -12055,6 +12533,7 @@ public
|
|
12055
12533
|
opentagpos = nil
|
12056
12534
|
end
|
12057
12535
|
if dom[key]['tag']
|
12536
|
+
addHtmlAnchor(@html_anchor) if @html_anchor
|
12058
12537
|
if dom[key]['opening']
|
12059
12538
|
# get text indentation (if any)
|
12060
12539
|
if dom[key]['text-indent'] and dom[key]['block']
|
@@ -12625,6 +13104,8 @@ public
|
|
12625
13104
|
when 'a'
|
12626
13105
|
if tag['attribute'].key?('href')
|
12627
13106
|
@href['url'] = get_sever_url(tag['attribute']['href'])
|
13107
|
+
elsif tag['attribute'].key?('id') || tag['attribute'].key?('name')
|
13108
|
+
@html_anchor = tag['attribute']['id'] || tag['attribute']['name']
|
12628
13109
|
end
|
12629
13110
|
when 'img'
|
12630
13111
|
if !tag['attribute']['src'].nil?
|
@@ -13136,6 +13617,7 @@ public
|
|
13136
13617
|
end
|
13137
13618
|
when 'a'
|
13138
13619
|
@href = {}
|
13620
|
+
@html_anchor = nil
|
13139
13621
|
when 'sup'
|
13140
13622
|
SetXY(GetX(), GetY() + (0.7 * parent['fontsize'] / @k))
|
13141
13623
|
when 'sub'
|
@@ -13836,6 +14318,17 @@ protected
|
|
13836
14318
|
end
|
13837
14319
|
end
|
13838
14320
|
|
14321
|
+
|
14322
|
+
#
|
14323
|
+
# Reset all links that points to pages after current
|
14324
|
+
# [@access protected]
|
14325
|
+
#
|
14326
|
+
def resetLinksAfterCurrentPage()
|
14327
|
+
@links.each do |link|
|
14328
|
+
link[0] = @page if link.present? && link[0] > @page
|
14329
|
+
end
|
14330
|
+
end
|
14331
|
+
|
13839
14332
|
#
|
13840
14333
|
# Get font buffer content.
|
13841
14334
|
# [@param string :font] font key
|