Feature #3261 » pdf_export_image_support.patch
| test/unit/lib/redmine/export/pdf_test.rb (working copy) | ||
|---|---|---|
| 34 | 34 | 
    assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, nil)  | 
| 35 | 35 | 
    end  | 
| 36 | 36 | |
| 37 | 
      def test_rdm_pdf_iconv_cannot_convert_ja_cp932
   | 
|
| 37 | 
      def test_fix_text_decoding_nil
   | 
|
| 38 | 38 | 
    set_language_if_valid 'ja'  | 
| 39 | 39 | 
    assert_equal 'CP932', l(:general_pdf_encoding)  | 
| 40 | 
    if RUBY_VERSION < '1.9'  | 
|
| 41 | 
    if RUBY_PLATFORM == 'java'  | 
|
| 42 | 
            ic = Iconv.new("UTF-8", 'SJIS')
   | 
|
| 43 | 
    else  | 
|
| 44 | 
            ic = Iconv.new('UTF-8', l(:general_pdf_encoding))
   | 
|
| 45 | 
    end  | 
|
| 46 | 
    end  | 
|
| 47 | 
    assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, nil, true)  | 
|
| 48 | 
    end  | 
|
| 49 | ||
| 50 | 
    def test_rdm_pdf_iconv_cannot_convert_ja_to_cp932  | 
|
| 51 | 
    set_language_if_valid 'ja'  | 
|
| 52 | 
    assert_equal 'CP932', l(:general_pdf_encoding)  | 
|
| 40 | 53 | 
    if RUBY_VERSION < '1.9'  | 
| 41 | 54 | 
    if RUBY_PLATFORM == 'java'  | 
| 42 | 55 | 
            ic = Iconv.new("SJIS", 'UTF-8')
   | 
| ... | ... | |
| 44 | 57 | 
    ic = Iconv.new(l(:general_pdf_encoding), 'UTF-8')  | 
| 45 | 58 | 
    end  | 
| 46 | 59 | 
    end  | 
| 60 | 
    # \xe7\x8b\x80 : invalid UTF-8 character  | 
|
| 61 | 
    # \xe6\x85\x8b : valid UTF-8 character => \x91\xd4 : valid CP932 character  | 
|
| 47 | 62 | 
    utf8_txt_1 = "\xe7\x8b\x80\xe6\x85\x8b"  | 
| 48 | 63 | 
    utf8_txt_2 = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"  | 
| 49 | 64 | 
    utf8_txt_3 = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"  | 
| ... | ... | |
| 54 | 69 | 
    assert_equal "?\x91\xd4", txt_1  | 
| 55 | 70 | 
    assert_equal "?\x91\xd4?", txt_2  | 
| 56 | 71 | 
    assert_equal "??\x91\xd4?", txt_3  | 
| 72 | 
    assert_equal "UTF-8", utf8_txt_1.encoding.to_s  | 
|
| 73 | 
    assert_equal "UTF-8", utf8_txt_2.encoding.to_s  | 
|
| 74 | 
    assert_equal "UTF-8", utf8_txt_3.encoding.to_s  | 
|
| 57 | 75 | 
    assert_equal "ASCII-8BIT", txt_1.encoding.to_s  | 
| 58 | 76 | 
    assert_equal "ASCII-8BIT", txt_2.encoding.to_s  | 
| 59 | 77 | 
    assert_equal "ASCII-8BIT", txt_3.encoding.to_s  | 
| ... | ... | |
| 74 | 92 | 
    end  | 
| 75 | 93 | 
    end  | 
| 76 | 94 | |
| 95 | 
    def test_rdm_pdf_iconv_cannot_convert_from_cp932  | 
|
| 96 | 
    set_language_if_valid 'ja'  | 
|
| 97 | 
    assert_equal 'CP932', l(:general_pdf_encoding)  | 
|
| 98 | 
    if RUBY_VERSION < '1.9'  | 
|
| 99 | 
    if RUBY_PLATFORM == 'java'  | 
|
| 100 | 
            ic = Iconv.new("UTF-8", 'SJIS')
   | 
|
| 101 | 
    else  | 
|
| 102 | 
            ic = Iconv.new('UTF-8', l(:general_pdf_encoding))
   | 
|
| 103 | 
    end  | 
|
| 104 | 
    end  | 
|
| 105 | 
    # \x90\xff : invalid CP932 character  | 
|
| 106 | 
    # \x91\xd4 : valid CP932 character => \xe6\x85\x8b : valid UTF-8 character  | 
|
| 107 | 
    cp932_txt_1 = "\x90\xff\x91\xd4"  | 
