package com.xenoage.zong.renderer.stamping;
import com.xenoage.utils.color.Color;
import com.xenoage.utils.math.geom.Point2f;
import com.xenoage.zong.core.music.barline.BarlineRepeat;
import com.xenoage.zong.core.music.barline.BarlineStyle;
import com.xenoage.zong.core.music.format.SP;
import com.xenoage.zong.core.music.group.BarlineGroup;
import com.xenoage.zong.musiclayout.stampings.BarlineStamping;
import com.xenoage.zong.musiclayout.stampings.StaffStamping;
import com.xenoage.zong.musiclayout.stampings.Stamping;
import com.xenoage.zong.musiclayout.stampings.bitmap.BitmapStaff;
import com.xenoage.zong.renderer.RendererArgs;
import com.xenoage.zong.renderer.canvas.Canvas;
import com.xenoage.zong.renderer.canvas.CanvasFormat;
import com.xenoage.zong.symbols.Symbol;
import com.xenoage.zong.symbols.common.CommonSymbol;
import java.util.List;
import static com.xenoage.zong.core.music.format.SP.sp;
/**
* Renderer for a {@link BarlineStamping}.
*
* @author Andreas Wenger
*/
public class BarlineRenderer
extends StampingRenderer {
/**
* Draws the given {@link BarlineStamping} on the given {@link Canvas},
* using the given {@link RendererArgs}.
*/
@Override public void draw(Stamping stamping, Canvas canvas, RendererArgs args) {
BarlineStamping barlineSt = (BarlineStamping) stamping;
List<StaffStamping> staves = barlineSt.staves;
float xPosition = barlineSt.xMm;
float xCorrection = 0;
//lines
BarlineGroup.Style group = barlineSt.groupStyle;
BarlineStyle style = barlineSt.barline.getStyle();
if (group == null || group == BarlineGroup.Style.Single || group == BarlineGroup.Style.Common) {
//draw single barlines
for (StaffStamping staff : staves) {
xCorrection = paintBarline(canvas, args, staff, (staff.linesCount - 1) * 2, staff, 0,
xPosition, style);
}
}
if (group == BarlineGroup.Style.Mensurstrich || group == BarlineGroup.Style.Common) {
//draw barlines between staves
for (int i = 0; i < staves.size() - 1; i++) {
xCorrection = paintBarline(canvas, args, staves.get(i), 0, staves.get(i + 1),
(staves.get(i + 1).linesCount - 1) * 2, xPosition, style);
}
}
//repeat dots
//TODO: xCorrection is the value of the last staff, but this may differ
//draw repeat dots directly after drawing the corresponding staff!
BarlineRepeat repeat = barlineSt.barline.getRepeat();
if (repeat == BarlineRepeat.Forward || repeat == BarlineRepeat.Both) {
paintRepeatDots(staves, xPosition + xCorrection, 1, canvas, args);
}
if (repeat == BarlineRepeat.Backward || repeat == BarlineRepeat.Both) {
paintRepeatDots(staves, xPosition + xCorrection, -1, canvas, args);
}
}
/**
* Draws repeat dots at the given side (-1 or 1) at the given
* horizontal position on the given staves.
*/
private static void paintRepeatDots(List<StaffStamping> staves, float xPosition, int side,
Canvas canvas, RendererArgs args) {
for (StaffStamping staff : staves) {
int lp1 = (staff.linesCount + 1) / 2;
int lp2 = lp1 + 2;
float x = xPosition + staff.is * 1.2f * side;
paintRepeatDot(canvas, args, staff, sp(x, lp1));
paintRepeatDot(canvas, args, staff, sp(x, lp2));
}
}
/**
* Draws a barline with the given style between the given line of the given
* staff and the other given line of the other
* given staff, using the given rendering parameters.
* The horizontal position correction in px is returned.
*
* TIDY TIDY TIDY
*/
private static float paintBarline(Canvas canvas, RendererArgs args, StaffStamping staff1,
float staff1LP, StaffStamping staff2, float staff2LP, float xPosition, BarlineStyle style) {
Color col = Color.black;
float lightMm = staff1.getLineWidthMm() * 1.5f; //barline a little bit thicker than staff line
float heavyMm = lightMm * 3f;
float gapMm = lightMm * 1.5f;
float l = lightMm;
float h = heavyMm;
float g = gapMm;
Color lightColor = col, heavyColor = col;
/* UNNEEDED... looks good anyway
//correction for bitmap display
if (canvas.getFormat() == CanvasFormat.Bitmap)
{
//screen
//light
BitmapLine screenLine = new BitmapLine(lightMm, col, scaling);
l = screenLine.widthMm;
lightColor = screenLine.color;
//heavy
screenLine = new BitmapLine(heavyMm, col, scaling);
h = screenLine.widthMm;
heavyColor = screenLine.color;
//gap (for a better look, use bigger gap at low zoom. tried out.)
float gapPxFloat = Units.mmToPx(gapMm, scaling);
if (gapPxFloat >= 2)
g = gapMm;
else if (gapPxFloat >= 1f)
g = Units.pxToMm(2, scaling);
else if (gapPxFloat >= 0.2f)
g = Units.pxToMm(1, scaling);
else
g = 0;
} */
//if on the very left or very right side of the staff, don't center
//the barline but place it completely within the staff
boolean isLeft = (xPosition <= staff1.positionMm.x + lightMm);
boolean isRight = (xPosition >= staff1.positionMm.x + staff1.lengthMm - lightMm);
float x = xPosition;
float c = 0;
//half of light/heavy/gap
float l2 = l / 2;
float h2 = h / 2;
float g2 = g / 2;
//TEST
//paintLine(params, staff1, staff1LP + 4, staff2, staff1LP + 1, x - c, 1, Color.blue);
//paintLine(params, staff1, staff2LP - 1, staff2, staff2LP - 4, x - c, 1, Color.blue);
//TEST
//style = BarlineStyle.HeavyHeavy;
//draw lines dependent on style
//all correction values have been found by trying out
//TODO: Dashed, Dotted
switch (style) {
case Regular:
if (isLeft) {
c = l2;
x += c;
}
else if (isRight) {
c = -l2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x, l, lightColor);
break;
case Heavy:
if (isLeft) {
c = h2;
x += c;
}
else if (isRight) {
c = -h2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x, h, heavyColor);
break;
case LightLight:
if (isLeft) {
c = g2 + 2 * l2;
x += c;
}
else if (isRight) {
c = -l2 - g2 - l2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x - g2 - l2, l, lightColor);
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x + g2 + l2, l, lightColor);
break;
case LightHeavy: //heavy is centered (if barline not at the border of the staff)
if (isLeft) {
c = 2 * l2 + g + h2;
x += c;
}
else if (isRight) {
c = -h2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x - h2 - g - l2, l, lightColor);
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x, h, heavyColor);
break;
case HeavyLight: //heavy is centered (if barline not at the border of the staff)
if (isLeft) {
c = h2;
x += c;
}
else if (isRight) {
c = -l2 - h2 - g - l2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x, h, heavyColor);
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x + h2 + g + l2, l, lightColor);
break;
case HeavyHeavy:
if (isLeft) {
c = g2 + 2 * h2;
x += c;
}
else if (isRight) {
c = -h2 - g2 - h2;
x += c;
}
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x - g2 - h2, h, heavyColor);
paintLine(canvas, args, staff1, staff1LP, staff2, staff2LP, x + g2 + h2, h, heavyColor);
break;
case None:
case Dashed:
case Dotted:
//TODO
break;
}
return c;
}
/**
* Draws the given line with the given width in px.
*/
private static void paintLine(Canvas canvas, RendererArgs args, StaffStamping staff1,
float staff1LinePosition, StaffStamping staff2, float staff2LinePosition, float xMm,
float widthMm, Color color) {
if (canvas.getFormat() == CanvasFormat.Raster) {
float scaling = args.targetScaling;
BitmapStaff screenStaff1 = staff1.getBitmapInfo().getBitmapStaff(scaling);
BitmapStaff screenStaff2 = staff2.getBitmapInfo().getBitmapStaff(scaling);
Point2f p1 = new Point2f(xMm, staff1.positionMm.y + screenStaff1.getYMm(staff1LinePosition));
Point2f p2 = new Point2f(xMm, staff2.positionMm.y + screenStaff2.getYMm(staff2LinePosition));
canvas.drawLine(p1, p2, color, widthMm);
}
else if (canvas.getFormat() == CanvasFormat.Vector) {
Point2f p1 = new Point2f(xMm, staff1.positionMm.y + staff1.is *
(staff1.linesCount - 1 - staff1LinePosition / 2));
Point2f p2 = new Point2f(xMm, staff2.positionMm.y + staff2.is *
(staff2.linesCount - 1 - staff2LinePosition / 2));
canvas.drawLine(p1, p2, color, widthMm);
}
}
/**
* Paints a repeat dot at the given position.
*/
private static void paintRepeatDot(Canvas canvas, RendererArgs args, StaffStamping staff,
SP position) {
Symbol dotSymbol = args.symbolPool.getSymbol(CommonSymbol.NoteDot);
StaffSymbolRenderer.drawWith(dotSymbol, Color.black, position, 1, staff, false,
canvas, args);
}
}