Hello, world! PDF版
Posted feedbacks - Flatten
Nested Hiddenとりあえず。iTextで。
1 2 3 4 5 6 7 8 9 | import com.lowagie.text._
import com.lowagie.text.pdf.PdfWriter
import java.io.FileOutputStream
val document = new Document(PageSize.A4, 50, 50, 50, 50);
val writer = PdfWriter.getInstance(document, new FileOutputStream("HelloWorld.pdf"));
document.open
document.add(new Paragraph("Hello, world!", FontFactory.getFont(FontFactory.COURIER, 60, Font.BOLD)));
document.close
|
うわぁ、一番乗りそこねたぁ
1 2 3 4 5 6 | require 'rubygems'
require 'pdf/writer'
PDF::Writer.new do |pdf|
pdf.text "Hello, world!", :font_size => 150, :justification => true
pdf.save_as "50.pdf"
end
|
'http://ja.doukaku.org/50' のところを location.href に置き換えると,カレントページのPDF版を取得するブックマークレットになります。
see: HTML2PDF.BIZ
1 | javascript:location.href='http://www.html2pdf.biz/api?url='+'http://ja.doukaku.org/50'+'&ret=PDF'
|
HPDFというライブラリを利用する A4サイズにななめに入れてみました
see: hpdf
1 2 3 4 5 6 7 8 9 10 | import Graphics.PDF
import Data.Monoid
main = let document = rgbSpace
<> chooseFont Helvetica 57
<> applyMatrix (rotate (Degree 58))
<> fillText 25 (-28) "Hello, world!"
<> emptyPdf 210 297
in
writePdf "hello.pdf" document
|
あ、なるほど、確かに対角線に入れるのが一番大きいですね。
Apache FOP 等で
fop -c fop.xconf hello.fo hello.pdf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master
page-height="210mm" page-width="297mm"
margin-top="20mm" margin-bottom="20mm"
margin-left="20mm" margin-right="20mm"
master-name="Pagemaster-1" >
<fo:region-body
margin-top="5mm" margin-bottom="5mm"
margin-left="5mm" margin-right="5mm" />
<fo:region-before extent="10mm" />
<fo:region-after extent="10mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="Pagemaster-1" >
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="96pt" text-align="center">
Hello, world!
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
|
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash
cat << EOS > foo
\documentclass{article}
\usepackage{type1cm}
\begin{document}
{\fontsize{200pt}{220pt}\selectfont Hello World}
\end{document}
EOS
latex foo
dvipdfm foo
|
tag に TeX 入れるべきだったかな?
文字列の幅を取得する関数が、多分あるんだろうけど、見つけられなかったので ダミーの書き込みにより取得しているところが、ちょっとばかり冗漫ですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from reportlab.pdfgen import canvas
c = canvas.Canvas('hello.pdf')
t = c.beginText()
t.setFont(t._fontname, 64)
t.setTextOrigin(0, 0)
t.textOut('Hello, World')
h = 64 / t.getX() * c._pagesize[1]
t.setFont(t._fontname, h)
c.setFontSize(h)
c.rotate(-90)
c.drawString(-c._pagesize[1], t._leading - h, 'Hello, World')
c.save()
|
他の人のコードを見たら、サイズ決め打ちでやってるようなので 同等の必要最小限版を投稿しておきます。
1 2 3 4 5 6 7 | from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
c = canvas.Canvas('hello.pdf', A4[::-1])
c.setFontSize(158.4)
c.drawString(0, 31.52, 'Hello, World')
c.save()
|
see: Trampoline!
1 2 3 4 5 6 7 | package require trampoline
. configure -menu [menu .menu]
.menu add command -label {Save as PDF} -command {::pdf::generate .c hello.pdf}
pack [canvas .c -width 297 -height 210 -bg white]
.c create text 150 105 -text "Hello,\nWorld!" -font {Helvetica 70} -justify center
|
連続投稿で失礼します。 #2480は、まだ無駄なコードが多かったので、ブラッシュアップ版を 投稿させてください。
1 2 3 4 5 6 7 8 9 10 | from reportlab.pdfgen import canvas
c = canvas.Canvas('hello.pdf')
t = c.beginText()
t.setFont(t._fontname, 64)
t.textOut('Hello, World')
c.setFont(c._fontname, 64 / t.getX() * c._pagesize[1])
c.rotate(-90)
c.drawString(-c._pagesize[1], c._leading - c._fontsize, 'Hello, World')
c.save()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | | file pdfWriter page text textState textPositioning |
file := FileStream fileNamed: 'doukaku50.pdf'.
pdfWriter := PDFWriter on: file.
pdfWriter compressionOff.
page := pdfWriter defaultPage.
text := PDFTextObject for: page pageDescription.
textState := PDFTextState for: text.
textState fontPitch: 140.
textState font: (PDFFont type1Helvetica).
textPositioning := PDFTextPositioning for: text.
textPositioning coordinate: (PDFPoint x: 10 y: 250).
text addOperator: textPositioning.
text addOperator: textState.
text write: 'Hello, world!'.
page addTextObject: text.
pdfWriter close.
file close
|
see: iText Homepage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import java.io.FileOutputStream;
import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.PageSize;
import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;
public class Sample {
static final String TEXT = "Hello, World!";
public static void main(String[] args) throws Exception {
Document doc = new Document(PageSize.A0.rotate());
PdfWriter.getInstance(doc, new FileOutputStream("HelloWorld.pdf"));
doc.open();
BaseFont bf = BaseFont.createFont(BaseFont.TIMES_ROMAN,
"US-ASCII", false);
float s = (doc.right() - doc.left() - doc.rightMargin()) /
bf.getWidthPoint(TEXT, 1.0f);
Font f = new Font(Font.TIMES_ROMAN, s);
doc.add(new Paragraph(TEXT, f));
doc.close();
}
}
|
xycairo (xyzzy の cairo バインディング) を使って書きました。 cl-cairo2 を使えばもう少しシンプルに書けると思います
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | (require :cairo)
(use-package :cairo)
(use-package :cairo.ext)
(defun hello-pdf (width height text)
(flet ((calc-font-size (cr x text)
(with-cairo-save (cr)
(cairo-set-font-size cr 100.0)
(* 100.0 (/ x (cdr (assoc :width (cairo-text-extents-alist cr text))))))))
(with-cairo-surface (surface (cairo-pdf-surface-create "hello.pdf" width height))
(with-cairo (cr (cairo-create surface))
(cairo-set-source-rgb cr 0 0 0) ; black
(cairo-set-font-size cr (calc-font-size cr width text))
(cairo-move-to cr 0 (/ height 2))
(cairo-show-text cr text)))))
(hello-pdf 291 210 "Hello, world!")
|
ページいっぱいにテキストを出力するために text extents から font size を計算していたが、
http://mmon.sourceforge.jp/memo/memo.html
を見ると width より x_advance を使ったほうがよさそうなのでそうしました。
see: Rubyist Magazine - cairo: 2 次元画像描画ライブラリ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | require 'cairo'
width, height = 291, 210
text = "Hello, world!"
Cairo::PDFSurface.new("hello.pdf", width, height) do |surface|
cr = Cairo::Context.new(surface)
font_size = cr.save {
cr.set_font_size(100.0)
width / cr.text_extents(text).x_advance * 100.0
}
cr.set_font_size(font_size)
cr.move_to(0, height / 2)
cr.show_text(text)
cr.show_page
end
|
FPDFを利用。 横長のA4で出力します。
see: FPDF
1 2 3 4 5 6 7 8 9 | <?php
require('fpdf/fpdf.php');
$pdf = new FPDF('L');
$pdf->AddPage();
$pdf->SetFont('Arial', '', 154);
$pdf->Text(0, 50, "Hello, world!");
$pdf->Output();
?>
|
shだったりps{2,to}pdfだったり使ってるのでちとアレですが、A4いっぱいのこんにちはなのでご容赦ください。。。
gs付属のps2pdfと、Mac OS Xのpstopdfで動作確認しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/bin/sh
large_hello() {
cat <<'EOHELLO'
%!
/inch {72 mul} bind def
/sheetheight 11.64 inch def
/sheetwidth 8.27 inch def
/hello (Hello, world!) def
/hellolen hello length def
/fontsz 10 def
/Helvetica fontsz selectfont
/capheightratio 0.8 def
0 0 moveto
sheetwidth hello stringwidth pop div
sheetheight fontsz capheightratio mul div
scale
hello show
showpage
EOHELLO
}
large_hello | {
outfile=large-hello.pdf
if type -p pstopdf >/dev/null; then
pstopdf /dev/stdin -o $outfile
elif type -p ps2pdf >/dev/null; then
ps2pdf /dev/stdin $outfile
else
echo 'converter not found...'
exit 1
fi
}
|
決め打ちです
1 2 3 4 5 6 7 | pdf("helloworld.pdf", width=8.27, height=11.69)
plot.new()
oldpar <- par(no.readonly = TRUE)
par(plt=c(0,1,0,1), mai=c(0,0,0,0), omi=c(0,0,0,0), adj=0, cex=9.2)
text(-0.178, 0.5, "Hello, world!")
par(oldpar)
dev.off()
|
plot.new()してからpar()してた。どおりで余白が反映されないと思った・・・。 すみません、ほとんど変化ないですが直します。
1 2 3 4 5 6 7 | pdf("helloworld.pdf", width=8.27, height=11.69)
oldpar <- par(no.readonly = TRUE)
par(plt=c(0,1,0,1), mai=c(0,0,0,0), omi=c(0,0,0,0), adj=0, cex=9.2)
plot.new()
text(-0.05, 0.5, "Hello, world!")
par(oldpar)
dev.off()
|
panda(http://www.stillhq.com/panda/)を使いました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h>
#include <stdlib.h>
#include <panda/functions.h>
#include <panda/constants.h>
int main(int argc, char *argv[])
{
panda_pdf *pdf;
panda_page *page;
panda_init();
pdf = panda_open ("hello.pdf", "w");
if(!pdf) panda_error(panda_true, "error");
page = panda_newpage(pdf, panda_pagesize_a4);
panda_setfontsize(pdf, 72);
panda_textbox(pdf, page, 10, 10, 100, 500, "Hello World!");
panda_close(pdf);
return EXIT_SUCCESS;
}
|
OpenOffice の COM インターフェイスを使って PDF にしてみました。 フォントサイズは決めうちです。 マクロで記録した Oo Basic をそのまま直訳した感じです。
see: Ruby: OpenOffice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | require "win32ole"
class Hash
def to_prop(manager)
inject([]){|acc,pair|
opt = manager.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
opt["Name"], opt["Value"] = *pair
acc << opt
}
end
end
manager = WIN32OLE.new("com.sun.star.ServiceManager")
desktop = manager.createInstance("com.sun.star.frame.Desktop")
document = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, [])
frame = document.getCurrentController().getFrame()
dispatcher = manager.createInstance("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(frame, ".uno:FontHeight", "", 0, {
"FontHeight.Height" => 80,
"FontHeight.Prop" => 100,
"FontHeight.Diff" => 0,
}.to_prop(manager))
text = document.GetText
cursor = text.createTextCursor
text.insertString(cursor, "Hello, world!", 0)
dispatcher.executeDispatch(frame, ".uno:ExportDirectToPDF", "", 0, {
"URL" => "file:///#{File.expand_path("hello.pdf")}" ,
"FilterName" => "writer_pdf_Export",
"SelectionOnly" => "true",
}.to_prop(manager))
document.close(false)
|
・用紙サイズを A0 から B0 に変更しました(どうでも良いですね……)
・描画サイズのマージンを取りすぎていたので、ぎりぎりまで大きくしました。
・FontをBaseFontから直接生成するようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 | diff 2487.java Sample.java
12c12
< Document doc = new Document(PageSize.A0.rotate());
---
> Document doc = new Document(PageSize.B0.rotate());
17,19c17,18
< float s = (doc.right() - doc.left() - doc.rightMargin()) /
< bf.getWidthPoint(TEXT, 1.0f);
< Font f = new Font(Font.TIMES_ROMAN, s);
---
> float size = (doc.right() - doc.left()) / bf.getWidthPoint(TEXT, 1.0f);
> Font f = new Font(bf, size);
|
これって要件満たしていないんじゃないんですか?
試してみましたが、少なくとも僕の環境では1ページに収まってHello, world!が含まれているので題意は満たしていると思います。
PDF::API2を使うのは初めて。フォントサイズが決めうちなのでよろしくなさげ。
1 2 3 4 5 6 7 8 9 10 11 12 | use PDF::API2;
my $pdf = PDF::API2->new(-file => 'hello.pdf');
my $fnt = $pdf->corefont('Times-Roman');
my $page = $pdf->page;
$page->mediabox('A4');
my $gfx = $page->gfx();
$gfx->rotate(90);
$gfx->translate( 0, -120 );
$gfx->textlabel( 0, 0, $fnt, 160, 'Hello, world!' );
$pdf->save;
|
>「Hello, world!」となるべく大きく書かれた と要件にはあります。 このページをただ出力することが「なるべく大きく」書こうと作っているようには思えませんでした。(実際に大きいかどうかは別として)
おっしゃりたいことはわかりますが 「なるべく大きくしようとしたかどうか」は 客観的にははかることができません。 もしお題に「A4の紙に印刷した場合に10cm以上であること」などと書いてあれば 客観的に判断できる「要件」だと思いますが 「なるべく大きく」が要件だというのには違和感を感じます。
ブラウザ上のJavaScriptではそもそもHello, worldをPDFで出力すること自体が かなり困難なのだと思います。 それを乗り越えたshimakumaさんの「Webサービスをライブラリのように使う」という発想は面白いと思いました。こういうコードを許容するためにもあまり要件を厳しく設定したくはないです。
誰かがJavaScriptでもっと大きく出力するコードを投稿したら、僕はそちらにプラスをつけてshimakumaさんのコードは0に戻すかも知れません。そちらの方が「このコードは要件を満たしていない」と書くよりも生産的だと思います。
技術的な話もありませんし不快に思っている方も多いようなので私の発言は消していただければ幸いです。
A4ページ全体に広げて。
see: iTextSharp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
class Program {
static void Main(string[] args) {
string s = "Hello, world!";
Document doc = new Document(PageSize.A4.Rotate(), 0f, 0f, 0f, 0f);
PdfWriter.GetInstance(doc, File.Create("hello.pdf"));
doc.Open();
Font f = FontFactory.GetFont(FontFactory.TIMES_BOLD);
f.Size *= doc.PageSize.Height /
(f.BaseFont.GetAscentPoint(s, f.Size) - f.BaseFont.GetDescentPoint(s, f.Size));
Chunk chunk = new Chunk(s, f);
chunk.SetTextRise(-f.BaseFont.GetAscentPoint(chunk.Content, f.Size));
chunk.SetHorizontalScaling((doc.PageSize.Width - 0f) / chunk.GetWidthPoint());
doc.Add(chunk);
doc.Close();
}
}
|
Gaucheだとkenhysさん作のlibharuがあるので、それを使えばPDF出力ができるのですが、 外部ライブラリを使用すると他言語の解答と似たものとなってつまらないので、自力でPDFを作成してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | (use srfi-1)
(use gauche.sequence)
(use util.list)
(define-method pdf-format ((port <port>) dict obj)
(format port "~a " obj))
(define-method pdf-format ((port <port>) dict (kw <keyword>))
(format port "/~a " kw))
(define-method pdf-format ((port <port>) dict (sym <symbol>))
(cond
((assq sym dict) => (compose (cut format port "~d 0 R " <>) cdr))
(else
(format port "~a " sym))))
(define-method pdf-format ((port <port>) dict (str <string>))
(format port "(~a) " str))
(define-method pdf-format ((port <port>) dict (vec <vector>))
(format port "[ ")
(for-each (cut pdf-format port dict <>) vec)
(format port "] "))
(define-method pdf-format ((port <port>) dict (lst <list>))
(cond
((null? lst) #f)
((is-a? (car lst) <pair>)
(format port "<< ")
(for-each (lambda (pair)
(pdf-format port dict (car pair))
(pdf-format port dict (cdr pair)))
lst)
(format port ">> "))
(else
(for-each (cut pdf-format port dict <>) lst))))
(define-method pdf-format ((port <port>) dict (proc <procedure>))
(proc port dict))
(define (pdf-stream cmd-list)
(lambda (port dict)
(let ((stream (call-with-output-string
(lambda (out)
(format out "~%BT~%")
(for-each (lambda (cmd)
(pdf-format out dict cmd)
(newline out))
cmd-list)
(format out "ET~%")))))
(pdf-format port dict `((:Length ,(string-length stream))))
(format port "~%stream~aendstream~%" stream))))
(define (pdf-object name content)
(lambda (port dict ctxt)
(let ((pos (port-tell port)))
(format port "~d 0 obj~%" (assq-ref dict name))
(pdf-format port dict content)
(format port "~%endobj~%")
(acons name pos ctxt))))
(define (pdf-trailer root)
(lambda (port dict ctxt)
(let ((xref-pos (port-tell port)))
(format port "xref~%0 ~d~%0000000000 65535 f~%" (+ (length dict) 1))
(for-each (cut format port "~10,'0d 00000 n~%" <>) (map cdr (reverse ctxt)))
(format port "trailer~%")
(pdf-format port dict `((:Root . ,root) (:Size ,(+ (length dict) 1))))
(format port "~%startxref~%~d~%%%EOF~%" xref-pos))))
(define (pdf-write filename root dict pdf-obj-list)
(call-with-output-file filename
(lambda (port)
(format port "%PDF-1.2~%")
(fold (cut <> port dict <>) '()
(append pdf-obj-list (list (pdf-trailer root)))))))
(define-syntax pdf-document
(syntax-rules ()
((_ filename root (name content) ...)
(pdf-write filename 'root
(map cons (list 'name ...) (iota (length (list 'name ...)) 1))
(list (pdf-object 'name content) ...)))))
(pdf-document "hello.pdf" root
(page '((:Type . :Page)
(:Parent . pages)
(:Resources . res)
(:Contents . contents)))
(pages '((:Type . :Pages)
(:Kids . #(page))
(:Count . 1)
(:MediaBox . #(0 0 842 595))))
(res '((:ProcSet . #(:PDF :Text))
(:Font . ((:F1 . font)))))
(contents (pdf-stream '((:F1 120 Tf)
(1 0 0 1 72 260 Tm)
("Hello, world!" Tj))))
(font '((:Type . :Font)
(:Subtype . :TrueType)
(:BaseFont . :Helvetica)))
(root '((:Type . :Catalog)
(:Pages . pages))))
|
Joeさんに感謝。
see: ErlGuten
1 2 3 4 5 6 7 8 9 10 11 12 13 | -module(helloworld).
-export([start/0]).
start()->
PDF = pdf:new(),
pdf:set_pagesize(PDF, 841, 595),
pdf:begin_text(PDF),
pdf:set_font(PDF, "Times-Italic", 148),
pdf:set_text_pos(PDF, 12, 280),
pdf:text(PDF, "Hello, World!"),
pdf:end_text(PDF),
file:write_file("helloworld.pdf",[pdf:export(PDF)]),
pdf:delete(PDF).
|
PDFも言語ですよね、ということで。
see: 手書きPDF入門
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | %PDF-1.4
1 0 obj
<<
/Type /Page
/Parent 5 0 R
/Resources 3 0 R
/Contents 2 0 R
>>
endobj
2 0 obj
<< /Length 53 >>
stream
BT
/F1 90 Tf
1 0 0 1 10 600 Tm
(Hello, World!) Tj
ET
endstream
endobj
3 0 obj
<<
/ProcSet [ /PDF /Text ]
/Font << /F1 4 0 R >>
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /Helv
/BaseFont /Helvetica
>>
endobj
5 0 obj
<<
/Type /Pages
/Kids [ 1 0 R ]
/Count 1
/MediaBox [ 0 0 595 842 ]
>>
endobj
6 0 obj
<<
/Type /Catalog
/Pages 5 0 R
>>
endobj
trailer
<< /Root 6 0 R >>
%%EOF
|





にしお
#3406()
Rating0/0=0.00
[ reply ]