|
| 108 | 
    cp932_txt_2 = "\x90\xff\x91\xd4\x90\xff"  | 
|
| 109 | 
    cp932_txt_3 = "\x90\xff\x90\xff\x91\xd4\x90\xff"  | 
|
| 110 | 
    if cp932_txt_1.respond_to?(:force_encoding)  | 
|
| 111 | 
    txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_1, true)  | 
|
| 112 | 
    txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_2, true)  | 
|
| 113 | 
    txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_3, true)  | 
|
| 114 | 
    assert_equal "ASCII-8BIT", cp932_txt_1.encoding.to_s  | 
|
| 115 | 
    assert_equal "ASCII-8BIT", cp932_txt_2.encoding.to_s  | 
|
| 116 | 
    assert_equal "ASCII-8BIT", cp932_txt_3.encoding.to_s  | 
|
| 117 | 
    assert_equal "UTF-8", txt_1.encoding.to_s  | 
|
| 118 | 
    assert_equal "UTF-8", txt_2.encoding.to_s  | 
|
| 119 | 
    assert_equal "UTF-8", txt_3.encoding.to_s  | 
|
| 120 | 
          assert_equal "??\xe6\x85\x8b", txt_1.force_encoding('ASCII-8BIT')
   | 
|
| 121 | 
          assert_equal "??\xe6\x85\x8b??", txt_2.force_encoding('ASCII-8BIT')
   | 
|
| 122 | 
          assert_equal "????\xe6\x85\x8b??", txt_3.force_encoding('ASCII-8BIT')
   | 
|
| 123 | 
    elsif RUBY_PLATFORM == 'java'  | 
|
| 124 | 
    assert_equal "????",  | 
|
| 125 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_1, true)  | 
|
| 126 | 
    assert_equal "??????",  | 
|
| 127 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_2, true)  | 
|
| 128 | 
    assert_equal "????????",  | 
|
| 129 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_3, true)  | 
|
| 130 | 
    else  | 
|
| 131 | 
    assert_equal "??\xe6\x85\x8b",  | 
|
| 132 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_1, true)  | 
|
| 133 | 
    assert_equal "??\xe6\x85\x8b??",  | 
|
| 134 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_2, true)  | 
|
| 135 | 
    assert_equal "????\xe6\x85\x8b??",  | 
|
| 136 | 
    Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, cp932_txt_3, true)  | 
|
| 137 | 
    end  | 
|
| 138 | 
    end  | 
|
| 139 | ||
| 77 | 140 | 
    def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en  | 
| 78 | 141 | 
    set_language_if_valid 'en'  | 
| 79 | 142 | 
    assert_equal 'UTF-8', l(:general_pdf_encoding)  | 
| ... | ... | |
| 86 | 149 | 
    end  | 
| 87 | 150 | 
    txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str1)  | 
| 88 | 151 | 
    txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str2)  | 
| 152 | 
    txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str1, true)  | 
|
| 153 | 
    txt_4 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str2, true)  | 
|
| 89 | 154 | 
    if txt_1.respond_to?(:force_encoding)  | 
| 155 | 
    assert_equal "UTF-8", str1.encoding.to_s  | 
|
| 156 | 
    assert_equal "UTF-8", str2.encoding.to_s  | 
|
| 90 | 157 | 
    assert_equal "ASCII-8BIT", txt_1.encoding.to_s  | 
| 91 | 158 | 
    assert_equal "ASCII-8BIT", txt_2.encoding.to_s  | 
| 159 | 
    assert_equal "ASCII-8BIT", txt_3.encoding.to_s  | 
|
| 160 | 
    assert_equal "ASCII-8BIT", txt_4.encoding.to_s  | 
|
| 92 | 161 | 
    end  | 
| 93 | 162 | 
    assert_equal "Texte encod? en ISO-8859-1", txt_1  | 
| 94 | 163 | 
    assert_equal "?a?b?c?d?e test", txt_2  | 
| 164 | 
    assert_equal "Texte encod? en ISO-8859-1", txt_3  | 
|
| 165 | 
    assert_equal "?a?b?c?d?e test", txt_4  | 
|
| 95 | 166 | 
    end  | 
| 96 | 167 | |
| 97 | 168 | 
    def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja  | 
| ... | ... | |
| 111 | 182 | 
    txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str1)  | 
| 112 | 183 | 
    txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv(ic, str2)  | 
| 113 | 184 | 
    if txt_1.respond_to?(:force_encoding)  | 
