/*
* Copyright (c) 2005 Matthew Hall and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthew Hall - initial API and implementation
*/
package org.eclipse.nebula.paperclips.core.text.internal;
import org.eclipse.nebula.paperclips.core.internal.util.ResourcePool;
import org.eclipse.nebula.paperclips.core.internal.util.Util;
import org.eclipse.nebula.paperclips.core.text.TextStyle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
public class TextPiece implements TextPrintPiece {
private final Point size;
private final String[] lines;
private final TextStyle style;
private final int ascent;
private final ResourcePool resources;
public TextPiece(Device device, TextStyle style, String[] text, Point size,
int ascent) {
Util.notNull(device, size, style);
Util.noNulls(text);
this.size = size;
this.lines = text;
this.style = style;
this.ascent = ascent;
this.resources = ResourcePool.forDevice(device);
}
public Point getSize() {
return new Point(size.x, size.y);
}
public int getAscent() {
return ascent;
}
public void paint(final GC gc, final int x, final int y) {
Font oldFont = gc.getFont();
Color oldForeground = gc.getForeground();
Color oldBackground = gc.getBackground();
final int width = getSize().x;
final int align = style.getAlignment();
try {
boolean transparent = initGC(gc);
FontMetrics fm = gc.getFontMetrics();
int lineHeight = fm.getHeight();
boolean strikeout = style.getStrikeout();
boolean underline = style.getUnderline();
int lineThickness = Math.max(1, fm.getDescent() / 3);
int strikeoutOffset = fm.getLeading() + fm.getAscent() / 2;
int underlineOffset = ascent + lineThickness;
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
int lineWidth = gc.stringExtent(line).x;
int offset = getHorzAlignmentOffset(align, lineWidth, width);
gc.drawString(lines[i], x + offset, y + lineHeight * i,
transparent);
if (strikeout || underline) {
Color saveBackground = gc.getBackground();
gc.setBackground(gc.getForeground());
if (strikeout)
gc.fillRectangle(x + offset, y + lineHeight * i
+ strikeoutOffset, lineWidth, lineThickness);
if (underline)
gc.fillRectangle(x + offset, y + lineHeight * i
+ underlineOffset, lineWidth, lineThickness);
gc.setBackground(saveBackground);
}
}
} finally {
restoreGC(gc, oldFont, oldForeground, oldBackground);
}
}
private boolean initGC(final GC gc) {
initGCFont(gc);
initGCForeground(gc);
boolean transparent = initGCBackground(gc);
return transparent;
}
private void restoreGC(final GC gc, Font font, Color foreground,
Color background) {
gc.setFont(font);
gc.setForeground(foreground);
gc.setBackground(background);
}
private int getHorzAlignmentOffset(int align, int lineWidth, int totalWidth) {
if (align == SWT.CENTER)
return (totalWidth - lineWidth) / 2;
else if (align == SWT.RIGHT)
return totalWidth - lineWidth;
return 0;
}
private boolean initGCBackground(GC gc) {
Color background = resources.getColor(style.getBackground());
boolean transparent = (background == null);
if (!transparent)
gc.setBackground(background);
return transparent;
}
private void initGCForeground(GC gc) {
Color foreground = resources.getColor(style.getForeground());
if (foreground != null)
gc.setForeground(foreground);
}
private void initGCFont(GC gc) {
Font font = resources.getFont(style.getFontData());
if (font != null)
gc.setFont(font);
}
public void dispose() {
} // Shared resources, nothing to dispose.
}