Allow setFont("FontName:1x2") for scaling in 2 directions (fix #2044)

This commit is contained in:
Gordon Williams 2021-09-20 11:51:23 +01:00
parent 21f55a697b
commit ad961bdf79
8 changed files with 178 additions and 43 deletions

View File

@ -15,6 +15,7 @@
Fix for issue with pretokenised code not creating correct text string for reserved words, eg {undefined:1}
Bangle.js: Turn vibrate off every time a new app loads
Fix issue where ({a:0}).a in the console would create a ReferenceError (works in code)
Graphics: Allow setFont("FontName:1x2") for scaling in 2 directions (fix #2044)
2v10 : Bangle.js: Improved HRM calculations - swapped autocorrelation for bandpass filter
Bangle.js: Significantly improved step counting algorithm using bandpass filter (fix #1846)

View File

@ -188,7 +188,7 @@ NO_INLINE void graphicsDrawChar4x6(JsGraphics *gfx, int x1, int y1, char ch, uns
graphicsFillRect(
gfx,
x1+x*sizex, ly,
x1+x*(sizex+1) - 1, ly+sizey-1,
x1+(x+1)*sizex-1, ly+sizey-1,
pixel ? gfx->data.fgColor : gfx->data.bgColor);
line <<= 1;
}

View File

@ -414,8 +414,6 @@ NO_INLINE void graphicsDrawChar6x8(JsGraphics *gfx, int x1, int y1, char ch, uns
int cidx = idx % 6;
idx = (idx/6)*8;
int y;
int sx = sizex-1;
int sy = sizey-1;
for (y=0;y<8;y++) {
unsigned int line = LCD_FONT_6X8[idx + y] >> (cidx*5);
int ly = y*sizey + y1;
@ -425,12 +423,17 @@ NO_INLINE void graphicsDrawChar6x8(JsGraphics *gfx, int x1, int y1, char ch, uns
graphicsFillRect(
gfx,
x1+x*sizex, ly,
x1+sx+x*sizex, ly+sy,
x1+(x+1)*sizex-1, ly+sizey-1,
pixel ? gfx->data.fgColor : gfx->data.bgColor);
line <<= 1;
}
}
if (solidBackground) graphicsFillRect(gfx, x1+5*sizex, y1, x1+sx+5*sizex, y1+sizey*7+sy, gfx->data.bgColor); // fill gap between chars
if (solidBackground)
graphicsFillRect(
gfx,
x1+5*sizex, y1,
x1+6*sizex-1, y1+sizey*8-1,
gfx->data.bgColor); // fill gap between chars
}
#endif // USE_FONT_6X8

View File

@ -71,7 +71,13 @@ typedef enum {
} JsGraphicsFlags;
typedef enum {
JSGRAPHICS_FONTSIZE_SCALE_MASK = 8191, ///< the size of the font
/** The size of the font
For bitmap fonts we can also pack X and Y scale in here. X is 0..63, Y is (0..63)<<6 */
JSGRAPHICS_FONTSIZE_SCALE_MASK = 8191,
JSGRAPHICS_FONTSIZE_SCALE_X_Y = 4096, ///< set if X and Y are packed into scale
JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT = 6,
JSGRAPHICS_FONTSIZE_SCALE_X_MASK = 63,
JSGRAPHICS_FONTSIZE_SCALE_Y_MASK = 63 << JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT,
JSGRAPHICS_FONTSIZE_FONT_MASK = 7 << 13, ///< the type of the font
JSGRAPHICS_FONTSIZE_VECTOR = 0,
JSGRAPHICS_FONTSIZE_4X6 = 1 << 13, // a bitmap font
@ -199,10 +205,6 @@ void graphicsDrawLine(JsGraphics *gfx, int x1, int y1, int x2, int y2);
void graphicsDrawLineAA(JsGraphics *gfx, int ix1, int iy1, int ix2, int iy2); ///< antialiased drawline. each pixel is 1/16th
void graphicsDrawCircleAA(JsGraphics *gfx, int x, int y, int r);
void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices); ///< each pixel is 1/16th a pixel may overwrite vertices...
#ifndef NO_VECTOR_FONT
unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int size, char ch); ///< prints character, returns width
unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int size, char ch); ///< returns the width of a character
#endif
/// Draw a simple 1bpp image in foreground colour
void graphicsDrawImage1bpp(JsGraphics *gfx, int x1, int y1, int width, int height, const unsigned char *pixelData);
/// Scroll the graphics device (in user coords). X>0 = to right, Y >0 = down

View File

@ -1120,7 +1120,7 @@ JsVar *jswrap_graphics_setFontSizeX(JsVar *parent, int size, bool isVectorFont)
#else
if (isVectorFont) {
if (size<1) size=1;
if (size>1023) size=1023;
if (size>JSGRAPHICS_FONTSIZE_SCALE_MASK) size=JSGRAPHICS_FONTSIZE_SCALE_MASK;
}
#ifndef SAVE_ON_FLASH
if ((gfx.data.fontSize&JSGRAPHICS_FONTSIZE_CUSTOM_BIT) &&
@ -1240,9 +1240,22 @@ JsVar *jswrap_graphics_setFontAlign(JsVar *parent, int x, int y, int r) {
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
"return_object" : "Graphics"
}
Set the font by name, eg "4x6", or "Vector:12".
Set the font by name. Various forms are available:
* `g.setFont("4x6")` - standard 4x6 bitmap font
* `g.setFont("Vector:12")` - vector font 12px high
* `g.setFont("4x6:2")` - 4x6 bitmap font, doubled in size
* `g.setFont("6x8:2x3")` - 6x8 bitmap font, doubled in width, tripled in height
You can also use these forms, but they are not recommended:
* `g.setFont("Vector12")` - vector font 12px high
* `g.setFont("4x6",2)` - 4x6 bitmap font, doubled in size
`g.getFont()` will return the current font as a String.
For a list of available font names, you can use `g.getFonts()`.
For bitmap fonts you can also specify a size multiplier, for example `g.setFont("4x6",2)` or `g.setFont("4x6:2")` will double the size of the standard 4x6 bitmap font to 8x12.
*/
JsVar *jswrap_graphics_setFont(JsVar *parent, JsVar *fontId, int size) {
#ifndef SAVE_ON_FLASH
@ -1261,8 +1274,21 @@ JsVar *jswrap_graphics_setFont(JsVar *parent, JsVar *fontId, int size) {
if (colonIdx>=0)
fontSizeCharIdx = colonIdx+1;
JsVar *name;
if (fontSizeCharIdx>=0) {
size = jsvGetIntegerAndUnLock(jsvNewFromStringVar(fontId, fontSizeCharIdx, JSVAPPENDSTRINGVAR_MAXLENGTH));
if (fontSizeCharIdx>=0) { // "FontName:FontSize"
JsVar *sizeVar = jsvNewFromStringVar(fontId, fontSizeCharIdx, JSVAPPENDSTRINGVAR_MAXLENGTH);
int xIndex = jsvGetStringIndexOf(sizeVar,'x');
if (xIndex>=0) { // "FontName:1x3"
int sizex = jsvGetIntegerAndUnLock(jsvNewFromStringVar(sizeVar, 0, xIndex));
int sizey = jsvGetIntegerAndUnLock(jsvNewFromStringVar(sizeVar, xIndex+1, JSVAPPENDSTRINGVAR_MAXLENGTH));
if (sizex<0) sizex=0;
if (sizey<0) sizey=0;
if (sizex>63) sizex=63;
if (sizey>63) sizey=63;
size = sizex | (sizey<<JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT) | JSGRAPHICS_FONTSIZE_SCALE_X_Y;
} else { // // "FontName:12"
size = jsvGetInteger(sizeVar);
}
jsvUnLock(sizeVar);
name = jsvNewFromStringVar(fontId, 0, (fontSizeCharIdx>0)?fontSizeCharIdx-1:0);
} else {
name = jsvLockAgain(fontId);
@ -1322,9 +1348,12 @@ JsVar *jswrap_graphics_getFont(JsVar *parent) {
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
JsGraphicsFontSize f = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_FONT_MASK;
const char *name = 0;
bool allowXYScaling = true;
#ifndef NO_VECTOR_FONT
if (f == JSGRAPHICS_FONTSIZE_VECTOR)
if (f == JSGRAPHICS_FONTSIZE_VECTOR) {
name = "Vector";
allowXYScaling = false;
}
#endif
if (f == JSGRAPHICS_FONTSIZE_4X6)
name = "4x6";
@ -1340,7 +1369,9 @@ JsVar *jswrap_graphics_getFont(JsVar *parent) {
}
if (name) {
int scale = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_SCALE_MASK;
if (scale>1) return jsvVarPrintf("%s:%d",name, scale);
if (scale & JSGRAPHICS_FONTSIZE_SCALE_X_Y)
return jsvVarPrintf("%s:%dx%d",name, scale&JSGRAPHICS_FONTSIZE_SCALE_X_MASK, (scale & JSGRAPHICS_FONTSIZE_SCALE_Y_MASK)>>JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT);
else if (scale>1) return jsvVarPrintf("%s:%d",name, scale);
else return jsvNewFromString(name);
}
#endif
@ -1408,17 +1439,22 @@ Return the height in pixels of the current font
static int jswrap_graphics_getFontHeightInternal(JsGraphics *gfx) {
JsGraphicsFontSize f = gfx->data.fontSize & JSGRAPHICS_FONTSIZE_FONT_MASK;
unsigned short scale = gfx->data.fontSize & JSGRAPHICS_FONTSIZE_SCALE_MASK;
unsigned short scalex = scale, scaley = scale;
if (scale & JSGRAPHICS_FONTSIZE_SCALE_X_Y) {
scalex = scale & JSGRAPHICS_FONTSIZE_SCALE_X_MASK;
scaley = (scale & JSGRAPHICS_FONTSIZE_SCALE_Y_MASK) >> JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT;
}
if (f == JSGRAPHICS_FONTSIZE_VECTOR) {
return scale;
return scaley;
} else if (f == JSGRAPHICS_FONTSIZE_4X6) {
return 6*scale;
return 6*scaley;
#ifdef USE_FONT_6X8
} else if (f == JSGRAPHICS_FONTSIZE_6X8) {
return 8*scale;
return 8*scaley;
#endif
#ifndef SAVE_ON_FLASH
} else if (f & JSGRAPHICS_FONTSIZE_CUSTOM_BIT) {
return scale*(int)jsvGetIntegerAndUnLock(jsvObjectGetChild(gfx->graphicsVar, JSGRAPHICS_CUSTOMFONT_HEIGHT, 0));
return scaley*(int)jsvGetIntegerAndUnLock(jsvObjectGetChild(gfx->graphicsVar, JSGRAPHICS_CUSTOMFONT_HEIGHT, 0));
#endif
}
return 0;
@ -1453,8 +1489,12 @@ JsVar *jswrap_graphics_drawString(JsVar *parent, JsVar *var, int x, int y, bool
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
JsGraphicsFontSize font = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_FONT_MASK;
unsigned short scalex = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_SCALE_MASK;
unsigned short scaley = scalex;
unsigned short scale = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_SCALE_MASK;
unsigned short scalex = scale, scaley = scale;
if (scale & JSGRAPHICS_FONTSIZE_SCALE_X_Y) {
scalex = scale & JSGRAPHICS_FONTSIZE_SCALE_X_MASK;
scaley = (scale & JSGRAPHICS_FONTSIZE_SCALE_Y_MASK) >> JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT;
}
int fontHeight = jswrap_graphics_getFontHeightInternal(&gfx);
#ifndef SAVE_ON_FLASH
@ -1517,9 +1557,9 @@ JsVar *jswrap_graphics_drawString(JsVar *parent, JsVar *var, int x, int y, bool
}
if (font == JSGRAPHICS_FONTSIZE_VECTOR) {
#ifndef NO_VECTOR_FONT
int w = (int)graphicsVectorCharWidth(&gfx, gfx.data.fontSize, ch);
if (x>minX-w && x<maxX && y>minY-gfx.data.fontSize && y<maxY)
graphicsFillVectorChar(&gfx, x, y, gfx.data.fontSize, ch);
int w = (int)graphicsVectorCharWidth(&gfx, scalex, ch);
if (x>minX-w && x<maxX && y>minY-scaley && y<maxY)
graphicsFillVectorChar(&gfx, x, y, scalex, scaley, ch);
x+=w;
#endif
} else if (font == JSGRAPHICS_FONTSIZE_4X6) {
@ -1622,6 +1662,11 @@ JsVarInt jswrap_graphics_stringWidth(JsVar *parent, JsVar *var) {
JsGraphicsFontSize font = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_FONT_MASK;
unsigned short scale = gfx.data.fontSize & JSGRAPHICS_FONTSIZE_SCALE_MASK;
unsigned short scalex = scale, scaley = scale;
if (scale & JSGRAPHICS_FONTSIZE_SCALE_X_Y) {
scalex = scale & JSGRAPHICS_FONTSIZE_SCALE_X_MASK;
scaley = (scale & JSGRAPHICS_FONTSIZE_SCALE_Y_MASK) >> JSGRAPHICS_FONTSIZE_SCALE_Y_SHIFT;
}
#ifndef SAVE_ON_FLASH
JsVar *customWidth = 0;
int customFirstChar = 0;
@ -1644,21 +1689,21 @@ JsVarInt jswrap_graphics_stringWidth(JsVar *parent, JsVar *var) {
}
if (font == JSGRAPHICS_FONTSIZE_VECTOR) {
#ifndef NO_VECTOR_FONT
width += (int)graphicsVectorCharWidth(&gfx, scale, ch);
width += (int)graphicsVectorCharWidth(&gfx, scalex, ch);
#endif
} else if (font == JSGRAPHICS_FONTSIZE_4X6) {
width += 4*scale;
width += 4*scalex;
#ifdef USE_FONT_6X8
} else if (font == JSGRAPHICS_FONTSIZE_6X8) {
width += 6*scale;
width += 6*scalex;
#endif
#ifndef SAVE_ON_FLASH
} else if (font & JSGRAPHICS_FONTSIZE_CUSTOM_BIT) {
if (jsvIsString(customWidth)) {
if (ch>=customFirstChar)
width += scale*(unsigned char)jsvGetCharInString(customWidth, (size_t)(ch-customFirstChar));
width += scalex*(unsigned char)jsvGetCharInString(customWidth, (size_t)(ch-customFirstChar));
} else
width += scale*(int)jsvGetInteger(customWidth);
width += scalex*(int)jsvGetInteger(customWidth);
#endif
}
jsvStringIteratorNext(&it);

View File

@ -440,7 +440,7 @@ static const uint8_t *vfGetCharPtr(char sch, int *charLen) {
}
// prints character, returns width
unsigned int vfDrawCharPtr(JsGraphics *gfx, int x1, int y1, int size, const uint8_t *charPtr, int charLen) {
unsigned int vfDrawCharPtr(JsGraphics *gfx, int x1, int y1, int sizex, int sizey, const uint8_t *charPtr, int charLen) {
x1 = (x1<<4) - 8;
y1 = (y1<<4) - 8;
int w = 0;
@ -453,20 +453,20 @@ unsigned int vfDrawCharPtr(JsGraphics *gfx, int x1, int y1, int size, const uint
int vx = vertex % VF_CHAR_WIDTH;
int vy = vertex / VF_CHAR_WIDTH;
if (vx>w) w=vx;
poly[j*2 ] = (short)(x1 + vx*size*16/VF_SCALE);
poly[j*2+1] = (short)(y1 + (vy+VF_OFFSET_Y)*size*16/VF_SCALE);
poly[j*2 ] = (short)(x1 + vx*sizex*16/VF_SCALE);
poly[j*2+1] = (short)(y1 + (vy+VF_OFFSET_Y)*sizey*16/VF_SCALE);
}
graphicsFillPoly(gfx, polyLen, poly);
}
return (unsigned int)(((w+1+VF_CHAR_SPACING)*size*16/VF_SCALE+7)>>4);
return (unsigned int)(((w+1+VF_CHAR_SPACING)*sizex*16/VF_SCALE+7)>>4);
}
// returns the width of a character
unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int size, char ch) {
unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int sizex, char ch) {
NOT_USED(gfx);
int charLen;
const uint8_t *charPtr = vfGetCharPtr(ch, &charLen);
if (!charPtr) return (unsigned int)(size/2);
if (!charPtr) return (unsigned int)(sizex/2); // space
int w = 0;
for (int i = 0; i < charLen; ++i) {
int polyLen;
@ -477,15 +477,15 @@ unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int size, char ch
if (vx>w) w=vx;
}
}
return ((unsigned int)(w+1+VF_CHAR_SPACING)*size*16/VF_SCALE+7)>>4;
return ((unsigned int)(w+1+VF_CHAR_SPACING)*sizex*16/VF_SCALE+7)>>4;
}
// prints character, returns width
unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int size, char ch) {
unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int sizex, int sizey, char ch) {
int charLen;
const uint8_t *charPtr = vfGetCharPtr(ch, &charLen);
if (!charPtr) return (unsigned int)(size/2);
return vfDrawCharPtr(gfx, x1, y1, size, charPtr, charLen);
if (!charPtr) return (unsigned int)(sizex/2); // space
return vfDrawCharPtr(gfx, x1, y1, sizex, sizey, charPtr, charLen);
}
#endif

View File

@ -16,7 +16,7 @@
#include "graphics.h"
// returns the width of a character
unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int size, char ch);
unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int sizex, char ch);
// prints character, returns width
unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int size, char ch);
unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int sizex, int sizey, char ch);
#endif

View File

@ -52,6 +52,27 @@ SHOULD_BE(`
................
................`);
g.clear();
g.setFont("Vector:10x20");
g.drawString("4");
SHOULD_BE(`
................
...#............
...#............
..##............
..##............
..##............
.###............
.#.#............
.#.#............
#..#............
#####...........
#####...........
...#............
...#............
...#............
...#............`);
g.clear();
g.setFont("4x6");
@ -95,6 +116,69 @@ SHOULD_BE(`
................
................`);
g.clear();
g.setFont("4x6:1x3"); // triple height, single width
g.drawString("42");
SHOULD_BE(`
.##.##..........
.##.##..........
.##.##..........
#.#...#.........
#.#...#.........
#.#...#.........
#.#..#..........
#.#..#..........
#.#..#..........
###.#...........
###.#...........
###.#...........
..#.###.........
..#.###.........
..#.###.........
................`);
g.clear();
g.setFont("6x8");
g.drawString("42");
SHOULD_BE(`
................
...#...###......
..##..#...#.....
.#.#......#.....
#..#...###......
#####.#.........
...#..#####.....
................
................
................
................
................
................
................
................
................`);
g.clear();
g.setFont("6x8:1x2"); // double height, singlw width
g.drawString("42");
SHOULD_BE(`
................
................
...#...###......
...#...###......
..##..#...#.....
..##..#...#.....
.#.#......#.....
.#.#......#.....
#..#...###......
#..#...###......
#####.#.........
#####.#.........
...#..#####.....
...#..#####.....
................
................`);
g.clear();
g.setFontCustom(font, "0".charCodeAt(0), 4, 8);
g.drawString("42");