| 185 | 
    assert_equal "UTF-8", str1.encoding.to_s  | 
|
| 186 | 
    assert_equal "UTF-8", str2.encoding.to_s  | 
|
| 114 | 187 | 
    assert_equal "ASCII-8BIT", txt_1.encoding.to_s  | 
| 115 | 188 | 
    assert_equal "ASCII-8BIT", txt_2.encoding.to_s  | 
| 116 | 189 | 
    end  | 
| vendor/plugins/rfpdf/lib/tcpdf.rb (working copy) | ||
|---|---|---|
| 72 | 72 | 
    include Core::RFPDF  | 
| 73 | 73 | 
    include RFPDF::Math  | 
| 74 | 74 | 
     | 
| 75 | 
    def logger  | 
|
| 76 | 
    RAILS_DEFAULT_LOGGER  | 
|
| 77 | 
    end  | 
|
| 78 | ||
| 75 | 79 | 
    cattr_accessor :k_cell_height_ratio  | 
| 76 | 80 | 
    @@k_cell_height_ratio = 1.25  | 
| 77 | 81 | |
| ... | ... | |
| 2045 | 2049 | 
    if (@images[file].nil?)  | 
| 2046 | 2050 | 
    #First use of image, get info  | 
| 2047 | 2051 | 
    if (type == '')  | 
| 2048 | 
    				pos = file.rindex('.');
   | 
|
| 2049 | 
    if (pos == 0)  | 
|
| 2052 | 
    				pos = File::basename(file).rindex('.');
   | 
|
| 2053 | 
    				if (pos.nil? or pos == 0)
   | 
|
| 2050 | 2054 | 
    					Error('Image file has no extension and no type was specified: ' + file);
   | 
| 2051 | 2055 | 
    end  | 
| 2056 | 
    				pos = file.rindex('.');
   | 
|
| 2052 | 2057 | 
    type = file[pos+1..-1];  | 
| 2053 | 2058 | 
    end  | 
| 2054 | 2059 | 
    type.downcase!  | 
| 2055 | 2060 | 
    if (type == 'jpg' or type == 'jpeg')  | 
| 2056 | 2061 | 
    info=parsejpg(file);  | 
| 2057 | 
    elsif (type == 'png')  | 
|
| 2058 | 
    info=parsepng(file);  | 
|
| 2062 | 
    elsif (type == 'png' or type == 'gif')  | 
|
| 2063 | 
    img = Magick::ImageList.new(file)  | 
|
| 2064 | 
    img.format = "PNG" # convert to PNG from gif  | 
|
| 2065 | 
    img.opacity = 0 # PNG alpha channel delete  | 
|
| 2066 | 
    				File.open( @@k_path_cache + File::basename(file), 'w'){|f|
   | 
|
| 2067 | 
    f.binmode  | 
|
| 2068 | 
    f.print img.to_blob  | 
|
| 2069 | 
    f.close  | 
|
| 2070 | 
    }  | 
|
| 2071 | 
    info=parsepng( @@k_path_cache + File::basename(file));  | 
|
| 2072 | 
    File.delete( @@k_path_cache + File::basename(file))  | 
|
| 2059 | 2073 | 
    else  | 
| 2060 | 2074 | 
    #Allow for additional formats  | 
| 2061 | 2075 | 
    mtd='parse' + type;  | 
| ... | ... | |
| 2071 | 2085 | 
    end  | 
| 2072 | 2086 | 
    #Automatic width and height calculation if needed  | 
| 2073 | 2087 | 
    if ((w == 0) and (h == 0))  | 
| 2088 | 
    rescale_x = (@w - @r_margin - x) / (info['w'] / (@img_scale * @k))  | 
|
| 2089 | 
    rescale_x = 1 if rescale_x >= 1  | 
|
| 2090 | 
    if (y + info['h'] * rescale_x / (@img_scale * @k) > @page_break_trigger and !@in_footer and AcceptPageBreak())  | 
|
| 2091 | 
    #Automatic page break  | 
|
| 2092 | 
    if @pages[@page+1].nil?  | 
|
| 2093 | 
    ws = @ws;  | 
|
| 2094 | 
    if (ws > 0)  | 
|
| 2095 | 
    @ws = 0;  | 
|
| 2096 | 
    						out('0 Tw');
   | 
|
| 2097 | 
    end  | 
|
| 2098 | 
    AddPage(@cur_orientation);  | 
|
| 2099 | 
    if (ws > 0)  | 
|
| 2100 | 
    @ws = ws;  | 
|
| 2101 | 
    						out(sprintf('%.3f Tw', ws * @k));
   | 
