Пример #1
0
/** 追加子部件 */
int $(Append)( LCUI_Widget container, LCUI_Widget widget )
{
	int i, n;
	LCUI_Widget old_container;
	LCUI_WidgetEvent e;
	DEBUG_MSG("container: %p, widget: %p\n", container, widget);
	if( !container || !widget || container == widget->parent ) {
		return -1;
	}
	if( container == widget ) {
		return -2;
	}
	if( widget->parent ) {
		old_container = widget->parent;
	} else {
		goto remove_done;
	}

	/* 移除在之前的容器中的记录 */
	n = LinkedList_GetTotal( &old_container->children );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &old_container->children, i );
		if( LinkedList_Get(&old_container->children) == widget ) {
			LinkedList_Delete( &old_container->children );
			break;
		}
	}
	/* 如果是从根级部件中移出,则触发 WET_REMOVE 事件 */
	if( i < n && old_container == LCUIRootWidget ) {
		e.type_name = "TopLevelWidget";
		e.target = widget;
		Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_REMOVE );
	}
	n = LinkedList_GetTotal( &old_container->children_show );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &old_container->children_show, i );
		if( LinkedList_Get(&old_container->children_show) == widget ) {
			LinkedList_Delete( &old_container->children_show );
			break;
		}
	}

remove_done:

	widget->parent = container;
	LinkedList_AddData( &container->children, widget );
	LinkedList_AddData( &container->children_show, widget );
	/* 如果是添加至根部件内,则触发 WET_ADD 事件 */
	if( container == LCUIRootWidget ) {
		int ret;
		e.type_name = "TopLevelWidget";
		e.target = widget;
		ret = Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_ADD );
		DEBUG_MSG("post done, ret = %d\n", ret);
	}
	Widget_UpdateTaskStatus( widget );
	DEBUG_MSG("tip\n");
	return 0;
}
Пример #2
0
/** 设备处理线程 */
static void DeviceThread( void *arg )
{
	DeviceData *data_ptr;
	int n, i, timeout_count = 0;
	
	is_running = TRUE;
	while( is_running ) {
		LCUIMutex_Lock( &list_mutex );
		n = LinkedList_GetTotal( &dev_list );
		for( i=0; i<n; ++i ) {
			data_ptr = (DeviceData*)LinkedList_Get( &dev_list );
			if( !data_ptr || !data_ptr->proc ) {
				continue;
			}
			if( data_ptr->proc() ) {
				++timeout_count;
			}
		}
		LCUIMutex_Unlock( &list_mutex );
		if( timeout_count > 20 ) {
			LCUI_MSleep( 10 );
			timeout_count = 0;
		}
		LCUI_MSleep( 5 );
	}
	LCUIThread_Exit(NULL);
}
Пример #3
0
/** 直接将事件发送至事件处理器进行处理 */
int $(Send)( LCUI_EventBox box, const char *name, void *data )
{
	int i, n;
	LCUI_Event event;
	LCUI_RBTreeNode *node;
	LCUI_EventSlot *slot;
	LCUI_EventHandler *handler;
	
	if( !(node = RBTree_CustomSearch(&box->event_name, (const void*)name)) ) {
		return -1;
	}
	if( !(node = RBTree_Search(&box->event_slot, node->key)) ) {
		return -2;
	}
	slot = (LCUI_EventSlot*)node->data;
	event.id = slot->id;
	event.name = slot->name;
	event.data = data;
	event.destroy_data = NULL;
	n = LinkedList_GetTotal( &slot->handlers );
	LinkedList_Goto( &slot->handlers, 0 );
	for( i=0; i<n; ++i ) {
		handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers );
		handler->func( &event, handler->func_data );
		LinkedList_ToNext( &slot->handlers );
	}
	return 0;
}
Пример #4
0
/** 解除事件连接 */
int $(Unbind)( LCUI_EventBox box, int handler_id )
{
	int i, n;
	LCUI_RBTreeNode *node;
	LCUI_EventSlot *slot;
	LCUI_EventHandler *handler;

	if( !(node = RBTree_Search(&box->event_handler, handler_id)) ) {
		return -1;
	}
	if( !(node = RBTree_Search(&box->event_slot, (int)(node->data))) ) {
		return -2;
	}
	slot = (LCUI_EventSlot*)node->data;
	LinkedList_Goto( &slot->handlers, 0 );
	n = LinkedList_GetTotal( &slot->handlers );
	for( i=0; i<n; ++i ) {
		handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers );
		if( handler->id == handler_id ) {
			LinkedList_Delete( &slot->handlers );
			RBTree_Erase( &box->event_handler, handler_id );
			return 0;
		}
		LinkedList_ToNext( &slot->handlers );
	}
	return -3;
}
Пример #5
0
/** 从已触发的事件记录中删除一个事件信息 */
int $(DeleteEvent)( LCUI_EventBox box )
{
	LinkedList *elist;
	elist = &box->events[box->current == 1 ? 0:1];
	if( LinkedList_GetTotal( elist ) <= 0 ) {
		return -2;
	}
	LinkedList_Delete( elist );
	return 0;
}
Пример #6
0
/** 更新各种图形元素的显示 */
static void LCUIDisplay_Update(void)
{
	int i, n, j, m;
	LCUI_Rect *p_rect;
	SurfaceRecord *p_sr;
	LCUI_DirtyRectList rlist;
	LCUI_PaintContext paint;

	DirtyRectList_Init( &rlist );
	n = LinkedList_GetTotal( &display.surfaces );
	/* 遍历当前的 surface 记录列表 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( !p_sr->widget || !p_sr->surface
		 || !Surface_IsReady(p_sr->surface) ) {
			continue;
		}
		/* 更新表面 */
		Surface_Update( p_sr->surface );
		/* 收集无效区域记录 */
		Widget_ProcInvalidArea( p_sr->widget, &rlist );
		m = LinkedList_GetTotal( &rlist );
		DEBUG_MSG("proc invalid area, m = %d\n", m);
		LinkedList_Goto( &rlist, 0 );
		/* 在 surface 上逐个重绘无效区域 */
		for( j=0; j<m; ++j ) {
			p_rect = (LCUI_Rect*)LinkedList_Get( &rlist );
			paint = Surface_BeginPaint( p_sr->surface, p_rect );
			DEBUG_MSG( "[%s]: render rect: (%d,%d,%d,%d), %d\n", p_sr->widget->type, paint->rect.left, paint->rect.top, paint->rect.w, paint->rect.h, j );
			Widget_Render( p_sr->widget, paint );
			Surface_EndPaint( p_sr->surface, paint );
			LinkedList_Delete( &rlist );
		}
		if( m > 0 ) {
			Surface_Present( p_sr->surface );
		}
	}

	LinkedList_Destroy( &rlist );
}
Пример #7
0
/** 将指定标签的样式数据从队列中删除,只删除队列尾部第一个匹配的标签 */
static void StyleTagStack_Delete( LCUI_StyleTagStack *tags, LCUI_StyleTagID tag )
{
	int i, total;
	LCUI_StyleTagData *p; 
	 
	total = LinkedList_GetTotal( tags );
	DEBUG_MSG("delete start, total tag: %d\n", total);
	if(total <= 0) {
		return;
	}
	for(i=total-1; i>=0; --i) {
		LinkedList_Goto( tags, i );
		p = (LCUI_StyleTagData*)LinkedList_Get( tags );
		if( p->tag_id == tag ) {
			LinkedList_Delete( tags );
			break;
		}
	} 
	DEBUG_MSG("delete end, total tag: %d\n", LinkedList_GetTotal( tags ));
}
Пример #8
0
/** 获取当前的文本样式 */
LCUI_TextStyle* StyleTagStack_GetTextStyle( LCUI_StyleTagStack *tags )
{
	LCUI_StyleTagData *tag_data;
	LCUI_TextStyle *style_data;
	int i, total, equal = 0, flags[MAX_TAG_NUM];
	
	style_data = (LCUI_TextStyle*)malloc( sizeof(LCUI_TextStyle) );
	TextStyle_Init( style_data );
	memset( flags, 0, sizeof(flags) );
	
	total = LinkedList_GetTotal( tags );
	if(total <= 0) {
		free( style_data );
		return NULL;
	}
	/* 根据已经记录的各种样式,生成当前应有的文本样式 */
	for(equal=0,i=total-1; i>=0; --i) {
		LinkedList_Goto( tags, i );
		tag_data = (LCUI_StyleTagData*)LinkedList_Get( tags );
		DEBUG_MSG("tag id: %d\n", tag_data->tag_id);
		switch( tag_data->tag_id ) {
		    case TAG_ID_COLOR: 
			if( flags[0] != 0 ) {
				break;
			}
			style_data->_fore_color = TRUE;
			style_data->fore_color = tag_data->style.color;
			DEBUG_MSG("color: %d,%d,%d\n", data->fore_color.red,
			 data->fore_color.green, data->fore_color.blue);
			flags[0] = 1;
			++equal;
			break;
		case TAG_ID_SIZE:
			if( flags[1] != 0 ) {
				break;
			}
			style_data->_pixel_size = TRUE;
			style_data->pixel_size = tag_data->style.size.px;
			flags[1] = 1;
			++equal;
			break;
		    default: break;
		}
		if(equal == MAX_TAG_NUM) {
			break;
		}
	}
	if( equal == 0 ) {
		free( style_data );
		return NULL;
	}
	return style_data;
}
Пример #9
0
static void LCUIDisplay_CleanSurfaces( void )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, 0 );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		Surface_Delete( p_sr->surface );
		LinkedList_Delete( &display.surfaces );
	}
}
Пример #10
0
/* 销毁程序占用的资源 */
static void LCUIApp_Destroy(void)
{
	if( LinkedList_GetTotal(&MainApp.loop_list) > 0 ) {
		/* 等待其它线程上的主循环都完全退出 */
		LCUICond_Wait( &MainApp.loop_list_empty );
	}
	/* 开始清理 */
	LCUICond_Destroy( &MainApp.loop_list_empty );
	LCUICond_Destroy( &MainApp.loop_cond );
	LCUIMutex_Destroy( &MainApp.loop_mutex );
	LCUIMutex_Destroy( &MainApp.loop_changed );
	LCUIMutex_Destroy( &MainApp.task_run_mutex );
	LCUIMutex_Destroy( &MainApp.task_list_mutex );
	LinkedList_Destroy( &MainApp.loop_list );
}
Пример #11
0
/** 退出所有主循环 */
static void LCUIApp_QuitAllMainLoop(void)
{
	LCUI_MainLoop loop;
	int n = LinkedList_GetTotal( &MainApp.loop_list );
	LinkedList_Goto( &MainApp.loop_list, 0 );
	while( n-- ) {
		loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list );
		if( !loop ) {
			break;
		}
		loop->state = STATE_EXITED;
		LinkedList_ToNext( &MainApp.loop_list );
	}
	LCUICond_Broadcast( &MainApp.loop_cond );
}
Пример #12
0
/** 获取指定按键的状态数据 */
static key_state* KeyStateRecord_FindData( int key_code )
{
	int i, n;
	key_state* data_ptr;

	n = LinkedList_GetTotal( &key_state_record );
	for( i=0; i<n; ++i ) {
		data_ptr = (key_state*)LinkedList_Get( &key_state_record );
		if( data_ptr && data_ptr->key_code == key_code ) {
			return data_ptr;
		}
		LinkedList_ToNext( &key_state_record );
	}
	return NULL;
}
Пример #13
0
/** 从已触发的事件记录中取出(不会移除)一个事件信息 */
int $(GetEvent)( LCUI_EventBox box, LCUI_Event *ebuff )
{
	int n;
	LCUI_Event *event;
	LinkedList *elist;
	
	elist = &box->events[box->current == 1 ? 0:1];
	n = LinkedList_GetTotal( elist );
	if( n <= 0 ) {
		return -1;
	}
	LinkedList_Goto( elist, 0 );
	event = (LCUI_Event*)LinkedList_Get( elist );
	*ebuff = *event;
	return 0;
}
Пример #14
0
static LCUI_Surface LCUIDisplay_GetBindSurface( LCUI_Widget widget )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->widget == widget ) {
			return p_sr->surface;
		}
	}
	return NULL;
}
Пример #15
0
/** 在 surface 主动产生无效区域的时候 */
static void OnInvalidRect( LCUI_Surface surface, LCUI_Rect *rect )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->surface != surface ) {
			continue;
		}
		Widget_InvalidateArea( p_sr->widget, rect, SV_GRAPH_BOX );
		continue;
	}
}
Пример #16
0
/**
 * 获取部件中的无效区域
 * @param[in] widget	目标部件
 * @area[out] area	无效区域
 */
