A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 819 lines 21 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* New greyscale framework 11* Drawing functions 12* 13* This is a generic framework to display 129 shades of grey on low-depth 14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. 15* 16* Copyright (C) 2008 Jens Arnold 17* 18* This program is free software; you can redistribute it and/or 19* modify it under the terms of the GNU General Public License 20* as published by the Free Software Foundation; either version 2 21* of the License, or (at your option) any later version. 22* 23* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 24* KIND, either express or implied. 25* 26****************************************************************************/ 27 28#include "plugin.h" 29#include "grey.h" 30 31extern struct viewport _grey_default_vp; 32 33/*** low-level drawing functions ***/ 34 35static void setpixel(unsigned char *address) 36{ 37 *address = _grey_info.vp->fg_pattern; 38} 39 40static void clearpixel(unsigned char *address) 41{ 42 *address = _grey_info.vp->bg_pattern; 43} 44 45static void flippixel(unsigned char *address) 46{ 47 *address = ~(*address); 48} 49 50static void nopixel(unsigned char *address) 51{ 52 (void)address; 53} 54 55void (* const _grey_pixelfuncs[8])(unsigned char *address) = { 56 flippixel, nopixel, setpixel, setpixel, 57 nopixel, clearpixel, nopixel, clearpixel 58}; 59 60/*** Drawing functions ***/ 61 62/* Clear the current viewport */ 63void grey_clear_viewport(void) 64{ 65 struct viewport *vp = _grey_info.vp; 66 int drawmode = vp->drawmode; 67 vp->drawmode = DRMODE_SOLID | DRMODE_INVERSEVID; 68 grey_fillrect(0, 0, vp->width, vp->height); 69 vp->drawmode = drawmode; 70} 71 72/* Clear the whole display */ 73void grey_clear_display(void) 74{ 75 struct viewport *vp = &_grey_default_vp; 76 77 int value = (vp->drawmode & DRMODE_INVERSEVID) ? 78 vp->fg_pattern : vp->bg_pattern; 79 80 rb->memset(_grey_info.curbuffer, value, 81 _GREY_MULUQ(_grey_info.cb_width, _grey_info.cb_height)); 82} 83 84/* Set a single pixel */ 85void grey_drawpixel(int x, int y) 86{ 87 if (x >= _grey_info.clip_l && x < _grey_info.clip_r && 88 y >= _grey_info.clip_t && y < _grey_info.clip_b) 89 { 90 int dst_stride = _grey_info.cb_width; 91 struct viewport *vp = _grey_info.vp; 92 _grey_pixelfuncs[vp->drawmode]( 93 &_grey_info.curbuffer[ 94 _GREY_MULUQ(dst_stride, vp->y - _grey_info.cb_y + y) + 95 vp->x - _grey_info.cb_x + x]); 96 } 97} 98 99/* Draw a line */ 100void grey_drawline(int x1, int y1, int x2, int y2) 101{ 102 struct viewport *vp = _grey_info.vp; 103 int numpixels; 104 int i; 105 int deltax, deltay; 106 int d, dinc1, dinc2; 107 int x, xinc1, xinc2; 108 int y, yinc1, yinc2; 109 void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[vp->drawmode]; 110 int dwidth; 111 int xoffs, yoffs; 112 113 deltax = abs(x2 - x1); 114 deltay = abs(y2 - y1); 115 xinc2 = 1; 116 yinc2 = 1; 117 118 if (deltax >= deltay) 119 { 120 numpixels = deltax; 121 d = 2 * deltay - deltax; 122 dinc1 = deltay * 2; 123 dinc2 = (deltay - deltax) * 2; 124 xinc1 = 1; 125 yinc1 = 0; 126 } 127 else 128 { 129 numpixels = deltay; 130 d = 2 * deltax - deltay; 131 dinc1 = deltax * 2; 132 dinc2 = (deltax - deltay) * 2; 133 xinc1 = 0; 134 yinc1 = 1; 135 } 136 numpixels++; /* include endpoints */ 137 138 if (x1 > x2) 139 { 140 xinc1 = -xinc1; 141 xinc2 = -xinc2; 142 } 143 144 if (y1 > y2) 145 { 146 yinc1 = -yinc1; 147 yinc2 = -yinc2; 148 } 149 150 x = x1; 151 y = y1; 152 153 dwidth = _grey_info.cb_width; 154 xoffs = vp->x - _grey_info.cb_x; 155 yoffs = vp->y - _grey_info.cb_y; 156 157 for (i = 0; i < numpixels; i++) 158 { 159 if (x >= _grey_info.clip_l && x < _grey_info.clip_r && 160 y >= _grey_info.clip_t && y < _grey_info.clip_b) 161 { 162 pfunc(&_grey_info.curbuffer[_GREY_MULUQ(dwidth, yoffs + y) + 163 xoffs + x]); 164 } 165 166 if (d < 0) 167 { 168 d += dinc1; 169 x += xinc1; 170 y += yinc1; 171 } 172 else 173 { 174 d += dinc2; 175 x += xinc2; 176 y += yinc2; 177 } 178 } 179} 180 181/* Draw a horizontal line (optimised) */ 182void grey_hline(int x1, int x2, int y) 183{ 184 struct viewport *vp = _grey_info.vp; 185 int x; 186 int value = 0; 187 unsigned char *dst; 188 bool fillopt = false; 189 int dwidth; 190 191 /* direction flip */ 192 if (x2 < x1) 193 { 194 x = x1; 195 x1 = x2; 196 x2 = x; 197 } 198 199 /* nothing to draw? */ 200 if (y < _grey_info.clip_t || y >= _grey_info.clip_b || 201 x1 >= _grey_info.clip_r || x2 < _grey_info.clip_l) 202 return; 203 204 /* drawmode and optimisation */ 205 if (vp->drawmode & DRMODE_INVERSEVID) 206 { 207 if (vp->drawmode & DRMODE_BG) 208 { 209 fillopt = true; 210 value = vp->bg_pattern; 211 } 212 } 213 else 214 { 215 if (vp->drawmode & DRMODE_FG) 216 { 217 fillopt = true; 218 value = vp->fg_pattern; 219 } 220 } 221 if (!fillopt && vp->drawmode != DRMODE_COMPLEMENT) 222 return; 223 224 /* clipping */ 225 if (x1 < _grey_info.clip_l) 226 x1 = _grey_info.clip_l; 227 if (x2 >= _grey_info.clip_r) 228 x2 = _grey_info.clip_r - 1; 229 230 dwidth = _grey_info.cb_width; 231 dst = &_grey_info.curbuffer[ 232 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y) + 233 vp->x - _grey_info.cb_x + x1]; 234 235 if (fillopt) 236 rb->memset(dst, value, x2 - x1 + 1); 237 else /* DRMODE_COMPLEMENT */ 238 { 239 unsigned char *dst_end = dst + x2 - x1; 240 do 241 *dst = ~(*dst); 242 while (++dst <= dst_end); 243 } 244} 245 246/* Draw a vertical line (optimised) */ 247void grey_vline(int x, int y1, int y2) 248{ 249 struct viewport *vp = _grey_info.vp; 250 int y; 251 unsigned char *dst, *dst_end; 252 void (*pfunc)(unsigned char *address); 253 int dwidth; 254 255 /* direction flip */ 256 if (y2 < y1) 257 { 258 y = y1; 259 y1 = y2; 260 y2 = y; 261 } 262 263 /* nothing to draw? */ 264 if (x < _grey_info.clip_l || x >= _grey_info.clip_r || 265 y1 >= _grey_info.clip_b || y2 < _grey_info.clip_t) 266 return; 267 268 /* clipping */ 269 if (y1 < _grey_info.clip_t) 270 y1 = _grey_info.clip_t; 271 if (y2 >= _grey_info.clip_b) 272 y2 = _grey_info.clip_b - 1; 273 274 dwidth = _grey_info.cb_width; 275 pfunc = _grey_pixelfuncs[vp->drawmode]; 276 dst = &_grey_info.curbuffer[ 277 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y1) + 278 vp->x - _grey_info.cb_x + x]; 279 280 dst_end = dst + _GREY_MULUQ(dwidth, y2 - y1); 281 do 282 { 283 pfunc(dst); 284 dst += dwidth; 285 } 286 while (dst <= dst_end); 287} 288 289/* Draw a filled triangle */ 290void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) 291{ 292 int x, y; 293 long fp_x1, fp_x2, fp_dx1, fp_dx2; 294 295 /* sort vertices by increasing y value */ 296 if (y1 > y3) 297 { 298 if (y2 < y3) /* y2 < y3 < y1 */ 299 { 300 x = x1; x1 = x2; x2 = x3; x3 = x; 301 y = y1; y1 = y2; y2 = y3; y3 = y; 302 } 303 else if (y2 > y1) /* y3 < y1 < y2 */ 304 { 305 x = x1; x1 = x3; x3 = x2; x2 = x; 306 y = y1; y1 = y3; y3 = y2; y2 = y; 307 } 308 else /* y3 <= y2 <= y1 */ 309 { 310 x = x1; x1 = x3; x3 = x; 311 y = y1; y1 = y3; y3 = y; 312 } 313 } 314 else 315 { 316 if (y2 < y1) /* y2 < y1 <= y3 */ 317 { 318 x = x1; x1 = x2; x2 = x; 319 y = y1; y1 = y2; y2 = y; 320 } 321 else if (y2 > y3) /* y1 <= y3 < y2 */ 322 { 323 x = x2; x2 = x3; x3 = x; 324 y = y2; y2 = y3; y3 = y; 325 } 326 /* else already sorted */ 327 } 328 329 if (y1 < y3) /* draw */ 330 { 331 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1); 332 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1); 333 334 if (y1 < y2) /* first part */ 335 { 336 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1); 337 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1); 338 for (y = y1; y < y2; y++) 339 { 340 grey_hline(fp_x1 >> 16, fp_x2 >> 16, y); 341 fp_x1 += fp_dx1; 342 fp_x2 += fp_dx2; 343 } 344 } 345 if (y2 < y3) /* second part */ 346 { 347 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2); 348 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1); 349 for (y = y2; y < y3; y++) 350 { 351 grey_hline(fp_x1 >> 16, fp_x2 >> 16, y); 352 fp_x1 += fp_dx1; 353 fp_x2 += fp_dx2; 354 } 355 } 356 } 357} 358 359/* Draw a rectangular box */ 360void grey_drawrect(int x, int y, int width, int height) 361{ 362 if ((width <= 0) || (height <= 0)) 363 return; 364 365 int x2 = x + width - 1; 366 int y2 = y + height - 1; 367 368 grey_vline(x, y, y2); 369 grey_vline(x2, y, y2); 370 grey_hline(x, x2, y); 371 grey_hline(x, x2, y2); 372} 373 374/* Fill a rectangular area */ 375void grey_fillrect(int x, int y, int width, int height) 376{ 377 struct viewport *vp = _grey_info.vp; 378 int value = 0; 379 unsigned char *dst, *dst_end; 380 bool fillopt = false; 381 int dwidth; 382 383 /* drawmode and optimisation */ 384 if (vp->drawmode & DRMODE_INVERSEVID) 385 { 386 if (vp->drawmode & DRMODE_BG) 387 { 388 fillopt = true; 389 value = vp->bg_pattern; 390 } 391 } 392 else 393 { 394 if (vp->drawmode & DRMODE_FG) 395 { 396 fillopt = true; 397 value = vp->fg_pattern; 398 399 } 400 } 401 if (!fillopt && vp->drawmode != DRMODE_COMPLEMENT) 402 return; 403 404 /* clipping */ 405 if (x < _grey_info.clip_l) 406 { 407 width += x - _grey_info.clip_l; 408 x = _grey_info.clip_l; 409 } 410 411 if (x + width > _grey_info.clip_r) 412 width = _grey_info.clip_r - x; 413 414 if (width <= 0) 415 return; 416 417 if (y < _grey_info.clip_t) 418 { 419 height += y - _grey_info.clip_t; 420 y = _grey_info.clip_t; 421 } 422 423 if (y + height > _grey_info.clip_b) 424 height = _grey_info.clip_b - y; 425 426 if (height <= 0) 427 return; 428 429 dwidth = _grey_info.cb_width; 430 dst = &_grey_info.curbuffer[ 431 _GREY_MULUQ(dwidth, _grey_info.vp->y - _grey_info.cb_y + y) + 432 _grey_info.vp->x - _grey_info.cb_x + x]; 433 dst_end = dst + _GREY_MULUQ(dwidth, height); 434 435 do 436 { 437 if (fillopt) 438 rb->memset(dst, value, width); 439 else /* DRMODE_COMPLEMENT */ 440 { 441 unsigned char *dst_row = dst; 442 unsigned char *row_end = dst_row + width; 443 444 do 445 *dst_row = ~(*dst_row); 446 while (++dst_row < row_end); 447 } 448 dst += dwidth; 449 } 450 while (dst < dst_end); 451} 452 453/* About Rockbox' internal monochrome bitmap format: 454 * 455 * A bitmap contains one bit for every pixel that defines if that pixel is 456 * foreground (1) or background (0). Bits within a byte are arranged 457 * vertically, LSB at top. 458 * The bytes are stored in row-major order, with byte 0 being top left, 459 * byte 1 2nd from left etc. The first row of bytes defines pixel rows 460 * 0..7, the second row defines pixel row 8..15 etc. */ 461 462/* Draw a partial monochrome bitmap */ 463void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, 464 int stride, int x, int y, int width, int height) 465{ 466 struct viewport *vp = _grey_info.vp; 467 const unsigned char *src_end; 468 unsigned char *dst, *dst_end; 469 unsigned dmask = 0x100; /* bit 8 == sentinel */ 470 int drmode = vp->drawmode; 471 int dwidth; 472 473 /* clipping */ 474 if (x < _grey_info.clip_l) 475 { 476 int dx = x - _grey_info.clip_l; 477 width += dx; 478 src_x -= dx; 479 x = _grey_info.clip_l; 480 } 481 482 if (x + width > _grey_info.clip_r) 483 width = _grey_info.clip_r - x; 484 485 if (width <= 0) 486 return; 487 488 if (y < _grey_info.clip_t) 489 { 490 int dy = y - _grey_info.clip_t; 491 height += dy; 492 src_y += dy; 493 y = _grey_info.clip_t; 494 } 495 496 if (y + height > _grey_info.clip_b) 497 height = _grey_info.clip_b - y; 498 499 if (height <= 0) 500 return; 501 502 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ 503 src_y &= 7; 504 src_end = src + width; 505 dwidth = _grey_info.cb_width; 506 dst = &_grey_info.curbuffer[ 507 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y) + 508 vp->x - _grey_info.cb_x + x]; 509 dst_end = dst + _GREY_MULUQ(dwidth, height); 510 511 if (drmode & DRMODE_INVERSEVID) 512 { 513 dmask = 0x1ff; /* bit 8 == sentinel */ 514 drmode &= DRMODE_SOLID; /* mask out inversevid */ 515 } 516 517 do 518 { 519 const unsigned char *src_col = src++; 520 unsigned char *dst_col = dst++; 521 unsigned data = (*src_col ^ dmask) >> src_y; 522 int fg, bg; 523 524#define UPDATE_SRC do { \ 525 data >>= 1; \ 526 if (data == 0x001) { \ 527 src_col += stride; \ 528 data = *src_col ^ dmask; \ 529 } \ 530 } while (0) 531 532 switch (drmode) 533 { 534 case DRMODE_COMPLEMENT: 535 do 536 { 537 if (data & 0x01) 538 *dst_col = ~(*dst_col); 539 540 dst_col += dwidth; 541 UPDATE_SRC; 542 } 543 while (dst_col < dst_end); 544 break; 545 546 case DRMODE_BG: 547 bg = vp->bg_pattern; 548 do 549 { 550 if (!(data & 0x01)) 551 *dst_col = bg; 552 553 dst_col += dwidth; 554 UPDATE_SRC; 555 } 556 while (dst_col < dst_end); 557 break; 558 559 case DRMODE_FG: 560 fg = vp->fg_pattern; 561 do 562 { 563 if (data & 0x01) 564 *dst_col = fg; 565 566 dst_col += dwidth; 567 UPDATE_SRC; 568 } 569 while (dst_col < dst_end); 570 break; 571 572 case DRMODE_SOLID: 573 fg = vp->fg_pattern; 574 bg = vp->bg_pattern; 575 do 576 { 577 *dst_col = (data & 0x01) ? fg : bg; 578 dst_col += dwidth; 579 UPDATE_SRC; 580 } 581 while (dst_col < dst_end); 582 break; 583 } 584 } 585 while (src < src_end); 586} 587 588/* Draw a full monochrome bitmap */ 589void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) 590{ 591 grey_mono_bitmap_part(src, 0, 0, width, x, y, width, height); 592} 593 594/* Draw a partial greyscale bitmap, canonical format */ 595void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, 596 int stride, int x, int y, int width, int height) 597{ 598 unsigned char *dst, *dst_end; 599 int dwidth; 600 601 /* clipping */ 602 if (x < _grey_info.clip_l) 603 { 604 int dx = x - _grey_info.clip_l; 605 width += dx; 606 src_x -= dx; 607 x = _grey_info.clip_l; 608 } 609 610 if (x + width > _grey_info.clip_r) 611 width = _grey_info.clip_r - x; 612 613 if (width <= 0) 614 return; 615 616 if (y < 0) 617 { 618 int dy = y - _grey_info.clip_t; 619 height += dy; 620 src_y -= dy; 621 y = _grey_info.clip_t; 622 } 623 624 if (y + height > _grey_info.clip_b) 625 height = _grey_info.clip_b - y; 626 627 if (height <= 0) 628 return; 629 630 dwidth = _grey_info.cb_width; 631 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ 632 dst = &_grey_info.curbuffer[ 633 _GREY_MULUQ(dwidth, _grey_info.vp->y - _grey_info.cb_y + y) + 634 _grey_info.vp->x - _grey_info.cb_x + x]; 635 dst_end = dst + _GREY_MULUQ(dwidth, height); 636 637 do 638 { 639 rb->memcpy(dst, src, width); 640 dst += dwidth; 641 src += stride; 642 } 643 while (dst < dst_end); 644} 645 646/* Draw a full greyscale bitmap, canonical format */ 647void grey_gray_bitmap(const unsigned char *src, int x, int y, int width, 648 int height) 649{ 650 grey_gray_bitmap_part(src, 0, 0, width, x, y, width, height); 651} 652 653/* Put a string at a given pixel position, skipping first ofs pixel columns */ 654void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str) 655{ 656 ucschar_t ch; 657 ucschar_t *ucs; 658 struct font* pf; 659 660 if (_grey_info.clip_b <= _grey_info.clip_t) 661 return; 662 663 pf = rb->font_get(_grey_info.vp->font); 664 ucs = rb->bidi_l2v(str, 1); 665 666 while ((ch = *ucs++) != 0 && x < _grey_info.clip_r) 667 { 668 int width; 669 const unsigned char *bits; 670 671 /* get proportional width and glyph bits */ 672 width = rb->font_get_width(pf, ch); 673 674 if (ofs > width) 675 { 676 ofs -= width; 677 continue; 678 } 679 680 bits = rb->font_get_bits(pf, ch); 681 682 grey_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); 683 684 x += width - ofs; 685 ofs = 0; 686 } 687} 688 689/* Put a string at a given pixel position */ 690void grey_putsxy(int x, int y, const unsigned char *str) 691{ 692 grey_putsxyofs(x, y, 0, str); 693} 694 695/*** Unbuffered drawing functions ***/ 696 697/* Clear the greyscale display (sets all pixels to white) */ 698void grey_ub_clear_display(void) 699{ 700 struct viewport *vp = &_grey_default_vp; 701 int value = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ? 702 vp->fg_pattern : vp->bg_pattern]; 703 704 rb->memset(_grey_info.values, value, 705 _GREY_MULUQ(_grey_info.width, _grey_info.height)); 706#ifdef SIMULATOR 707 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, 708 _grey_info.width, _grey_info.height); 709#endif 710} 711 712/* Assembler optimised helper function for copying a single line to the 713 * greyvalue buffer. */ 714void _grey_line1(int width, unsigned char *dst, const unsigned char *src, 715 const unsigned char *lut); 716 717/* Draw a partial greyscale bitmap, canonical format */ 718void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, 719 int stride, int x, int y, int width, int height) 720{ 721 int yc, ye; 722 unsigned char *dst; 723 724 /* nothing to draw? */ 725 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) 726 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) 727 return; 728 729 /* clipping */ 730 if (x < 0) 731 { 732 width += x; 733 src_x -= x; 734 x = 0; 735 } 736 if (y < 0) 737 { 738 height += y; 739 src_y -= y; 740 y = 0; 741 } 742 if (x + width > _grey_info.width) 743 width = _grey_info.width - x; 744 if (y + height > _grey_info.height) 745 height = _grey_info.height - y; 746 747 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ 748 yc = y; 749 ye = y + height; 750 dst = _grey_info.values + (x << _GREY_BSHIFT); 751 752 do 753 { 754#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 755 int idx = _GREY_MULUQ(_grey_info.width, yc); 756#else /* vertical packing or vertical interleaved */ 757 int idx = _GREY_MULUQ(_grey_info.width, yc & ~_GREY_BMASK) 758 + (~yc & _GREY_BMASK); 759#endif /* LCD_PIXELFORMAT */ 760 761#if ((LCD_PIXELFORMAT == VERTICAL_PACKING) && (LCD_DEPTH == 2) && defined(CPU_COLDFIRE)) \ 762 || ((LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) && defined(CPU_COLDFIRE)) 763 _grey_line1(width, dst + idx, src, _grey_info.gvalue); 764#else 765 unsigned char *dst_row = dst + idx; 766 const unsigned char *src_row = src; 767 const unsigned char *src_end = src + width; 768 769 do 770 { 771 *dst_row = _grey_info.gvalue[*src_row++]; 772 dst_row += _GREY_BSIZE; 773 } 774 while (src_row < src_end); 775#endif 776 777 src += stride; 778 } 779 while (++yc < ye); 780#ifdef SIMULATOR 781 rb->sim_lcd_ex_update_rect(_grey_info.x + x, _grey_info.y + y, 782 width, height); 783#endif 784} 785 786/* Draw a full greyscale bitmap, canonical format */ 787void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, 788 int height) 789{ 790 grey_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height); 791} 792 793static void output_row_grey_8(uint32_t row, void * row_in, 794 struct scaler_context *ctx) 795{ 796 uint8_t *dest = (uint8_t*)ctx->bm->data + ctx->bm->width * row; 797 rb->memcpy(dest, row_in, ctx->bm->width); 798} 799 800static void output_row_grey_32(uint32_t row, void * row_in, 801 struct scaler_context *ctx) 802{ 803 int col; 804 uint32_t *qp = (uint32_t*)row_in; 805 uint8_t *dest = (uint8_t*)ctx->bm->data + ctx->bm->width * row; 806 for (col = 0; col < ctx->bm->width; col++) 807 *dest++ = SC_OUT(*qp++, ctx); 808} 809 810static unsigned int get_size_grey(struct bitmap *bm) 811{ 812 return bm->width * bm->height; 813} 814 815const struct custom_format format_grey = { 816 .output_row_8 = output_row_grey_8, 817 .output_row_32 = output_row_grey_32, 818 .get_size = get_size_grey 819};