|
| 2102 | 
    end  | 
|
| 2103 | 
    else  | 
|
| 2104 | 
    @page += 1;  | 
|
| 2105 | 
    end  | 
|
| 2106 | 
    y=@t_margin;  | 
|
| 2107 | 
    end  | 
|
| 2108 | 
    rescale_y = (@page_break_trigger - y) / (info['h'] / (@img_scale * @k))  | 
|
| 2109 | 
    rescale_y = 1 if rescale_y >= 1  | 
|
| 2110 | 
    rescale = rescale_y >= rescale_x ? rescale_x : rescale_y  | 
|
| 2111 | ||
| 2074 | 2112 | 
    #Put image at 72 dpi  | 
| 2075 | 2113 | 
    # 2004-06-14 :: Nicola Asuni, scale factor where added  | 
| 2076 | 
    w = info['w'] / (@img_scale * @k);  | 
|
| 2077 | 
    h = info['h'] / (@img_scale * @k);  | 
|
| 2078 | 
    end  | 
|
| 2079 | 
    if (w == 0)  | 
|
| 2114 | 
    w = info['w'] * rescale / (@img_scale * @k);  | 
|
| 2115 | 
    h = info['h'] * rescale / (@img_scale * @k);  | 
|
| 2116 | 
    elsif (w == 0)  | 
|
| 2080 | 2117 | 
    w = h * info['w'] / info['h'];  | 
| 2081 | 
    end  | 
|
| 2082 | 
    if (h == 0)  | 
|
| 2118 | 
    elsif (h == 0)  | 
|
| 2083 | 2119 | 
    h = w * info['h'] / info['w'];  | 
| 2084 | 2120 | 
    end  | 
| 2085 | 2121 | 
    		out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', w*@k, h*@k, x*@k, (@h-(y+h))*@k, info['i']));
   | 
| ... | ... | |
| 2842 | 2878 | 
    if (a.empty?)  | 
| 2843 | 2879 | 
    			Error('Missing or incorrect image file: ' + file);
   | 
| 2844 | 2880 | 
    end  | 
| 2845 | 
    if (a[2]!='JPEG')  | 
|
| 2881 | 
    		if (!a[2].nil? and a[2]!='JPEG')
   | 
|
| 2846 | 2882 | 
    			Error('Not a JPEG file: ' + file);
   | 
| 2847 | 2883 | 
    end  | 
| 2848 | 2884 | 
    if (a['channels'].nil? or a['channels']==3)  | 
| ... | ... | |
| 2855 | 2891 | 
    bpc=!a['bits'].nil? ? a['bits'] : 8;  | 
| 2856 | 2892 | 
    #Read whole file  | 
| 2857 | 2893 | 
    data='';  | 
| 2858 | 
    open(file,'rb') do |f|  | 
|
| 2894 | ||
| 2895 | 
    open( @@k_path_cache + File::basename(file),'rb') do |f|  | 
|
| 2859 | 2896 | 
    data<<f.read();  | 
| 2860 | 2897 | 
    end  | 
| 2898 | 
    File.delete( @@k_path_cache + File::basename(file))  | 
|
| 2899 | ||
| 2861 | 2900 | 
    		return {'w' => a[0],'h' => a[1],'cs' => colspace,'bpc' => bpc,'f'=>'DCTDecode','data' => data}
   | 
| 2862 | 2901 | 
    end  | 
| 2863 | 2902 | |
| ... | ... | |
| 2878 | 2917 | 
    end  | 
| 2879 | 2918 | 
    w=freadint(f);  | 
| 2880 | 2919 | 
    h=freadint(f);  | 
| 2881 | 
    bpc=f.read(1)[0];  | 
|
| 2920 | 
    		bpc=f.read(1).unpack('C')[0];
   | 
|
| 2882 | 2921 | 
    if (bpc>8)  | 
| 2883 | 2922 | 
    			Error('16-bit depth not supported: ' + file);
   | 
| 2884 | 2923 | 
    end  | 
| 2885 | 
    ct=f.read(1)[0];  | 
|
| 2924 | 
    		ct=f.read(1).unpack('C')[0];
   | 
|
| 2886 | 2925 | 
    if (ct==0)  | 
| 2887 | 2926 | 
    colspace='DeviceGray';  | 
| 2888 | 2927 | 
    elsif (ct==2)  | 
| ... | ... | |
| 2892 | 2931 | 
    else  | 
| 2893 | 2932 | 
    			Error('Alpha channel not supported: ' + file);
   | 
| 2894 | 2933 | 
    end  | 