int Widget_GetInvalidArea( LCUI_Widget widget, LCUI_Rect *area )
{
	LCUI_Rect *p_rect;
	if( LinkedList_GetTotal(&widget->dirty_rects) <= 0 ) {
		return -1;
	}
	LinkedList_Goto( &widget->dirty_rects, 0 );
	DEBUG_MSG("list: %p, used node num: %d, current: %p, pos: %d\n",
		&widget->dirty_rects, widget->dirty_rects.used_node_num,
		widget->dirty_rects.current_node, widget->dirty_rects.current_node_pos);
	p_rect = (LCUI_Rect*)LinkedList_Get( &widget->dirty_rects );
	if( !p_rect ) {
		return -2;
	}
	DEBUG_MSG("p_rect: %d,%d,%d,%d\n", p_rect->x, p_rect->y, p_rect->w, p_rect->h);
	*area = *p_rect;
	return 0;
}
Пример #17
0
/** 解除 widget 与 sruface 的绑定 */
static void LCUIDisplay_UnbindSurface( LCUI_Widget widget )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->widget != widget ) {
			continue;
		}
		Surface_Delete( p_sr->surface  );
		LinkedList_Delete( &display.surfaces );
		break;
	}
}
Пример #18
0
/** 停用设备处理模块 */
void LCUIModule_Device_End(void)
{
	int n, i;
	DeviceData *data_ptr;
	
	LCUIMutex_Lock( &list_mutex );
	n = LinkedList_GetTotal( &dev_list );
	for( i=0; i<n; ++i ) {
		data_ptr = (DeviceData*)LinkedList_Get( &dev_list );
		if( !data_ptr ) {
			break;
		}
		if( data_ptr->exit ) {
			data_ptr->exit();
		}
		LinkedList_ToNext( &dev_list );
	}
	LCUIMutex_Unlock( &list_mutex );
}
Пример #19
0
/** 前置显示 */
int $(Front)( LCUI_Widget widget )
{
	int i, n, src_pos = -1, des_pos = -1;
	LCUI_Widget parent, child;

	parent = widget->parent ? widget->parent:LCUIRootWidget;
	n = LinkedList_GetTotal( &parent->children_show );
	/* 先在队列中找到自己,以及z-index值小于或等于它的第一个部件 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &parent->children_show, i );
		child = (LCUI_Widget)LinkedList_Get( &parent->children_show );
		if( child == widget ) {
			src_pos = i;
			continue;
		}
		if( des_pos >= 0 ) {
			if( src_pos >= 0 ) {
				break;
			}
			continue;
		}
		/* 如果该位置的图层的z-index值不大于自己 */
		if( child->style.z_index <= widget->style.z_index ) {
			/* 如果未找到自己的源位置 */
			if( src_pos == -1 ) {
				des_pos = i;
				continue;
			}
			/* 否则,退出循环,因为已经在前排了 */
			break;
		}
	}
	/* 没有找到就退出 */
	if( des_pos == -1 || src_pos == -1 ) {
		return -1;
	}
	/* 找到的话就移动位置 */
	LinkedList_Goto( &parent->children_show, src_pos );
	LinkedList_MoveTo( &parent->children_show, des_pos );
	// XXX
	return 0;
}
Пример #20
0
/** 派发当前待处理的事件至对应的处理器 */
int $(Dispatch)( LCUI_EventBox box )
{
	int i, n;
	LCUI_Event *e;
	LinkedList *elist;
	
	box->current = box->current ? 0:1;
	elist = &box->events[box->current ? 0:1];
	n = LinkedList_GetTotal( elist );
	LinkedList_Goto( elist, 0 );
	for( i=0; i<n; ++i ) {
		e = (LCUI_Event*)LinkedList_Get( elist );
		$(Send)( box, e->name, e->data );
		e->destroy_data ? e->destroy_data( e->data ):0;
		LinkedList_Goto( elist, 0 );
		LinkedList_Delete( elist );
	}
	box->current = box->current ? 0:1;
	return 0;
}
Пример #21
0
/** 更新数据 */
void TextLayer_Update( LCUI_TextLayer* layer, LinkedList *rect_list )
{
	if( layer->task.update_bitmap ) {
		TextLayer_InvalidateAllRowRect( layer );
		TextLayer_ReloadCharBitmap( layer );
		TextLayer_InvalidateAllRowRect( layer );
		layer->task.update_bitmap = FALSE;
		layer->task.redraw_all = TRUE;
	}

	if( layer->task.update_typeset ) {
		TextLayer_TextTypeset( layer, layer->task.typeset_start_row );
		layer->task.update_typeset = FALSE;
		layer->task.typeset_start_row = 0;
	}

	/* 如果坐标偏移量有变化,记录各个文本行区域 */
	if( layer->new_offset_x != layer->offset_x
	 || layer->new_offset_y != layer->offset_y ) {
		TextLayer_InvalidateAllRowRect( layer );
		layer->offset_x = layer->new_offset_x;
		layer->offset_y = layer->new_offset_y;
		TextLayer_InvalidateAllRowRect( layer );
		layer->task.redraw_all = TRUE;
	}
	
	if( rect_list ) {
		int n;
		void *data_ptr;

		n = LinkedList_GetTotal( &layer->dirty_rect );
		LinkedList_Goto( &layer->dirty_rect, 0 );
		/* 转移脏矩形记录,供利用 */
		while(n--) {
			data_ptr = LinkedList_Get( &layer->dirty_rect );
			LinkedList_AddDataCopy( rect_list, data_ptr );
			LinkedList_ToNext( &layer->dirty_rect );
		}
	 } 
}
Пример #22
0
/** 从程序任务队列中删除有指定回调函数的任务 */
int LCUI_RemoveTask( CallBackFunc task_func, LCUI_BOOL need_lock )
{
	int n;
	LCUI_Task *exist_task;

	if( need_lock ) {
		LCUIMutex_Lock( &MainApp.task_list_mutex );
	}
	n = LinkedList_GetTotal( &MainApp.task_list );
	for ( ; n>0; --n ) {
		exist_task = (LCUI_Task*)LinkedList_Get( &MainApp.task_list );
		if( exist_task && exist_task->func == task_func ) {
			LinkedList_Delete( &MainApp.task_list );
		} else {
			LinkedList_ToNext( &MainApp.task_list );
		}
	}
	if( need_lock ) {
		LCUIMutex_Unlock( &MainApp.task_list_mutex );
	}
	return n;
}
Пример #23
0
/** 派发当前待处理的事件至对应的处理器 */
int $(Dispatch)( LCUI_EventBox box )
{
	int i, n;
	LCUI_Event *e;
	LinkedList *elist;

	elist = &box->events[box->current];
	box->current = box->current ? 0:1;
	n = LinkedList_GetTotal( elist );
	LinkedList_Goto( elist, 0 );
	DEBUG_MSG("event total: %d\n", n);
	for( i=0; i<n; ++i ) {
		e = (LCUI_Event*)LinkedList_Get( elist );
		$(Send)( box, e->name, e->data );
		e->destroy_data ? e->destroy_data( e->data ):0;
		e->data = NULL;
		LinkedList_Goto( elist, 0 );
		LinkedList_Delete( elist );
	}
	DEBUG_MSG("quit\n");
	return 0;
}
Пример #24
0
/** 清除已记录的无效矩形 */
void TextLayer_ClearInvalidRect( LCUI_TextLayer *layer )
{
	int n;
	LCUI_Rect *rect_ptr;
	LCUI_Graph invalid_graph;

	if( !layer->is_using_buffer ) {
		DirtyRectList_Destroy( &layer->dirty_rect );
		DirtyRectList_Init( &layer->dirty_rect );
		return;
	}

	n = LinkedList_GetTotal( &layer->dirty_rect );
	LinkedList_Goto( &layer->dirty_rect, 0 );
	while(n--) {
		rect_ptr = (LCUI_Rect*)LinkedList_Get( &layer->dirty_rect );
		Graph_Quote( &invalid_graph, &layer->graph, rect_ptr );
		Graph_FillAlpha( &invalid_graph, 0 );
		LinkedList_ToNext( &layer->dirty_rect );
	}
	DirtyRectList_Destroy( &layer->dirty_rect );
	DirtyRectList_Init( &layer->dirty_rect );
}
Пример #25
0
static int LCUIDisplay_Seamless( void )
{
	int i, n;
	LCUI_Widget widget;
	DEBUG_MSG("display.mode: %d\n", display.mode);
	switch( display.mode ) {
	case LDM_SEAMLESS:
		return 0;
	case LDM_FULLSCREEN:
	case LDM_WINDOWED:
	default:
		LCUIDisplay_CleanSurfaces();
		break;
	}
	n = LinkedList_GetTotal( &LCUIRootWidget->children );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &LCUIRootWidget->children, i );
		widget = (LCUI_Widget)
		LinkedList_Get( &LCUIRootWidget->children );
		LCUIDisplay_BindSurface( widget );
	}
	display.mode = LDM_SEAMLESS;
	return 0;
}
Пример #26
0
/** 运行目标主循环 */
int LCUI_MainLoop_Run( LCUI_MainLoop loop )
{
	if( loop->state == STATE_RUNNING ) {
		_DEBUG_MSG("error: main-loop already running.");
		return -1;
	}
	DEBUG_MSG("loop: %p, enter\n", loop);
	loop->state = STATE_RUNNING;
	/* 将主循环记录插入至列表表头 */
	LinkedList_Goto( &MainApp.loop_list, 0 );
	LinkedList_Insert( &MainApp.loop_list, loop );
	MainApp.loop = loop;
	LCUIMutex_Lock( &MainApp.loop_changed );
	/* 广播,让其它线程交出主循环运行权 */
	LCUICond_Broadcast( &MainApp.loop_cond );
	/* 获取运行权 */
	LCUIMutex_Lock( &MainApp.loop_mutex );
	LCUIMutex_Unlock( &MainApp.loop_changed );
	loop->tid = LCUIThread_SelfID();
	while( loop->state != STATE_EXITED ) {
		if( LinkedList_GetTotal(&MainApp.task_list) <= 0 ) {
			DEBUG_MSG("loop: %p, sleeping...\n", loop);
			LCUICond_TimedWait( &MainApp.loop_cond, 1000 );
			DEBUG_MSG("loop: %p, wakeup\n", loop);
			/** 如果当前运行的主循环不是自己 */
			if( MainApp.loop != loop ) {
				loop->state = STATE_PAUSED;
				DEBUG_MSG("loop: %p, release control.\n", loop);
				LCUIMutex_Unlock( &MainApp.loop_mutex );
				/* 等待其它线程获得主循环运行权 */
				LCUIMutex_Lock( &MainApp.loop_changed );
				LCUIMutex_Unlock( &MainApp.loop_changed );
				DEBUG_MSG("loop: %p, waiting...\n", loop);
				/* 等待其它线程释放主循环运行权 */
				LCUIMutex_Lock( &MainApp.loop_mutex );
			}
			continue;
		}
		DEBUG_MSG("loop: %p, run task.\n", loop);
		LCUI_RunTask();
	}
	loop->state = STATE_EXITED;
	LinkedList_Goto( &MainApp.loop_list, 0 );
	LinkedList_Delete( &MainApp.loop_list );
	/* 获取处于列表表头的主循环 */
	loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list );
	if( loop ) {
		/* 改变当前运行的主循环 */
		MainApp.loop = loop;
		LCUICond_Broadcast( &MainApp.loop_cond );
	}
	/* 释放运行权 */
	LCUIMutex_Unlock( &MainApp.loop_mutex );
	/* 如果列表为空,一般意味着LCUI需要退出了 */
	if( LinkedList_GetTotal( &MainApp.loop_list ) <= 0 ) {
		/** 广播,通知相关线程开始进行清理操作 */
		LCUICond_Broadcast( &MainApp.loop_list_empty );
	}
	DEBUG_MSG("loop: %p, exit\n", loop);
	return 0;
}
Пример #27
0
/**
 * 渲染指定部件呈现的图形内容
 * @param[in] w		部件
 * @param[in] paint 	进行绘制时所需的上下文
 */
