Exemple #1
0
//split all existing clip rectangles against the passed rect
void Context_subtract_clip_rect(Context* context, Rect* subtracted_rect) {

    //Check each item already in the list to see if it overlaps with
    //the new rectangle
    int i, j;
    Rect* cur_rect;
    List* split_rects;

    context->clipping_on = 1;

    for(i = 0; i < context->clip_rects->count; ) {

        cur_rect = (Rect*)List_get_at(context->clip_rects, i);

        //Standard rect intersect test (if no intersect, skip to next)
        //see here for an example of why this works:
        //http://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other#tab-top
        if(!(cur_rect->left <= subtracted_rect->right &&
		   cur_rect->right >= subtracted_rect->left &&
		   cur_rect->top <= subtracted_rect->bottom &&
		   cur_rect->bottom >= subtracted_rect->top)) {

            i++;
            continue;
        }

        //If this rectangle does intersect with the new rectangle, 
        //we need to split it
        List_remove_at(context->clip_rects, i); //Original will be replaced w/splits
        split_rects = Rect_split(cur_rect, subtracted_rect); //Do the split
        Object_delete((Object*)cur_rect); //We can throw this away now, we're done with it

        //Copy the split, non-overlapping result rectangles into the list 
        while(split_rects->count) {

            cur_rect = (Rect*)List_remove_at(split_rects, 0);
            List_add(context->clip_rects, (Object*)cur_rect);
        }

        //Free the empty split_rect list 
        Object_delete((Object*)split_rects);

        //Since we removed an item from the list, we need to start counting over again 
        //In this way, we'll only exit this loop once nothing in the list overlaps 
        i = 0;    
    }
}
Exemple #2
0
//Remove all of the clipping rects from the passed context object
void Context_clear_clip_rects(Context* context) {

    Rect* cur_rect;

    context->clipping_on = 0;

    while(context->clip_rects->count)
        Object_delete(List_remove_at(context->clip_rects, 0)); 
}
Exemple #3
0
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;
}