| 2895 | 
    if (f.read(1)[0] != 0)  | 
|
| 2934 | 
    		if (f.read(1).unpack('C')[0] != 0)
   | 
|
| 2896 | 2935 | 
    			Error('Unknown compression method: ' + file);
   | 
| 2897 | 2936 | 
    end  | 
| 2898 | 
    		if (f.read(1)[0]!=0)
   | 
|
| 2937 | 
    		if (f.read(1).unpack('C')[0] != 0)
   | 
|
| 2899 | 2938 | 
    			Error('Unknown filter method: ' + file);
   | 
| 2900 | 2939 | 
    end  | 
| 2901 | 
    		if (f.read(1)[0]!=0)
   | 
|
| 2940 | 
    		if (f.read(1).unpack('C')[0] != 0)
   | 
|
| 2902 | 2941 | 
    			Error('Interlacing not supported: ' + file);
   | 
| 2903 | 2942 | 
    end  | 
| 2904 | 2943 | 
    f.read(4);  | 
| ... | ... | |
| 2918 | 2957 | 
    #Read transparency info  | 
| 2919 | 2958 | 
    t=f.read( n);  | 
| 2920 | 2959 | 
    if (ct==0)  | 
| 2921 | 
    trns = t[1][0]  | 
|
| 2960 | 
    					trns = t[1].unpack('C')[0]
   | 
|
| 2922 | 2961 | 
    elsif (ct==2)  | 
| 2923 | 
    					trns = t[[1][0], t[3][0], t[5][0]]
   | 
|
| 2962 | 
    					trns = t[[1].unpack('C')[0], t[3].unpack('C')[0], t[5].unpack('C')[0]]
   | 
|
| 2924 | 2963 | 
    else  | 
| 2925 | 2964 | 
    pos=t.include?(0.chr);  | 
| 2926 | 2965 | 
    if (pos!=false)  | 
| ... | ... | |
| 3762 | 3801 | 
    end  | 
| 3763 | 3802 | |
| 3764 | 3803 | 
    #  | 
| 3804 | 
    # Convert to accessible file path  | 
|
| 3805 | 
    # @param string :attrname image file name  | 
|
| 3806 | 
    # @access private  | 
|
| 3807 | 
    #  | 
|
| 3808 | 
    def getImageFilename( attrname )  | 
|
| 3809 | 
    # check of unsafe URI  | 
|
| 3810 | 
    if img.to_s =~ /[^-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]/n  | 
|
| 3811 | 
    URI.encode(attrname)  | 
|
| 3812 | 
    else  | 
|
| 3813 | 
    attrname  | 
|
| 3814 | 
    end  | 
|
| 3815 | 
    end  | 
|
| 3816 | ||
| 3817 | 
    #  | 
|
| 3765 | 3818 | 
    # Process opening tags.  | 
| 3766 | 3819 | 
    # @param string :tag tag name (in upcase)  | 
| 3767 | 3820 | 
    # @param string :attr tag attribute (in upcase)  | 
| ... | ... | |
| 3874 | 3927 | 
     | 
| 3875 | 3928 | 
    when 'img'  | 
| 3876 | 3929 | 
    if (!attrs['src'].nil?)  | 
| 3877 | 
    Write(@lasth, '!' + attrs['src'] + '!', '', fill);  | 
|
| 3878 | 
    =begin Comment out. Because not implement image output yet.  | 
|
| 3879 | 
    # replace relative path with real server path  | 
|
| 3880 | 
    attrs['src'] = attrs['src'].gsub(@@k_path_url_cache, @@k_path_cache);  | 
|
| 3930 | 
    # Only generates image include a pdf if RMagick is avalaible  | 
|
| 3931 | 
    unless Object.const_defined?(:Magick)  | 
|
| 3932 | 
    Write(@lasth, attrs['src'], '', fill);  | 
|
| 3933 | 
    return  | 
|
| 3934 | 
    end  | 
|
| 3935 | 
    file = getImageFilename(attrs['src'])  | 
|
| 3936 | 
    if (file.nil?)  | 
|
| 3937 | 
    Write(@lasth, attrs['src'], '', fill);  | 
|
| 3938 | 
    return  | 
|
| 3939 | 
    end  | 
|
| 3940 | ||
| 3881 | 3941 | 
    if (attrs['width'].nil?)  | 
| 3882 | 3942 | 
    attrs['width'] = 0;  | 
| 3883 | 3943 | 
    end  | 
| ... | ... | |
| 3885 | 3945 | 
    attrs['height'] = 0;  | 