void Widget_Render( LCUI_Widget w, LCUI_PaintContext paint )
{
	int i, content_left, content_top;
	LCUI_Rect content_rect;
	LCUI_Graph content_graph, self_graph, layer_graph;
	LCUI_BOOL has_overlay, has_content_graph = FALSE,
		  has_self_graph = FALSE,has_layer_graph = FALSE,
		  is_cover_border = FALSE;

	Graph_Init( &layer_graph );
	Graph_Init( &self_graph );
	Graph_Init( &content_graph );
	/* 若部件本身是透明的 */
	if( w->style.opacity < 1.0 ) {
		has_self_graph = TRUE;
		has_content_graph = TRUE;
		has_layer_graph = TRUE;
	} else {
		/* 若使用了圆角边框,则判断当前脏矩形区域是否在圆角边框内
		...
		if( ... ) {
			has_content_graph = TRUE;
			is_cover_border = TRUE;
		}
		*/
	}
	/* 如果需要缓存自身的位图 */
	if( has_self_graph ) {
		LCUI_PaintContextRec_ self_paint;
		/* 有位图缓存则直接截取出来,否则绘制一次 */
		if( Graph_IsValid(&w->graph) ) {
			Graph_Quote( &self_graph, &w->graph, &paint->rect );
		} else {
			Graph_Create(
				&self_graph,
				paint->rect.width, paint->rect.height
			);
		}
		self_paint.canvas = self_graph;
		self_paint.rect = paint->rect;
		Widget_OnPaint( w, &self_paint );
	} else {
		/* 直接将部件绘制到目标位图缓存中 */
		if( Graph_IsValid(&w->graph) ) {
			Graph_Quote( &self_graph, &w->graph, &paint->rect );
			Graph_Mix( &paint->canvas, &self_graph, Pos(0,0) );
			Graph_WritePNG( "1,paint_canvas.png", &paint->canvas );
			Graph_WritePNG( "2,self_graph.png", &self_graph );
		} else {
			Widget_OnPaint( w, paint );
		}
	}
	/* 计算内容框相对于图层的坐标 */
	content_left = w->base.box.content.x - w->base.box.graph.x;
	content_top = w->base.box.content.y - w->base.box.graph.y;
	/* 获取内容框 */
	content_rect.x = content_left;
	content_rect.y = content_top;
	content_rect.width = w->base.box.content.width;
	content_rect.height = w->base.box.content.height;
	/* 获取内容框与脏矩形重叠的区域 */
	has_overlay = LCUIRect_GetOverlayRect(
		&content_rect, &paint->rect, &content_rect
	);
	/* 如果没有与内容框重叠,则跳过内容绘制 */
	if( !has_overlay ) {
		goto content_paint_done;
	}
	/* 将换重叠区域的坐标转换为相对于脏矩形的坐标 */
	content_rect.x -= paint->rect.x;
	content_rect.y -= paint->rect.y;
	/* 若需要部件内容区的位图缓存 */
	if( has_content_graph ) {
		content_graph.color_type = COLOR_TYPE_ARGB;
		Graph_Create( &content_graph, content_rect.w, content_rect.h );
	} else {
		/* 引用该区域的位图,作为内容框的位图 */
		Graph_Quote( &content_graph, &paint->canvas, &content_rect );
	}
	i = LinkedList_GetTotal( &w->children_show );
	/* 按照显示顺序,从底到顶,递归遍历子级部件 */
	while( i-- ) {
		LCUI_Widget child;
		LCUI_Rect child_rect;
		LCUI_PaintContextRec_ child_paint;

		child = (LCUI_Widget)LinkedList_Get( &w->children_show );
		if( !child->style.visible ) {
			continue;
		}
		/* 将子部件的区域,由相对于内容框转换为相对于当前脏矩形 */
		child_rect = child->base.box.graph;
		child_rect.x += (content_left - paint->rect.x);
		child_rect.y += (content_top - paint->rect.y);
		/* 获取于内容框重叠的区域,作为子部件的绘制区域 */
		has_overlay = LCUIRect_GetOverlayRect(
			&content_rect, &child_rect, &child_paint.rect
		);
		/* 区域无效则不绘制 */
		if( !has_overlay ) {
			continue;
		}
		/* 将子部件绘制区域转换相对于当前部件内容框 */
		child_rect.x = child_paint.rect.x - content_rect.x;
		child_rect.y = child_paint.rect.y - content_rect.y;
		child_rect.width = child_paint.rect.width;
		child_rect.height = child_paint.rect.height;
		/* 在内容位图中引用所需的区域,作为子部件的画布 */
		Graph_Quote( &child_paint.canvas, &content_graph, &child_rect );
		Widget_Render( child, &child_paint );
	}
	/* 如果与圆角边框重叠,则裁剪掉边框外的内容 */
	if( is_cover_border ) {
		/* content_graph ... */
	}

content_paint_done:

	/* 若需要绘制的是当前部件图层,则先混合部件自身位图和内容位图,得出当
	 * 前部件的图层,然后将该图层混合到输出的位图中
	 */
	if( has_layer_graph ) {
		Graph_Init( &layer_graph );
		layer_graph.color_type = COLOR_TYPE_ARGB;
		Graph_Copy( &layer_graph, &self_graph );
		Graph_Mix(
			&layer_graph, &content_graph,
			Pos(content_rect.x, content_rect.y)
		);
		layer_graph.opacity = w->style.opacity;
		Graph_Mix( &paint->canvas, &layer_graph, Pos(0,0) );
	}
	else if( has_content_graph ) {
		Graph_Mix(
			&paint->canvas, &content_graph,
			Pos(content_rect.x, content_rect.y)
		);
	}
	Graph_WritePNG( "layer_graph.png", &layer_graph );
	Graph_WritePNG( "self_graph.png", &self_graph );
	Graph_WritePNG( "content_graph.png", &content_graph );
	Graph_Free( &layer_graph );
	Graph_Free( &self_graph );
	Graph_Free( &content_graph );
}
Пример #28
0
static int _Widget_ProcInvalidArea( LCUI_Widget w, LCUI_BOOL is_root, int x, int y,
			LCUI_Rect *valid_box, LCUI_DirtyRectList *rlist )
{
	int i, n, count;
	LCUI_Widget child;
	LCUI_Rect rect, child_box, *r;

	count = n = LinkedList_GetTotal( &w->dirty_rects );
	/* 取出当前记录的脏矩形 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &w->dirty_rects, 0 );
		r = (LCUI_Rect*)LinkedList_Get( &w->dirty_rects );
		/* 若有独立位图缓存,则重绘脏矩形区域 */
		if( Graph_IsValid(&w->graph) ) {
			LCUI_PaintContextRec_ paint;
			paint.rect = *r;
			Graph_Quote( &paint.canvas, &w->graph, &paint.rect );
			Widget_OnPaint( w, &paint );
		}
		/* 转换为相对于父部件的坐标 */
		rect.x = r->x;
		rect.y = r->y;
		/* 如果当前是根部件,则不用加上自身坐标 */
		if( !is_root ) {
			rect.x += w->base.box.graph.x;
			rect.y += w->base.box.graph.y;
		}
		rect.w = r->w;
		rect.h = r->h;
		/* 取出与容器内有效区域相交的区域 */
		if( LCUIRect_GetOverlayRect(&rect, valid_box, &rect) ) {
			/* 转换相对于根级部件的坐标 */
			rect.x += x;
			rect.y += y;
			DirtyRectList_Add( rlist, &rect );
		}
		LinkedList_Delete( &w->dirty_rects );
	}
	/* 若子级部件没有脏矩形记录 */
	if( !w->has_dirty_child ) {
		return count;
	}
	/* 缩小有效区域到当前部件内容框内,若没有重叠区域,则不向子级部件递归 */
	if( !LCUIRect_GetOverlayRect(valid_box, &w->base.box.content, &child_box) ) {
		return count;
	}
	/* 转换有效区域的坐标,相对于当前部件的内容框 */
	child_box.x -= w->base.box.content.x;
	child_box.y -= w->base.box.content.y;
	n = LinkedList_GetTotal( &w->children );
	/* 向子级部件递归 */
	for( i=0; i<n; ++i ) {
		child = (LCUI_Widget)LinkedList_Get( &w->children );
		if( !child->style.visible ) {
			continue;
		}
		count += _Widget_ProcInvalidArea(
			child, FALSE, child->base.box.graph.x + x,
			child->base.box.graph.y + y, &child_box, rlist
		);
	}
	return count;
}