Пример #1
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int reduceOrder(const Cubic& cubic, Cubic& reduction, ReduceOrder_Quadratics allowQuadratics,
        ReduceOrder_Styles reduceStyle) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 4; ++index) {
        if (cubic[minX].x > cubic[index].x) {
            minX = index;
        }
        if (cubic[minY].y > cubic[index].y) {
            minY = index;
        }
        if (cubic[maxX].x < cubic[index].x) {
            maxX = index;
        }
        if (cubic[maxY].y < cubic[index].y) {
            maxY = index;
        }
    }
    for (index = 0; index < 4; ++index) {
        double cx = cubic[index].x;
        double cy = cubic[index].y;
        double denom = SkTMax(fabs(cx), SkTMax(fabs(cy),
                SkTMax(fabs(cubic[minX].x), fabs(cubic[minY].y))));
        if (denom == 0) {
            minXSet |= 1 << index;
            minYSet |= 1 << index;
            continue;
        }
        double inv = 1 / denom;
        if (approximately_equal_half(cx * inv, cubic[minX].x * inv)) {
            minXSet |= 1 << index;
        }
        if (approximately_equal_half(cy * inv, cubic[minY].y * inv)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0xF) { // test for vertical line
        if (minYSet == 0xF) { // return 1 if all four are coincident
            return coincident_line(cubic, reduction);
        }
        return vertical_line(cubic, reduceStyle, reduction);
    }
    if (minYSet == 0xF) { // test for horizontal line
        return horizontal_line(cubic, reduceStyle, reduction);
    }
    int result = check_linear(cubic, reduceStyle, minX, maxX, minY, maxY, reduction);
    if (result) {
        return result;
    }
    if (allowQuadratics == kReduceOrder_QuadraticsAllowed
            && (result = check_quadratic(cubic, reduction))) {
        return result;
    }
    memcpy(reduction, cubic, sizeof(Cubic));
    return 4;
}
Пример #2
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int SkReduceOrder::reduce(const SkDCubic& cubic, Quadratics allowQuadratics) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 4; ++index) {
        if (cubic[minX].fX > cubic[index].fX) {
            minX = index;
        }
        if (cubic[minY].fY > cubic[index].fY) {
            minY = index;
        }
        if (cubic[maxX].fX < cubic[index].fX) {
            maxX = index;
        }
        if (cubic[maxY].fY < cubic[index].fY) {
            maxY = index;
        }
    }
    for (index = 0; index < 4; ++index) {
        double cx = cubic[index].fX;
        double cy = cubic[index].fY;
        double denom = SkTMax(fabs(cx), SkTMax(fabs(cy),
                SkTMax(fabs(cubic[minX].fX), fabs(cubic[minY].fY))));
        if (denom == 0) {
            minXSet |= 1 << index;
            minYSet |= 1 << index;
            continue;
        }
        double inv = 1 / denom;
        if (approximately_equal_half(cx * inv, cubic[minX].fX * inv)) {
            minXSet |= 1 << index;
        }
        if (approximately_equal_half(cy * inv, cubic[minY].fY * inv)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0xF) {  // test for vertical line
        if (minYSet == 0xF) {  // return 1 if all four are coincident
            return coincident_line(cubic, fCubic);
        }
        return vertical_line(cubic, fCubic);
    }
    if (minYSet == 0xF) {  // test for horizontal line
        return horizontal_line(cubic, fCubic);
    }
    int result = check_linear(cubic, minX, maxX, minY, maxY, fCubic);
    if (result) {
        return result;
    }
    if (allowQuadratics == SkReduceOrder::kAllow_Quadratics
            && (result = check_quadratic(cubic, fCubic))) {
        return result;
    }
    fCubic = cubic;
    return 4;
}
Пример #3
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int reduceOrder(const Cubic& cubic, Cubic& reduction, ReduceOrder_Flags allowQuadratics) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 4; ++index) {
        if (cubic[minX].x > cubic[index].x) {
            minX = index;
        }
        if (cubic[minY].y > cubic[index].y) {
            minY = index;
        }
        if (cubic[maxX].x < cubic[index].x) {
            maxX = index;
        }
        if (cubic[maxY].y < cubic[index].y) {
            maxY = index;
        }
    }
    for (index = 0; index < 4; ++index) {
        if (approximately_equal(cubic[index].x, cubic[minX].x)) {
            minXSet |= 1 << index;
        }
        if (approximately_equal(cubic[index].y, cubic[minY].y)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0xF) { // test for vertical line
        if (minYSet == 0xF) { // return 1 if all four are coincident
            return coincident_line(cubic, reduction);
        }
        return vertical_line(cubic, reduction);
    }
    if (minYSet == 0xF) { // test for horizontal line
        return horizontal_line(cubic, reduction);
    }
    int result = check_linear(cubic, reduction, minX, maxX, minY, maxY);
    if (result) {
        return result;
    }
    if (allowQuadratics && (result = check_quadratic(cubic, reduction))) {
        return result;
    }
    memcpy(reduction, cubic, sizeof(Cubic));
    return 4;
}
Пример #4
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int SkReduceOrder::reduce(const SkDQuad& quad) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 3; ++index) {
        if (quad[minX].fX > quad[index].fX) {
            minX = index;
        }
        if (quad[minY].fY > quad[index].fY) {
            minY = index;
        }
        if (quad[maxX].fX < quad[index].fX) {
            maxX = index;
        }
        if (quad[maxY].fY < quad[index].fY) {
            maxY = index;
        }
    }
    for (index = 0; index < 3; ++index) {
        if (AlmostEqualUlps(quad[index].fX, quad[minX].fX)) {
            minXSet |= 1 << index;
        }
        if (AlmostEqualUlps(quad[index].fY, quad[minY].fY)) {
            minYSet |= 1 << index;
        }
    }
    if ((minXSet & 0x05) == 0x5 && (minYSet & 0x05) == 0x5) { // test for degenerate
        // this quad starts and ends at the same place, so never contributes
        // to the fill
        return coincident_line(quad, fQuad);
    }
    if (minXSet == 0x7) {  // test for vertical line
        return vertical_line(quad, fQuad);
    }
    if (minYSet == 0x7) {  // test for horizontal line
        return horizontal_line(quad, fQuad);
    }
    int result = check_linear(quad, minX, maxX, minY, maxY, fQuad);
    if (result) {
        return result;
    }
    fQuad = quad;
    return 3;
}
Пример #5
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int SkReduceOrder::reduce(const SkDQuad& quad) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 3; ++index) {
        if (quad[minX].fX > quad[index].fX) {
            minX = index;
        }
        if (quad[minY].fY > quad[index].fY) {
            minY = index;
        }
        if (quad[maxX].fX < quad[index].fX) {
            maxX = index;
        }
        if (quad[maxY].fY < quad[index].fY) {
            maxY = index;
        }
    }
    for (index = 0; index < 3; ++index) {
        if (AlmostEqualUlps(quad[index].fX, quad[minX].fX)) {
            minXSet |= 1 << index;
        }
        if (AlmostEqualUlps(quad[index].fY, quad[minY].fY)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0x7) {  // test for vertical line
        if (minYSet == 0x7) {  // return 1 if all four are coincident
            return coincident_line(quad, fQuad);
        }
        return vertical_line(quad, fQuad);
    }
    if (minYSet == 0xF) {  // test for horizontal line
        return horizontal_line(quad, fQuad);
    }
    int result = check_linear(quad, minX, maxX, minY, maxY, fQuad);
    if (result) {
        return result;
    }
    fQuad = quad;
    return 3;
}
Пример #6
0
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int reduceOrder(const Quadratic& quad, Quadratic& reduction) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 3; ++index) {
        if (quad[minX].x > quad[index].x) {
            minX = index;
        }
        if (quad[minY].y > quad[index].y) {
            minY = index;
        }
        if (quad[maxX].x < quad[index].x) {
            maxX = index;
        }
        if (quad[maxY].y < quad[index].y) {
            maxY = index;
        }
    }
    for (index = 0; index < 3; ++index) {
        if (AlmostEqualUlps(quad[index].x, quad[minX].x)) {
            minXSet |= 1 << index;
        }
        if (AlmostEqualUlps(quad[index].y, quad[minY].y)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0x7) { // test for vertical line
        if (minYSet == 0x7) { // return 1 if all four are coincident
            return coincident_line(quad, reduction);
        }
        return vertical_line(quad, reduction);
    }
    if (minYSet == 0xF) { // test for horizontal line
        return horizontal_line(quad, reduction);
    }
    int result = check_linear(quad, reduction, minX, maxX, minY, maxY);
    if (result) {
        return result;
    }
    memcpy(reduction, quad, sizeof(Quadratic));
    return 3;
}
Пример #7
0
int main(int argc, char *argv[]) {
    struct cell **drawing;
    int i;
    enum mode_t { lines = 0, boxes = 1, text = 2, erase = 3 } mode = lines;
    char *mode_name[] = { "Draw lines", "Draw boxes", "Write text", "Erase" };

    /* Click positions, used for line/box drawing. */
    MEVENT click[2];
    int nclick = 0;

    /* Text cursor location. */
    struct {
        int insert;
        int writing, startx, x, wsx, y;
    } textcursor = {0};
    
    initscr(); cbreak(); noecho();
    nonl();
    intrflush(stdscr, FALSE);
    keypad(stdscr, TRUE);

    mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED, NULL);

    drawing = cells_alloc(COLS, LINES);
    
    while ((i = getch()) != ERR) {
        if (i == KEY_MOUSE) {
            MEVENT ev;
            getmouse(&ev);
            move(ev.y, ev.x);
            refresh();

            if (mode == text) {
                /* Click in text mode; set start-of-writing. */
                textcursor.writing = 1;
                textcursor.startx = textcursor.x = textcursor.wsx = ev.x;
                textcursor.y = ev.y;
            } else if (ev.bstate == BUTTON3_CLICKED && mode == lines) {
                /* Button 3 click starts a new line. */
                nclick = 1;
                click[0] = ev;
            } else {
                /* Any random click in lines/boxes/erase mode. */
                click[nclick++] = ev;
                if (nclick == 2) {
                    nclick = 0;

                    if (mode == lines) {
                        /* We draw two types of corners:
                         *
                         *  .---X
                         *  |       button 1, button 1
                         *  X
                         *
                         *      X
                         *      |   button 1, button 2
                         *  X---'
                         * 
                         */
/*                        if (click[0].x == click[1].x)
                            vertical_line(drawing, click[0].x, click[0].y, click[1].y);
                        else if (click[0].y == click[1].y)
                            horizontal_line(drawing, click[0].x, click[1].x, click[0].y);
                        else */{
                            if (click[1].bstate & BUTTON1_CLICKED) {
                                if (click[0].x < click[1].x) {
                                    horizontal_line(drawing, click[0].x, click[1].x, click[1].y);
                                    vertical_line(drawing, click[0].x, click[0].y, click[1].y);
                                } else {
                                    horizontal_line(drawing, click[1].x, click[0].x, click[0].y);
                                    vertical_line(drawing, click[1].x, click[1].y, click[0].y);
                                }
                            } else if (click[1].bstate & BUTTON2_CLICKED) {
                                if (click[0].x > click[1].x) {
                                    horizontal_line(drawing, click[0].x, click[1].x, click[1].y);
                                    vertical_line(drawing, click[0].x, click[0].y, click[1].y);
                                } else {
                                    horizontal_line(drawing, click[1].x, click[0].x, click[0].y);
                                    vertical_line(drawing, click[1].x, click[1].y, click[0].y);
                                }
                            } else
                                beep();
                        }
                        display_drawing(drawing, COLS, LINES);

                        /* Allow drawing of `polylines'. */
                        click[0] = click[1];
                        nclick = 1;
                        move(click[0].y, click[0].x);
                        refresh();
                    } else if (mode == boxes) {
                        /* Boxes are drawn between the two corners specified. */
                        vertical_line(drawing, click[0].x, click[0].y, click[1].y);
                        vertical_line(drawing, click[1].x, click[0].y, click[1].y);
                        horizontal_line(drawing, click[0].x, click[1].x, click[0].y);
                        horizontal_line(drawing, click[0].x, click[1].x, click[1].y);
                        display_drawing(drawing, COLS, LINES);
                    } else if (mode == erase) {
                        /* Erase the contents of the box between the two
                         * corners. */
                        int i, i0, i1, j, j0, j1;
                        i0 = min(click[0].x, click[1].x);
                        i1 = max(click[0].x, click[1].x);
                        j0 = min(click[0].y, click[1].y);
                        j1 = max(click[0].y, click[1].y);
                        flash_box(i0, j0, i1, j1);
                        for (j = j0; j <= j1; ++j)
                            for (i = i0; i <= i1; ++i)
                                drawing[j][i].lines = drawing[j][i].c = 0;
                        display_drawing(drawing, COLS, LINES);
                    }
                }
            }
        } else if (mode != text || !textcursor.writing) {
            /* Key pressed in non-writing mode; maybe switch mode. */
            enum mode_t mm;
            mm = mode;
            switch (i) {
                case 'L':
                case 'l':
                    mode = lines;
                    break;

                case 'B':
                case 'b':
                    mode = boxes;
                    break;

                case 'T':
                case 't':
                    mode = text;
                    break;

                case 'E':
                case 'e':
                    mode = erase;
                    break;

                case ' ':
                    nclick = 0;
                    break;
            }
            if (mm != mode) {
                flash_modelabel(mode_name[mode], drawing);
                nclick = 0;
            }
        } else {
            /* Key pressed in writing mode; say something, probably. */
            switch (i) {
                case KEY_LEFT:
                    if (textcursor.x > textcursor.startx)
                        --textcursor.x;
                    else
                        beep();
                    break;

                case KEY_RIGHT:
                    if (textcursor.x < find_end_of_text_block(drawing, textcursor.x, textcursor.y, COLS) - 1)
                        ++textcursor.x;
                    else
                        beep();
                    break;

                case KEY_UP:
                    if (textcursor.y > 0)
                        --textcursor.y;
                    else
                        beep();
                    break;

                case KEY_DOWN:
                    if (textcursor.y < LINES - 1)
                        ++textcursor.y;
                    else
                        beep();
                    break;

                case KEY_HOME:
                    textcursor.x = textcursor.startx;
                    break;

                case KEY_END: {
                    /* Try to go to the end of the current bit of text. */
                    int I;
                    for (I = textcursor.x; I < COLS && drawing[textcursor.y][I].c; ++I);
                    --I;
                    textcursor.x = I;
                    break;
                }

                case KEY_IC:
                    textcursor.insert = !textcursor.insert;
                    flash_modelabel(textcursor.insert ? "Insert" : "Replace", drawing);
                    break;

                case KEY_BACKSPACE:
                    if (textcursor.x > textcursor.startx) {
                        --textcursor.x;
                        if (textcursor.insert) {
                            /* Move characters to left. */
                            int i0, i1;
                            i0 = find_end_of_text_block(drawing, textcursor.x, textcursor.y, COLS);
                            for (i1 = textcursor.x; i1 < i0; ++i1)
                                drawing[textcursor.y][i1].c = drawing[textcursor.y][i1 + 1].c;
                        } else
                            drawing[textcursor.y][textcursor.x].c = ' ';
                    }
                    break;

                case KEY_ENTER:
                    textcursor.writing = 0;
                    break;

                default:
                    if (isprint(i)) {
                        if (textcursor.insert) {
                            /* Move characters to right. */
                            int i0, i1;
                            i0 = find_end_of_text_block(drawing, textcursor.x, textcursor.y, COLS);
                            for (i1 = min(i0 + 1, COLS); i1 > textcursor.x; --i1)
                                drawing[textcursor.y][i1].c = drawing[textcursor.y][i1 - 1].c;
                        }
                        drawing[textcursor.y][textcursor.x].c = i;
                        if (i == ' ')
                            textcursor.wsx = textcursor.x;
                        ++textcursor.x;
                    }
                    break;
            }

            
            display_drawing(drawing, COLS, LINES);
            move(textcursor.y, textcursor.x);
            refresh();
        }
    }
}