| 3886 | 3946 | 
    end  | 
| 3887 | 3947 | 
     | 
| 3888 | 
    Image(attrs['src'], GetX(),GetY(), pixelsToMillimeters(attrs['width']), pixelsToMillimeters(attrs['height']));  | 
|
| 3889 | 
    #SetX(@img_rb_x);  | 
|
| 3890 | 
    SetY(@img_rb_y);  | 
|
| 3891 | 
    =end  | 
|
| 3948 | 
    begin  | 
|
| 3949 | 
    Image(file, GetX(),GetY(), pixelsToMillimeters(attrs['width']), pixelsToMillimeters(attrs['height']));  | 
|
| 3950 | 
    #SetX(@img_rb_x);  | 
|
| 3951 | 
    SetY(@img_rb_y);  | 
|
| 3952 | 
    rescue => err  | 
|
| 3953 | 
    						logger.error "pdf: Image: error: #{err.message}"
   | 
|
| 3954 | 
    Write(@lasth, attrs['src'], '', fill);  | 
|
| 3955 | 
    if File.file?( @@k_path_cache + File::basename(file))  | 
|
| 3956 | 
    File.delete( @@k_path_cache + File::basename(file))  | 
|
| 3957 | 
    end  | 
|
| 3958 | 
    end  | 
|
| 3892 | 3959 | 
    end  | 
| 3893 | 3960 | 
     | 
| 3894 | 3961 | 
    when 'ul', 'ol'  | 
| vendor/plugins/rfpdf/lib/core/rmagick.rb (working copy) | ||
|---|---|---|
| 57 | 57 | 
    end  | 
| 58 | 58 | |
| 59 | 59 | 
    out['bits'] = image.channel_depth  | 
| 60 | 
        File.open( TCPDF.k_path_cache + File::basename(filename), 'w'){|f|
   | 
|
| 61 | 
    f.binmode  | 
|
| 62 | 
    f.print image.to_blob  | 
|
| 63 | 
    f.close  | 
|
| 64 | 
    }  | 
|
| 60 | 65 | 
     | 
| 61 | 66 | 
    out  | 
| 62 | 67 | 
    end  | 
| 63 | 68 | 
     | 
| 64 | 
    end  | 
|
| 69 | 
    end  | 
|
| lib/redmine/export/pdf.rb (working copy) | ||
|---|---|---|
| 18 | 18 | 
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  | 
| 19 | 19 | |
| 20 | 20 | 
    require 'iconv'  | 
| 21 | 
    require 'rfpdf/fpdf'  | 
|
| 22 | 21 | 
    require 'fpdf/chinese'  | 
| 23 | 22 | 
    require 'fpdf/japanese'  | 
| 24 | 23 | 
    require 'fpdf/korean'  | 
| 24 | 
    require 'core/rmagick'  | 
|
| 25 | 25 | |
| 26 | 26 | 
    module Redmine  | 
| 27 | 27 | 
    module Export  | 
| ... | ... | |
| 34 | 34 | 
    attr_accessor :footer_date  | 
| 35 | 35 | |
| 36 | 36 | 
    def initialize(lang)  | 
| 37 | 
              @@k_path_cache = Rails.root.join('tmp', 'pdf')
   | 
|
| 38 | 
    FileUtils.mkdir_p @@k_path_cache unless File::exist?(@@k_path_cache)  | 
|
| 37 | 39 | 
    set_language_if_valid lang  | 
| 38 | 40 | 
    pdf_encoding = l(:general_pdf_encoding).upcase  | 
| 39 | 41 | 
    if RUBY_VERSION < '1.9'  | 
| 40 | 
    @ic = Iconv.new(pdf_encoding, 'UTF-8')  | 
|
| 42 | 
    @ic_encode = Iconv.new(pdf_encoding, 'UTF-8')  | 
|
| 43 | 
                @ic_decode = Iconv.new('UTF-8', pdf_encoding)
   | 
|
| 41 | 44 | 
    end  | 
| 42 | 45 | 
              super('P', 'mm', 'A4', (pdf_encoding == 'UTF-8'), pdf_encoding)
   | 
| 43 | 46 | 
    case current_language.to_s.downcase  | 
| ... | ... | |
| 104 | 107 | 
    end  | 
| 105 | 108 | |
| 106 | 109 | 
    def fix_text_encoding(txt)  | 
| 107 | 
    RDMPdfEncoding::rdm_pdf_iconv(@ic, txt)  | 
|
| 110 | 
              RDMPdfEncoding::rdm_pdf_iconv(@ic_encode, txt)
   | 
