Esempio n. 1
0
void fill_span_from_shadow (hf_type *buffer_in, hf_type *buffer_out, gint xmax, gint ymax,
	hf_type v1, hf_type v2, hf_type filling_value,
	gint y, gint x1, gint x2, gint direction, gint select_mode) {
	
	gint i, mark1, mark2;
	glong value_to_test;
	hf_type output_value;
	gboolean span_end, filled, to_fill;

	filled = FALSE;

//	printf("FILLING y = %d, from x = %d to %d, direction = %d; value: %d\n",y, x1, x2, direction, filling_value);

	if (write_span(y,encode_span(direction,x1,x2))) { 
	
//		printf("FILLING in DOUBLE y = %d, from x = %d to %d, direction = %s; value: %d; mode: %s\n",y, x1, x2, 
//		((direction==0)?"FILL_UP":((direction==1)?"FILL_DOWN":"FILL_BOTH")), filling_value,
//		 ((select_mode==0)?"SELECT_REPLACE":((select_mode==1)?"SELECT_ADD":"SELECT_SUBTRACT")));
		return;
	}
//	Direction: FILL_UP (North), FILL_DOWN (South), FILL_BOTH

	if ( direction==FILL_BOTH ) {

		if ( (y-1) >= 0 )
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
				filling_value, y, x1, x2, FILL_UP, select_mode);
		if ( (y+1) <= ymax)
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
				filling_value, y, x1, x2, FILL_DOWN, select_mode);
		return;
	}

	// 1. Calculate direction (FILL_UP or FILL_DOWN)

	if ( direction==FILL_UP )
		y--;
	else
		y++;

	// Test the boundaries in case the function is called
	// at the first recursivity level with direction <> FILL_BOTH
	if ( (y<0) || (y>=ymax) )
		return;

	// 2. Process span

	// 2.1 Backup original span
	mark1 = x1;
	mark2 = x2;

	// 2.2 For x1, if the filling test is true, extend the span as needed

	output_value = *(buffer_out + VECTORIZE(x1,y,xmax));
	if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
		value_to_test  = *(buffer_in + VECTORIZE(x1,y,xmax));
	else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
		value_to_test = ((glong) *(buffer_in + VECTORIZE(x1,y,xmax))) + ((glong) output_value);

	if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) {
	
		// Filling test is true, we extend the span backwards, filling pixels
		for (mark1 = x1-1; mark1>=0; mark1--) {
				
			output_value = *(buffer_out + VECTORIZE(mark1,y,xmax));
			if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
				value_to_test  = *(buffer_in + VECTORIZE(mark1,y,xmax));
			else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
				value_to_test = ((glong) *(buffer_in + VECTORIZE(mark1,y,xmax))) + ((glong) output_value);
				
			// Stop when the filling test is false
			if (! test_fill (value_to_test, v1, v2, select_mode, output_value)){
				break;
			}
			else
				*(buffer_out + VECTORIZE(mark1,y,xmax)) = filling_value;
		}
		mark1++;
	}
	else {
	//	If the filling test is false, narrow the span as needed
		while ( mark1<=mark2 ) {
			mark1++;
			
			output_value = 	*(buffer_out + VECTORIZE(mark1,y,xmax));	
			if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
				value_to_test  = *(buffer_in + VECTORIZE(mark1,y,xmax));
			else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
				value_to_test = ((glong) *(buffer_in + VECTORIZE(mark1,y,xmax))) + ((glong) output_value);
			
			if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) 
				break;
		}
	}

	if (mark1>mark2)
		return;

	// Run from mark1 through mark2, filling pixels and calling recursively fill_from_shadow
	// for the current span, each time a discontinuity is encountered

	// At this point, the filling test is true for mark1
	// If mark1 < x1, then the mark1-x1 range is already filled, including x1

	span_end = FALSE;

	// 	We don't need to fill pixels before x1,
 	//	but we need mark1 to specify the shadow for the span on the next y
	i = MAX(x1,mark1);

	// We need to fill the shadow between x1 and mark1, if mark1<(x1-1)
	
	if (mark1<(x1-1))
		fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, mark1, x1, ((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
	
	to_fill = TRUE;
	while (i<=mark2) {
//		count++;
//		if (i==384)
//		printf("Count: %d; I: %d; Mark1: %d; Mark2: %d\n",count, i, mark1, mark2);
		if ( to_fill ) {
			*(buffer_out + VECTORIZE(i,y,xmax)) = filling_value;
			if (span_end) // begin a new span
				mark1 = i;
			span_end = FALSE;
			filled = TRUE;
		}
		else {
			// The first time the fill condition is false, a span has ended,
			// we must call "fill_from_shadow" for this span
			// After, we're looking for the beginning of a new span
			if ( (!span_end) && (i>x1)) {
				fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1, v2, filling_value, y, mark1, i-1, direction, select_mode);
				// If the new span boundary exceeds the old one by more than one pixel,
				// we start a filling movement on the other direction
				if ( (i-1) > x2 )
					fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, x2+1, i-1,
					((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
				span_end = TRUE;
				filled = TRUE;
			}
			mark1 = i+1;
			if (mark1>=x2)
				break;
		}
		i++;
		if (i==xmax)
			break;

		output_value = *(buffer_out + VECTORIZE(i,y,xmax));
		if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
			value_to_test  = *(buffer_in + VECTORIZE(i,y,xmax));
		else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
			value_to_test = ((glong) *(buffer_in + VECTORIZE(i,y,xmax))) + ((glong) output_value);
					
		if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) {	
			to_fill = TRUE;
			if (i>x2) {
				mark2++; // We extend the span as necessary
				if (mark2==xmax) {
					mark2--;
					break;
				}
			}
		}
		else
			to_fill = FALSE;
	}

	// "Flush" the last span if required

	if (filled && ((i>mark2) || (i==xmax-1))) {
		fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
			filling_value, y, mark1, mark2, direction, select_mode);

			// If the new span boundary exceeds the old one by more than one pixel,
			// we start a filling movement on the other direction
		if ( mark2 > x2 )
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, x2+1, mark2, ((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
	}
}
Esempio n. 2
0
/* 
 * escape_to_html
 */
VALUE escape_to_html(VALUE self, VALUE rawdata)
{
    VALUE result;

    if (rawdata == Qnil) {
        return rb_str_new2("");
    }

    if (TYPE(rawdata) != T_STRING) {
        rb_raise(rb_eTypeError, "invalid type for rawdata");
        return Qnil;
    }

    char *dataStr = StringValueCStr(rawdata);
    size_t dataStrLen = strlen(dataStr);
    char code[CODE_BUF_SIZE];
    bool inCode = false;
    size_t in_pos = 0, scratch_pos = 0, code_pos = 0;

    /*
     * Pre alloc scratch space that's at least as big as the input string, plus
     * some space for inserted span elements.
     *
     * Every string gets wrapped in a <span class="ansible_none"></span>
     *
     * Assume that every new escape code that's encountered will produce open
     * and close span tags that together consume 100 bytes (this allows for 3-5
     * codes per span, which is generous).  This should be good enough for
     * pretty much everything.  If it's not, we'll still notice when we run out
     * of space and try to realloc.
     */
    int spans = 1 + count_escapes(dataStr, dataStrLen);
    size_t scratchLen = dataStrLen + (spans * MAX_SPAN_SIZE);
    char *scratch = malloc(scratchLen);
    memset(scratch, 0, scratchLen);

    write_scratch((char *)SPAN_START(ansible_none),
            sizeof(SPAN_START(ansible_none))-1, &scratch, &scratch_pos,
            &scratchLen);


    for (; in_pos < dataStrLen; in_pos++) {
        char c = dataStr[in_pos];

        /*
         * Copy characters into scratch that arent within an escape code block.
         */
        if (c == '\033') {          // Enter escape code on ^[
            inCode = true;
            code_pos = 0;
        } else if (c == 'm') { 
            if (inCode) {           // Exit escape code on m
                inCode = false;
                code[code_pos] = 0;
                DBG("code: %s\n", code);
                write_span(code, &scratch, &scratch_pos, &scratchLen);
            } else {                // Copy an m that's not terminating an escape code
                write_scratch(&c, 1, &scratch, &scratch_pos, &scratchLen);
            }
        } else if (!inCode) {       // Copy everything else
            write_scratch(&c, 1, &scratch, &scratch_pos, &scratchLen);
        } else {                    // fill code buffer
           if (code_pos < sizeof(code)) {
              code[code_pos++] = c;
           }
        } 
    }

    write_scratch((char *)SPAN_CLOSE, sizeof(SPAN_CLOSE)-1, &scratch, &scratch_pos, &scratchLen);

    result = rb_enc_str_new(scratch, scratch_pos, rb_enc_find("BINARY"));
    free(scratch);

    return result;
}