blob: abe5df446777d554b41ca2cf98566dfc75d2843b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.fop.pdf;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
import org.apache.fop.fonts.CIDFontType;
// based on work by Takayuki Takeuchi
/**
* Class representing a "character identifier" font (p 210 and onwards).
*/
public class PDFCIDFont extends PDFObject {
private String basefont;
private CIDFontType cidtype;
private Integer dw;
private PDFWArray w;
private int[] dw2;
private PDFWArray w2;
private PDFCIDSystemInfo systemInfo;
private PDFCIDFontDescriptor descriptor;
private PDFCMap cmap;
/**
* /CIDToGIDMap (only for CIDFontType2, see p 212)
* can be either "Identity" (default) or a PDFStream
*/
private PDFStream cidMap;
/**
* Create the /Font object
* @param basefont Name of the basefont
* @param cidtype CID type
* @param dw default width
* @param w array of character widths
* @param registry name of the issuer
* @param ordering Unique name of the font
* @param supplement Supplement number
* @param descriptor CID font descriptor
*/
public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
int[] w, String registry, String ordering,
int supplement, PDFCIDFontDescriptor descriptor) {
this(basefont, cidtype, dw,
new PDFWArray(w),
new PDFCIDSystemInfo(registry, ordering, supplement),
descriptor);
}
/**
* Create the /Font object
* @param basefont Name of the basefont
* @param cidtype CID type
* @param dw default width
* @param w array of character widths
* @param systemInfo CID system info
* @param descriptor CID font descriptor
*/
public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
int[] w, PDFCIDSystemInfo systemInfo,
PDFCIDFontDescriptor descriptor) {
this(basefont, cidtype, dw,
new PDFWArray(w),
systemInfo,
descriptor);
}
/**
* Create the /Font object
* @param basefont Name of the basefont
* @param cidtype CID type
* @param dw default width
* @param w array of character widths
* @param systemInfo CID system info
* @param descriptor CID font descriptor
*/
public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
PDFWArray w, PDFCIDSystemInfo systemInfo,
PDFCIDFontDescriptor descriptor) {
super();
this.basefont = basefont;
this.cidtype = cidtype;
this.dw = dw;
this.w = w;
this.dw2 = null;
this.w2 = null;
systemInfo.setParent(this);
this.systemInfo = systemInfo;
this.descriptor = descriptor;
this.cidMap = null;
this.cmap = null;
}
/**
* Set the /DW attribute
* @param dw the default width
*/
public void setDW(int dw) {
this.dw = dw;
}
/**
* Set the /W array
* @param w the width array
*/
public void setW(PDFWArray w) {
this.w = w;
}
/**
* Set the (two elements) /DW2 array
* @param dw2 the default metrics for vertical writing
*/
public void setDW2(int[] dw2) {
this.dw2 = dw2;
}
/**
* Set the two elements of the /DW2 array
* @param posY position vector
* @param displacementY displacement vector
*/
public void setDW2(int posY, int displacementY) {
this.dw2 = new int[] {
posY, displacementY
};
}
/**
* Set the CMap used as /ToUnicode cmap
* @param cmap character map
*/
public void setCMAP(PDFCMap cmap) {
this.cmap = cmap;
}
/**
* Set the /W2 array
* @param w2 array of metrics for vertical writing
*/
public void setW2(PDFWArray w2) {
this.w2 = w2;
}
/**
* Set the /CIDToGIDMap (to be used only for CIDFontType2)
* @param map mapping information
*/
public void setCIDMap(PDFStream map) {
this.cidMap = map;
}
/**
* Set the /CIDToGIDMap (to be used only for CIDFontType2) to "Identity"
*/
public void setCIDMapIdentity() {
this.cidMap = null; // not an error here, simply use the default
}
/**
* Returns the PDF name for a certain CID font type.
* @param cidFontType CID font type
* @return corresponding PDF name
*/
protected String getPDFNameForCIDFontType(CIDFontType cidFontType) {
if (cidFontType == CIDFontType.CIDTYPE0) {
return cidFontType.getName();
} else if (cidFontType == CIDFontType.CIDTYPE2) {
return cidFontType.getName();
} else {
throw new IllegalArgumentException("Unsupported CID font type: "
+ cidFontType.getName());
}
}
/**
* {@inheritDoc}
*/
public String toPDFString() {
StringBuffer p = new StringBuffer(128);
p.append("<< /Type /Font");
p.append("\n/BaseFont /");
p.append(this.basefont);
p.append(" \n/CIDToGIDMap ");
if (cidMap != null) {
p.append(cidMap.referencePDF());
} else {
p.append("/Identity");
//This is the default. We still write it because PDF/A requires it.
}
p.append(" \n/Subtype /");
p.append(getPDFNameForCIDFontType(this.cidtype));
p.append("\n");
p.append(systemInfo.toPDFString());
p.append("\n/FontDescriptor ");
p.append(this.descriptor.referencePDF());
if (cmap != null) {
p.append("\n/ToUnicode ");
p.append(cmap.referencePDF());
}
if (dw != null) {
p.append("\n/DW ");
p.append(this.dw);
}
if (w != null) {
p.append("\n/W ");
p.append(w.toPDFString());
}
if (dw2 != null) {
p.append("\n/DW2 ["); // always two values, see p 211
p.append(this.dw2[0]);
p.append(this.dw2[1]);
p.append("]");
}
if (w2 != null) {
p.append("\n/W2 ");
p.append(w2.toPDFString());
}
p.append("\n>>");
return p.toString();
}
/**
* {@inheritDoc}
*/
public byte[] toPDF() {
ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
try {
bout.write(encode("<< /Type /Font\n"));
bout.write(encode("/BaseFont /"));
bout.write(encode(this.basefont));
bout.write(encode(" \n"));
bout.write(encode("/CIDToGIDMap "));
bout.write(encode(cidMap != null ? cidMap.referencePDF() : "/Identity"));
bout.write(encode(" \n"));
bout.write(encode("/Subtype /"));
bout.write(encode(getPDFNameForCIDFontType(this.cidtype)));
bout.write(encode("\n"));
bout.write(encode("/CIDSystemInfo "));
bout.write(systemInfo.toPDF());
bout.write(encode("\n"));
bout.write(encode("/FontDescriptor "));
bout.write(encode(this.descriptor.referencePDF()));
bout.write(encode("\n"));
if (cmap != null) {
bout.write(encode("/ToUnicode "));
bout.write(encode(cmap.referencePDF()));
bout.write(encode("\n"));
}
if (dw != null) {
bout.write(encode("/DW "));
bout.write(encode(this.dw.toString()));
bout.write(encode("\n"));
}
if (w != null) {
bout.write(encode("/W "));
bout.write(encode(w.toPDFString()));
bout.write(encode("\n"));
}
if (dw2 != null) {
bout.write(encode("/DW2 [")); // always two values, see p 211
bout.write(encode(Integer.toString(this.dw2[0])));
bout.write(encode(Integer.toString(this.dw2[1])));
bout.write(encode("]\n"));
}
if (w2 != null) {
bout.write(encode("/W2 "));
bout.write(encode(w2.toPDFString()));
bout.write(encode("\n"));
}
bout.write(encode(">>"));
} catch (IOException ioe) {
log.error("Ignored I/O exception", ioe);
}
return bout.toByteArray();
}
@Override
public void getChildren(Set<PDFObject> children) {
super.getChildren(children);
if (cidMap != null) {
children.add(cidMap);
cidMap.getChildren(children);
}
children.add(descriptor);
descriptor.getChildren(children);
if (cmap != null) {
children.add(cmap);
cmap.getChildren(children);
}
}
}