|
| 108 | 111 | 
    end  | 
| 109 | 112 | |
| 113 | 
    def fix_text_decoding(txt)  | 
|
| 114 | 
    RDMPdfEncoding::rdm_pdf_iconv(@ic_decode, txt, true)  | 
|
| 115 | 
    end  | 
|
| 116 | ||
| 110 | 117 | 
    def RDMCell(w ,h=0, txt='', border=0, ln=0, align='', fill=0, link='')  | 
| 111 | 118 | 
    Cell(w, h, fix_text_encoding(txt), border, ln, align, fill, link)  | 
| 112 | 119 | 
    end  | 
| ... | ... | |
| 115 | 122 | 
    MultiCell(w, h, fix_text_encoding(txt), border, align, fill, ln)  | 
| 116 | 123 | 
    end  | 
| 117 | 124 | |
| 118 | 
    def RDMwriteHTMLCell(w, h, x, y, html='', border=0, ln=1, fill=0)  | 
|
| 119 | 
    writeHTMLCell(w, h, x, y, fix_text_encoding(html), border, ln, fill)  | 
|
| 125 | 
    def RDMwriteHTMLCell(w, h, x, y, txt='', attachments=[], border=0, ln=1, fill=0)  | 
|
| 126 | 
    @attachments = attachments.sort_by(&:created_on).reverse  | 
|
| 127 | ||
| 128 | 
    writeHTMLCell(w, h, x, y,  | 
|
| 129 | 
    fix_text_encoding(Redmine::WikiFormatting.to_html(Setting.text_formatting, txt)),  | 
|
| 130 | 
    border, ln, fill)  | 
|
| 120 | 131 | 
    end  | 
| 121 | 132 | |
| 133 | 
    def getImageFilename(attrname)  | 
|
| 134 | 
    # attrname : general_pdf_encoding string file/uri name  | 
|
| 135 | 
    if /^https?:\/\//i =~ attrname  | 
|
| 136 | 
    uri = fix_text_decoding(attrname) # get original URI  | 
|
| 137 | ||
| 138 | 
    # check of unsafe URI  | 
|
| 139 | 
    if uri =~ /[^-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]/n  | 
|
| 140 | 
    return URI.encode(uri)  | 
|
| 141 | 
    else  | 
|
| 142 | 
    return uri  | 
|
| 143 | 
    end  | 
|
| 144 | 
    else  | 
|
| 145 | 
    for attachment in @attachments  | 
|
| 146 | 
    # attachment.filename : UTF-8 string name  | 
|
| 147 | 
    # attachment.diskfile : real server path file name  | 
|
| 148 | 
    if fix_text_encoding(attachment.filename) == attrname && File.file?(attachment.diskfile)  | 
|
| 149 | 
    return attachment.diskfile  | 
|
| 150 | 
    end  | 
|
| 151 | 
    end  | 
|
| 152 | 
    end  | 
|
| 153 | 
    return nil  | 
|
| 154 | 
    end  | 
|
| 155 | ||
| 122 | 156 | 
    def Footer  | 
| 123 | 157 | 
    SetFont(@font_for_footer, 'I', 8)  | 
| 124 | 158 | 
    SetY(-15)  | 
| ... | ... | |
| 344 | 378 | 
            pdf.SetFontStyle('B',9)
   | 
| 345 | 379 | 
    pdf.RDMCell(35+155, 5, l(:field_description), "LRT", 1)  | 
| 346 | 380 | 
            pdf.SetFontStyle('',9)
   | 
| 381 | ||
| 382 | 
    # Set resize image scale  | 
|
| 383 | 
    pdf.SetImageScale(1.6)  | 
|
| 347 | 384 | 
    pdf.RDMwriteHTMLCell(35+155, 5, 0, 0,  | 
| 348 | 
    Redmine::WikiFormatting.to_html(  | 
|
| 349 | 
    Setting.text_formatting, issue.description.to_s),"LRB")  | 
|
| 385 | 
    issue.description.to_s, issue.attachments, "LRB")  | 
|
| 350 | 386 | 
    pdf.Ln  | 
| 351 | 387 | |
| 352 | 388 | 
    if issue.changesets.any? &&  | 
| ... | ... | |
| 363 | 399 | 
    unless changeset.comments.blank?  | 
| 364 | 400 | 
                  pdf.SetFontStyle('',8)
   | 
| 365 | 401 | 
    pdf.RDMwriteHTMLCell(190,5,0,0,  | 
| 366 | 
    Redmine::WikiFormatting.to_html(  | 
|
| 367 | 
    Setting.text_formatting, changeset.comments.to_s), "")  | 
