package jp.crwdev.app.container.epub;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import jp.crwdev.app.BufferedImageIO;
import jp.crwdev.app.constant.Constant;
import jp.crwdev.app.container.BlankImageFileInfo;
import jp.crwdev.app.interfaces.IImageFileInfo;
import jp.crwdev.app.interfaces.IImageFileInfoList;
import jp.crwdev.app.interfaces.IImageFileWriter;
import jp.crwdev.app.interfaces.IImageFilter;
public class EpubImageFileWriter implements IImageFileWriter {
private final static String META_INF_DIR = "META-INF";
private final static String CONTAINER_FILENAME = "container.xml";
private final static String STYLE_FILENAME = "fixed-layout-jp.css";
private final static String OPF_FILENAME = "standard.opf";
private final static String NCX_FILENAME = "toc.ncx";
private final static String NAVIGATION_FILENAME = "navigation-documents.xhtml";
private final static String ITEM_DIR = "OEBPS";
private final static String STYLE_DIR = ITEM_DIR + "/" + "style";
private final static String IMAGE_DIR = ITEM_DIR + "/" + "image";
private final static String XHTML_DIR = ITEM_DIR + "/" + "xhtml";
/** 出力先ファイル */
private File mOutputFile = null;
/** 画像フィルタ */
private IImageFilter mBaseFilter = null;
/** 処理中断フラグ */
private boolean mIsCancel = false;
/** Blankページ挿入フラグ */
private boolean mIsInsertBlankPage = false;
private String mTitle = "";
private String mTitleKana = "";
private String mAuthor = "";
private String mAuthorKana = "";
private String mSeriesTitle = "";
private String mSeriesTitleKana = "";
private int mSeriesNumber = 0;
private String mBookType = "book";
/**
* コンストラクタ
* @param title
* @param titleKana
* @param author
* @param authorKana
* @param bookType "book", "magazine", "comic"
*/
public EpubImageFileWriter(String title, String titleKana, String author, String authorKana, String bookType,
String seriesTitle, String seriesTitleKana, int seriesNumber, boolean insertBlankPage){
mTitle = title;
mTitleKana = titleKana;
mAuthor = author;
mAuthorKana = authorKana;
mBookType = bookType;
mSeriesTitle = seriesTitle;
mSeriesTitleKana = seriesTitleKana;
mSeriesNumber = seriesNumber;
mIsInsertBlankPage = insertBlankPage;
}
@Override
public boolean open(String filepath) {
File file = new File(filepath);
if(file.exists()){
if(!file.delete()){
return false;
}
}
mOutputFile = file;
return true;
}
@Override
public void setImageFilter(IImageFilter filter) {
mBaseFilter = filter;
}
@Override
public boolean write(IImageFileInfoList list, OnProgressListener listener) {
if(mOutputFile == null){
return false;
}
mIsCancel = false;
if(listener != null){
listener.onProgress(0, null);
}
if(mIsInsertBlankPage){
list = insertBlankPage(list);
}
ZipOutputStream zipOut = null;
String uuid = getUUID();
try {
zipOut = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(mOutputFile)));
zipOut.setLevel(0);
writeMimeTypeFile(zipOut);
mkdir(META_INF_DIR, zipOut);
writeContainerFile(zipOut);
mkdir(STYLE_DIR, zipOut);
writeCssFile(zipOut);
if(listener != null){
listener.onProgress(5, null);
}
if(mIsCancel){
return false;
}
mkdir(IMAGE_DIR, zipOut);
List<Dimension> sizeList = writeImageFiles(IMAGE_DIR, list, zipOut, listener);
mkdir(XHTML_DIR, zipOut);
writeXHtmlFiles(sizeList, zipOut);
writeNcxFile(uuid, mTitle, zipOut, list);
mkdir(ITEM_DIR, zipOut);
writeStandardOpf(zipOut, list, uuid, mBookType, mTitle, mTitleKana, mSeriesTitle, mSeriesTitleKana, mSeriesNumber, mAuthor, mAuthorKana, -1, -1);
writeNavigationFile(zipOut, list);
}catch(Exception e){
if(!e.getMessage().equals("user cancel")){
e.printStackTrace();
}
}finally{
if(zipOut != null){
try {
zipOut.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
zipOut = null;
}
}
return true;
}
@Override
public void close() {
if(mIsCancel){
if(mOutputFile != null){
if(mOutputFile.exists()){
mOutputFile.delete();
}
}
}
if(mOutputFile != null){
mOutputFile = null;
}
}
@Override
public void cancel() {
mIsCancel = true;
}
@Override
public String getSuffix() {
return ".epub";
}
public String getUUID(){
UUID uuid = UUID.randomUUID();
return uuid.toString();
}
private void mkdir(String name, ZipOutputStream zipOut) throws IOException{
name = name.endsWith("/") ? name : name + "/";
zipOut.putNextEntry(new ZipEntry(name));
}
private void writeMimeTypeFile(ZipOutputStream zipOut) throws IOException{
ZipEntry entry = new ZipEntry("mimetype");
entry.setMethod(ZipEntry.STORED);
byte[] content = "application/epub+zip".getBytes();
entry.setSize(content.length);
CRC32 crc = new CRC32();
crc.update(content);
entry.setCrc(crc.getValue());
zipOut.putNextEntry(entry);
zipOut.write(content);
}
private void writeContainerFile(ZipOutputStream zipOut) throws IOException {
zipOut.putNextEntry(new ZipEntry(META_INF_DIR + "/" + CONTAINER_FILENAME));
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
out.println("<?xml version=\"1.0\"?>");
out.println("<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">");
out.println("<rootfiles>");
out.println("<rootfile full-path=\"" + ITEM_DIR + "/standard.opf\" media-type=\"application/oebps-package+xml\" />");
out.println("</rootfiles>");
out.println("</container>");
out.flush();
zipOut.closeEntry();
}
private void writeCssFile(ZipOutputStream zipOut) throws IOException {
zipOut.putNextEntry(new ZipEntry(STYLE_DIR + "/" + STYLE_FILENAME));
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
out.println("@charset \"utf-8\";");
out.println("svg{");
out.println(" margin:0;");
out.println(" padding:0;");
out.println("}");
out.println("body, html{");
out.println(" margin:0;");
out.println(" font-size:0;");
out.println(" padding:0;");
out.println(" background-color:white;");
out.println("}");
out.flush();
zipOut.closeEntry();
}
private List<Dimension> writeImageFiles(String imageDir, IImageFileInfoList list, ZipOutputStream zipOut, OnProgressListener listener) throws Exception {
if(!imageDir.isEmpty()){
imageDir += "/";
}
int size = list.size();
float progressOffset = 95 / (float)size;
List<Dimension> sizeList = new ArrayList<Dimension>(size);
for(int i=0; i<size; i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
if(mIsCancel){
throw new Exception("user cancel");
}
if(info.isBlankPage()){
sizeList.add(new Dimension(0, 0));
continue;
}
String filename = getImageFileName(sizeList.size(), ".jpg");
zipOut.putNextEntry(new ZipEntry(imageDir + filename));
try {
//File file = new File(info.getFullPath());
synchronized(info){
InputStream in = info.getInputStream();
BufferedImage image = null;
if(in != null){
image = BufferedImageIO.read(in, info.isJpeg());
}
else{
image = info.getImage(false);
}
if(image != null && mBaseFilter != null){
image = mBaseFilter.filter(image, info.getFilterParam());
}
if(image != null){
BufferedImageIO.write(image, "jpeg", Constant.jpegQuality, zipOut);
}
if(in != null){
in.close();
}
if(image != null){
sizeList.add(new Dimension(image.getWidth(), image.getHeight()));
}else{
sizeList.add(new Dimension(0, 0));
}
}
}catch(Exception ex){
ex.printStackTrace();
}
zipOut.flush();
zipOut.closeEntry();
if(listener != null){
listener.onProgress((int)((i*1)*progressOffset)+5, null);
}
}
return sizeList;
}
private void writeXHtmlFiles(List<Dimension> list, ZipOutputStream zipOut) throws Exception {
Dimension dim = new Dimension();
int size = list.size();
for(int i=0; i<size; i++){
Dimension d = list.get(i);
if(dim.width < d.width){ dim.width = d.width; }
if(dim.height < d.height){ dim.height = d.height; }
}
for(int i=0; i<size; i++){
if(mIsCancel){
throw new Exception("user cancel");
}
Dimension imageSize = list.get(i);
String filename = getXhtmlFileName(i);
zipOut.putNextEntry(new ZipEntry(XHTML_DIR + "/" + filename));
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
if(imageSize.width == 0 || imageSize.height == 0){
out.write(getXhtml(dim, null));
}else{
out.write(getXhtml(imageSize, getImageFileName(i, ".jpg")));
dim.setSize(imageSize);
}
out.flush();
zipOut.closeEntry();
}
}
private void writeNcxFile(String uuid, String title, ZipOutputStream zipOut, IImageFileInfoList list) throws IOException{
zipOut.putNextEntry(new ZipEntry(ITEM_DIR + "/" + NCX_FILENAME));
title = convEscape(title);
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
//sb.append("<!DOCTYPE ncx PUBLIC \"-//NISO//DTD ncx 2005-1//EN\" \"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">\n");
sb.append("<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\">\n");
sb.append("<head>\n");
sb.append(" <meta name=\"dtb:uid\" content=\"" + uuid + "\" />\n");
sb.append(" <meta name=\"dtb:depth\" content=\"1\" />\n");
sb.append(" <meta name=\"dtb:totalPageCount\" content=\"0\" />\n");
sb.append(" <meta name=\"dtb:maxPageNumber\" content=\"0\" />\n");
sb.append("</head>\n");
sb.append("<docTitle>\n");
sb.append(" <text>" + title + "</text>\n");
sb.append("</docTitle>\n");
sb.append("<navMap>\n");
int index = 0;
int playOrder = 1;
int count = list.size();
for(int i=0; i<count; i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
String tocText = info.getTocText();
if(tocText != null && tocText.length() > 0){
String filename = getXhtmlFileName(index);
sb.append(" <navPoint id=\"navPoint-" + playOrder + "\" playOrder=\"" + playOrder + "\">\n");
sb.append(" <navLabel>\n");
sb.append(" <text>" + tocText + "</text>\n");
sb.append(" </navLabel>\n");
sb.append(" <content src=\"xhtml/" + filename + "\" />\n");
sb.append(" </navPoint>\n");
playOrder++;
}
else if(index == 0){
String filename = getXhtmlFileName(0);
sb.append(" <navPoint id=\"navPoint-" + playOrder + "\" playOrder=\"" + playOrder + "\">\n");
sb.append(" <navLabel>\n");
sb.append(" <text>表紙</text>\n");
sb.append(" </navLabel>\n");
sb.append(" <content src=\"xhtml/" + filename + "\" />\n");
sb.append(" </navPoint>\n");
playOrder++;
}
index++;
}
sb.append("</navMap>\n");
sb.append("</ncx>\n");
out.write(new String(sb));
out.flush();
zipOut.closeEntry();
}
private void writeNavigationFile(ZipOutputStream zipOut, IImageFileInfoList list) throws IOException{
zipOut.putNextEntry(new ZipEntry(ITEM_DIR + "/" + NAVIGATION_FILENAME));
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<!DOCTYPE html>\n");
sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\" xml:lang=\"ja\">\n");
sb.append("<head>\n");
sb.append("<meta charset=\"UTF-8\"/>\n");
sb.append("<title>Navigation</title>\n");
sb.append("</head>\n");
sb.append("<body>\n");
sb.append("<nav epub:type=\"toc\" id=\"toc\">\n");
sb.append("<h1>目次</h1>\n");
sb.append("<ol>\n");
int index = 0;
int count = list.size();
for(int i=0; i<count; i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
String tocText = info.getTocText();
if(tocText != null && tocText.length() > 0){
String filename = getXhtmlFileName(index);
sb.append("<li><a href=\"xhtml/" + filename + "\">" + tocText + "</a></li>\n");
}
else if(index == 0){
String filename = getXhtmlFileName(index);
sb.append("<li><a href=\"xhtml/" + filename + "\">表紙</a></li>\n");
}
index++;
}
sb.append("</ol>\n");
sb.append("</nav>\n");
sb.append("</body>\n");
sb.append("</html>\n");
out.write(new String(sb));
out.flush();
zipOut.closeEntry();
}
private void writeStandardOpf(ZipOutputStream zipOut, IImageFileInfoList list, String uuid, String booktype, String title, String title_kana, String seriesTitle, String seriesTitleKana, int serieseNum, String creator, String creator_kana, int baseWidth, int baseHeight) throws IOException {
zipOut.putNextEntry(new ZipEntry(ITEM_DIR + "/" + OPF_FILENAME));
title = convEscape(title);
title_kana = convEscape(title_kana);
creator = convEscape(creator);
creator_kana = convEscape(creator_kana);
PrintWriter out = new PrintWriter(new OutputStreamWriter(zipOut, "UTF-8"));
String head = getStandardOpfHead(booktype, title, title_kana, seriesTitle, seriesTitleKana, serieseNum, creator, creator_kana,
"", "", uuid, new Date(), baseWidth, baseHeight);
String body = getStandardOpfBody(list);
String foot = getStandardOpfFoot();
out.print(head);
out.print(body);
out.print(foot);
out.flush();
zipOut.closeEntry();
}
@SuppressWarnings("deprecation")
public String getStandardOpfHead(String booktype, String title, String title_kana, String serieseTitle, String serieseTitleKana, int serieseNum, String creator, String creator_kana,
String publisher, String publisher_kana, String uuid, Date modifiedDate, int baseWidth, int baseHeight){
String datatype = booktype; //"comic";// "magazine", "book"
String date = String.format("%04d-%02d-%02dT00:00:00Z", modifiedDate.getYear()+1900, modifiedDate.getMonth()+1, modifiedDate.getDate());
String head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<package xmlns=\"http://www.idpf.org/2007/opf\" version=\"3.0\" xml:lang=\"ja\" unique-identifier=\"BookID\"\n" //=\"" + uuid + "\"\n"
+ "prefix=\"rendition: http://www.idpf.org/vocab/rendition/#\n"
+ " prs: http://xmlns.sony.net/e-book/prs/\n"
+ " prism: http://prism.dummy.jp/\n"
+ " ebpaj: http://www.ebpaj.jp/\n"
+ " fixed-layout-jp: http://www.digital-comic.jp/\">\n"
+ "<metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
+ "<!-- 作品名 -->\n";
head += titleTag(title, title_kana, serieseTitle, serieseTitleKana, serieseNum);
head += "<!-- 著者名 -->\n"
+ authorTag(creator, creator_kana)
+ "<!-- 出版社名 -->\n"
+ publisherTag(publisher, publisher_kana)
+ "<!-- 言語 -->\n"
+ "<dc:language>ja</dc:language>\n"
+ "<!-- ファイルid -->\n"
+ "<dc:identifier id=\"BookID\">urn:uuid:" + uuid + "</dc:identifier>\n"
+ "<!-- 更新日 -->\n"
+ "<meta property=\"dcterms:modified\">" + date + "</meta>\n"
+ "<meta property=\"prs:datatype\">" + datatype + "</meta>\n"
+ "<!-- Fixed-Layout Documents指定 -->\n"
+ "<meta property=\"rendition:layout\">pre-paginated</meta>\n";
//+ "<meta property=\"rendition:spread\">landscape</meta>\n";
if(baseWidth > 0 && baseHeight > 0){
head += "<!-- 基準サイズ -->\n"
+ "<meta property=\"fixed-layout-jp:viewport\">width=" + baseWidth + ", height=" + baseHeight + "</meta>\n";
}
head += "<!-- etc. -->\n"
+ "<meta name=\"book-type\" content=\"comic\"/>\n"
+ "<meta property=\"ebpaj:guide-version\">1.1</meta>\n"
+ "</metadata>\n"
+ "<manifest>\n"
+ "<!-- navigation -->\n"
+ "<item media-type=\"application/xhtml+xml\" id=\"toc\" href=\"navigation-documents.xhtml\" properties=\"nav\" />\n"
+ "<item href=\"toc.ncx\" id=\"ncx\" media-type=\"application/x-dtbncx+xml\" />\n"
+ "<!-- style -->\n"
+ "<item media-type=\"text/css\" id=\"fixed-layout-jp\" href=\"style/fixed-layout-jp.css\"/>\n";
return head;
}
private String getStandardOpfFoot(){
return "</package>";
}
private String titleTag(String displayTitle, String displayTitleKana, String seriesTitle, String seriesTitleKana, int seriesPosition){
StringBuilder sb = new StringBuilder();
//if(seriesTitle == null || seriesTitle.length() == 0){
sb.append("<dc:title id=\"title\">" + displayTitle + "</dc:title>\n");
if(displayTitleKana != null && !displayTitleKana.isEmpty()){
sb.append("<meta refines=\"#title\" property=\"file-as\">" + displayTitleKana + "</meta>\n");
}
if(seriesTitle != null && seriesTitle.length() > 0){
sb.append("<meta property=\"prism:publicationName\" id=\"publicationName\">" + seriesTitle + "</meta>\n");
if(seriesTitleKana != null && seriesTitleKana.length() > 0){
sb.append("<meta refines=\"#publicationName\" property=\"file-as\">" + seriesTitleKana + "</meta>\n");
}
if(seriesPosition == 0){
seriesPosition = 1;
}
sb.append("<meta property=\"prism:volume\" id=\"volume\">" + seriesPosition + "</meta>\n");
//sb.append("<meta property=\"prism:number\" id=\"number\"></meta>\n");
}
// }
// else{
// sb.append("<dc:title id=\"t1\">" + displayTitle + "</dc:title>\n");
// if(displayTitleKana != null && !displayTitleKana.isEmpty()){
// sb.append("<meta refines=\"#t1\" property=\"title-type\">main</meta>\n");
// sb.append("<meta refines=\"#t1\" property=\"file-as\">" + displayTitleKana + "</meta>\n");
// }
// }
return new String(sb);
}
private String authorTag(String creator, String creator_kana){
if(creator == null || creator.isEmpty()){
return "";
}
StringBuilder sb = new StringBuilder();
sb.append("<dc:creator id=\"creator01\">" + creator + "</dc:creator>\n");
sb.append("<meta refines=\"#creator01\" property=\"role\" scheme=\"marc:relators\">aut</meta>\n");
if(creator_kana != null && !creator_kana.isEmpty()){
sb.append("<meta refines=\"#creator01\" property=\"file-as\">" + creator_kana + "</meta>\n");
}
return new String(sb);
}
private String publisherTag(String publisher, String publisher_kana){
if(publisher == null || publisher.isEmpty()){
return "";
}
StringBuilder sb = new StringBuilder();
sb.append("<dc:creator id=\"publisher\">" + publisher + "</dc:creator>\n");
if(publisher_kana != null && !publisher_kana.isEmpty()){
sb.append("<meta refines=\"#publisher\" property=\"file-as\">" + publisher_kana + "</meta>\n");
}
return new String(sb);
}
public String getStandardOpfBody(IImageFileInfoList list){
StringBuilder sb = new StringBuilder();
sb.append("<!-- image -->\n");
int size = list.size();
int index = 0;
for(int i=0; i<size; i++){
if(!list.get(i).isEnable()){
continue;
}
if(!list.get(i).isBlankPage()){
String properties = "";
if(!getImageProperties(index).equals("")){
properties = " properties=\"" + getImageProperties(index) + "\"";
}
sb.append("<item media-type=\"" + getMimeType("jpg") + "\" id=\"" + getImageId(index) + "\" href=\"image/" + getImageFileName(index, ".jpg") + "\"" + properties + "/>\n");
}
index++;
}
sb.append("<!-- xhtml -->\n");
index = 0;
for(int i=0; i<list.size(); i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
String imageprop = "fallback=\"" + getImageId(index) + "\"";
if(info.isBlankPage()){
imageprop = "";
}
sb.append("<item media-type=\"application/xhtml+xml\" id=\"" + getXhtmlId(index)+ "\" href=\"xhtml/" + getXhtmlFileName(index) + "\" properties=\"svg\" " + imageprop + "/>\n");
index++;
}
sb.append("</manifest>\n");
sb.append("<spine page-progression-direction=\"rtl\" toc=\"ncx\">\n");
sb.append("<!-- itemref -->\n");
index = 0;
String prevSpread = Constant.PAGESPREAD_AUTO;
for(int i=0; i<size; i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
String properties = "";
String curSpread = info.getFilterParam().getPageSpread();
System.out.println("info[" + i + "]=" + curSpread);
//if(!getItemRefProperties(index).equals("")){
// properties = " properties=\"" + getItemRefProperties(index) + "\"";
//}
String spreadProp = getItemRefProperties(prevSpread, curSpread);
if(!spreadProp.isEmpty()){
properties = " properties=\"" + spreadProp + "\"";
}
prevSpread = propToConstant(spreadProp);
sb.append("<itemref linear=\"yes\" idref=\"" + getXhtmlId(index) + "\"" + properties + "/>\n");
index++;
}
sb.append("</spine>\n");
return new String(sb);
}
private String getImageProperties(int index){
if(index == 0){
return "cover-image";
}
else{
return "";
}
}
@SuppressWarnings("unused")
private String getItemRefProperties(int index){
if(index == 0){
return "rendition:page-spread-center";
}
else{
if(index%2 == 1){
return "page-spread-right";
}
else{
return "page-spread-left";
}
}
}
private String getItemRefProperties(String prev, String current){
String next = "rendition:page-spread-center";
if(current.equals(Constant.PAGESPREAD_AUTO)){
if(prev.equals(Constant.PAGESPREAD_CENTER)){
next = "rendition:page-spread-right";
}
else if(prev.equals(Constant.PAGESPREAD_RIGHT)){
next = "rendition:page-spread-left";
}
else if(prev.equals(Constant.PAGESPREAD_LEFT)){
next = "rendition:page-spread-right";
}
}
else{
if(current.equals(Constant.PAGESPREAD_CENTER)){
next = "rendition:page-spread-center";
}
else if(current.equals(Constant.PAGESPREAD_RIGHT)){
next = "rendition:page-spread-right";
}
else if(current.equals(Constant.PAGESPREAD_LEFT)){
next = "rendition:page-spread-left";
}
}
return next;
}
private String propToConstant(String spread){
if(spread.equals("rendition:page-spread-right")){
return Constant.PAGESPREAD_RIGHT;
}
if(spread.equals("rendition:page-spread-left")){
return Constant.PAGESPREAD_LEFT;
}
return Constant.PAGESPREAD_CENTER;
}
private String getXhtml(Dimension size, String imageFilename){
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<!DOCTYPE html>\n");
sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\" xml:lang=\"ja\">\n");
sb.append("<head>\n");
sb.append("<meta charset=\"UTF-8\"/>\n");
sb.append("<title></title>\n");
sb.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"../style/fixed-layout-jp.css\"/>\n");
sb.append("<meta name=\"viewport\" content=\"width=" + size.width + ", height=" + size.height + "\"/>\n");
sb.append("</head>\n");
sb.append("<body>\n");
// if(imageFilename != null){
sb.append("<div class=\"main\">\n");
sb.append("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100%\" height=\"100%\" viewBox=\"0 0 " + size.width + " " + size.height + "\">\n");
if(imageFilename != null){
sb.append("<image width=\"" + size.width + "\" height=\"" + size.height + "\" xlink:href=\"../image/" + imageFilename + "\"/>\n");
}
sb.append("</svg>\n");
sb.append("</div>\n");
// }
sb.append("</body>\n");
sb.append("</html>");
return new String(sb);
}
private String convEscape(String text){
text = text.replaceAll("&", "&");
text = text.replaceAll("<", "<");
text = text.replaceAll(">", ">");
return text;
}
private String getMimeType(String suffix){
if(suffix.equals("jpg")){
return "image/jpeg";
}
else if(suffix.equals("png")){
return "image/png";
}
else if(suffix.equals("gif")){
return "image/gif";
}
else{
return "image/jpeg";
}
}
private String getImageId(int index){
return String.format("I%04d", index);
}
private String getXhtmlId(int index){
return String.format("P%04d", index);
}
private String getImageFileName(int index, String suffix){
return getImageId(index) + suffix;
}
private String getXhtmlFileName(int index){
return getXhtmlId(index) + ".xhtml";
}
private IImageFileInfoList insertBlankPage(IImageFileInfoList orgList){
CopyImageFileInfoList list = new CopyImageFileInfoList(orgList);
String prevSpread = null;
for(int i=0; i<list.size(); i++){
IImageFileInfo info = list.get(i);
if(!info.isEnable()){
continue;
}
String curSpread = info.getFilterParam().getPageSpread();
if(prevSpread != null){
if(prevSpread.equals(Constant.PAGESPREAD_CENTER) || prevSpread.equals(Constant.PAGESPREAD_LEFT)){
if(curSpread.equals(Constant.PAGESPREAD_LEFT)){
list.insert(i, new BlankImageFileInfo());
System.out.println("i=" + i + " spread=auto");
i++;
}
}
else if(prevSpread.equals(Constant.PAGESPREAD_RIGHT)){
if(curSpread.equals(Constant.PAGESPREAD_RIGHT)){
list.insert(i, new BlankImageFileInfo());
System.out.println("i=" + i + " spread=auto");
i++;
}
else if(curSpread.equals(Constant.PAGESPREAD_CENTER)){
list.insert(i, new BlankImageFileInfo());
System.out.println("i=" + i + " spread=auto");
i++;
}
}
if(curSpread.equals(Constant.PAGESPREAD_AUTO)){
if(prevSpread.equals(Constant.PAGESPREAD_CENTER)){
prevSpread = Constant.PAGESPREAD_RIGHT;
}
else if(prevSpread.equals(Constant.PAGESPREAD_LEFT)){
prevSpread = Constant.PAGESPREAD_RIGHT;
}
else if(prevSpread.equals(Constant.PAGESPREAD_RIGHT)){
prevSpread = Constant.PAGESPREAD_LEFT;
}
}else{
prevSpread = curSpread;
}
}
else{
if(curSpread.equals(Constant.PAGESPREAD_AUTO)){
prevSpread = Constant.PAGESPREAD_CENTER;
}else{
prevSpread = curSpread;
}
}
System.out.println("i=" + i + " spread=" + prevSpread);
}
return list;
}
}