/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package webcamstudio.streams;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;
import webcamstudio.mixers.Frame;
import webcamstudio.mixers.MasterFrameBuilder;
import webcamstudio.mixers.MasterMixer;
import webcamstudio.mixers.PreviewFrameBuilder;
import webcamstudio.sources.effects.Effect;
/**
*
* @author patrick (modified by karl)
*/
public class SourceText extends Stream {
BufferedImage image = null;
BufferedImage txImage = null;
boolean isPlaying = false;
boolean stop = false;
int bgColor = 0x000000;
Frame frame = null;
float bgOpacity = 1f;
private Shape shape = Shape.NONE;
private String strShape = "";
private final MasterMixer mixer = MasterMixer.getInstance();
private int textCW = mixer.getWidth();
private int textCH = mixer.getHeight();
public SourceText(String content) {
super();
this.content = content;
name = "Text";
updateContent(content);
color = 0xFFFFFF;
fontName = Font.MONOSPACED;
}
@Override
public void readNext() {
if (frame != null && isPlaying) {
frame.setImage(image);
if (frame != null) {
txImage = frame.getImage();
applyEffects(txImage);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
nextFrame=frame;
}
}
}
@Override
public void play() {
// nothing here.
}
public void setTextCW (int tCW) {
textCW = tCW;
}
public int getTextCW(){
return textCW;
}
public void setTextCH(int tCH) {
textCH = tCH;
}
public int getTextCH(){
return textCH;
}
@Override
public void setX(int x){
this.x=x;
// System.out.println("X set ... "+x);
}
@Override
public void setY(int y){
this.y=y;
// System.out.println("Y set ... "+y);
}
public void setBackgroundOpacity(float o){
bgOpacity=o;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
}
public float getBackgroundOpacity(){
return bgOpacity;
}
public void setBackground(Shape s) {
shape = s;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
}
public Shape getBackground() {
return shape;
}
public void setStrBackground(String strS) {
strShape = strS;
}
@Override
public void setIsPlaying(boolean setIsPlaying) {
isPlaying = setIsPlaying;
}
public String getStrBackground() {
return strShape;
}
@Override
public void setWidth(int w) {
width = w;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
// System.out.println("W set ... "+w);
}
}
@Override
public void setHeight(int h) {
height = h;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
// System.out.println("H set ... "+h);
}
}
@Override
public void setColor(int c) {
color = c;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
}
@Override
public int getColor() {
return color;
}
public void setBackGroundColor(int bgColor) {
this.bgColor = bgColor;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
}
public int getBackgroundColor() {
return bgColor;
}
@Override
public void setFont(String f) {
fontName = f;
if (this.isATimer || this.isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
}
@Override
public String getFont() {
return fontName;
}
@Override
public void setZOrder(int layer) {
zorder = layer;
}
// for Clock and Timer
@Override
public void updateLineContent(String content) {
Color bkgColor = new Color(bgColor);
this.content = content;
if (this.getIsQRCode()) {
captureWidth = width;
captureHeight = height;
if (content != null && content.length() > 0) {
frame = new Frame(captureWidth, captureHeight, rate);
MultiFormatWriter w = new MultiFormatWriter();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
BitMatrix b;
try {
b = w.encode(content, BarcodeFormat.QR_CODE, width, height);
image = com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(b);
} catch (WriterException ex) {
Logger.getLogger(SourceText.class.getName()).log(Level.SEVERE, null, ex);
}
if (frame != null) {
frame.setImage(image);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
}
}
} else {
captureWidth = width;
captureHeight = height;
int textHeight = captureHeight;
int textWidth; // = captureWidth;
image = new BufferedImage(captureWidth, captureHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D buffer = image.createGraphics();
buffer.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
buffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
buffer.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
buffer.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
buffer.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
buffer.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Font font = new Font(fontName, Font.PLAIN, textHeight);
buffer.setFont(font);
FontMetrics fm = buffer.getFontMetrics();
textHeight = fm.getHeight();
textWidth = fm.stringWidth(content);
int fontSize = font.getSize();
while ((textHeight > captureHeight || textWidth > captureWidth) && fontSize>1){
font = new Font(fontName, Font.PLAIN, fontSize--);
buffer.setFont(font);
fm = buffer.getFontMetrics();
textHeight = fm.getHeight();
textWidth = fm.stringWidth(content);
}
frame = new Frame(captureWidth, captureHeight, rate);
buffer.setBackground(new Color(0,0,0,0));
buffer.clearRect(0, 0, captureWidth, captureHeight);
switch (shape) {
case RECTANGLE:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fill3DRect(0, 0, captureWidth, captureHeight,true);
break;
case OVAL:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fillOval(0, 0, captureWidth, captureHeight);
break;
case ROUNDRECT:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fillRoundRect(0, 0, captureWidth, captureHeight,captureWidth/5,captureHeight/5);
break;
}
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, 1F));
buffer.setColor(new Color(color));
buffer.drawString(content, (captureWidth-textWidth)/2, captureHeight/2 + textHeight/2 - fm.getDescent());
buffer.dispose();
if (frame != null) {
frame.setImage(image);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
}
}
}
// for Text-Area
@Override
public void updateContent(String content) throws NoSuchElementException {
ArrayList<String> linee = new ArrayList<>();
Color bkgColor = new Color(bgColor);
this.content = content;
String[] datas = content.split("\n");
linee.clear();
linee.addAll(Arrays.asList(datas));
if (this.getIsQRCode()) {
captureWidth = width;
captureHeight = height;
if (content != null && content.length() > 0) {
frame = new Frame(captureWidth, captureHeight, rate);
MultiFormatWriter w = new MultiFormatWriter();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
BitMatrix b;
try {
b = w.encode(content, BarcodeFormat.QR_CODE, width, height);
image = com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(b);
} catch (WriterException ex) {
Logger.getLogger(SourceText.class.getName()).log(Level.SEVERE, null, ex);
}
if (frame != null) {
frame.setImage(image);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
}
}
} else {
captureWidth = width;
captureHeight = height;
int textHeight = captureHeight;
int textWidth; // = captureWidth;
image = new BufferedImage(captureWidth, captureHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D buffer = image.createGraphics();
buffer.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
buffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
buffer.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
buffer.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
buffer.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
buffer.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Font font = new Font(fontName, Font.PLAIN, textHeight);
buffer.setFont(font);
FontMetrics fm = buffer.getFontMetrics();
textHeight = getHeight();
int currentLineSize = 0;
ArrayList<Integer>lineSizes = new ArrayList<>();
for (String line : linee) {
lineSizes.add(fm.stringWidth(line));
currentLineSize = fm.stringWidth(line);
}
if (lineSizes.size() == 1) {
textWidth = currentLineSize;
} else {
textWidth = Collections.max(lineSizes);
}
int fontSize = font.getSize();
while ((textHeight*linee.size() > captureHeight || textWidth > captureWidth) && fontSize>1){
font = new Font(fontName, Font.PLAIN, fontSize--);
buffer.setFont(font);
fm = buffer.getFontMetrics();
textHeight = fm.getHeight();
lineSizes = new ArrayList<>();
for (String line : linee) {
lineSizes.add(fm.stringWidth(line));
}
textWidth = Collections.max(lineSizes);
}
frame = new Frame(captureWidth, captureHeight, rate);
buffer.setBackground(new Color(0,0,0,0));
buffer.clearRect(0, 0, captureWidth, captureHeight);
switch (shape) {
case RECTANGLE:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fill3DRect(0, 0, captureWidth, captureHeight,true);
break;
case OVAL:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fillOval(0, 0, captureWidth, captureHeight);
break;
case ROUNDRECT:
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, bgOpacity));
buffer.setColor(bkgColor);
buffer.fillRoundRect(0, 0, captureWidth, captureHeight,captureWidth/5,captureHeight/5);
break;
}
buffer.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, 1F));
buffer.setColor(new Color(color));
int tHeight = textHeight;
// System.out.println("FontHeight: "+textHeight);
int k = (int)(textHeight*(15.0f/100.0f));
for (String line : linee) {
buffer.drawString(line, (captureWidth-textWidth)/2, tHeight - k); //
tHeight += textHeight;
}
tHeight = 0;
buffer.dispose();
if (frame != null) {
frame.setImage(image);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
}
}
}
@Override
public String getContent() {
return content;
}
@Override
public void read() {
boolean isTimer = this.getIsATimer();
boolean isACDown = this.getIsACDown();
stop = false;
isPlaying = true;
if (getPreView()){
PreviewFrameBuilder.register(this);
} else {
MasterFrameBuilder.register(this);
}
this.setBackground(shape);
try {
if (isTimer || isACDown) {
updateLineContent(content);
} else {
updateContent(content);
}
frame.setID(uuid);
frame.setImage(image);
frame.setOutputFormat(x, y, width, height, opacity, volume);
frame.setZOrder(zorder);
} catch (NoSuchElementException e) {
e.printStackTrace();
}
}
@Override
public void pause() {
// nothing here.
}
@Override
public void stop() {
for (int fx = 0; fx < this.getEffects().size(); fx++) {
Effect fxT = this.getEffects().get(fx);
if (fxT.getName().endsWith("Shapes")){
fxT.setDoOne(true);
} else if (fxT.getName().endsWith("Stretch") || fxT.getName().endsWith("Crop")) {
// do nothing.
} else {
fxT.resetFX();
}
}
stop = true;
isPlaying = false;
frame = null;
if (getPreView()){
PreviewFrameBuilder.unregister(this);
} else {
MasterFrameBuilder.unregister(this);
}
}
@Override
public boolean needSeek() {
return needSeekCTRL=false;
}
@Override
public Frame getFrame() {
return nextFrame;
}
@Override
public boolean isPlaying() {
return isPlaying;
}
@Override
public BufferedImage getPreview() {
return image;
}
@Override
public boolean hasAudio() {
return false;
}
@Override
public boolean hasVideo() {
return true;
}
public enum Shape {
NONE, RECTANGLE, ROUNDRECT, OVAL
}
}