|
| 402 | 
    changeset.comments.to_s, issue.attachments, "")  | 
|
| 368 | 403 | 
    end  | 
| 369 | 404 | 
    pdf.Ln  | 
| 370 | 405 | 
    end  | 
| ... | ... | |
| 388 | 423 | 
    pdf.Ln unless journal.details.empty?  | 
| 389 | 424 | 
                pdf.SetFontStyle('',8)
   | 
| 390 | 425 | 
    pdf.RDMwriteHTMLCell(190,5,0,0,  | 
| 391 | 
    Redmine::WikiFormatting.to_html(  | 
|
| 392 | 
    Setting.text_formatting, journal.notes.to_s), "")  | 
|
| 426 | 
    journal.notes.to_s, issue.attachments, "")  | 
|
| 393 | 427 | 
    end  | 
| 394 | 428 | 
    pdf.Ln  | 
| 395 | 429 | 
    end  | 
| ... | ... | |
| 412 | 446 | |
| 413 | 447 | 
    class RDMPdfEncoding  | 
| 414 | 448 | 
    include Redmine::I18n  | 
| 415 | 
    def self.rdm_pdf_iconv(ic, txt)  | 
|
| 449 | 
            def self.rdm_pdf_iconv(ic, txt, toUTF8 = false)
   | 
|
| 416 | 450 | 
    txt ||= ''  | 
| 417 | 451 | 
    if txt.respond_to?(:force_encoding)  | 
| 418 | 
                txt.force_encoding('UTF-8')
   | 
|
| 419 | 452 | 
    if l(:general_pdf_encoding).upcase != 'UTF-8'  | 
| 420 | 
    txt = txt.encode(l(:general_pdf_encoding), :invalid => :replace,  | 
|
| 421 | 
    :undef => :replace, :replace => '?')  | 
|
| 453 | 
    if toUTF8 == false  | 
|
| 454 | 
                    txt.force_encoding('UTF-8')
   | 
|
| 455 | 
    txtar = txt.encode(l(:general_pdf_encoding), :invalid => :replace,  | 
|
| 456 | 
    :undef => :replace, :replace => '?')  | 
|
| 457 | 
                    txtar.force_encoding('ASCII-8BIT')
   | 
|
| 458 | 
    else  | 
|
| 459 | 
    txt.force_encoding(l(:general_pdf_encoding))  | 
|
| 460 | 
                    txtar = txt.encode('UTF-8', :invalid => :replace,
   | 
|
| 461 | 
    :undef => :replace, :replace => '?')  | 
|
| 462 | 
                    txt.force_encoding('ASCII-8BIT')
   | 
|
| 463 | 
    end  | 
|
| 422 | 464 | 
    else  | 
| 423 | 
    txt = Redmine::CodesetUtil.replace_invalid_utf8(txt)  | 
|
| 465 | 
                  txt.force_encoding('UTF-8')
   | 
|
| 466 | 
    txtar = Redmine::CodesetUtil.replace_invalid_utf8(txt)  | 
|
| 467 | 
                  txtar.force_encoding('ASCII-8BIT')
   | 
|
| 424 | 468 | 
    end  | 
| 425 | 
                txt.force_encoding('ASCII-8BIT')
   | 
|
| 469 | 
                txt = txtar
   | 
|
| 426 | 470 | 
    elsif RUBY_PLATFORM == 'java'  | 
| 427 | 471 | 
    begin  | 
| 428 | 
    ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')  | 
|
| 472 | 
    if toUTF8 == false  | 
|
| 473 | 
    ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')  | 
|
| 474 | 
    else  | 
|
| 475 | 
                    ic ||= Iconv.new('UTF-8', l(:general_pdf_encoding))
   | 
|
| 476 | 
    end  | 
|
| 429 | 477 | 
    txt = ic.iconv(txt)  | 
| 430 | 478 | 
    rescue  | 
| 431 | 479 | 
                  txt = txt.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
   | 
| 432 | 480 | 
    end  | 
| 433 | 481 | 
    else  | 
| 434 | 
    ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')  | 
|
| 482 | 
    if toUTF8 == false  | 
|
| 483 | 
    ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')  | 
|
| 484 | 
    else  | 
|
| 485 | 
                  ic ||= Iconv.new('UTF-8', l(:general_pdf_encoding))
   | 
|
| 486 | 
    end  | 
|
| 435 | 487 | 
    txtar = ""  | 
| 436 | 488 | 
    begin  | 
| 437 | 489 | 
    txtar += ic.iconv(txt)  |