Couldn't find where to post sources, so I'll just write it here.
Here is my code for ReplacedElementFactory:
public class RTLTextReplacedElementFactory implements
ReplacedElementFactory{
private String cssClassName;
private ITextReplacedElementFactory defaultFactory;
public RTLTextReplacedElementFactory(ITextOutputDevice
outputDevice, String cssClassName) {
ValidatorUtil.checkNotNull(outputDevice, "outputDevice");
ValidatorUtil.checkNotNull(cssClassName, "cssClassName");
defaultFactory = new
ITextReplacedElementFactory(outputDevice);
this.cssClassName = cssClassName;
}
@Override
public ReplacedElement createReplacedElement(LayoutContext c,
BlockBox box, UserAgentCallback uac, int cssWidth, int cssHeight) {
Element element = box.getElement();
if (element == null){
return null;
}
if (element.getAttribute("class").contains(cssClassName)) {
String text = element.getTextContent().replaceAll("(?m)\\s
+", " ");
return new RTLText(c, box, uac, cssWidth, cssHeight,
text);
} else {
return defaultFactory.createReplacedElement(c, box, uac,
cssWidth, cssHeight);
}
}
@Override
public void reset() {
}
@Override
public void remove(Element e) {
}
@Override
public void setFormSubmissionListener(FormSubmissionListener
listener) {
}
}
class RTLText implements ITextReplacedElement {
private static final Logger logger =
Logger.getLogger(RTLText.class.getName());
private int width;
private int height;
private String text;
private int align;
private BaseColor color;
private float fontSize = -1;
private int direction = PdfWriter.RUN_DIRECTION_LTR;
RTLText(LayoutContext c, BlockBox box, UserAgentCallback uac, int
cssWidth, int cssHeight, String text){
this.text = text;
initDimensions(c, box, cssWidth, cssHeight);
float fontSize = box.getStyle().getFSFont(c).getSize2D();
align = com.itextpdf.text.Element.ALIGN_LEFT;
Element element = box.getElement();
String as = element.getAttribute("align");{
if (as.equalsIgnoreCase("left")) {
align = com.itextpdf.text.Element.ALIGN_LEFT;
} else if (as.equalsIgnoreCase("center")) {
align = com.itextpdf.text.Element.ALIGN_CENTER;
} else if (as.equalsIgnoreCase("right")) {
align = com.itextpdf.text.Element.ALIGN_RIGHT;
}
}
as = element.getAttribute("direction"); {
if (as.equalsIgnoreCase("ltr")){
direction = PdfWriter.RUN_DIRECTION_LTR;
} else if (as.equals("default")){
direction = PdfWriter.RUN_DIRECTION_DEFAULT;
} else if (as.equals("no-bidi")){
direction = PdfWriter.RUN_DIRECTION_NO_BIDI;
} else if (as.equals("rtl")){
direction = PdfWriter.RUN_DIRECTION_RTL;
}
}
String ecolor = element.getAttribute("color");
if (!ecolor.isEmpty()){
color = new BaseColor(Color.decode(ecolor));
}
String efontSize = element.getAttribute("font-size");
if (!efontSize.isEmpty()){
this.fontSize = Float.parseFloat(efontSize);
}
}
@Override
public int getIntrinsicWidth() {
return width;
}
@Override
public int getIntrinsicHeight() {
return height;
}
private Point location = new Point();
@Override
public Point getLocation() {
return location;
}
@Override
public void setLocation(int x, int y) {
location.x = x;
location.y = y;
}
@Override
public void detach(LayoutContext c) {
}
@Override
public boolean isRequiresInteractivePaint() {
return false;
}
@Override
public boolean hasBaseline() {
return false;
}
@Override
public int getBaseline() {
return 0;
}
@Override
public void paint(RenderingContext c, ITextOutputDevice
outputDevice, BlockBox box) {
try{
PdfWriter writer = outputDevice.getWriter();
PdfContentByte cb = writer.getDirectContent();
ITextFSFont font =
(ITextFSFont)box.getStyle().getFSFont(c);
float pdfFontSize =
outputDevice.getDeviceLength(font.getSize2D());
if (fontSize != -1){
pdfFontSize = fontSize;
}
FSColor color = box.getStyle().getColor();
BaseColor bc = null;
if (this.color != null){
bc = this.color;
} else if (color instanceof FSRGBColor) {
FSRGBColor cc = (FSRGBColor) color;
bc = new BaseColor(cc.getRed(), cc.getGreen(),
cc.getBlue());
}
ColumnText ct = new ColumnText(cb);
setupColumnCoordinates(c, outputDevice, box);
ct.setSimpleColumn(llx, lly, urx, ury);
ct.setSpaceCharRatio(PdfWriter.NO_SPACE_CHAR_RATIO);
ct.setLeading(0, 1);
ct.setRunDirection(direction);
ct.setAlignment(align);
if (bc == null){
ct.addText(new Phrase(text, new
com.itextpdf.text.Font(font.getFontDescription().getFont(),
pdfFontSize)));
} else {
ct.addText(new Phrase(text, new
com.itextpdf.text.Font(font.getFontDescription().getFont(),
pdfFontSize, 0, bc)));
}
ct.go();
} catch (DocumentException e){
logger.log(Level.WARNING, "error while processing rtl
text", e);
e.printStackTrace();
}
}
private int llx, lly, urx, ury;
private void setupColumnCoordinates(RenderingContext c,
ITextOutputDevice outputDevice, BlockBox box){
PageBox page = c.getPage();
float dotsPerPoint = outputDevice.getDotsPerPoint();
float marginBorderPaddingLeft = page.getMarginBorderPadding(c,
CalculatedStyle.LEFT) ;
float marginBorderPaddingBottom =
page.getMarginBorderPadding(c, CalculatedStyle.BOTTOM) ;
RectPropertySet margin = box.getMargin(c);
RectPropertySet padding = box.getPadding(c);
float dist = (page.getBottom() - box.getAbsY() +
marginBorderPaddingBottom); //from box top to page bottom
llx = (int) ((margin.left() + padding.left() + box.getAbsX() +
marginBorderPaddingLeft) / dotsPerPoint);
lly = (int) ((dist - box.getHeight())/dotsPerPoint);
urx = (int) ((box.getAbsX() + box.getWidth() +
marginBorderPaddingLeft)/dotsPerPoint);
ury = (int) ((dist + margin.bottom() + padding.bottom()) /
dotsPerPoint);
}
protected void initDimensions(LayoutContext c, BlockBox box, int
cssWidth, int cssHeight) {
CalculatedStyle style = box.getStyle();
Element element = box.getElement();
float scalex = 0.1f;
float scaley = 0.06f;
int lines = 1; {
String lines1 = element.getAttribute("lines");
if (!lines1.isEmpty()){
lines = Integer.parseInt(lines1);
}
}
String sx = element.getAttribute("scale-x");
if (!sx.isEmpty()){
try{
scalex = Float.parseFloat(sx);
} catch (Exception e){
System.err.println("Bad scale-x attribute value: " +
sx);
// do nothing
}
}
String sy = element.getAttribute("scale-y");
if (!sy.isEmpty()){
try{
scaley = Float.parseFloat(sy);
} catch (Exception e){
System.err.println("Bad scale-y attribute value: " +
sx);
// do nothing
}
}
String ewidth = element.getAttribute("width");
if (!ewidth.isEmpty()){
width = Integer.parseInt(ewidth) * c.getDotsPerPixel();
} else if (cssWidth != -1) {
width = cssWidth;
} else {
width = (c.getTextRenderer().getWidth(
c.getFontContext(),
style.getFSFont(c),
text)/2);
}
String eheight = element.getAttribute("height");
if (!eheight.isEmpty()){
height = Integer.parseInt(eheight) * c.getDotsPerPixel();
} else if (cssHeight != -1) {
height = cssHeight;
} else {
height = ((int) (style.getLineHeight(c) * lines));
}
width *= c.getDotsPerPixel() * scalex;
height *= c.getDotsPerPixel() * scaley;