RtfTextConverter.java 6.28 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.scene7.is.sleng.FontId
 *  com.scene7.is.sleng.FontSpec
 *  com.scene7.is.sleng.Text
 *  com.scene7.is.sleng.TextRendererEnum
 *  com.scene7.is.util.Converter
 *  com.scene7.is.util.collections.CollectionUtil
 *  org.apache.commons.beanutils.ConversionException
 *  org.jetbrains.annotations.NotNull
 */
package com.scene7.is.ps.provider.parsers;

import com.scene7.is.sleng.FontId;
import com.scene7.is.sleng.FontSpec;
import com.scene7.is.sleng.Text;
import com.scene7.is.sleng.TextRendererEnum;
import com.scene7.is.util.Converter;
import com.scene7.is.util.collections.CollectionUtil;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.StyleContext;
import javax.swing.text.rtf.RTFEditorKit;
import org.apache.commons.beanutils.ConversionException;
import org.jetbrains.annotations.NotNull;

public class RtfTextConverter
extends Converter<String, Text> {
    public static final Logger LOGGER = Logger.getLogger(RtfTextConverter.class.getName());
    private static final Converter<String, Text> IN_DESIGN = new RtfTextConverter(TextRendererEnum.IN_DESIGN);
    private static final Converter<String, Text> PHOTOSHOP = new RtfTextConverter(TextRendererEnum.PHOTOSHOP);
    private static final Converter<String, Text> FREE_TYPE = new RtfTextConverter(TextRendererEnum.FREE_TYPE);
    private final TextRendererEnum textRenderer;

    @NotNull
    public static Converter<String, Text> inDesignRtfTextConverter() {
        return IN_DESIGN;
    }

    @NotNull
    public static Converter<String, Text> photoshopRtfTextConverter() {
        return PHOTOSHOP;
    }

    @NotNull
    public static Converter<String, Text> freetypeRtfTextConverter() {
        return FREE_TYPE;
    }

    @NotNull
    public Text convert(@NotNull String src) {
        String encodedValue = RtfTextConverter.encodeString(src);
        if (encodedValue.isEmpty() || encodedValue.charAt(0) != '{') {
            return Text.createText((TextRendererEnum)this.textRenderer, (String)encodedValue);
        }
        if (!encodedValue.startsWith("{\\rtf")) {
            encodedValue = "{\\rtf1\\ansi" + encodedValue + '}';
        }
        DefaultStyledDocument doc = new DefaultStyledDocument(new TextStyleContext());
        RtfTextConverter.parseRtf(doc, encodedValue);
        return Text.createText((TextRendererEnum)this.textRenderer, (String)encodedValue, (String)"", RtfTextConverter.extractUsedFonts(doc));
    }

    @NotNull
    public String revert(@NotNull Text src) {
        return src.getText();
    }

    private RtfTextConverter(@NotNull TextRendererEnum textRenderer) {
        super(String.class, Text.class);
        this.textRenderer = textRenderer;
    }

    @NotNull
    private static String encodeString(@NotNull String value) {
        StringBuilder buffer = new StringBuilder(value.length());
        for (short ch : value.toCharArray()) {
            short val = ch;
            if (RtfTextConverter.isInAsciiRange(val)) {
                buffer.append((char)ch);
                continue;
            }
            buffer.append("{\\uc0");
            buffer.append("\\u").append(val);
            buffer.append('}');
        }
        return buffer.toString();
    }

    private static boolean isInAsciiRange(int val) {
        return val >= 0 && val < 128;
    }

    private static void parseRtf(@NotNull Document doc, @NotNull String value) {
        try {
            RTFEditorKit kit = new RTFEditorKit();
            kit.read(new StringReader(value), doc, 0);
        }
        catch (ArrayIndexOutOfBoundsException e) {
            LOGGER.log(Level.WARNING, "Error parsing RTF String: \"" + value + '\"', e);
        }
        catch (IllegalArgumentException e) {
            LOGGER.log(Level.WARNING, "Error parsing RTF String: \"" + value + '\"', e);
        }
        catch (IOException e) {
            LOGGER.log(Level.SEVERE, "Error parsing RTF String: \"" + value + '\"', e);
        }
        catch (BadLocationException e) {
            LOGGER.log(Level.SEVERE, "Error parsing RTF String: \"" + value + '\"', e);
        }
    }

    @NotNull
    private static Map<FontId, FontSpec> extractUsedFonts(@NotNull Document doc) {
        HashMap usedFonts = CollectionUtil.hashMap();
        for (Element element : doc.getRootElements()) {
            RtfTextConverter.scanElement(usedFonts, element);
        }
        return usedFonts;
    }

    private static void scanElement(@NotNull Map<FontId, FontSpec> usedFonts, @NotNull Element element) {
        RtfTextConverter.scanAttributes(usedFonts, element.getAttributes());
        for (int i = 0; i < element.getElementCount(); ++i) {
            RtfTextConverter.scanElement(usedFonts, element.getElement(i));
        }
    }

    private static void scanAttributes(@NotNull Map<FontId, FontSpec> usedFonts, @NotNull AttributeSet attributes) {
        String fontName = "";
        boolean bold = false;
        boolean italic = false;
        Enumeration e = attributes.getAttributeNames();
        while (e.hasMoreElements()) {
            Object key = e.nextElement();
            if (!(key instanceof AttributeSet.FontAttribute)) continue;
            String name = key.toString().toUpperCase();
            Object value = attributes.getAttribute(key);
            if ("FAMILY".equals(name)) {
                fontName = (String)value;
                continue;
            }
            if ("BOLD".equals(name)) {
                bold = (Boolean)value;
                continue;
            }
            if (!"ITALIC".equals(name)) continue;
            italic = (Boolean)value;
        }
        if (!fontName.isEmpty()) {
            usedFonts.put(FontId.createFontId((String)fontName, (boolean)bold, (boolean)italic), FontSpec.fontSpec());
        }
    }

    private static class TextStyleContext
    extends StyleContext {
        private TextStyleContext() {
        }

        @Override
        public void reclaim(AttributeSet a) {
        }
    }

}