static void rtgui_list_view_calc(struct rtgui_list_view* view) { rtgui_rect_t rect; rt_uint32_t image_width, image_height; rt_ubase_t text_width, text_height; rt_ubase_t item_width, item_height; if (view->items_count == 0) return; /* get image width and height */ if (view->items[0].image != RT_NULL) { image_width = view->items[0].image->w; image_height = view->items[0].image->h; } else { image_width = 0; image_height = 0; } rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect); text_height = rtgui_rect_height(rect); text_width = rtgui_rect_width(rect); rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); item_width = (image_width + LIST_MARGIN); if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN; item_height = image_height + 8 + text_height + LIST_MARGIN; if (item_width > item_height) item_height = item_width; else item_width = item_height; view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height; view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width; view->page_items = view->row_items * view->col_items; }
static void rtgui_image_hdcmm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect) { rt_uint8_t *ptr; rt_uint16_t y, w, h; struct rtgui_image_hdcmm *hdc; RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL); /* this dc is not visible */ if (rtgui_dc_get_visible(dc) != RT_TRUE) return; hdc = (struct rtgui_image_hdcmm *) image; RT_ASSERT(hdc != RT_NULL); /* the minimum rect */ if (image->w < rtgui_rect_width(*dst_rect)) w = image->w; else w = rtgui_rect_width(*dst_rect); if (image->h < rtgui_rect_height(*dst_rect)) h = image->h; else h = rtgui_rect_height(*dst_rect); /* get pixel pointer */ ptr = hdc->pixels; for (y = 0; y < h; y ++) { dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y, ptr); ptr += hdc->pitch; } }
rtgui_view_t *demo_view_buffer_animation(rtgui_workbench_t* workbench) { rtgui_view_t *view; view = demo_view(workbench, "DC 缓冲区动画"); if (view != RT_NULL) rtgui_widget_set_event_handler(RTGUI_WIDGET(view), animation_event_handler); rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "缓冲动画", &text_rect); if (dc_buffer == RT_NULL) { rtgui_rect_t rect; rect.x1 = 0; rect.x2 = rtgui_rect_width(text_rect) + 2; rect.y1 = 0; rect.y2 = rtgui_rect_height(text_rect) + 2; /* 创建 DC Buffer,长 50,宽 50 */ dc_buffer = rtgui_dc_buffer_create(rtgui_rect_width(rect), rtgui_rect_height(rect)); RTGUI_DC_FC(dc_buffer) = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)); rtgui_dc_fill_rect(dc_buffer, &rect); RTGUI_DC_FC(dc_buffer) = black; rect.x1 = 1; rect.y1 = 1; rtgui_dc_draw_text(dc_buffer, "缓冲动画", &rect); } /* 启动定时器以触发动画 */ timer = rtgui_timer_create(1, RT_TIMER_FLAG_PERIODIC, timeout, (void*)view); rtgui_timer_start(timer); return view; }
static void rtgui_list_view_calc(struct rtgui_list_view* view) { /* get image of first item*/ rtgui_image_t *image; rtgui_rect_t rect; rt_ubase_t text_width, text_height; rt_ubase_t item_width, item_height; if (view->items_count == 0) return; image = view->items[0].image; rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect); text_height = rtgui_rect_height(rect); text_width = rtgui_rect_width(rect); rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); item_width = (image->w + LIST_MARGIN); if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN; item_height = image->h + 3 + text_height + LIST_MARGIN; view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height; view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width; view->page_items = view->row_items * view->col_items; }
void rtgui_edit_adjust_scroll(rtgui_scrollbar_t *bar) { struct rtgui_edit *edit; RT_ASSERT(bar != RT_NULL); if(bar->WIDGET_GROUP != RT_NULL) { rtgui_rect_t rect; rt_uint32_t _left=0,_top=0,_width=RTGUI_DEFAULT_SB_WIDTH,_len=0; edit = bar->WIDGET_GROUP; rtgui_widget_get_rect(edit, &rect); rtgui_widget_rect_to_device(edit,&rect); if(bar->orient==RTGUI_HORIZONTAL) { if(RTGUI_WIDGET_IS_HIDE(edit->hscroll)) { if(edit->max_rows > edit->row_per_page) { RTGUI_WIDGET_SHOW(edit->hscroll); rtgui_scrollbar_set_line_step(edit->hscroll, 1); rtgui_scrollbar_set_page_step(edit->hscroll, edit->row_per_page); rtgui_scrollbar_set_range(edit->hscroll, edit->max_rows); } else RTGUI_WIDGET_HIDE(edit->vscroll); rtgui_widget_update_clip(RTGUI_WIDGET(edit)); } else { _left = RTGUI_WIDGET_BORDER_SIZE(edit); _top = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER_SIZE(edit)-_width; _len = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER_SIZE(edit)*2; if(!RTGUI_WIDGET_IS_HIDE(edit->vscroll)) _len -= _width; rect.x1 += _left; rect.y1 += _top; rect.x2 = rect.x1+_len; rect.y2 = rect.y1+_width; } } else if(bar->orient==RTGUI_VERTICAL) { _left = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER_SIZE(edit)-_width; _top = RTGUI_WIDGET_BORDER_SIZE(edit); _len = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER_SIZE(edit)*2; if(!RTGUI_WIDGET_IS_HIDE(edit->hscroll)) _len -= _width; rect.x1 += _left; rect.y1 += _top; rect.x2 = rect.x1+_width; rect.y2 = rect.y1+_len; } rtgui_widget_set_rect(bar,&rect); } }
/* get active area length */ rt_uint32_t get_sbar_active_len(rtgui_scrollbar_t *bar) { rtgui_rect_t rect; rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect); if(bar->orient & RTGUI_VERTICAL) return rtgui_rect_height(rect) - 2*rtgui_rect_width(rect); else return rtgui_rect_width(rect) - 2*rtgui_rect_height(rect); }
static void rtgui_image_hdc_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect) { rt_uint16_t y, w, h; struct rtgui_image_hdc *hdc; RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL); /* this dc is not visible */ if (rtgui_dc_get_visible(dc) != RT_TRUE) return; hdc = (struct rtgui_image_hdc *) image->data; RT_ASSERT(hdc != RT_NULL); /* the minimum rect */ if (image->w < rtgui_rect_width(*dst_rect)) w = image->w; else w = rtgui_rect_width(*dst_rect); if (image->h < rtgui_rect_height(*dst_rect)) h = image->h; else h = rtgui_rect_height(*dst_rect); if (hdc->pixels != RT_NULL) { rt_uint8_t *ptr; /* get pixel pointer */ ptr = hdc->pixels; for (y = 0; y < h; y ++) { dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y, ptr); ptr += hdc->pitch; } } else { rt_uint8_t *ptr; ptr = rtgui_malloc(hdc->pitch); if (ptr == RT_NULL) return; /* no memory */ /* seek to the begin of pixel data */ rtgui_filerw_seek(hdc->filerw, hdc->pixel_offset, RTGUI_FILE_SEEK_SET); for (y = 0; y < h; y ++) { /* read pixel data */ if (rtgui_filerw_read(hdc->filerw, ptr, 1, hdc->pitch) != hdc->pitch) break; /* read data failed */ dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y, ptr); } rtgui_free(ptr); } }
rt_uint32_t _rtgui_scrollbar_get_length(rtgui_scrollbar_t *bar) { rtgui_rect_t rect; rt_uint32_t result; rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect); if(bar->orient & RTGUI_VERTICAL) result = rtgui_rect_height(rect) - 2*rtgui_rect_width(rect) - bar->thumb_len; else result = rtgui_rect_width(rect) - 2*rtgui_rect_height(rect) - bar->thumb_len; return result; }
static void _calc_width(rtgui_textview_t *textview) { rtgui_rect_t rect; rt_uint16_t width, height; width = rtgui_rect_width(RTGUI_WIDGET(textview)->extent) - 6; height = rtgui_rect_height(RTGUI_WIDGET(textview)->extent); rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &rect); textview->line_width = width / rtgui_rect_width(rect) + 1; textview->line_page_count = height / (rtgui_rect_height(rect) + 3); /* set minimal value */ if (textview->line_page_count == 0) textview->line_page_count = 1; }
struct rtgui_radiobox *rtgui_radiobox_create(const char *label, int orient, char **radio_items, int number) { struct rtgui_radiobox *radiobox; radiobox = (struct rtgui_radiobox *) rtgui_widget_create(RTGUI_RADIOBOX_TYPE); if (radiobox != RT_NULL) { rt_uint8_t board_size; struct rtgui_rect rect; radiobox->items = radio_items; radiobox->item_count = number; radiobox->item_selection = -1; radiobox->text = rt_strdup(label); /* set proper of control */ rtgui_radiobox_set_orientation(radiobox, orient); rtgui_font_get_metrics(RTGUI_WIDGET_FONT(radiobox), "H", &rect); board_size = rtgui_rect_height(rect); if (orient == RTGUI_VERTICAL) { radiobox->item_size = board_size; } else { int index; struct rtgui_font *font; struct rtgui_rect rect; /* set init item size */ radiobox->item_size = 0; font = RTGUI_WIDGET_FONT(radiobox); for (index = 0; index < number; index ++) { rtgui_font_get_metrics(font, radio_items[index], &rect); if ((board_size + 3 + rtgui_rect_width(rect)) > radiobox->item_size) radiobox->item_size = board_size + 3 + rtgui_rect_width(rect); } } if (radiobox->item_size < RADIO_BOX_H + 2) radiobox->item_size = RADIO_BOX_H + 2; } return radiobox; }
static void rtgui_textbox_init_caret(rtgui_textbox_t *box, rt_uint16_t position) { int x, y; rtgui_color_t color; rtgui_rect_t rect; int ofs = 0; RT_ASSERT(box != RT_NULL); if (!RTGUI_WIDGET_IS_FOCUSED(box)) return; rtgui_textbox_get_caret_rect(box, &box->caret_rect, position); rect = box->caret_rect; rtgui_widget_rect_to_device(RTGUI_WIDGET(box), &rect); if (box->caret == RT_NULL) box->caret = rtgui_malloc(rtgui_rect_width(rect) * rtgui_rect_height(rect) * sizeof(rtgui_color_t)); for (x = rect.x1; x < rect.x2; x++) { for (y = rect.y1; y < rect.y2; y++) { rtgui_graphic_driver_get_default()->ops->get_pixel(&color, x, y); *(box->caret + ofs) = color; ofs++; } } }
static void _rtgui_textbox_constructor(rtgui_textbox_t *box) { rtgui_rect_t rect; RTGUI_WIDGET_FLAG(RTGUI_WIDGET(box)) |= RTGUI_WIDGET_FLAG_FOCUSABLE; rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_textbox_event_handler); rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus); rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus); #ifndef RTGUI_USING_SMALL_SIZE rtgui_widget_set_onkey(RTGUI_WIDGET(box), rtgui_textbox_onkey); #endif RTGUI_WIDGET_FOREGROUND(box) = black; RTGUI_WIDGET_BACKGROUND(box) = white; /* set default text align */ RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_CENTER_VERTICAL; /* set proper of control */ box->caret_timer = RT_NULL; box->caret = RT_NULL; box->line = box->line_begin = box->position = 0; box->flag = RTGUI_TEXTBOX_SINGLE; /* allocate default line buffer */ box->text = RT_NULL; rtgui_textbox_set_mask_char(box, '*'); rtgui_font_get_metrics(RTGUI_WIDGET_FONT(box), "H", &rect); box->font_width = rtgui_rect_width(rect); box->on_enter = RT_NULL; box->dis_length = 0; box->first_pos = 0; }
static void _rtgui_textbox_constructor(rtgui_textbox_t *box) { rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT}; rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect); RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_textbox_event_handler); rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus); rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus); /* set default text align */ RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL; /* set proper of control */ box->caret_timer = rtgui_timer_create(RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC, _rtgui_textbox_caret_timeout, box); box->line = box->line_begin = box->position = 0; box->flag = RTGUI_TEXTBOX_SINGLE; /* allocate default line buffer */ box->text = RT_NULL; rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect); box->font_width = rtgui_rect_width(rect); }
static rt_bool_t app_list_view_onmouse(struct app_list_view *view, struct rtgui_event_mouse *emouse) { if (rtgui_rect_contains_point(&view->view_rect, emouse->x, emouse->y) == RT_EOK) { rt_uint16_t index; rt_uint16_t old_item; /* get old item */ old_item = view->current_item; { rt_uint16_t x, y; rt_uint16_t item_height, item_width; item_width = (rtgui_rect_width(view->view_rect) - 2 * LIST_MARGIN) / view->col_items; item_height = (rtgui_rect_height(view->view_rect) - 4) / view->row_items; x = emouse->x - view->view_rect.x1; y = emouse->y - view->view_rect.y1; index = (y / item_height * view->col_items) + x / item_width; if ((index + (view->current_page * view->page_items) < view->items_count)) { if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) { view->current_item = index + (view->current_page * view->page_items); /* down event */ // rtgui_list_view_update_icon(view, old_item); } else { if (view->current_item == index + (view->current_page * view->page_items)) { rt_kprintf("mouse up,current item:%d\n", view->current_item); /* up event */ if (view->on_select != RT_NULL) { view->on_select(&view->items[view->current_item]); } } } } } return RT_TRUE; } return RT_FALSE; }
static void gui_win_entry(void* parameter) { const struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default(); struct rt_messagequeue *mq; rtgui_win_t *win; rtgui_button_t *button; rtgui_point_t p; rtgui_rect_t rect = {0,0,200,180}; rtgui_label_t *label; rtgui_font_t *font; /* 创建GUI应用需要的消息队列 */ mq = rt_mq_create("demo_win", 256, 32, RT_IPC_FLAG_FIFO); /* 注册当前线程 */ rtgui_thread_register(rt_thread_self(), mq); /* 窗口居中 */ rtgui_rect_moveto(&rect, (gd->width - rtgui_rect_width(rect))/2, (gd->height - rtgui_rect_height(rect))/2); /* 创建窗口 */ win = rtgui_win_create(RT_NULL,"demo_win",&rect,RTGUI_WIN_DEFAULT); if(win == RT_NULL) return; /* 取得客户区坐标零点 */ p = rtgui_win_get_client_zero(win); label = rtgui_label_create(win, "hello world!", p.x+5, p.y+5, 100,25); font = rtgui_font_refer("asc", 12); RTGUI_WIDGET_FONT(label) = font; button = rtgui_button_create(win, "Exit", (rtgui_rect_width(rect)-50)/2, rtgui_rect_height(rect)-40,50,25); rtgui_button_set_onbutton(button,rtgui_win_close); rtgui_widget_set_event_handler(win, demo_gui_win_event_handler); rtgui_win_show(win,RT_FALSE); /* 执行工作台事件循环 */ rtgui_win_event_loop(win); demo_win_inited = RT_FALSE; /* 去注册GUI线程 */ rtgui_thread_deregister(rt_thread_self()); rt_mq_delete(mq); }
static void rtgui_list_view_onicondraw(struct rtgui_list_view *view, struct rtgui_dc *dc) { struct rtgui_rect rect, item_rect, drawing_rect; rt_ubase_t c, r, item_index; /* col and row index */ rt_ubase_t item_width, item_height; rtgui_image_t *image; if (view->items_count == 0) return; rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); item_index = (view->current_item / view->page_items) * view->page_items; item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / view->col_items; item_height = (rtgui_rect_height(rect) - 4) / view->row_items; image = view->items[0].image; for (r = 0; r < view->row_items; r ++) { for (c = 0; c < view->col_items; c ++) { if (item_index < view->items_count) { item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; item_rect.x2 = item_rect.x1 + item_width; item_rect.y2 = item_rect.y1 + item_height; if (item_index == view->current_item) { rtgui_theme_draw_selected(dc, &item_rect); } drawing_rect.x1 = drawing_rect.y1 = 0; drawing_rect.x2 = image->w; drawing_rect.y2 = image->h; rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); drawing_rect.y1 += 5; drawing_rect.y2 += 5; rtgui_image_blit(view->items[item_index].image, dc, &drawing_rect); item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; item_rect.x1 += 3; item_rect.x2 -= 3; rtgui_font_get_metrics(RTGUI_WIDGET_FONT(view), view->items[item_index].name, &drawing_rect); rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); rtgui_dc_draw_text(dc, view->items[item_index].name, &drawing_rect); item_index ++; } else break; } } }
struct rtgui_dc* rtgui_graphic_driver_get_rect_buffer(const struct rtgui_graphic_driver *driver, struct rtgui_rect *r) { int w, h; struct rtgui_dc_buffer *buffer; rt_uint8_t *pixel, *dst; struct rtgui_rect src, rect; /* use virtual framebuffer in default */ if (driver == RT_NULL) driver = _current_driver; if (r == RT_NULL) { rtgui_graphic_driver_get_rect(driver, &rect); } else { rtgui_graphic_driver_get_rect(driver, &src); rect = *r; rtgui_rect_intersect(&src, &rect); } w = rtgui_rect_width (rect); h = rtgui_rect_height(rect); if (!(w && h) || driver->framebuffer == RT_NULL) return RT_NULL; /* create buffer DC */ buffer = (struct rtgui_dc_buffer*)rtgui_dc_buffer_create_pixformat(driver->pixel_format, w, h); if (buffer == RT_NULL) return (struct rtgui_dc*)buffer; /* get source pixel */ pixel = (rt_uint8_t*)driver->framebuffer + rect.y1 * driver->pitch + rect.x1 * rtgui_color_get_bpp(driver->pixel_format); dst = buffer->pixel; while (h--) { memcpy(dst, pixel, buffer->pitch); dst += buffer->pitch; pixel += driver->pitch; } return (struct rtgui_dc*)buffer; }
static void _rtgui_plot_update_scale(struct rtgui_plot *plot) { struct rtgui_plot_curve *curve; struct rtgui_rect rect; rtgui_plot_curve_dtype max_x = 0; rtgui_plot_curve_dtype min_x = 0; rtgui_plot_curve_dtype max_y = 0; rtgui_plot_curve_dtype min_y = 0; rt_uint32_t iter = 0; rtgui_widget_get_rect(RTGUI_WIDGET(plot), &rect); curve = RTGUI_PLOT_CURVE( rtgui_mv_view_foreach_in_model(RTGUI_MV_VIEW(plot), &iter)); max_x = curve->max_x; min_x = curve->min_x; max_y = curve->max_y; min_y = curve->min_y; while (curve) { if (curve->max_x > max_x) max_x = curve->max_x; if (curve->min_x < min_x) min_x = curve->min_x; if (curve->max_y > max_y) max_y = curve->max_y; if (curve->min_y < min_y) min_y = curve->min_y; curve = RTGUI_PLOT_CURVE( rtgui_mv_view_foreach_in_model(RTGUI_MV_VIEW(plot), &iter)); } plot->scale_x = (max_x - min_x + rtgui_rect_width(rect)) / rtgui_rect_width(rect); plot->scale_y = (max_y - min_y + rtgui_rect_height(rect)) / rtgui_rect_height(rect); }
void _rtgui_edit_constructor(struct rtgui_edit *edit) { rtgui_rect_t font_rect; RTGUI_WIDGET_FLAG(edit) |= RTGUI_WIDGET_FLAG_FOCUSABLE; rtgui_widget_set_event_handler(edit, rtgui_edit_event_handler); rtgui_widget_set_onfocus(edit, rtgui_edit_onfocus); rtgui_widget_set_onunfocus(edit, rtgui_edit_onunfocus); RTGUI_WIDGET_FC(edit) = theme.foreground; RTGUI_WIDGET_BC(edit) = theme.blankspace; /* set default text align */ RTGUI_WIDGET_TEXTALIGN(edit) = RTGUI_ALIGN_CENTER_VERTICAL; /* set proper of control */ edit->caret_timer = RT_NULL; edit->caret = RT_NULL; edit->tabsize = 4; edit->margin = 1; edit->max_rows = edit->max_cols = 0; edit->visual.x = edit->visual.y = 0; edit->upleft.x = edit->upleft.y = 0; edit->row_per_page = edit->col_per_page = 0; edit->update_buf = RT_NULL; edit->flag = RTGUI_EDIT_NONE; #ifdef RTGUI_EDIT_USING_SCROLL edit->flag |= RTGUI_EDIT_VSCROLL; edit->flag |= RTGUI_EDIT_HSCROLL; #endif /* allocate default line buffer */ edit->bzsize = 16; rtgui_font_get_metrics(RTGUI_WIDGET_FONT(edit), "H", &font_rect); edit->font_width = rtgui_rect_width(font_rect); edit->font_height = rtgui_rect_height(font_rect); edit->dbl_buf = rtgui_dc_buffer_create(edit->font_width*2+1, edit->font_height+1); edit->head = RT_NULL; edit->tail = RT_NULL; edit->first_line = RT_NULL; #ifdef RTGUI_EDIT_USING_SCROLL edit->hscroll = RT_NULL; edit->vscroll = RT_NULL; #endif }
struct rtgui_container* demo_plot(void) { struct rtgui_container *cnt; struct rtgui_plot_curve *curve1, *curve2, *curve3; struct rtgui_plot *plot; struct rtgui_rect rect; cnt = demo_view("ÇúÏß»æͼ"); plot = rtgui_plot_create(); curve1 = rtgui_plot_curve_create(); rtgui_plot_curve_set_y(curve1, sin_ydata); RTGUI_MV_MODEL(curve1)->length = sizeof(sin_ydata)/sizeof(sin_ydata[0]); curve1->min_x = 0; curve1->max_x = sizeof(sin_ydata)/sizeof(sin_ydata[0]); curve1->min_y = -100; curve1->min_y = 100; curve1->color = red; rtgui_mv_model_add_view(RTGUI_MV_MODEL(curve1), RTGUI_MV_VIEW(plot)); curve2 = rtgui_plot_curve_create(); rtgui_plot_curve_set_y(curve2, cos_ydata); RTGUI_MV_MODEL(curve2)->length = sizeof(cos_ydata)/sizeof(cos_ydata[0]); curve2->min_x = 0; curve2->max_x = sizeof(cos_ydata)/sizeof(cos_ydata[0]); curve1->min_y = -50; curve1->min_y = 50; curve2->color = blue; rtgui_mv_model_add_view(RTGUI_MV_MODEL(curve2), RTGUI_MV_VIEW(plot)); curve3 = rtgui_plot_curve_create(); rtgui_plot_curve_set_x(curve3, cos_ydata); rtgui_plot_curve_set_y(curve3, sin_ydata); RTGUI_MV_MODEL(curve3)->length = sizeof(sin_ydata)/sizeof(sin_ydata[0]); curve3->color = black; rtgui_mv_model_add_view(RTGUI_MV_MODEL(curve3), RTGUI_MV_VIEW(plot)); rtgui_widget_get_rect(RTGUI_WIDGET(cnt), &rect); rtgui_widget_set_rect(RTGUI_WIDGET(plot), &rect); rtgui_plot_set_base(plot, -rtgui_rect_width(rect)/3, rtgui_rect_height(rect)/2); rtgui_container_add_child(cnt, RTGUI_WIDGET(plot)); return cnt; }
static void rtgui_slider_onmouse(struct rtgui_slider* slider, struct rtgui_event_mouse* event) { RT_ASSERT(slider != RT_NULL); RT_ASSERT(event != RT_NULL); if (event->button & RTGUI_MOUSE_BUTTON_DOWN && event->button & RTGUI_MOUSE_BUTTON_LEFT) { int sel; int range = slider->max - slider->min; int x0, xsize; int x; x0 = 1 + slider->thumb_width/2; if (slider->orient == RTGUI_VERTICAL) { x = event->y - RTGUI_WIDGET(slider)->extent.y1; x -= x0; xsize = rtgui_rect_height(RTGUI_WIDGET(slider)->extent) - 2 * x0; } else { x = event->x - RTGUI_WIDGET(slider)->extent.x1; x -= x0; xsize = rtgui_rect_width(RTGUI_WIDGET(slider)->extent) - 2 * x0; } if (x <= 0) { sel = slider->min; } else if (x >= xsize) { sel = slider->max; } else { sel = ((range * x) + xsize/2) / xsize; sel += slider->min; } rtgui_widget_focus(RTGUI_WIDGET(slider)); rtgui_slider_set_value(slider, sel); if (slider->on_changed != RT_NULL) /* invoke callback function */ slider->on_changed(RTGUI_WIDGET(slider), RT_NULL); } }
static void rtgui_textbox_get_caret_rect(rtgui_textbox_t *box, rtgui_rect_t *rect, rt_uint16_t position) { int font_h, box_h; rtgui_rect_t item_rect; RT_ASSERT(box != RT_NULL); rtgui_widget_get_rect(RTGUI_WIDGET(box), rect); rtgui_font_get_metrics(RTGUI_WIDGET_FONT(box), "H", &item_rect); font_h = rtgui_rect_height(item_rect); box->font_width = rtgui_rect_width(item_rect); box_h = rtgui_rect_height(*rect); rect->x1 += position * box->font_width + 2; rect->x2 = rect->x1 + 2; rect->y1 += (box_h - font_h) / 2; rect->y2 = rect->y1 + font_h; }
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect) { int x, y; int w, h; struct rtgui_blit_info info; struct rtgui_graphic_driver *hw_driver = rtgui_graphic_driver_get_default(); RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL); RT_ASSERT(image->data != RT_NULL); #define blending(s, d, a) (((unsigned)(((s) - (d)) * (a)) >> 8) + (d)) /* this dc is not visible */ if (rtgui_dc_get_visible(dc) != RT_TRUE) return; w = _UI_MIN(image->w, rtgui_rect_width(*rect)); h = _UI_MIN(image->h, rtgui_rect_height(*rect)); /* border checking */ if (rect->x1 < 0) { x = -rect->x1; w += rect->x1; } else x = 0; if (rect->y1 < 0) { y = -rect->y1; h += rect->y1; } else y = 0; if (w < 0 || h < 0) return; /* no drawing */ if ((dc->type == RTGUI_DC_CLIENT) || (dc->type == RTGUI_DC_HW && hw_driver->framebuffer == RT_NULL)) { int dx, dy, start_x; rtgui_rect_t r; rtgui_color_t *pixel; rt_uint8_t alpha; rtgui_widget_t *owner = RT_NULL; if (dc->type == RTGUI_DC_CLIENT) { /* get owner and calculate dx,dy */ owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); dx = owner->extent.x1; dy = owner->extent.y1; }
void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *erect) { rtgui_rect_t rect; rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect); if(bar->orient & RTGUI_VERTICAL) { /* vertical scroll bar */ erect->x1 = rect.x1; erect->x2 = rect.x2; erect->y1 = rect.y1 + rtgui_rect_width(rect) + get_scrollbar_pos(bar); erect->y2 = erect->y1 + bar->thumb_len; } else { /* horizontal scroll bar */ erect->x1 = rect.x1 + rtgui_rect_height(rect) + get_scrollbar_pos(bar); erect->x2 = erect->x1 + bar->thumb_len; erect->y1 = rect.y1; erect->y2 = rect.y2; } }
static rt_bool_t rtgui_textbox_onkey(struct rtgui_object *widget, rtgui_event_t *event) { rtgui_textbox_t *box = RTGUI_TEXTBOX(widget); struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd *)event; rt_size_t length; rt_uint16_t posbak = box->position; RT_ASSERT(box != RT_NULL); RT_ASSERT(ekbd != RT_NULL); /* handle the key at down time and nothing to do with up */ if (RTGUI_KBD_IS_UP(ekbd)) return RT_TRUE; if (box->dis_length == 0) { rtgui_rect_t rect; rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); if (box->font_width == 0) return RT_FALSE; box->dis_length = ((rtgui_rect_width(rect) - 5) / box->font_width) & ~0x1; } length = rt_strlen((char*)box->text); if (ekbd->key == RTGUIK_DELETE) { int chw; unsigned char *c; if (TB_ABSPOS(box) == length) { goto _exit; } chw = _string_char_width((char*)box->text, length, TB_ABSPOS(box)).char_width; /* remove character */ for (c = &box->text[TB_ABSPOS(box)]; c[chw] != '\0'; c++) *c = c[chw]; *c = '\0'; } else if (ekbd->key == RTGUIK_BACKSPACE) { /* delete front character */ if (box->position == 0) { if(box->first_pos == 0) goto _exit; if(box->first_pos > box->dis_length) { int head_fix; int chw = _string_char_width((char*)box->text, length, TB_ABSPOS(box) - 1).char_width; rt_memmove(box->text + TB_ABSPOS(box) - chw, box->text + TB_ABSPOS(box), length - TB_ABSPOS(box) + 1); head_fix = 0; /* FIXME: */ if (box->text[box->first_pos - box->dis_length - chw] > 0x80) { int i; for (i = box->first_pos - box->dis_length - chw; i < box->first_pos; i++) { if (box->text[i] > 0x80) head_fix++; else break; } /* if the head is in middle of wide char, move one less * byte */ head_fix = head_fix % 2; } box->first_pos = box->first_pos - box->dis_length + head_fix - chw; box->position = box->dis_length - head_fix; } else { int chw; if (box->text[TB_ABSPOS(box) - 1] < 0x80) { /* also copy the \0 */ rt_memmove(box->text + TB_ABSPOS(box) - 1, box->text + TB_ABSPOS(box), length - TB_ABSPOS(box) + 1); chw = 1; } else { rt_memmove(box->text + TB_ABSPOS(box) - 2, box->text + TB_ABSPOS(box), length - TB_ABSPOS(box) + 1); chw = 2; } box->position = box->first_pos - chw; box->first_pos = 0; } } else { unsigned char *c; int chw; chw = _string_char_width((char*)box->text, length, TB_ABSPOS(box) - 1).char_width; /* remove character */ for (c = &box->text[TB_ABSPOS(box) - chw]; c[chw] != '\0'; c++) *c = c[chw]; *c = '\0'; box->position -= chw; } } else if (ekbd->key == RTGUIK_LEFT) { int chw; if (box->first_pos == 0 && box->position == 0) goto _exit; if (box->text[TB_ABSPOS(box) - 1] > 0x80) chw = 2; else chw = 1; /* move to prev */ if (box->position >= chw) { box->position -= chw; } else { if (box->first_pos >= chw) box->first_pos -= chw; else box->first_pos = 0; } } else if (ekbd->key == RTGUIK_RIGHT) { int chw; if ((TB_ABSPOS(box) + 2) <= length && box->text[TB_ABSPOS(box)] > 0x80) chw = 2; else chw = 1; /* move to next */ if (TB_ABSPOS(box) < length) { if(box->position + chw <= box->dis_length) box->position += chw; else { /* always move one wide char when the first char is wide */ if (box->text[box->first_pos] > 0x80) { box->first_pos += 2; if (chw == 2) { int i; int head_fix = 0; for (i = box->first_pos; i < box->first_pos + box->dis_length; i++) { if (box->text[i] > 0x80) head_fix++; } head_fix %= 2; if (head_fix) { box->first_pos += 2; box->position = box->dis_length - 1; } } else if (chw == 1) /* we have moved the box by 2 bytes but the last one is * a narrow char */ box->position -= 1; else RT_ASSERT(0); } else box->first_pos += chw; } } } else if (ekbd->key == RTGUIK_HOME) { /* move cursor to start */ box->position = 0; box->first_pos = 0; } else if (ekbd->key == RTGUIK_END) { /* move cursor to end */ if(length > box->dis_length) { box->position = box->dis_length; box->first_pos = length - box->dis_length; } else { box->position = length; box->first_pos = 0; } } else if (ekbd->key == RTGUIK_RETURN) { if (box->on_enter != RT_NULL) { box->on_enter(box, event); } } else if (ekbd->key == RTGUIK_NUMLOCK) { /* change numlock state */ /* extern void update_number_lock(void); update_number_lock(); */ } else { rt_uint16_t chr; int chw; if (!(ekbd->unicode || isprint(ekbd->key))) goto _exit; if (ekbd->unicode) { chr = ekbd->unicode; chw = 2; } else { chr = ekbd->key; chw = 1; } if (box->flag & RTGUI_TEXTBOX_DIGIT) { /* only input digit */ if (!isdigit(chr)) { /* exception: '.' and '-' */ if (chr != '.' && chr != '-')return RT_FALSE; if (chr == '.' && strchr((char*)box->text, '.'))return RT_FALSE; if (chr == '-') { if (length + chw > box->line_length) return RT_FALSE; if (strchr((char*)box->text, '-')) { unsigned char *c; for (c = &box->text[0]; c != &box->text[length]; c++) *c = *(c + 1); box->text[length] = '\0'; box->position --; goto _exit; } else { unsigned char *c; for (c = &box->text[length]; c != &box->text[0]; c--) *c = *(c - 1); box->text[0] = '-'; box->text[length + 1] = '\0'; box->position ++; goto _exit; } } } } if (length + chw > box->line_length) return RT_FALSE; if (TB_ABSPOS(box) <= length - 1) { unsigned char *c; for (c = &box->text[length + chw - 1]; c != &box->text[TB_ABSPOS(box)]; c -= 1) *c = *(c - chw); } if (chw == 1) { box->text[TB_ABSPOS(box)] = chr; } else if (chw == 2) { box->text[TB_ABSPOS(box)] = chr >> 8; box->text[TB_ABSPOS(box)+1] = chr & 0xFF; } else {
static rt_bool_t rtgui_list_view_onmouse(struct rtgui_list_view* view, struct rtgui_event_mouse* emouse) { rtgui_rect_t rect; /* calculate selected item */ /* get physical extent information */ rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); rtgui_widget_rect_to_device(RTGUI_WIDGET(view), &rect); if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) { rt_uint16_t index; rt_uint16_t old_item; /* get old item */ old_item = view->current_item; switch (view->flag) { case RTGUI_LIST_VIEW_LIST: index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); if ((index < view->items_count) && (index < view->page_items)) { /* set selected item */ view->current_item = (view->current_item/view->page_items) * view->page_items + index; if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) { /* down event */ rtgui_list_view_update_list(view, old_item); } else { /* up event */ if (view->items[view->current_item].action != RT_NULL) { view->items[view->current_item].action(view->items[view->current_item].parameter); } } } break; case RTGUI_LIST_VIEW_ICON: { rt_uint16_t x, y; rt_uint16_t item_height, item_width; rt_ubase_t current_page; item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; item_height = (rtgui_rect_height(rect) - 4)/view->row_items; x = emouse->x - rect.x1; y = emouse->y - rect.y1; index = (y / item_height * view->col_items) + x / item_width; current_page = view->current_item / view->page_items; if ((index + (current_page * view->page_items) < view->items_count)) { if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) { view->current_item = index + (current_page * view->page_items); /* down event */ rtgui_list_view_update_icon(view, old_item); } else { /* up event */ if (view->items[view->current_item].action != RT_NULL) { view->items[view->current_item].action(view->items[view->current_item].parameter); } } } } break; case RTGUI_LIST_VIEW_REPORT: break; } return RT_TRUE; } return RT_FALSE; }
static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_uint16_t old_item) { struct rtgui_rect rect, item_rect, drawing_rect; rt_ubase_t c, r; /* col and row index */ rt_ubase_t item_width, item_height; rtgui_image_t* image; struct rtgui_dc* dc; if ((view->items_count == 0) || (old_item == view->current_item)) return; if (old_item/view->page_items != view->current_item/view->page_items) { /* it's not a same page, update all */ rtgui_widget_update(RTGUI_WIDGET(view)); return; } dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); if (dc == RT_NULL) return; rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; item_height = (rtgui_rect_height(rect) - 4)/view->row_items; image = view->items[0].image; /* update old item */ r = (old_item % view->page_items)/ view->col_items; c = (old_item % view->page_items)% view->col_items; item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; item_rect.x2 = item_rect.x1 + item_width; item_rect.y2 = item_rect.y1 + item_height; rtgui_dc_fill_rect(dc, &item_rect); /* draw image */ drawing_rect.x1 = drawing_rect.y1 = 0; drawing_rect.x2 = image->w; drawing_rect.y2 = image->h; rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); drawing_rect.y1 += 3; drawing_rect.y2 += 3; rtgui_image_blit(view->items[old_item].image, dc, &drawing_rect); /* draw text */ item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; item_rect.x1 += 3; item_rect.x2 -=3; rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[old_item].name, &drawing_rect); rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); rtgui_dc_draw_text(dc, view->items[old_item].name, &drawing_rect); /* update new item as selected */ r = (view->current_item % view->page_items) / view->col_items; c = (view->current_item % view->page_items) % view->col_items; item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; item_rect.x2 = item_rect.x1 + item_width; item_rect.y2 = item_rect.y1 + item_height; rtgui_theme_draw_selected(dc, &item_rect); /* draw image */ drawing_rect.x1 = 0; drawing_rect.y1 = 3; drawing_rect.x2 = image->w; drawing_rect.y2 = 3 + image->h; rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); rtgui_image_blit(view->items[view->current_item].image, dc, &drawing_rect); /* draw text */ item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; item_rect.x1 += 3; item_rect.x2 -=3; rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[view->current_item].name, &drawing_rect); rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); rtgui_dc_draw_text(dc, view->items[view->current_item].name, &drawing_rect); rtgui_dc_end_drawing(dc); }
/* blit a dc to another dc */ static void rtgui_dc_buffer_blit(struct rtgui_dc *self, struct rtgui_point *dc_pt, struct rtgui_dc *dest, rtgui_rect_t *rect) { int pitch; rt_uint16_t rect_width, rect_height; struct rtgui_rect _rect, *dest_rect; struct rtgui_point dc_point; struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *)self; if (rtgui_dc_get_visible(dest) == RT_FALSE) return; /* use the (0,0) origin point */ if (dc_pt == RT_NULL) dc_point = rtgui_empty_point; else { dc_point = *dc_pt; } rtgui_dc_get_rect(dest, &_rect); /* use the rect of dest dc */ if (rect == RT_NULL) { dest_rect = &_rect; } else { dest_rect = rect; if (dest_rect->x1 > _rect.x2 || dest_rect->y1 > _rect.y2) return; if (dest_rect->x1 < 0) { if (-dest_rect->x1 > dc->width) return; dc_point.x += -dest_rect->x1; dest_rect->x1 = 0; } if (dest_rect->y1 < 0) { if (-dest_rect->y1 > dc->height) return; dc_point.y += -dest_rect->y1; dest_rect->y1 = 0; } if (dest_rect->x2 > _rect.x2) dest_rect->x2 = _rect.x2; if (dest_rect->y2 > _rect.y2) dest_rect->y2 = _rect.y2; } if (dc_point.x > dc->width || dc_point.y > dc->height) return; /* get the minimal width and height */ rect_width = _UI_MIN(rtgui_rect_width(*dest_rect), dc->width - dc_point.x); rect_height = _UI_MIN(rtgui_rect_height(*dest_rect), dc->height - dc_point.y); if ((dest->type == RTGUI_DC_HW) || (dest->type == RTGUI_DC_CLIENT)) { int index; rt_uint8_t *line_ptr, *pixels; rtgui_blit_line_func blit_line; struct rtgui_graphic_driver *hw_driver; hw_driver = rtgui_graphic_driver_get_default(); /* prepare pixel line */ pixels = _dc_get_pixel(dc, dc_point.x, dc_point.y); if (hw_driver->bits_per_pixel == _dc_get_bits_per_pixel(dc)) { if (dest->type == RTGUI_DC_HW && hw_driver->framebuffer != RT_NULL) { rt_uint8_t *hw_pixels; struct rtgui_dc_hw *hw; hw = (struct rtgui_dc_hw*)dest; /* NOTES: the rect of DC is the logic coordination. * It should be converted to client */ if (dest_rect != &_rect) { /* use local rect */ _rect = *dest_rect; dest_rect = &_rect; } rtgui_rect_moveto(dest_rect, hw->owner->extent.x1, hw->owner->extent.y1); pitch = rtgui_color_get_bpp(hw_driver->pixel_format) * rect_width; hw_pixels = (rt_uint8_t*)(hw_driver->framebuffer + dest_rect->y1 * hw_driver->pitch + dest_rect->x1 * rtgui_color_get_bpp(hw_driver->pixel_format)); /* do the blit with memory copy */ for (index = 0; index < rect_height; index ++) { rt_memcpy(hw_pixels, pixels, pitch); pixels += dc->pitch; hw_pixels += hw_driver->pitch; } } else { /* it's the same bits per pixel, draw it directly */ for (index = dest_rect->y1; index < dest_rect->y1 + rect_height; index++) { dest->engine->blit_line(dest, dest_rect->x1, dest_rect->x1 + rect_width, index, pixels); pixels += dc->pitch; } } } else { struct rtgui_graphic_driver *hw_driver; hw_driver = rtgui_graphic_driver_get_default(); if ((dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) && (dest->type == RTGUI_DC_HW) && (hw_driver->framebuffer != RT_NULL) && (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)) { /* do the fast ARGB to RGB565 blit */ struct rtgui_blit_info info; struct rtgui_widget *owner; /* blit source */ info.src = _dc_get_pixel(dc, dc_point.x, dc_point.y); info.src_fmt = dc->pixel_format; info.src_h = rect_height; info.src_w = rect_width; info.src_pitch = dc->pitch; info.src_skip = info.src_pitch - info.src_w * rtgui_color_get_bpp(dc->pixel_format); owner = ((struct rtgui_dc_hw*)dest)->owner; /* blit destination */ info.dst = (rt_uint8_t*)hw_driver->framebuffer; info.dst = info.dst + (owner->extent.y1 + dest_rect->y1) * hw_driver->pitch + (owner->extent.x1 + dest_rect->x1) * rtgui_color_get_bpp(hw_driver->pixel_format); info.dst_fmt = hw_driver->pixel_format; info.dst_h = rect_height; info.dst_w = rect_width; info.dst_pitch = hw_driver->pitch; info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(hw_driver->pixel_format); rtgui_blit(&info); } else { /* get blit line function */ blit_line = rtgui_blit_line_get(_UI_BITBYTES(hw_driver->bits_per_pixel), rtgui_color_get_bpp(dc->pixel_format)); /* calculate pitch */ pitch = rect_width * rtgui_color_get_bpp(dc->pixel_format); /* create line buffer */ line_ptr = (rt_uint8_t *) rtgui_malloc(rect_width * _UI_BITBYTES(hw_driver->bits_per_pixel)); /* draw each line */ for (index = dest_rect->y1; index < dest_rect->y1 + rect_height; index ++) { /* blit on line buffer */ blit_line(line_ptr, (rt_uint8_t *)pixels, pitch); pixels += dc->pitch; /* draw on hardware dc */ dest->engine->blit_line(dest, dest_rect->x1, dest_rect->x1 + rect_width, index, line_ptr); } /* release line buffer */ rtgui_free(line_ptr); } } } else if (dest->type == RTGUI_DC_BUFFER) { struct rtgui_dc_buffer *dest_dc = (struct rtgui_dc_buffer*)dest; if (dest_dc->pixel_format == dc->pixel_format && dest_dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) { int index; rt_uint8_t *pixels, *dest_pixels; /* get pitch */ pitch = rect_width * rtgui_color_get_bpp(dc->pixel_format); pixels = _dc_get_pixel(dc, dc_point.x, dc_point.y); dest_pixels = _dc_get_pixel(dest_dc, dest_rect->x1, dest_rect->y1); for (index = 0; index < rect_height; index ++) { rt_memcpy(dest_pixels, pixels, pitch); pixels += dc->pitch; dest_pixels += dest_dc->pitch; } } else /* use rtgui_blit to handle buffer blit */ { /* do the fast ARGB to RGB565 blit */ struct rtgui_blit_info info; /* blit source */ info.src = _dc_get_pixel(dc, dc_point.x, dc_point.y); info.src_fmt = dc->pixel_format; info.src_h = rect_height; info.src_w = rect_width; info.src_pitch = dc->pitch; info.src_skip = info.src_pitch - info.src_w * rtgui_color_get_bpp(dc->pixel_format); /* blit destination */ info.dst = _dc_get_pixel(dest_dc, dest_rect->x1, dest_rect->y1); info.dst_fmt = dest_dc->pixel_format; info.dst_h = rect_height; info.dst_w = rect_width; info.dst_pitch = dest_dc->pitch; info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(dest_dc->pixel_format); rtgui_blit(&info); } } }
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect) { rt_uint16_t x, y, w, h; rtgui_color_t *ptr; struct rtgui_image_png *png; int fg_maxsample; int ialpha; float alpha; rtgui_color_t color; rtgui_color_t c, bgcolor; int fc[3], bc[3]; struct rtgui_graphic_driver *hwdev = rtgui_graphic_get_device(); RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL); RT_ASSERT(image->data != RT_NULL); png = (struct rtgui_image_png *) image->data; w = _UI_MIN(image->w, rtgui_rect_width(*rect)); h = _UI_MIN(image->h, rtgui_rect_height(*rect)); fg_maxsample = (1 << png->info_ptr->bit_depth) - 1; if (png->pixels != RT_NULL) { ptr = (rtgui_color_t *)png->pixels; bgcolor = RTGUI_DC_BC(dc); bc[0] = RTGUI_RGB_R(bgcolor); bc[1] = RTGUI_RGB_G(bgcolor); bc[2] = RTGUI_RGB_B(bgcolor); /* draw each point within dc */ for (y = 0; y < h; y ++) { for (x = 0; x < w; x++) { c = *ptr; ialpha = RTGUI_RGB_A(c); if (ialpha == 0) { /* * Foreground image is transparent hear. * If the background image is already in the frame * buffer, there is nothing to do. */ } else if (ialpha == fg_maxsample) { /* * Copy foreground pixel to frame buffer. */ rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, c); } else { /* output = alpha * foreground + (1-alpha) * background */ /* * Compositing is necessary. * Get floating-point alpha and its complement. * Note: alpha is always linear: gamma does not * affect it. */ fc[0] = RTGUI_RGB_R(c); fc[1] = RTGUI_RGB_G(c); fc[2] = RTGUI_RGB_B(c); alpha = (float) ialpha / fg_maxsample; color = RTGUI_RGB((rt_uint8_t)(fc[0] * alpha + bc[0] * (1 - alpha)), (rt_uint8_t)(fc[1] * alpha + bc[1] * (1 - alpha)), (rt_uint8_t)(fc[2] * alpha + bc[2] * (1 - alpha))); rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, color); } /* move to next color buffer */ ptr ++; } } } else { png_bytep row; png_bytep data; row = (png_bytep) rtgui_malloc(png_get_rowbytes(png->png_ptr, png->info_ptr)); if (row == RT_NULL) return ; switch (png->info_ptr->color_type) { case PNG_COLOR_TYPE_RGB: for (y = 0; y < h; y++) { png_read_row(png->png_ptr, row, png_bytep_NULL); for (x = 0; x < w; x++) { data = &(row[x * 3]); rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, RTGUI_RGB(data[0], data[1], data[2])); } } break; case PNG_COLOR_TYPE_RGBA: for (y = 0; y < h; y++) { png_read_row(png->png_ptr, row, png_bytep_NULL); for (x = 0; x < w; x++) { data = &(row[x * 4]); if (data[3] != 0) { rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, RTGUI_ARGB(data[3], data[0], data[1], data[2])); } } } break; case PNG_COLOR_TYPE_PALETTE: for (y = 0; y < h; y++) { png_read_row(png->png_ptr, row, png_bytep_NULL); for (x = 0; x < w; x++) { data = &(row[x]); rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, RTGUI_ARGB(0, png->info_ptr->palette[data[0]].red, png->info_ptr->palette[data[0]].green, png->info_ptr->palette[data[0]].blue)); } } default: break; }; rtgui_free(row); } }
rt_bool_t demo_bitmap_showbox(struct rtgui_object* object, struct rtgui_event* event) { rtgui_container_t *container; rtgui_widget_t *widget; RT_ASSERT(object != RT_NULL); container = RTGUI_CONTAINER(object); widget = RTGUI_WIDGET(object); if(event->type == RTGUI_EVENT_PAINT) { int w, h; rtgui_rect_t rect; struct rtgui_dc *dc; struct rtgui_image *image = bmpdt.showimg; /* 如果从其他标签切换到当前标签, image应该是RT_NULL, 重置它 */ if(image == RT_NULL && bmpdt.image != RT_NULL) { image = bmpdt.image; bmpdt.scale = 1.0f; bmpdt.angle = 0.0f; rtgui_widget_get_rect(RTGUI_WIDGET(bmpdt.showbox), &bmpdt.lastrect); rtgui_rect_inflate(&bmpdt.lastrect, -RTGUI_WIDGET_BORDER(bmpdt.showbox)); } dc = rtgui_dc_begin_drawing(widget); if (dc == RT_NULL) return RT_FALSE; rtgui_widget_get_rect(widget, &rect); /* 在绘制边框后, 再将rect缩小填充背景, 可以降低闪烁现象 */ rtgui_dc_draw_border(dc, &rect, RTGUI_WIDGET_BORDER_STYLE(widget)); rtgui_rect_inflate(&rect, -RTGUI_WIDGET_BORDER(widget)); w = rtgui_rect_width(bmpdt.lastrect); h = rtgui_rect_height(bmpdt.lastrect); if(w > rtgui_rect_width(rect)) w = rtgui_rect_width(rect); if(h > rtgui_rect_height(rect)) h = rtgui_rect_height(rect); /* fill container with background */ /* * 参数lastrect会记录上一次绘图所用区域 * 每次重绘时,只需与lastrect比较,即可得知那些背景区域需要刷新 * 例如当放大图片时,lastrect比当前绘图区小,所有无需更新背景区, * 当缩小图片时, 也仅需要更新绘图区比lastrect大的区域. */ if(image != RT_NULL) { /* 减少不必要的绘图 */ rtgui_rect_t rc; if(w > image->w) { rc.x1 = image->w; rc.y1 = bmpdt.lastrect.y1; rc.x2 = bmpdt.lastrect.x2; rc.y2 = (h > image->h) ? image->h : bmpdt.lastrect.y2; rtgui_dc_fill_rect(dc, &rc); } if(h > image->h) { rc.x1 = bmpdt.lastrect.x1; rc.y1 = image->h; rc.x2 = bmpdt.lastrect.x2; rc.y2 = bmpdt.lastrect.y2; rtgui_dc_fill_rect(dc, &rc); } } else rtgui_dc_fill_rect(dc, &bmpdt.lastrect); /* 将图像数据blit到画布上 */ if (image != RT_NULL) { int value; rtgui_image_blit(image, dc, &rect); bmpdt.lastrect.x1 = bmpdt.lastrect.y1 = RTGUI_WIDGET_BORDER(bmpdt.showbox); if(image->w > rtgui_rect_width(rect)) value = rtgui_rect_width(rect); else value = image->w; bmpdt.lastrect.x2 = bmpdt.lastrect.x1 + value; if(image->h > rtgui_rect_height(rect)) value = rtgui_rect_height(rect); else value = image->h; bmpdt.lastrect.y2 = bmpdt.lastrect.y1 + value; } rtgui_dc_end_drawing(dc); return RT_FALSE; } return rtgui_container_event_handler(object, event); }