tubbutec Posted June 4, 2016 Report Posted June 4, 2016 Hi, I have a little attribution to ugfx. This function draws a text in a given box, similar to gdispGFillStringBox, but the optimal font is chosen so the text fits into the box with the least lines. The user can select a subset of fonts by passing a font name with a wildcard in place of the size. Example 'DejaVuSans*' This function must be placed in gdisp.c and gdisp.h as it uses static functions declared there.One must also place a copy of 'matchfont2' function (from gdisp_font.c) in gdisp.c, since it is declared static as well. I hope someone can make use of this and I am of course looking forward to comments. If anyone is interested: I also have a version of this that saves the wrapping parameters, so faster redraw is possible... gdisp.h /** \brief Draws a string vertically centered within the specified box. The font size is chosen to make sure the whole text fits in the box * \pre GDISP_NEED_TEXT and GDISP_NEED_TEXT_WORDWRAP must be TRUE in your gfxconf.h * \note This uses word wrap to find the largest font to determine how many lines are needed. Fonts are passed using their short name with wildcard * * instead of the number. e.g.: DejaVuSans* * Text will not be rendered if it could not be fitted inside the specified box * * \param g The display to use * \param x,y The position for the text * \param cx,cy The width and height of the box * \param str The string to draw * \param fontNames Short name of fonts to use + wildcard * * \param color The color to use * \param bgcolor The background color to use * \param justify Justify the text left, center or right within the box * \return bool_t Returns TRUE if the text could be fitted inside the box, FALSE otherwise * */ #if GDISP_NEED_TEXT_WORDWRAP bool_t gdispGFillStringBoxAutoScale(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, const char* fontNames, color_t color, color_t bgcolor, justify_t justify); #define gdispFillStringBoxAutoScale(x,y,cx,cy,s,f,c,b,j) gdispGFillStringBoxAutoScale(GDISP,x,y,cx,cy,s,f,c,b,j) #endif //NEEDS_WORDWRAP #if GDISP_NEED_TEXT_WORDWRAP bool_t gdispGFillStringBoxAutoScale(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, const char* fontNames, color_t color, color_t bgcolor, justify_t justify) { wrapParameters_t wrapParameters; font_t resFont = 0; uint16_t resLines = 0; MUTEX_ENTER(g); g->p.cx = cx; g->p.cy = cy; g->t.clipx0 = g->p.x = x; g->t.clipy0 = g->p.y = y; g->t.clipx1 = x+cx; g->t.clipy1 = y+cy; g->t.color = color; g->t.bgcolor = g->p.color = bgcolor; TEST_CLIP_AREA(g) { // background fill fillarea(g); //get available fonts const struct mf_font_list_s *fp = mf_get_font_list(); for(;fp ;fp = fp->next) //iterate over all fonts { if((fp->font->line_height <= cy) && matchfont2(fontNames,fp->font->short_name)) { // Count the number of lines needed by this font uint16_t nbrLines = 0; mf_wordwrap(fp->font, cx, str, mf_countline_callback, &nbrLines); if(cy / nbrLines >= fp->font->line_height) //is there space for this font? { //find the largest fitting font if((resFont == 0) || (fp->font->line_height > resFont->line_height)) { resFont = fp->font; resLines = nbrLines; } } } } if(!resFont) //found no font that fits all the text in this area return FALSE; /* Select the anchor position */ switch(justify) { case justifyCenter: x += (cx + 1) / 2; break; case justifyRight: x += cx; break; default: // justifyLeft x += resFont->baseline_x; break; } /* Render */ wrapParameters.x = x; wrapParameters.y = y; wrapParameters.font = resFont; wrapParameters.justify = justify; wrapParameters.g = g; g->t.font = resFont; wrapParameters.y += (cy+1 - resLines*resFont->height)/2; mf_wordwrap(resFont, cx, str, mf_fillline_callback, &wrapParameters); } autoflush(g); MUTEX_EXIT(g); return TRUE; } #endif //NEEDS_WORDWRAP /From gdisp_font.c, can not access, because it is static so there is a copy here.. static bool_t matchfont2(const char *pattern, const char *name) { while(1) { switch (pattern[0]) { case '*': if (name[0] == 0) return pattern[1] == 0; if (pattern[1] == name[0]) pattern++; else name++; break; case 0: return name[0] == 0; default: if (name[0] != pattern[0]) return FALSE; pattern++; name++; break; } } }
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now