Changes in uspace/lib/gfxfont/src/text.c [9eb8d12:f2d4a46] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/gfxfont/src/text.c
r9eb8d12 rf2d4a46 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2022 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 97 97 /** Print string using text characters in text mode. 98 98 * 99 * @param font Font100 99 * @param pos Position of top-left corner of text 101 * @param color Text color100 * @param fmt Formatting 102 101 * @param str String 103 102 * @return EOK on success or an error code 104 103 */ 105 static errno_t gfx_puttext_textmode(gfx_ font_t *font, gfx_coord2_t *pos,106 gfx_color_t *color,const char *str)107 { 108 gfx_context_t *gc = f ont->typeface->gc;104 static errno_t gfx_puttext_textmode(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, 105 const char *str) 106 { 107 gfx_context_t *gc = fmt->font->typeface->gc; 109 108 gfx_bitmap_params_t params; 110 109 gfx_bitmap_t *bitmap; 111 110 gfx_bitmap_alloc_t alloc; 112 uint16_t r, g, b; 111 gfx_coord_t width; 112 uint8_t attr; 113 113 pixelmap_t pmap; 114 114 gfx_coord_t x; 115 gfx_coord_t rmargin; 115 116 pixel_t pixel; 117 char32_t c; 118 size_t off; 119 bool ellipsis; 116 120 errno_t rc; 121 122 width = str_width(str); 123 if (fmt->abbreviate && width > fmt->width) { 124 ellipsis = true; 125 width = fmt->width; 126 if (width > 3) 127 rmargin = width - 3; 128 else 129 rmargin = width; 130 } else { 131 ellipsis = false; 132 rmargin = width; 133 } 117 134 118 135 /* … … 121 138 */ 122 139 123 gfx_color_get_rgb_i16(color, &r, &g, &b); 124 125 /* 126 * We are setting the *background* color, the foreground color 127 * will be set to its complement. 128 */ 129 r = 0xff ^ (r >> 8); 130 g = 0xff ^ (g >> 8); 131 b = 0xff ^ (b >> 8); 140 gfx_color_get_ega(fmt->color, &attr); 132 141 133 142 gfx_bitmap_params_init(¶ms); 134 143 params.rect.p0.x = 0; 135 144 params.rect.p0.y = 0; 136 params.rect.p1.x = str_width(str);145 params.rect.p1.x = width; 137 146 params.rect.p1.y = 1; 138 147 … … 156 165 pmap.data = alloc.pixels; 157 166 158 for (x = 0; x < params.rect.p1.x; x++) { 159 pixel = PIXEL(str[x], r, g, b); 167 off = 0; 168 for (x = 0; x < rmargin; x++) { 169 c = str_decode(str, &off, STR_NO_LIMIT); 170 pixel = PIXEL(attr, 171 (c >> 16) & 0xff, 172 (c >> 8) & 0xff, 173 c & 0xff); 160 174 pixelmap_put_pixel(&pmap, x, 0, pixel); 175 } 176 177 if (ellipsis) { 178 for (x = rmargin; x < params.rect.p1.x; x++) { 179 c = '.'; 180 pixel = PIXEL(attr, 181 (c >> 16) & 0xff, 182 (c >> 8) & 0xff, 183 c & 0xff); 184 pixelmap_put_pixel(&pmap, x, 0, pixel); 185 } 161 186 } 162 187 … … 169 194 /** Get text starting position. 170 195 * 171 * @param font Font172 196 * @param pos Anchor position 173 197 * @param fmt Text formatting … … 175 199 * @param spos Place to store starting position 176 200 */ 177 void gfx_text_start_pos(gfx_ font_t *font, gfx_coord2_t *pos,178 gfx_text_fmt_t *fmt,const char *str, gfx_coord2_t *spos)201 void gfx_text_start_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, 202 const char *str, gfx_coord2_t *spos) 179 203 { 180 204 gfx_font_metrics_t fmetrics; 181 gfx_coord2_t cpos;182 205 gfx_coord_t width; 183 206 … … 186 209 /* Adjust position for horizontal alignment */ 187 210 if (fmt->halign != gfx_halign_left) { 188 width = gfx_text_width(font, str); 211 /* Compute text width */ 212 width = gfx_text_width(fmt->font, str); 213 if (fmt->abbreviate && width > fmt->width) 214 width = fmt->width; 215 189 216 switch (fmt->halign) { 190 217 case gfx_halign_center: … … 192 219 break; 193 220 case gfx_halign_right: 194 spos->x -= width - 1;221 spos->x -= width; 195 222 break; 196 223 default: … … 200 227 201 228 /* Adjust position for vertical alignment */ 202 gfx_font_get_metrics(f ont, &fmetrics);229 gfx_font_get_metrics(fmt->font, &fmetrics); 203 230 204 231 if (fmt->valign != gfx_valign_baseline) { … … 211 238 break; 212 239 case gfx_valign_bottom: 213 cpos.y -= fmetrics.descent;240 spos->y -= fmetrics.descent + 1; 214 241 break; 215 242 default: … … 221 248 /** Render text. 222 249 * 223 * @param font Font224 250 * @param pos Anchor position 225 251 * @param fmt Text formatting … … 227 253 * @return EOK on success or an error code 228 254 */ 229 errno_t gfx_puttext(gfx_font_t *font, gfx_coord2_t *pos, 230 gfx_text_fmt_t *fmt, const char *str) 255 errno_t gfx_puttext(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str) 231 256 { 232 257 gfx_glyph_metrics_t gmetrics; 258 gfx_font_metrics_t fmetrics; 233 259 size_t stradv; 234 260 const char *cp; 235 261 gfx_glyph_t *glyph; 236 262 gfx_coord2_t cpos; 263 gfx_coord2_t spos; 264 gfx_rect_t rect; 265 gfx_coord_t width; 266 gfx_coord_t rmargin; 267 bool ellipsis; 237 268 errno_t rc; 238 269 239 gfx_text_start_pos( font, pos, fmt, str, &cpos);270 gfx_text_start_pos(pos, fmt, str, &spos); 240 271 241 272 /* Text mode */ 242 if ((f ont->finfo->props.flags & gff_text_mode) != 0)243 return gfx_puttext_textmode( font, &cpos, fmt->color, str);244 245 rc = gfx_set_color(f ont->typeface->gc, fmt->color);273 if ((fmt->font->finfo->props.flags & gff_text_mode) != 0) 274 return gfx_puttext_textmode(&spos, fmt, str); 275 276 rc = gfx_set_color(fmt->font->typeface->gc, fmt->color); 246 277 if (rc != EOK) 247 278 return rc; 248 279 280 width = gfx_text_width(fmt->font, str); 281 282 if (fmt->abbreviate && width > fmt->width) { 283 /* Need to append ellipsis */ 284 ellipsis = true; 285 rmargin = spos.x + fmt->width - gfx_text_width(fmt->font, "..."); 286 } else { 287 ellipsis = false; 288 rmargin = spos.x + width; 289 } 290 291 cpos = spos; 249 292 cp = str; 250 293 while (*cp != '\0') { 251 rc = gfx_font_search_glyph(f ont, cp, &glyph, &stradv);294 rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv); 252 295 if (rc != EOK) { 253 296 ++cp; … … 257 300 gfx_glyph_get_metrics(glyph, &gmetrics); 258 301 302 /* Stop if we would run over the right margin */ 303 if (fmt->abbreviate && cpos.x + gmetrics.advance > rmargin) 304 break; 305 259 306 rc = gfx_glyph_render(glyph, &cpos); 260 307 if (rc != EOK) … … 265 312 } 266 313 314 /* Text underlining */ 315 if (fmt->underline) { 316 gfx_font_get_metrics(fmt->font, &fmetrics); 317 318 rect.p0.x = spos.x; 319 rect.p0.y = spos.y + fmetrics.underline_y0; 320 rect.p1.x = cpos.x; 321 rect.p1.y = spos.y + fmetrics.underline_y1; 322 323 rc = gfx_fill_rect(fmt->font->typeface->gc, &rect); 324 if (rc != EOK) 325 return rc; 326 } 327 328 /* Render ellipsis, if required */ 329 if (ellipsis) { 330 rc = gfx_font_search_glyph(fmt->font, ".", &glyph, &stradv); 331 if (rc != EOK) 332 return EOK; 333 334 gfx_glyph_get_metrics(glyph, &gmetrics); 335 336 rc = gfx_glyph_render(glyph, &cpos); 337 if (rc != EOK) 338 return rc; 339 340 cpos.x += gmetrics.advance; 341 342 rc = gfx_glyph_render(glyph, &cpos); 343 if (rc != EOK) 344 return rc; 345 346 cpos.x += gmetrics.advance; 347 348 rc = gfx_glyph_render(glyph, &cpos); 349 if (rc != EOK) 350 return rc; 351 } 352 267 353 return EOK; 268 354 } … … 270 356 /** Find character position in string by X coordinate. 271 357 * 272 * @param font Font273 358 * @param pos Anchor position 274 359 * @param fmt Text formatting … … 282 367 * offset of the following character. 283 368 */ 284 size_t gfx_text_find_pos(gfx_ font_t *font, gfx_coord2_t *pos,285 gfx_text_fmt_t *fmt,const char *str, gfx_coord2_t *fpos)369 size_t gfx_text_find_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, 370 const char *str, gfx_coord2_t *fpos) 286 371 { 287 372 gfx_glyph_metrics_t gmetrics; … … 294 379 errno_t rc; 295 380 296 gfx_text_start_pos( font,pos, fmt, str, &cpos);381 gfx_text_start_pos(pos, fmt, str, &cpos); 297 382 298 383 /* Text mode */ 299 if ((f ont->finfo->props.flags & gff_text_mode) != 0) {384 if ((fmt->font->finfo->props.flags & gff_text_mode) != 0) { 300 385 off = 0; 301 386 strsize = str_size(str); … … 313 398 off = 0; 314 399 while (*cp != '\0') { 315 rc = gfx_font_search_glyph(f ont, cp, &glyph, &stradv);400 rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv); 316 401 if (rc != EOK) { 317 402 ++cp; … … 339 424 * to the same objects, respectively. 340 425 * 341 * @param font Font342 426 * @param pos Anchor position 343 427 * @param fmt Text formatting … … 346 430 * @param cfmt Place to store format for continuation 347 431 */ 348 void gfx_text_cont(gfx_font_t *font, gfx_coord2_t *pos, 349 gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *cpos, 350 gfx_text_fmt_t *cfmt) 432 void gfx_text_cont(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str, 433 gfx_coord2_t *cpos, gfx_text_fmt_t *cfmt) 351 434 { 352 435 gfx_coord2_t spos; … … 354 437 355 438 /* Continuation should start where the current string ends */ 356 gfx_text_start_pos( font,pos, fmt, str, &spos);357 cpos->x = spos.x + gfx_text_width(f ont, str);439 gfx_text_start_pos(pos, fmt, str, &spos); 440 cpos->x = spos.x + gfx_text_width(fmt->font, str); 358 441 cpos->y = spos.y; 359 442 … … 366 449 tfmt.valign = gfx_valign_baseline; 367 450 451 /* Remaining available width */ 452 tfmt.width = fmt->width - (cpos->x - spos.x); 453 368 454 *cfmt = tfmt; 369 455 } … … 371 457 /** Get text bounding rectangle. 372 458 * 373 * @param font Font374 459 * @param pos Anchor position 375 460 * @param fmt Text formatting … … 377 462 * @param rect Place to store bounding rectangle 378 463 */ 379 void gfx_text_rect(gfx_ font_t *font, gfx_coord2_t *pos,380 gfx_ text_fmt_t *fmt, const char *str, gfx_rect_t *rect)464 void gfx_text_rect(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str, 465 gfx_rect_t *rect) 381 466 { 382 467 gfx_coord2_t spos; 383 384 gfx_text_start_pos(font, pos, fmt, str, &spos); 468 gfx_coord_t width; 469 470 gfx_text_start_pos(pos, fmt, str, &spos); 471 width = gfx_text_width(fmt->font, str); 472 if (fmt->abbreviate && width > fmt->width) 473 width = fmt->width; 385 474 386 475 rect->p0.x = spos.x; 387 rect->p0.y = spos.y - f ont->metrics.ascent;388 rect->p1.x = spos.x + gfx_text_width(font, str);389 rect->p1.y = spos.y + font->metrics.descent + 1;476 rect->p0.y = spos.y - fmt->font->metrics.ascent; 477 rect->p1.x = spos.x + width; 478 rect->p1.y = spos.y + fmt->font->metrics.descent + 1; 390 479 } 391 480
Note:
See TracChangeset
for help on using the changeset viewer.