All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.swt.custom.RTFWriter Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.custom;

import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * The {@code RTFWriter} class is used to write styled content as rich text.
 * The implementation complies with the RTF specification version 1.5.
 *
 * 

{@code toString()} is guaranteed to return a valid formatted string only after * {@code close()} has been called.

* *

Whole and partial lines and line breaks can be written. Lines will be * formatted using the styles queried from the {@link LineStyleListener}, * if set, or those set directly in the widget. All styles are applied to * the stream like they are rendered by the widget. In addition, the * widget font name and size is used for the whole text.

*/ class RTFWriter extends StyledTextWriterBase { static final int DEFAULT_FOREGROUND = 0; static final int DEFAULT_BACKGROUND = 1; List colorTable; List fontTable; public RTFWriter(StyledText styledText, int start, int length) { super(styledText, start, length); colorTable = new ArrayList<>(); fontTable = new ArrayList<>(); colorTable.add(this.styledText.getForeground()); colorTable.add(this.styledText.getBackground()); fontTable.add(this.styledText.getFont()); } @Override public void close() { if (!isClosed()) { writeHeader(); write("\n}}\0"); super.close(); } } /** * Writes the RTF header including font table and color table. */ @Override void writeHeader() { StringBuilder header = new StringBuilder(); FontData fontData = styledText.getFont().getFontData()[0]; header.append("{\\rtf1\\ansi"); // specify code page, necessary for copy to work in bidi // systems that don't support Unicode RTF. String cpg = System.getProperty("file.encoding").toLowerCase(); if (cpg.startsWith("cp") || cpg.startsWith("ms")) { cpg = cpg.substring(2, cpg.length()); header.append("\\ansicpg"); header.append(cpg); } header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil "); header.append(fontData.getName()); header.append(";"); for (int i = 1; i < fontTable.size(); i++) { header.append("\\f"); header.append(i); header.append(" "); FontData fd = fontTable.get(i).getFontData()[0]; header.append(fd.getName()); header.append(";"); } header.append("}}\n{\\colortbl"); for (Color color : colorTable) { header.append("\\red"); header.append(color.getRed()); header.append("\\green"); header.append(color.getGreen()); header.append("\\blue"); header.append(color.getBlue()); header.append(";"); } // some RTF readers ignore the deff0 font tag. Explicitly // set the font for the whole document to work around this. header.append("}\n{\\f0\\fs"); // font size is specified in half points header.append(fontData.getHeight() * 2); header.append(" "); write(header.toString(), 0); } @Override public void writeLineDelimiter(String lineDelimiter) { if (isClosed()) { SWT.error(SWT.ERROR_IO); } write(lineDelimiter); write("\\par "); } @Override String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { write("\\fi"); write(indent); switch (alignment) { case SWT.LEFT: write("\\ql"); break; case SWT.CENTER: write("\\qc"); break; case SWT.RIGHT: write("\\qr"); break; } if (justify) { write("\\qj"); } write(" "); if (lineBackground != null) { // Background colors are written using the {@code \chshdng0\chcbpat} tag (vs. the {@code \cb} tag). write("{\\chshdng0\\chcbpat"); write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); write(" "); } // This is what will be used to close the line return lineBackground == null ? "" : "}"; } @Override void writeEmptyLine() { // Do nothing. RTF does not need special treatment for empty paragraph. } @Override String writeSpanStart(StyleRange style) { write("{\\cf"); write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); if (colorIndex != DEFAULT_BACKGROUND) { write("\\chshdng0\\chcbpat"); write(colorIndex); } int fontStyle = style.fontStyle; Font font = style.font; if (font != null) { int fontIndex = getFontIndex(font); write("\\f"); write(fontIndex); FontData fontData = font.getFontData()[0]; write("\\fs"); write(fontData.getHeight() * 2); fontStyle = fontData.getStyle(); } if ((fontStyle & SWT.BOLD) != 0) { write("\\b"); } if ((fontStyle & SWT.ITALIC) != 0) { write("\\i"); } if (style.underline) { write("\\ul"); } if (style.strikeout) { write("\\strike"); } write(" "); // This is what will be used to close the span StringBuilder toCloseSpan = new StringBuilder(); if ((fontStyle & SWT.BOLD) != 0) { toCloseSpan.append("\\b0"); } if ((style.fontStyle & SWT.ITALIC) != 0) { toCloseSpan.append("\\i0"); } if (style.underline) { toCloseSpan.append("\\ul0"); } if (style.strikeout) { toCloseSpan.append("\\strike0"); } toCloseSpan.append("}"); return toCloseSpan.toString(); } // ==== Helper methods ==== @Override String escapeText(String string) { // The resulting string is at least as long as the original. StringBuilder result = new StringBuilder(string.length()); string.chars().forEach(ch -> { if (ch > 0x7F) { result.append("\\u"); result.append(Integer.toString((short) ch)); result.append('?'); // ANSI representation (1 byte long, \\uc1) } else if (ch == '}' || ch == '{' || ch == '\\') { result.append('\\'); result.append((char) ch); } else { // Fixes bug 21698. result.append((char) ch); } }); return result.toString(); } /** * Returns the index of the specified color in the RTF color table. * * @param color the color * @param defaultIndex return value if color is null * @return the index of the specified color in the RTF color table * or "defaultIndex" if "color" is null. */ private int getColorIndex(Color color, int defaultIndex) { if (color == null) return defaultIndex; int index = colorTable.indexOf(color); if (index == -1) { index = colorTable.size(); colorTable.add(color); } return index; } /** * Returns the index of the specified color in the RTF color table. * * @param color the color * @param defaultIndex return value if color is null * @return the index of the specified color in the RTF color table * or "defaultIndex" if "color" is null. */ private int getFontIndex(Font font) { int index = fontTable.indexOf(font); if (index == -1) { index = fontTable.size(); fontTable.add(font); } return index; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy