void nxbe_setposition(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_point_s *pos) { struct nxgl_rect_s before; struct nxgl_rect_s rect; #ifdef CONFIG_DEBUG_FEATURES if (!wnd) { return; } #endif /* Back out the old window origin position from the bounding box */ nxgl_rectoffset(&rect, &wnd->bounds, -wnd->bounds.pt1.x, -wnd->bounds.pt1.y); /* Add the new window origin into the bounding box */ nxgl_rectcopy(&before, &wnd->bounds); nxgl_rectoffset(&wnd->bounds, &rect, pos->x, pos->y); /* Get the union of the 'before' bounding box and the 'after' bounding * this union is the region of the display that must be updated. */ nxgl_rectunion(&rect, &before, &wnd->bounds); nxgl_rectintersect(&rect, &rect, &wnd->be->bkgd.bounds); /* Report the new size/position */ nxfe_reportposition(wnd); /* Then redraw this window AND all windows below it. Having moved the * window, we may have exposed previoulsy obscured portions of windows * below this one. */ nxbe_redrawbelow(wnd->be, wnd, &rect); }
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 nxbe_filltrapezoid(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *clip, FAR const struct nxgl_trapezoid_s *trap, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) { struct nxbe_filltrap_s info; struct nxgl_rect_s remaining; int i; #ifdef CONFIG_DEBUG if (!wnd || !trap) { return; } #endif /* Offset the trapezoid by the window origin to position it within * the framebuffer region */ nxgl_trapoffset(&info.trap, trap, wnd->bounds.pt1.x, wnd->bounds.pt1.y); /* Create a bounding box that contains the trapezoid */ remaining.pt1.x = b16toi(ngl_min(info.trap.top.x1, info.trap.bot.x1)); remaining.pt1.y = info.trap.top.y; remaining.pt2.x = b16toi(ngl_max(info.trap.top.x2, info.trap.bot.x2)); remaining.pt2.y = info.trap.bot.y; /* Clip to any user specified clipping window */ if (clip) { struct nxgl_rect_s tmp; nxgl_rectoffset(&tmp, clip, wnd->bounds.pt1.x, wnd->bounds.pt1.y); nxgl_rectintersect(&remaining, &remaining, &tmp); } /* Clip to the limits of the window and of the background screen */ nxgl_rectintersect(&remaining, &remaining, &wnd->bounds); nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds); if (!nxgl_nullrect(&remaining)) { info.cops.visible = nxbe_clipfilltrapezoid; info.cops.obscured = nxbe_clipnull; /* Then process each color plane */ #if CONFIG_NX_NPLANES > 1 for (i = 0; i < wnd->be->vinfo.nplanes; i++) #else i = 0; #endif { info.color = color[i]; nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT, &info.cops, &wnd->be->plane[i]); } } }
void nxbe_clipper(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *dest, uint8_t order, FAR struct nxbe_clipops_s *cops, FAR struct nxbe_plane_s *plane) { struct nxbe_clipstack_s stack; FAR struct nxbe_window_s *currw; struct nxgl_rect_s rect; struct nxgl_rect_s obscuredrect; struct nxgl_rect_s currbounds; struct nxgl_rect_s nonoverlapped[4]; int i; /* Initialize the stack where we will keep deferred rectangle operations */ stack.npushed = 0; stack.mxrects = 0; stack.stack = NULL; /* Loop until there are no further pending operations */ nxgl_rectcopy(&rect, dest); /* Start with the whole dest rectangle */ do { /* Loop for every window from the current window and above. Only windows * above the current window can obscure the current window */ for (currw = wnd; currw; currw = currw->above) { /* Does the current window overlap the dest rectangle? */ currbounds = currw->bounds; if (nxgl_rectoverlap(&rect, &currbounds)) { /* Yes.. then it obscures all or part of the dest rectangle. * Divide the potentially visible, non-overlapping regions into 4 * smaller rectangles and push them onto the stack for processing * on the next time through the outer loop. */ nxgl_nonintersecting(nonoverlapped, &rect, &currbounds); for (i = 3; i >= 0; i--) { /* Push the rectangles in the order specific by the input * argument of that name. */ struct nxgl_rect_s *candidate = &nonoverlapped[g_nxcliporder[order][i]]; if (!nxgl_nullrect(candidate)) { nxbe_pushrectangle(&stack, currw->above, candidate); } } /* Now performed any required processing on the obscurred, * overlapped region. */ nxgl_rectintersect(&obscuredrect, &rect, &currbounds); cops->obscured(cops, plane, &obscuredrect); /* Break out of the loop to process the pushed rectangles */ break; } } /* If there are no other windows overlapping this rectangle, then this * rectangular region must be visible. */ if (!currw && !nxgl_nullrect(&rect)) { cops->visible(cops, plane, &rect); } } while (nxbe_poprectangle(&stack, &wnd, &rect)); /* Done! If any stack was allocated, then free it before exit-ting */ if (stack.stack) { free(stack.stack); } }
void nxbe_move(FAR struct nxbe_window_s *wnd, FAR const struct nxgl_rect_s *rect, FAR const struct nxgl_point_s *offset) { struct nxbe_move_s info; int i; #ifdef CONFIG_DEBUG_FEATURES if (!wnd || !rect) { return; } #endif /* Offset the rectangle by the window origin to create a bounding box */ nxgl_rectoffset(&info.srcrect, rect, wnd->bounds.pt1.x, wnd->bounds.pt1.y); /* Clip to the limits of the window and of the background screen */ nxgl_rectintersect(&info.srcrect, &info.srcrect, &wnd->bounds); nxgl_rectintersect(&info.srcrect, &info.srcrect, &wnd->be->bkgd.bounds); if (nxgl_nullrect(&info.srcrect)) { return; } info.cops.visible = nxbe_clipmovedest; info.cops.obscured = nxbe_clipnull; info.offset.x = offset->x; info.offset.y = offset->y; info.wnd = wnd; /* The clip order depends up the direction that the rectangle is being * moved. */ if (offset->y < 0) { /* Moving rectangle up */ if (offset->x < 0) { /* Moving to upper-left */ info.order = NX_CLIPORDER_TLRB; /* Top-left-right-bottom */ } else { /* Moving to upper-right (or just up) */ info.order = NX_CLIPORDER_TRLB; /* Top-right-left-bottom */ } } else { /* Moving rectangle down (or just left/right) */ if (offset->x < 0) { /* Moving to lower-left */ info.order = NX_CLIPORDER_BLRT; /* Bottom-left-right-top */ } else { /* Moving to lower-right */ info.order = NX_CLIPORDER_BRLT; /* Bottom-right-left-top */ } } /* Then perform the move */ #if CONFIG_NX_NPLANES > 1 for (i = 0; i < wnd->be->vinfo.nplanes; i++) #else i = 0; #endif { nxbe_clipper(wnd->above, &info.srcrect, info.order, &info.cops, &wnd->be->plane[i]); } }
int vnc_update_rectangle(FAR struct vnc_session_s *session, FAR const struct nxgl_rect_s *rect, bool change) { FAR struct vnc_fbupdate_s *update; struct nxgl_rect_s intersection; bool whupd; /* Clip rectangle to the screen dimensions */ nxgl_rectintersect(&intersection, rect, &g_wholescreen); /* Make sure that the clipped rectangle has a area */ if (!nxgl_nullrect(&intersection)) { /* Check for a whole screen update. The RealVNC client sends a lot * of these (especially when it is confused) */ whupd = (memcmp(&intersection, &g_wholescreen, sizeof(struct nxgl_rect_s)) == 0); /* Ignore any client update requests if there have been no changes to * the framebuffer since the last whole screen update. */ sched_lock(); if (!change && !session->change) { /* No.. ignore the client update. We have nothing new to report. */ sched_unlock(); return OK; } /* Ignore all updates if there is a queued whole screen update */ if (session->nwhupd == 0) { /* No whole screen updates in the queue. Is this a new whole * screen update? */ if (whupd) { /* Yes.. Discard all of the previously queued updates */ FAR struct vnc_fbupdate_s *curr; FAR struct vnc_fbupdate_s *next; updvdbg("New whole screen update...\n"); curr = (FAR struct vnc_fbupdate_s *)session->updqueue.head; sq_init(&session->updqueue); sem_reset(&session->queuesem, 0); for (; curr != NULL; curr = next) { next = curr->flink; vnc_free_update(session, curr); } /* One whole screen update will be queued. There have been * no frame buffer data changes since this update was queued. */ session->nwhupd = 1; session->change = false; } else { /* We are not updating the whole screen. Remember if this * update (OR a preceding update) was due to a data change. */ session->change |= change; } /* Allocate an update structure... waiting if necessary */ update = vnc_alloc_update(session); DEBUGASSERT(update != NULL); /* Copy the clipped rectangle into the update structure */ update->whupd = whupd; nxgl_rectcopy(&update->rect, &intersection); /* Add the upate to the end of the update queue. */ vnc_add_queue(session, update); updvdbg("Queued {(%d, %d),(%d, %d)}\n", intersection.pt1.x, intersection.pt1.y, intersection.pt2.x, intersection.pt2.y); } sched_unlock(); } /* Since we ignore bad rectangles and wait for updata structures, there is * really no way a failure can occur. */ return OK; }