=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/EmulatedWindowState.java' --- src/com/goldencode/p2j/ui/client/gui/driver/EmulatedWindowState.java 2015-09-07 21:26:31 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/EmulatedWindowState.java 2015-09-08 10:10:09 +0000 @@ -452,12 +452,22 @@ extra = String.format(" x = %d; y = %d", ps.x, ps.y); break; case DRAW_STRING: - extra = String.format(" text = %s; x = %d; y = %d, centered = %b", + extra = String.format(" text = %s; x = %d; y = %d; centered = %b", ps.text, ps.x, ps.y, ps.centered); break; + case DRAW_STRING_SCALED: + extra = String.format( + " text = %s; x = %d; y = %d; centered = %b; lwidth = %d; lheight = %d", + ps.text, + ps.x, + ps.y, + ps.centered, + ps.width, + ps.height); + break; case SET_TITLE: extra = String.format(" title = %s", ps.title); break; === modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js' --- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js 2015-09-06 23:47:37 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js 2015-09-08 09:58:48 +0000 @@ -23,15 +23,18 @@ * The canvas 2D graphics context on which to draw. * @param {LinesStroke} strokesManager * The stroke manager + * @param {Object} fontsManager + * The p2j fonts manager. * @param {Object} logger * The p2j logger. */ -function CanvasRenderer(canvas, ctx, strokesManager, logger) +function CanvasRenderer(canvas, ctx, strokesManager, fontsManager, logger) { this.canvas = canvas; this.ctx = ctx; this.strokesManager = strokesManager; this.logger = logger; + this.fontsManager = fontsManager; /** Color scaling factor, compatible with Java2D. */ var SCALE_FACTOR = 0.7; @@ -233,6 +236,35 @@ } /** + * Fill or stroke the current path on the given context, first using the current path as a + * clipping region. This ensures that the drawing of the path will not extend outside of the + * path by a half-pixel (which it would otherwise). The state of the context is saved on + * entry and restored after the drawing operation, so there will be no residual clipping + * region when this function returns. + * + * @param {CanvasRenderingContext2D} ctx + * The canvas 2D graphics context on which to draw. + * @param {Boolean} fill + * true to fill the drawn rectangle with the given color. + */ +CanvasRenderer.prototype.renderClosedPath = function(ctx, fill) +{ + ctx.save(); + ctx.clip(); + + if (fill) + { + ctx.fill(); + } + else + { + ctx.stroke(); + } + + ctx.restore(); +}; + +/** * Adjust the origin for pixel drawing on the canvas. * * @param {Number} x @@ -421,35 +453,6 @@ } /** - * Fill or stroke the current path on the given context, first using the current path as a - * clipping region. This ensures that the drawing of the path will not extend outside of the - * path by a half-pixel (which it would otherwise). The state of the context is saved on - * entry and restored after the drawing operation, so there will be no residual clipping - * region when this function returns. - * - * @param {CanvasRenderingContext2D} ctx - * The canvas 2D graphics context on which to draw. - * @param {Boolean} fill - * true to fill the drawn rectangle with the given color. - */ -function renderClosedPath(ctx, fill) -{ - ctx.save(); - ctx.clip(); - - if (fill) - { - ctx.fill(); - } - else - { - ctx.stroke(); - } - - ctx.restore(); -}; - -/** * Draw a rectangle in the given color and dimensions with the line drawing being overwritten * using direct drawing to eliminate the negative/unwanted effects of alni-aliasing. * @@ -483,7 +486,7 @@ inset = 1; ctx.beginPath(); ctx.rect(x, y, width - inset, height - inset); - renderClosedPath(ctx, fill); + this.renderClosedPath(ctx, fill); } // now overdraw the stroked portion to eliminate anti-aliasing, we draw in a @@ -527,7 +530,7 @@ inset = 1; ctx.beginPath(); ctx.rect(x, y, width - inset, height - inset); - renderClosedPath(ctx, fill); + this.renderClosedPath(ctx, fill); } // now overdraw the stroked portion to eliminate anti-aliasing, we draw in a @@ -662,7 +665,7 @@ ctx.quadraticCurveTo(northWestX, northWestY, topLeftX, topLeftY); ctx.closePath(); - renderClosedPath(ctx, fill); + this.renderClosedPath(ctx, fill); // overdraw the anti-aliased line segments var path = []; @@ -738,7 +741,7 @@ ctx.fillStyle = this.createColorString(current); ctx.beginPath(); ctx.rect(x, y, width - 2, height - 2); - renderClosedPath(ctx, fill); + this.renderClosedPath(ctx, fill); } current = raised ? lighter : darker; @@ -807,7 +810,7 @@ ctx.lineTo(xPoints[i], yPoints[i]); } ctx.closePath(); - renderClosedPath(ctx, fill); + this.renderClosedPath(ctx, fill); } var path = []; // now overdraw the stroked portion @@ -1144,3 +1147,90 @@ this.ctx.translate(x, y); }; + +/** + * Draws a given text at the given (x,y) position. + * + * @param {Number} text + * The text to draw. + * @param {Number} x + * The X-axis of the coordinate for the text starting point. + * @param {Number} y + * The Y-axis of the coordinate for the text starting point or the height + * of the text rectangle from the most top screen position. + * @param {Boolean} centered + * Defines the text base line and the interpretation of y. + * If it is true, the text base line is set to 'middle' and interprets y as a height, + * otherwise the text base line is set to 'bottom'. + */ +CanvasRenderer.prototype.drawText = function(text, x, y, centered) +{ + if (centered) + { + // in this case, the "y" is the height in which it needs to be vertically centered + y = y / 2; + + this.ctx.textBaseline = 'middle'; + } + else + { + this.ctx.textBaseline = 'bottom'; + } + + this.ctx.fillText(text, x, y); +} + +/** + * Draws a given text at the given (x,y) position fitted to the given text rectangle. + * + * @param {Number} currentFont + * The current font ID, in the js font-table. + * @param {Number} text + * The text to draw. + * @param {Number} x + * The X-axis of the coordinate for the text starting point. + * @param {Number} y + * The Y-axis of the coordinate for the text starting point or the height + * of the text rectangle from the most top screen position. + * @param {Boolean} centered + * Defines the text base line and the interpretation of y. + * If it is true, the text base line is set to 'middle' and interprets y as a height, + * otherwise the text base line is set to 'bottom'. + * @param {Number} lwidth + * The space width to be used to display the given text. + * The text is scaled to fit this width, squeezed or extended + * @param {Number} lheight + * The space height to be used to display the given text. + * The text is scaled to fit this height, squeezed or extended. + */ +CanvasRenderer.prototype.drawScaledText = function(currentFont, text, x, y, centered, lwidth, lheight) +{ + var textWidth = this.fontsManager.getTextWidth(currentFont, text); + var textHeight = this.fontsManager.getTextHeight(currentFont, text); + + var widthScale = lwidth / textWidth; + var heightScale = lheight / textHeight; + + // scale drawing context to computed width + // this scales the desired structure.x as well so it needs adjusting + this.ctx.save(); + this.ctx.scale(widthScale, heightScale); + + var scaleBackWidth = 1 / widthScale; + var scaleBackHeight = 1 / heightScale; + + if (centered) + { + // in this case, the "y" is the height in which it needs to be vertically centered + y = y / 2; + + this.ctx.textBaseline = 'middle'; + } + else + { + this.ctx.textBaseline = 'bottom'; + } + + this.ctx.fillText(text, x * scaleBackWidth, y * scaleBackHeight); + this.ctx.restore(); +} \ No newline at end of file === modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.screen.js' --- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.screen.js 2015-09-07 21:26:31 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.screen.js 2015-09-08 09:59:32 +0000 @@ -184,7 +184,8 @@ this.iconHeight = 0; /** Creates canvas renderer. */ - this.canvasRenderer = new CanvasRenderer(this.canvas, this.ctx, strokesManager, p2j.logger); + this.canvasRenderer = new CanvasRenderer(this.canvas, this.ctx, strokesManager, + p2j.fonts, p2j.logger); /** List of widgets which are aware of mouse events. */ this.mouseAwareWidgets = new Array(); @@ -556,20 +557,7 @@ y = p2j.socket.readInt32BinaryMessage(message, idx + offset); offset = offset + 4; - if (centered) - { - // in this case, the "y" is the height in which it needs to be vertically centered - y = y / 2; - - this.ctx.textBaseline = 'middle'; - } - else - { - this.ctx.textBaseline = 'bottom'; - } - - this.ctx.fillText(text, x, y); - + this.canvasRenderer.drawText(text, x, y, centered); extra = " text = " + text + "; x = " + x + "; y = " + y + "; centered = " + centered; break; @@ -597,35 +585,10 @@ var lheight = p2j.socket.readInt32BinaryMessage(message, idx + offset); offset = offset + 4; - var textWidth = p2j.fonts.getTextWidth(currentFont, text); - var textHeight = p2j.fonts.getTextHeight(currentFont, text); - - var widthScale = lwidth / textWidth; - var heightScale = lheight / textHeight; - - // scale drawing context to computed width - // this scales the desired structure.x as well so it needs adjusting - this.ctx.save(); - this.ctx.scale(widthScale, heightScale); - - var scaleBackWidth = 1 / widthScale; - var scaleBackHeight = 1 / heightScale; - - if (centered) - { - // in this case, the "y" is the height in which it needs to be vertically centered - y = y / 2; - - this.ctx.textBaseline = 'middle'; - } - else - { - this.ctx.textBaseline = 'bottom'; - } - - this.ctx.fillText(text, x * scaleBackWidth, y * scaleBackHeight); - this.ctx.restore(); - + this.canvasRenderer.drawScaledText(currentFont, text, x, y, centered, lwidth, lheight); + extra = " text = " + text + "; x = " + x + "; y = " + y + + "; centered = " + centered + + "; lwidth = " + lwidth + "; lheight = " + lheight; break; case ops.DRAW_PARAGRAPH: offset = 1;