int nxtk_bitmapwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *dest, FAR const void **src, FAR const struct nxgl_point_s *origin, unsigned int stride) { FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd; struct nxgl_point_s wndorigin; struct nxgl_rect_s clipdest; #ifdef CONFIG_DEBUG_FEATURES if (!hfwnd || !dest || !src || !origin) { set_errno(EINVAL); return ERROR; } #endif /* Clip the rectangle so that it lies within the sub-window bounds * then move the rectangle to that it is relative to the containing * window. */ nxtk_subwindowclip(fwnd, &clipdest, dest, &fwnd->fwrect); /* Now, move the bitmap origin so that it is relative to the containing * window, not the sub-window. * * Temporarily, position the origin in absolute screen coordinates */ nxgl_vectoradd(&wndorigin, origin, &fwnd->fwrect.pt1); /* Then move the origin so that is relative to the containing window, not the * client subwindow */ nxgl_vectsubtract(&wndorigin, &wndorigin, &fwnd->wnd.bounds.pt1); /* Then copy the bitmap */ nx_bitmap((NXWINDOW)hfwnd, &clipdest, src, &wndorigin, stride); return OK; }
int oled_image_draw_img(uint8_t pos_x, uint8_t pos_y, const oled_image_canvas_t * const img) { int ret = OK; FAR struct nxgl_rect_s dest; FAR void *src[CONFIG_NX_NPLANES]; FAR struct nxgl_point_s pos; uint32_t i, j; uint8_t stride; if (pos_x >= OLED_IMG_SCREEN_WIDTH || pos_y >= OLED_IMG_SCREEN_HEIGHT || (pos_x + img->width) > OLED_IMG_SCREEN_WIDTH || (pos_y + img->height) > OLED_IMG_SCREEN_HEIGHT) { lcd_dbg("Wrong coordinates to start draw image" "or image too big\n"); return ERROR; } pos.x = pos_x; pos.y = pos_y; dest.pt1.x = pos.x; dest.pt2.x = pos.x + img->width - 1; stride = img->width / 8 + (!(img->width % 8) ? 0 : 1); for (i = 0, j = 0; i < img->height; i++, j += stride) { dest.pt1.y = pos.y; dest.pt2.y = pos.y; src[0] = (FAR void *) (img->bitmap + j); ret = nx_bitmap(g_img.hwnd, &dest, (FAR void *)src, &pos, img->width); if (ret < 0) { lcd_dbg("nx_bitmapwindow failed: %d\n", errno); return ERROR; } pos.y++; } return ret; }
void nxtext_fillchar(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, FAR struct nxtext_state_s *st, NXHANDLE hfont, FAR const struct nxtext_bitmap_s *bm) { FAR struct nxtext_glyph_s *glyph; struct nxgl_rect_s bounds; struct nxgl_rect_s intersection; struct nxgl_size_s fsize; int ret; /* Handle the special case of spaces which have no glyph bitmap */ if (BM_ISSPACE(bm)) { return; } /* Get the size of the font glyph (which may not have been created yet) */ ret = nxtext_fontsize(hfont, bm->code, &fsize); if (ret < 0) { /* This would mean that there is no bitmap for the character code and * that the font would be rendered as a space. But this case should * never happen here because the BM_ISSPACE() should have already * found all such cases. */ return; } /* Construct a bounding box for the glyph */ bounds.pt1.x = bm->pos.x; bounds.pt1.y = bm->pos.y; bounds.pt2.x = bm->pos.x + fsize.w - 1; bounds.pt2.y = bm->pos.y + fsize.h - 1; /* Should this also be clipped to a region in the window? */ if (rect) { /* Get the intersection of the redraw region and the character bitmap */ nxgl_rectintersect(&intersection, rect, &bounds); } else { /* The intersection is the whole glyph */ nxgl_rectcopy(&intersection, &bounds); } /* Check for empty intersections */ if (!nxgl_nullrect(&intersection)) { FAR const void *src; /* Find (or create) the glyph that goes with this font */ glyph = nxtext_getglyph(hfont, st, bm->code); if (!glyph) { /* Shouldn't happen */ return; } /* Blit the font bitmap into the window */ src = (FAR const void *)glyph->bitmap; ret = nx_bitmap((NXWINDOW)hwnd, &intersection, &src, &bm->pos, (unsigned int)glyph->stride); if (ret < 0) { printf("nxtext_fillchar: nx_bitmapwindow failed: %d\n", errno); } } }
void nxhello_hello(NXWINDOW hwnd) { FAR const struct nx_font_s *fontset; FAR const struct nx_fontbitmap_s *fbm; FAR uint8_t *glyph; FAR const char *ptr; FAR struct nxgl_point_s pos; FAR struct nxgl_rect_s dest; FAR const void *src[CONFIG_NX_NPLANES]; unsigned int glyphsize; unsigned int mxstride; int ret; /* Get information about the font we are going to use */ fontset = nxf_getfontset(g_nxhello.hfont); /* Allocate a bit of memory to hold the largest rendered font */ mxstride = (fontset->mxwidth * CONFIG_EXAMPLES_NXHELLO_BPP + 7) >> 3; glyphsize = (unsigned int)fontset->mxheight * mxstride; glyph = (FAR uint8_t*)malloc(glyphsize); /* NOTE: no check for failure to allocate the memory. In a real application * you would need to handle that event. */ /* Get a position so the the "Hello, World!" string will be centered on the * display. */ nxhello_center(&pos, fontset); message("nxhello_hello: Position (%d,%d)\n", pos.x, pos.y); /* Now we can say "hello" in the center of the display. */ for (ptr = g_hello; *ptr; ptr++) { /* Get the bitmap font for this ASCII code */ fbm = nxf_getbitmap(g_nxhello.hfont, *ptr); if (fbm) { uint8_t fheight; /* Height of this glyph (in rows) */ uint8_t fwidth; /* Width of this glyph (in pixels) */ uint8_t fstride; /* Width of the glyph row (in bytes) */ /* Get information about the font bitmap */ fwidth = fbm->metric.width + fbm->metric.xoffset; fheight = fbm->metric.height + fbm->metric.yoffset; fstride = (fwidth * CONFIG_EXAMPLES_NXHELLO_BPP + 7) >> 3; /* Initialize the glyph memory to the background color */ nxhello_initglyph(glyph, fheight, fwidth, fstride); /* Then render the glyph into the allocated memory */ #if CONFIG_NX_NPLANES > 1 # warning "More logic is needed for the case where CONFIG_NX_PLANES > 1" #endif (void)RENDERER((FAR nxgl_mxpixel_t*)glyph, fheight, fwidth, fstride, fbm, CONFIG_EXAMPLES_NXHELLO_FONTCOLOR); /* Describe the destination of the font with a rectangle */ dest.pt1.x = pos.x; dest.pt1.y = pos.y; dest.pt2.x = pos.x + fwidth - 1; dest.pt2.y = pos.y + fheight - 1; /* Then put the font on the display */ src[0] = (FAR const void *)glyph; #if CONFIG_NX_NPLANES > 1 # warning "More logic is needed for the case where CONFIG_NX_PLANES > 1" #endif ret = nx_bitmap((NXWINDOW)hwnd, &dest, src, &pos, fstride); if (ret < 0) { message("nxhello_write: nx_bitmapwindow failed: %d\n", errno); } /* Skip to the right the width of the font */ pos.x += fwidth; } else { /* No bitmap (probably because the font is a space). Skip to the * right the width of a space. */ pos.x += fontset->spwidth; } }
void nximage_image(NXWINDOW hwnd) { FAR const void *state = NULL; FAR struct nxgl_point_s pos; FAR struct nxgl_rect_s dest; FAR const void *src[CONFIG_NX_NPLANES]; nxgl_coord_t row; int ret; #if defined(CONFIG_EXAMPLES_NXIMAGE_YSCALEp5) || defined(CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5) int i; #endif /* Center the image. Note: these may extend off the display. */ pos.x = (g_nximage.xres - SCALED_WIDTH) / 2; pos.y = (g_nximage.yres - SCALED_HEIGHT) / 2; /* Set up the invariant part of the destination bounding box */ dest.pt1.x = pos.x; dest.pt2.x = pos.x + SCALED_WIDTH - 1; /* Now output the rows */ for (row = 0; row < IMAGE_HEIGHT; row += NINPUT_ROWS) { /* Read input row(s) */ nximage_blitrow(g_runs[0].run, &state); #if NINPUT_ROWS > 1 nximage_blitrow(g_runs[1].run, &state); #endif /* Output rows before averaging */ #if defined(CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5) || defined(CONFIG_EXAMPLES_NXIMAGE_YSCALE2p0) /* Output row[0] */ dest.pt1.y = pos.y; dest.pt2.y = pos.y; src[0] = (FAR const void *)g_runs[0].run; #if CONFIG_NX_NPLANES > 1 # warning "More logic is needed for the case where CONFIG_NX_PLANES > 1" #endif ret = nx_bitmap((NXWINDOW)hwnd, &dest, src, &pos, SCALED_WIDTH*sizeof(nxgl_mxpixel_t)); if (ret < 0) { message("nximage_image: nx_bitmapwindow failed: %d\n", errno); } /* Increment the vertical position */ pos.y++; #endif /* Perform averaging */ #if defined(CONFIG_EXAMPLES_NXIMAGE_YSCALEp5) || defined(CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5) /* Average row[0] and row[1], output results in row[0] */ for (i = 0; i < SCALED_WIDTH; i++) { /* Only average if the corresponding pixels in each row differ */ nxgl_mxpixel_t pix0 = g_runs[0].run[i]; nxgl_mxpixel_t pix1 = g_runs[1].run[i]; if (pix0 != pix1) { g_runs[0].run[i] = nximage_avgcolor(pix0, pix1); } } #endif /* Output rows after averaging */ /* Output row[0] */ dest.pt1.y = pos.y; dest.pt2.y = pos.y; src[0] = (FAR const void *)g_runs[0].run; #if CONFIG_NX_NPLANES > 1 # warning "More logic is needed for the case where CONFIG_NX_PLANES > 1" #endif ret = nx_bitmap((NXWINDOW)hwnd, &dest, src, &pos, SCALED_WIDTH*sizeof(nxgl_mxpixel_t)); if (ret < 0) { message("nximage_image: nx_bitmapwindow failed: %d\n", errno); } /* Increment the vertical position */ pos.y++; #if defined(CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5) /* Output row[0] and row[1] */ dest.pt1.y = pos.y; dest.pt2.y = pos.y; src[0] = (FAR const void *)g_runs[1].run; #if CONFIG_NX_NPLANES > 1 # warning "More logic is needed for the case where CONFIG_NX_PLANES > 1" #endif ret = nx_bitmap((NXWINDOW)hwnd, &dest, src, &pos, SCALED_WIDTH*sizeof(nxgl_mxpixel_t)); if (ret < 0) { message("nximage_image: nx_bitmapwindow failed: %d\n", errno); } /* Increment the vertical position */ pos.y++; #endif } }
int oled_image_crop_img(uint8_t pos_x, uint8_t pos_y, oled_image_canvas_t *img, oled_image_crop_pxs_t *crop_pxs) { const uint8_t byte_length = 8; int ret = OK; FAR struct nxgl_rect_s dest; FAR void *src[CONFIG_NX_NPLANES]; FAR struct nxgl_point_s pos; uint32_t i, j, pxs; uint8_t stride; uint16_t left_pad,top_pad; uint8_t img_width_crop, img_height_crop; uint8_t pic_line[16] = { 0 }; /* The only way to draw line from the image * is addressing to this line byte by byte. * Thus we need variables to save pixels pads * from the left side of the image */ uint8_t left_pxs_offset; /* check if crop_pxs structure's data is valid */ if (crop_pxs->bottom_pxs >= img->height || crop_pxs->top_pxs >= img->height || crop_pxs->left_pxs >= img->width || crop_pxs->right_pxs >= img->width || (crop_pxs->left_pxs + crop_pxs->right_pxs) >= img->width || (crop_pxs->top_pxs + crop_pxs->bottom_pxs) >= img->height) { lcd_lldbg("Cannot proceed. Amount of pixels to be cropped is greater or equal to the" " image height or width\n"); return ERROR; } /* check, will image fit on the screen after crop */ if (pos_x >= OLED_IMG_SCREEN_WIDTH || pos_y >= OLED_IMG_SCREEN_HEIGHT || (pos_x + img->width - crop_pxs->left_pxs - crop_pxs->right_pxs) > OLED_IMG_SCREEN_WIDTH || (pos_y + img->height - crop_pxs->top_pxs - crop_pxs->bottom_pxs) > OLED_IMG_SCREEN_HEIGHT) { lcd_dbg("Wrong coordinates to start draw image" "or image too big\n"); return ERROR; } left_pad = crop_pxs->left_pxs / byte_length; left_pxs_offset = crop_pxs->left_pxs % byte_length; top_pad = crop_pxs->top_pxs; /* New width and height calculation */ img_width_crop = img->width - crop_pxs->left_pxs - crop_pxs->right_pxs; img_height_crop = img->height - crop_pxs->top_pxs - crop_pxs->bottom_pxs; pos.x = pos_x - left_pxs_offset; pos.y = pos_y; dest.pt1.x = pos.x; dest.pt2.x = pos.x + img_width_crop - 1; stride = img->width / 8 + (!(img->width % 8) ? 0 : 1); for (i = 0, j = left_pad + stride * top_pad; i < img_height_crop; i++, j += stride) { dest.pt1.y = pos.y; dest.pt2.y = pos.y; memcpy(pic_line, (const uint8_t *)(img->bitmap + j), stride - left_pad); for (pxs = 0; pxs < left_pxs_offset; pxs++) { DEBUGASSERT(pxs <= byte_length); if (!CONFIG_THINGSEE_DISPLAY_BKGND_COLOR) { *(pic_line) &= ~(1 << (byte_length - pxs)); } else { *(pic_line) |= (1 << (byte_length - pxs)); } } src[0] = (FAR void *) pic_line; ret = nx_bitmap(g_img.hwnd, &dest, (FAR void *)src, &pos, img_width_crop); if (ret < 0) { lcd_dbg("nx_bitmapwindow failed: %d\n", errno); return ERROR; } pos.y++; } return ret; }