//----------------------------------------------------------------------------//
// //
// S l a n t e d S y m b o l //
// //
//----------------------------------------------------------------------------//
// <editor-fold defaultstate="collapsed" desc="hdr"> //
// Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. //
// This software is released under the GNU General Public License. //
// Goto http://kenai.com/projects/audiveris to report bugs or suggestions. //
//----------------------------------------------------------------------------//
// </editor-fold>
package omr.ui.symbol;
import omr.glyph.Shape;
import static omr.ui.symbol.Alignment.*;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
/**
* Class {@code SlantedSymbol} draws symbols made of several slanted parts
* (such as in DYNAMICS_FP, where both the F and the P are slanted and appear
* too far for each other)
*/
public class SlantedSymbol
extends ShapeSymbol
{
//~ Constructors -----------------------------------------------------------
//---------------//
// SlantedSymbol //
//---------------//
/**
* Creates a new SlantedSymbol object, standard size
*
* @param shape the related shape
* @param codes the codes for MusicFont characters
*/
public SlantedSymbol (Shape shape,
int... codes)
{
this(false, shape, codes);
}
//---------------//
// SlantedSymbol //
//---------------//
/**
* Creates a new SlantedSymbol object.
*
* @param isIcon true for icon
* @param shape the related shape
* @param codes the codes for MusicFont characters
*/
protected SlantedSymbol (boolean isIcon,
Shape shape,
int... codes)
{
super(isIcon, shape, false, codes);
}
//~ Methods ----------------------------------------------------------------
//------------//
// createIcon //
//------------//
@Override
protected ShapeSymbol createIcon ()
{
return new SlantedSymbol(true, shape, codes);
}
//-----------//
// getParams //
//-----------//
@Override
protected MyParams getParams (MusicFont font)
{
MyParams p = new MyParams();
p.layouts = new SmartLayout[codes.length];
// Union of all rectangles
Rectangle2D rect = null;
// Current abscissa
float x = 0;
for (int i = 0; i < codes.length; i++) {
int code = codes[i];
TextLayout layout = font.layout(code);
Rectangle2D r = layout.getBounds();
// Abscissa reduction because of slanted characters
// It's value depends on whether we have a 'f' or not
float dx;
int c = code - MusicFont.CODE_OFFSET;
if ((c == 102) || // F
(c == 196) || // FF
(c == 236) || // FFF
(c == 83) || // SF
(c == 90)) { // FZ
dx = (float) r.getHeight() * 0.215f; // Measured
} else {
dx = (float) r.getHeight() * 0.075f; // Measured
}
p.layouts[i] = new SmartLayout(layout, dx);
if (i > 0) {
x -= dx;
}
if (i == 0) {
rect = layout.getPixelBounds(null, x, 0);
} else {
Rectangle2D.union(
rect,
layout.getPixelBounds(null, x, 0),
rect);
}
x += (r.getWidth() - dx);
}
p.rect = new Rectangle(
(int) Math.floor(rect.getX()),
(int) Math.floor(rect.getY()),
(int) Math.ceil(rect.getWidth()),
(int) Math.ceil(rect.getHeight()));
return p;
}
//-------//
// paint //
//-------//
@Override
protected void paint (Graphics2D g,
Params params,
Point location,
Alignment alignment)
{
MyParams p = (MyParams) params;
Point loc = alignment.translatedPoint(
BASELINE_LEFT,
p.rect,
location);
// Precise abscissa
float x = loc.x;
for (int i = 0; i < p.layouts.length; i++) {
SmartLayout smart = p.layouts[i];
if (i > 0) {
x -= smart.dx; // Before symbol
}
OmrFont.paint(
g,
smart.layout,
new Point((int) Math.rint(x), loc.y),
BASELINE_LEFT);
x += smart.layout.getBounds()
.getWidth();
x -= smart.dx; // After symbol
}
}
//~ Inner Classes ----------------------------------------------------------
//--------//
// Params //
//--------//
protected class MyParams
extends Params
{
//~ Instance fields ----------------------------------------------------
// layout not used
// rect for global image
// Sequence of layouts
SmartLayout[] layouts;
}
//-------------//
// SmartLayout //
//-------------//
protected static class SmartLayout
{
//~ Instance fields ----------------------------------------------------
// The standard character glyph
final TextLayout layout;
// Translation before & after
final float dx;
//~ Constructors -------------------------------------------------------
public SmartLayout (TextLayout layout,
float dx)
{
this.layout = layout;
this.dx = dx;
}
}
}