Ejemplo n.º 1
0
void drawOccluded(Window* win, Rect* baserect, List* splitrect_list) {

	if (!splitrect_list)
		return;

	int split_count = 0;
	int total_count = 1;
	int working_total = 0;
	List* out_rects;
	Rect* working_rects = (Rect*)0;
	int i, j, k;
	Rect *new_rect, *rect, *split_rect, *out_rect;

	//If there's nothing occluding us, just render the bitmap and get out of here
	if (!splitrect_list->count) {

		drawBmpRect(win, baserect);
		return;
	}

	out_rects = List_new();

	if (!out_rects) {

		return;
	}

	rect = Rect_new(baserect->top, baserect->left, baserect->bottom, baserect->right);

	if (!rect) {

		List_delete(out_rects, Rect_deleter);
		return;
	}

	if (!List_add(out_rects, (void*)rect)) {

		free((void*)rect);
		List_delete(out_rects, Rect_deleter);
		return;
	}

	//For each splitting rect, split each rect in out_rects, delete the rectangle that was split, and add the resultant split rectangles
	List_for_each(splitrect_list, split_rect, Rect*) {

		List_for_each(out_rects, out_rect, Rect*) {

			if ((split_rect->left <= out_rect->right &&
				split_rect->right >= out_rect->left &&
				split_rect->top <= out_rect->bottom &&
				split_rect->bottom >= out_rect->top)) {

				List* clip_list = splitRect(out_rect, split_rect);

				if (!clip_list) {

					List_delete(out_rects, Rect_deleter);
					return;
				}

				//If nothing was returned, we actually want to clip a rectangle in its entirety
				if (!clip_list->count) {

					List_remove(out_rects, (void*)out_rect, Rect_deleter);

					//If we deleted the last output rectangle, we are completely 
					//occluded and can return early
					if (out_rects->count == 0) {

						List_delete(clip_list, Rect_deleter);
						List_delete(out_rects, Rect_deleter);
						return;
					}

					//Otherwise, go back to the top of the loop and test the next out_rect
					continue;
				}

				//Replace the rectangle that got split with the first result rectangle 
				rect = (Rect*)List_get_at(clip_list, 0);
				out_rect->top = rect->top;
				out_rect->left = rect->left;
				out_rect->bottom = rect->bottom;
				out_rect->right = rect->right;

				//Append the rest of the result rectangles to the output collection
				List_for_each_skip(clip_list, rect, Rect*, 1) {

					new_rect = Rect_new(rect->top, rect->left, rect->bottom, rect->right);

					if (!new_rect) {
						List_delete(clip_list, Rect_deleter);
						List_delete(out_rects, Rect_deleter);
						return;
					}

					if (!List_add(out_rects, (void*)new_rect)){

						free((void*)new_rect);
						List_delete(clip_list, Rect_deleter);
						List_delete(out_rects, Rect_deleter);
						return;
					}
				}

				//Free the space that was used for the split 
				List_delete(clip_list, Rect_deleter);

				//Restart the list 
				List_rewind(out_rects);
			}
		}
Ejemplo n.º 2
0
List* splitRect(Rect* rdest, Rect* rknife) {
	
	Rect baserect;
	List* outrect;
	Rect* new_rect;
	
	baserect.top = rdest->top;
	baserect.left = rdest->left;
	baserect.bottom = rdest->bottom;
	baserect.right = rdest->right;
	
/*
	cons_prints("Splitting rect (");
	cons_printDecimal(rdest->top);
	cons_prints(", ");
	cons_printDecimal(rdest->left);
	cons_prints(", ");
	cons_printDecimal(rdest->bottom);
	cons_prints(", ");
	cons_printDecimal(rdest->right);
	cons_prints(") with (");   
	cons_printDecimal(rknife->top);
	cons_prints(", ");
	cons_printDecimal(rknife->left);
	cons_prints(", ");
	cons_printDecimal(rknife->bottom);
	cons_prints(", ");
	cons_printDecimal(rknife->right);
	cons_prints(")\n");
*/
	
#ifdef RECT_TEST    
    //printf("splitting (%u, %u, %u, %u)", baserect.top, baserect.left, baserect.bottom, baserect.right);
    //printf("against (%u, %u, %u, %u)\n", rknife.top, rknife.left, rknife.bottom, rknife.right);
#endif //RECT_TEST
		
    //prints("Allocating space for ");
     //printDecimal(sizeof(rect)*rect_count);
    //prints(" rect bytes\n");
	outrect = List_new();
    if(!outrect) {
		
        prints("Couldn't allocate rect space\n");
		return outrect;
	}
	
//    cons_prints("Doing left edge split\n");
	//Split by left edge
	if(rknife->left >= baserect.left && rknife->left <= baserect.right) {
		
		new_rect = Rect_new(baserect.top, baserect.left, baserect.bottom, rknife->left - 1);
		
		if(!new_rect) {
			
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		if(!List_add(outrect, new_rect)) {
			
			free((void*)new_rect);
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		baserect.left = rknife->left;
	}

//    cons_prints("Doing top edge split\n");
	//Split by top edge
	if(rknife->top <= baserect.bottom && rknife->top >= baserect.top) {
		
		new_rect = Rect_new(baserect.top, baserect.left, rknife->top - 1, baserect.right);
		
		if(!new_rect) {
			
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		if(!List_add(outrect, new_rect)) {
			
			free((void*)new_rect);
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		baserect.top = rknife->top;
	}

//    cons_prints("Doing right edge split\n");
	//Split by right edge
	if(rknife->right >= baserect.left && rknife->right <= baserect.right) {
		
		new_rect = Rect_new(baserect.top, rknife->right + 1, baserect.bottom, baserect.right);
		
		if(!new_rect) {
			
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		if(!List_add(outrect, new_rect)) {
			
			free((void*)new_rect);
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		baserect.right = rknife->right;
	}

//    cons_prints("Doing bottom edge split\n");
	//Split by bottom edge
	if(rknife->bottom >= baserect.top && rknife->bottom <= baserect.bottom) {
		
		new_rect = Rect_new(rknife->bottom + 1, baserect.left, baserect.bottom, baserect.right);
		
		if(!new_rect) {
			
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		if(!List_add(outrect, new_rect)) {
			
			free((void*)new_rect);
			List_delete(outrect, Rect_deleter);
			return (List*)0;
		}
		
		baserect.bottom = rknife->bottom;
	}

/*    cons_prints("Result: \n");
	
	List_for_each(outrect, new_rect, Rect*) {
	
	    cons_prints("    ");
		cons_printDecimal(new_rect->top);
		cons_prints(", ");
		cons_printDecimal(new_rect->left);
		cons_prints(", ");
		cons_printDecimal(new_rect->bottom);
		cons_prints(", ");
		cons_printDecimal(new_rect->right);
		cons_prints("\n");
	}
	
	scans(10, inbuf);
*/
	return outrect;	
}
Ejemplo n.º 3
0
Archivo: rect.c Proyecto: codyd51/axle
List* Rect_split(Rect subject_rect, Rect cutting_rect) {
    //Allocate the list of result rectangles
    List* output_rects;
    if(!(output_rects = List_new()))
        return output_rects;

    Rect subject_copy = subject_rect;

    //We need a rectangle to hold new rectangles before
    //they get pushed into the output list
    Rect* temp_rect;

    //Begin splitting
    //1 -Split by left edge if that edge is between the subject's left and right edges 
    if(rect_min_x(cutting_rect) > rect_min_x(subject_copy) && rect_min_x(cutting_rect) <= rect_max_x(subject_copy)) {

        //Try to make a new rectangle spanning from the subject rectangle's left and stopping before 
        //the cutting rectangle's left
        if(!(temp_rect = Rect_new(rect_min_y(subject_copy), rect_min_x(subject_copy),
                                  rect_max_y(subject_copy), rect_min_x(cutting_rect) - 1))) {

            //If the object creation failed, we need to delete the list and exit failed
            kfree(output_rects);

            return (List*)0;
        }

        //Add the new rectangle to the output list
        List_add(output_rects, temp_rect);

        //Shrink the subject rectangle to exclude the split portion
		int diff = rect_min_x(cutting_rect) - rect_min_x(subject_copy);
		rect_min_x(subject_copy) += diff;
		subject_copy.size.width -= diff;
    }

    //2 -Split by top edge if that edge is between the subject's top and bottom edges 
    if(rect_min_y(cutting_rect) > rect_min_y(subject_copy) && rect_min_y(cutting_rect) <= rect_max_y(subject_copy)) {

        //Try to make a new rectangle spanning from the subject rectangle's top and stopping before 
        //the cutting rectangle's top
        if(!(temp_rect = Rect_new(rect_min_y(subject_copy), rect_min_x(subject_copy),
                                  rect_min_y(cutting_rect) - 1, rect_max_x(subject_copy)))) {

            //If the object creation failed, we need to delete the list and exit failed
            //This time, also delete any previously allocated rectangles
            for(; output_rects->count; temp_rect = List_remove_at(output_rects, 0))
                kfree(temp_rect);

            kfree(output_rects);

            return (List*)0;
        }

        //Add the new rectangle to the output list
        List_add(output_rects, temp_rect);

        //Shrink the subject rectangle to exclude the split portion
		int diff = rect_min_y(cutting_rect) - rect_min_y(subject_copy);
		rect_min_y(subject_copy) += diff;
		subject_copy.size.height -= diff;
    }

    //3 -Split by right edge if that edge is between the subject's left and right edges 
    if(rect_max_x(cutting_rect) >= rect_min_x(subject_copy) && rect_max_x(cutting_rect) < rect_max_x(subject_copy)) {

        //Try to make a new rectangle spanning from the subject rectangle's right and stopping before 
        //the cutting rectangle's right
        if(!(temp_rect = Rect_new(rect_min_y(subject_copy), rect_max_x(cutting_rect) + 1,
                                  rect_max_y(subject_copy), rect_max_x(subject_copy)))) {

            //Free on fail
            for(; output_rects->count; temp_rect = List_remove_at(output_rects, 0))
                kfree(temp_rect);

            kfree(output_rects);

            return (List*)0;
        }

        //Add the new rectangle to the output list
        List_add(output_rects, temp_rect);

        //Shrink the subject rectangle to exclude the split portion
		int shrink_amount = rect_max_x(subject_copy) - rect_max_x(cutting_rect);
		subject_copy.size.width -= shrink_amount;
    }

    //4 -Split by bottom edge if that edge is between the subject's top and bottom edges 
    if(rect_max_y(cutting_rect) >= rect_min_y(subject_copy) && rect_max_y(cutting_rect) < rect_max_y(subject_copy)) {

        //Try to make a new rectangle spanning from the subject rectangle's bottom and stopping before 
        //the cutting rectangle's bottom
        if(!(temp_rect = Rect_new(rect_max_y(cutting_rect) + 1, rect_min_x(subject_copy),
                                  rect_max_y(subject_copy), rect_max_x(subject_copy)))) {

            //Free on fail
            for(; output_rects->count; temp_rect = List_remove_at(output_rects, 0))
                kfree(temp_rect);

            kfree(output_rects);

            return (List*)0;
        }

        //Add the new rectangle to the output list
        List_add(output_rects, temp_rect);

        //Shrink the subject rectangle to exclude the split portion
		int shrink_amount = rect_max_y(subject_copy) - rect_max_y(cutting_rect);
		subject_copy.size.height -= shrink_amount;
    }
 
    //Finally, after all that, we can return the output rectangles 
    return output_rects;
}