package com.xenoage.zong.renderer.gwtcanvas.canvas; import com.google.gwt.canvas.dom.client.Context2d; import com.google.gwt.canvas.dom.client.Context2d.LineCap; import com.google.gwt.canvas.dom.client.Context2d.LineJoin; import com.xenoage.utils.color.Color; import com.xenoage.utils.font.TextMetrics; import com.xenoage.utils.gwt.color.GwtColorUtils; import com.xenoage.utils.gwt.font.GwtFontUtils; import com.xenoage.utils.math.Units; import com.xenoage.utils.math.geom.Point2f; import com.xenoage.utils.math.geom.Rectangle2f; import com.xenoage.utils.math.geom.Size2f; import com.xenoage.zong.core.text.*; import com.xenoage.zong.io.selection.text.TextSelection; import com.xenoage.zong.renderer.canvas.CanvasDecoration; import com.xenoage.zong.renderer.canvas.CanvasFormat; import com.xenoage.zong.renderer.canvas.CanvasIntegrity; import com.xenoage.zong.renderer.symbol.SymbolsRenderer; import com.xenoage.zong.symbols.path.Path; import com.xenoage.zong.renderer.gwtcanvas.path.GwtPath; /** * This class contains methods for painting * on a HTML5 canvas using GWT. * * @author Andreas Wenger */ public class GwtCanvas extends com.xenoage.zong.renderer.canvas.Canvas { //the HTML5 graphics context private Context2d context; /** * Creates an {@link GwtCanvas} with the given size in mm for the given context, * format, decoration mode and itegrity. */ public GwtCanvas(Context2d context, CanvasFormat format, CanvasDecoration decoration, CanvasIntegrity integrity) { super(new Size2f(10, 10), format, decoration, integrity); this.context = context; } /** * Gets the HTML5 canvas. */ @Override public Context2d getGraphicsContext() { return context; } /** * {@inheritDoc} * The text selection is ignored. */ @Override public void drawText(FormattedText text, TextSelection selection, Point2f position, boolean yIsBaseline, float frameWidth) { context.save(); context.translate(position.x, position.y); //print the text frame paragraph for paragraph float offsetX = 0; float offsetY = 0; for (FormattedTextParagraph p : text.getParagraphs()) { TextMetrics pMetrics = p.getMetrics(); if (!yIsBaseline) offsetY += pMetrics.getAscent(); //adjustment if (p.getAlignment() == Alignment.Center) offsetX = (frameWidth - pMetrics.getWidth()) / 2; else if (p.getAlignment() == Alignment.Right) offsetX = frameWidth - pMetrics.getWidth(); else offsetX = 0; //draw elements for (FormattedTextElement e : p.getElements()) { if (e instanceof FormattedTextString) { FormattedTextString t = (FormattedTextString) e; context.setFillStyle(GwtColorUtils.createColor(t.getStyle().getColor())); context.save(); context.scale(Units.pxToMm_1_1, Units.pxToMm_1_1); context.setFont(GwtFontUtils.getCssFont(t.getStyle().getFont())); context.fillText(t.getText(), offsetX / Units.pxToMm_1_1, offsetY / Units.pxToMm_1_1); //Debug: Paint dot at text offset //context.fillRect(offsetX / Units.pxToMm_1_1, offsetY / Units.pxToMm_1_1, 2, 2); context.restore(); } else { //symbol FormattedTextSymbol fts = (FormattedTextSymbol) e; float scaling = fts.getScaling(); SymbolsRenderer.draw(fts.getSymbol(), this, Color.black, new Point2f( offsetX + fts.getOffsetX(), offsetY + fts.getSymbol().baselineOffset * scaling), new Point2f(scaling, scaling)); } offsetX += e.getMetrics().getWidth(); } //next line offsetY += p.getMetrics().getAscent() + p.getMetrics().getDescent() + p.getMetrics().getLeading(); } context.restore(); } @Override public void drawLine(Point2f p1, Point2f p2, Color color, float lineWidth) { //set style context.setStrokeStyle(GwtColorUtils.createColor(color)); context.setLineWidth(lineWidth); context.setLineCap(LineCap.BUTT); context.setLineJoin(LineJoin.BEVEL); //draw line context.beginPath(); context.moveTo(p1.x, p1.y); context.lineTo(p2.x, p2.y); context.stroke(); } @Override public void drawStaff(Point2f pos, float length, int lines, Color color, float lineWidth, float interlineSpace) { context.setFillStyle(GwtColorUtils.createColor(color)); for (int i = 0; i < lines; i++) { float x = pos.x; float y = pos.y + i * interlineSpace - lineWidth / 2; context.fillRect(x, y, length, lineWidth); } } @Override public void drawSimplifiedStaff(Point2f pos, float length, float height, Color color) { context.setFillStyle(GwtColorUtils.createColor(color)); context.fillRect(pos.x, pos.y, length, height); } @Override public void fillPath(Path path, Color color) { context.setFillStyle(GwtColorUtils.createColor(color)); GwtPath.drawPath(path, context); context.fill(); } @Override public void fillRect(Rectangle2f rect, Color color) { context.setFillStyle(GwtColorUtils.createColor(color)); context.fillRect(rect.position.x, rect.position.y, rect.size.width, rect.size.height); } @Override public void drawImage(Rectangle2f rect, String imagePath) { //TODO } @Override public void transformSave() { context.save(); } @Override public void transformRestore() { context.restore(); } @Override public void transformTranslate(float x, float y) { context.translate(x, y); } @Override public void transformScale(float x, float y) { context.scale(x, y); } @Override public void transformRotate(float angle) { context.rotate(angle); } }