示例#1
0
/***********************************************************************
 *           dibdrv_SelectPen
 */
HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen )
{
    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectPen );
    dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
    LOGPEN logpen;
    DWORD style;

    TRACE("(%p, %p)\n", dev, hpen);

    if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
    {
        /* must be an extended pen */
        EXTLOGPEN *elp;
        INT size = GetObjectW( hpen, 0, NULL );

        if (!size) return 0;

        elp = HeapAlloc( GetProcessHeap(), 0, size );

        GetObjectW( hpen, size, elp );
        /* FIXME: add support for user style pens */
        logpen.lopnStyle = elp->elpPenStyle;
        logpen.lopnWidth.x = elp->elpWidth;
        logpen.lopnWidth.y = 0;
        logpen.lopnColor = elp->elpColor;

        HeapFree( GetProcessHeap(), 0, elp );
    }

    if (hpen == GetStockObject( DC_PEN ))
        logpen.lopnColor = GetDCPenColor( dev->hdc );

    pdev->pen_colorref = logpen.lopnColor;
    pdev->pen_color = get_fg_color( pdev, pdev->pen_colorref );
    calc_and_xor_masks(GetROP2(dev->hdc), pdev->pen_color, &pdev->pen_and, &pdev->pen_xor);

    pdev->pen_pattern = dash_patterns[PS_SOLID];

    pdev->defer |= DEFER_PEN;

    style = logpen.lopnStyle & PS_STYLE_MASK;

    switch(style)
    {
    case PS_SOLID:
        if(logpen.lopnStyle & PS_GEOMETRIC) break;
        if(logpen.lopnWidth.x > 1) break;
        pdev->pen_line = solid_pen_line;
        pdev->defer &= ~DEFER_PEN;
        break;

    case PS_DASH:
    case PS_DOT:
    case PS_DASHDOT:
    case PS_DASHDOTDOT:
        if(logpen.lopnStyle & PS_GEOMETRIC) break;
        if(logpen.lopnWidth.x > 1) break;
        pdev->pen_line = dashed_pen_line;
        pdev->pen_pattern = dash_patterns[style];
        pdev->defer &= ~DEFER_PEN;
        break;

    case PS_NULL:
        pdev->pen_line = null_pen_line;
        pdev->defer &= ~DEFER_PEN;
        break;

    default:
        break;
    }

    return next->funcs->pSelectPen( next, hpen );
}
示例#2
0
/* ----------------------------------------------------------------------------
 * Draws the button. It' just a rectangle with a fancy border;
 * the latter is drawn one line at a time.
 */
void button::draw_self() {
    unsigned int w = x2 - x1;
    unsigned int h = y2 - y1;
    
    ALLEGRO_COLOR top_color, bottom_color;
    if(mouse_clicking && mouse_in) {
        top_color =    get_darker_bg_color();
        bottom_color = get_lighter_bg_color();
    } else {
        top_color =    get_lighter_bg_color();
        bottom_color = get_darker_bg_color();
    }
    
    al_draw_filled_rectangle(x1, y1, x2, y2, get_bg_color());
    //Top line, outermost.
    draw_line(this, DRAW_LINE_TOP,    0, 1, 0, top_color);
    //Top line, innermost.
    draw_line(this, DRAW_LINE_TOP,    0, 2, 1, top_color);
    //Left line, outermost.
    draw_line(this, DRAW_LINE_LEFT,   0, 1, 0, top_color);
    //Left line, innermost.
    draw_line(this, DRAW_LINE_LEFT,   0, 2, 1, top_color);
    //Bottom line, outermost.
    draw_line(this, DRAW_LINE_BOTTOM, 1, 0, 0, bottom_color);
    //Bottom line, innermost.
    draw_line(this, DRAW_LINE_BOTTOM, 2, 0, 1, bottom_color);
    //Right line, outermost.
    draw_line(this, DRAW_LINE_RIGHT,  1, 0, 0, bottom_color);
    //Right line, innermost.
    draw_line(this, DRAW_LINE_RIGHT,  2, 0, 1, bottom_color);
    
    //This is the center of the text, not top left. Also, relative coordinates.
    signed short final_text_y = 0;
    //Top left of the icon.
    signed short final_icon_y = 0;
    
    if(icon && text.size()) {
        //If there's an icon and text.
        unsigned short total_height =
            al_get_bitmap_height(icon) +
            al_get_font_line_height(style->text_font) + 2;
        //The icon goes to the top of the 2.
        final_icon_y = h / 2 - total_height / 2;
        //The text uses the same base y as the icon, except lowered, obviously.
        final_text_y =
            final_icon_y + al_get_bitmap_height(icon) +
            al_get_font_line_height(style->text_font) / 2 + 2;
            
    } else if(icon) {    //Icon, but no text.
        final_icon_y = h / 2 - al_get_bitmap_height(icon) / 2;
        
    } else if(!icon && text.size()) {    //Text, but no icon.
        final_text_y = h / 2;
    }
    
    if(icon) {
        al_draw_bitmap(
            icon,
            x1 + (w / 2 - al_get_bitmap_width(icon) / 2),
            y1 + final_icon_y,
            0);
    }
    
    if(text.size()) {
        draw_text_lines(
            style->text_font,
            get_fg_color(),
            x1 + (w / 2),
            y1 + final_text_y,
            ALLEGRO_ALIGN_CENTRE,
            true,
            text);
    }
}
示例#3
0
/***********************************************************************
 *           dibdrv_SelectBrush
 */
HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
{
    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectBrush );
    dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
    LOGBRUSH logbrush;

    TRACE("(%p, %p)\n", dev, hbrush);

    if (!GetObjectW( hbrush, sizeof(logbrush), &logbrush )) return 0;

    if (hbrush == GetStockObject( DC_BRUSH ))
        logbrush.lbColor = GetDCBrushColor( dev->hdc );

    pdev->brush_style = logbrush.lbStyle;

    pdev->defer |= DEFER_BRUSH;

    free_pattern_brush( pdev );

    switch(logbrush.lbStyle)
    {
    case BS_SOLID:
        pdev->brush_colorref = logbrush.lbColor;
        pdev->brush_color = get_fg_color( pdev, pdev->brush_colorref );
        calc_and_xor_masks(GetROP2(dev->hdc), pdev->brush_color, &pdev->brush_and, &pdev->brush_xor);
        pdev->brush_rects = solid_brush;
        pdev->defer &= ~DEFER_BRUSH;
        break;

    case BS_NULL:
        pdev->brush_rects = null_brush;
        pdev->defer &= ~DEFER_BRUSH;
        break;

    case BS_DIBPATTERN:
    {
        BITMAPINFOHEADER *bi = GlobalLock((HGLOBAL)logbrush.lbHatch);
        dib_info orig_dib;
        WORD usage = LOWORD(logbrush.lbColor);
        HPALETTE pal = (usage == DIB_PAL_COLORS) ? GetCurrentObject(dev->hdc, OBJ_PAL) : NULL;

        if(!bi) return NULL;
        if(init_dib_info_from_packed(&orig_dib, bi, usage, pal))
        {
            copy_dib_color_info(&pdev->brush_dib, &pdev->dib);
            if(convert_dib(&pdev->brush_dib, &orig_dib))
            {
                pdev->brush_rects = pattern_brush;
                pdev->defer &= ~DEFER_BRUSH;
            }
            free_dib_info(&orig_dib, FALSE);
        }
        GlobalUnlock((HGLOBAL)logbrush.lbHatch);
        break;
    }

    case BS_HATCHED:
    {
        if(logbrush.lbHatch > HS_DIAGCROSS) return 0;
        pdev->brush_hatch = logbrush.lbHatch;
        pdev->brush_colorref = logbrush.lbColor;
        pdev->brush_color = get_fg_color( pdev, pdev->brush_colorref );
        calc_and_xor_masks(GetROP2(dev->hdc), pdev->brush_color, &pdev->brush_and, &pdev->brush_xor);
        pdev->brush_rects = pattern_brush;
        pdev->defer &= ~DEFER_BRUSH;
        break;
    }

    default:
        break;
    }

    return next->funcs->pSelectBrush( next, hbrush );
}
示例#4
0
static gboolean
calf_vumeter_expose (GtkWidget *widget, GdkEventExpose *event)
{
    g_assert(CALF_IS_VUMETER(widget));

    CalfVUMeter *vu = CALF_VUMETER(widget);
    cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(widget->window));

    float r, g, b;

    int x = widget->allocation.x;
    int y = widget->allocation.y;
    int width = widget->allocation.width;
    int height = widget->allocation.height;
    int border_x = widget->style->xthickness;
    int border_y = widget->style->ythickness;
    int space_x = 1;
    int space_y = 1; // inner border around led bar
    int led = 2; // single LED size
    int led_m = 1; // margin between LED
    int led_s = led + led_m; // size of LED with margin
    int led_x = widget->style->xthickness;
    int led_y = widget->style->ythickness; // position of first LED
    int led_w = width - 2 * led_x + led_m; // width of LED bar w/o text calc (additional led margin, is removed later; used for filling the led bar completely w/o margin gap)
    int led_h = height - 2 * led_y; // height of LED bar w/o text calc
    int text_x = 0;
    int text_y = 0;
    int text_w = 0;
    int text_h = 0;

    // only valid if vumeter is enabled
    cairo_text_extents_t extents;

    if(vu->vumeter_position) {
        cairo_select_font_face(c, "cairo:sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
        cairo_set_font_size(c, 8);

        cairo_text_extents(c, "-88.88", &extents);
        text_w = extents.width;
        text_h = extents.height;
        switch(vu->vumeter_position) {
        case 1:
            text_x = width / 2 - text_w / 2;
            text_y = border_y + led_y - extents.y_bearing;
            led_y += text_h + led_y;
            led_h -= text_h + led_y;
            break;
        case 2:
            text_x = width - border_x - led_x - text_w;
            text_y = height / 2 - text_h / 2 - extents.y_bearing;
            led_w -= led_x + text_w;
            break;
        case 3:
            text_x = width / 2 - text_w / 2;
            text_y = height - border_y - led_y - text_h - extents.y_bearing;
            led_h -= led_y + text_h;
            break;
        case 4:
            text_x = border_x + led_x;
            text_y = height / 2 - text_h / 2 - extents.y_bearing;
            led_x += led_x + text_w;
            led_w -= led_x + text_w;
            break;
        }
    }

    led_w -= led_w % led_s + led_m; //round LED width to LED size and remove margin gap, width is filled with LED without margin gap now

    if( vu->cache_surface == NULL ) {
        // looks like its either first call or the widget has been resized.
        // create the cache_surface.
        vu->cache_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height );
        cairo_t *cache_cr = cairo_create( vu->cache_surface );

        float radius, bevel;
        get_bg_color(widget, NULL, &r, &g, &b);
        gtk_widget_style_get(widget, "border-radius", &radius, "bevel",  &bevel, NULL);
        create_rectangle(cache_cr, 0, 0, width, height, radius);
        cairo_set_source_rgb(cache_cr, r, g, b);
        cairo_fill(cache_cr);
        draw_bevel(cache_cr, 0, 0, width, height, radius, bevel);

        // border around LED
        cairo_rectangle(cache_cr, led_x, led_y, led_w, led_h);
        cairo_set_source_rgb (cache_cr, 0, 0, 0);
        cairo_fill(cache_cr);

        led_x += space_x;
        led_y += space_y;
        led_w -= 2 * space_x;
        led_h -= 2 * space_y;

        // LED bases
        cairo_set_line_width(cache_cr, 1);
        for (int x = led_x; x + led <= led_x + led_w; x += led_s)
        {
            float ts = (x - led_x) * 1.0 / led_w;
            float r = 0.f, g = 0.f, b = 0.f;
            switch(vu->mode)
            {
            case VU_STANDARD:
            default:
                if (ts < 0.75)
                    r = ts / 0.75, g = 0.5 + ts * 0.66, b = 1 - ts / 0.75;
                else
                    r = 1, g = 1 - (ts - 0.75) / 0.25, b = 0;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_STANDARD_CENTER:
                if (ts < 0.25)
                    // 0.0 -> 0.25
                    // green: 0.f -> 1.f
                    r = 1, g = (ts) / 0.25, b = 0;
                else if (ts > 0.75)
                    // 0.75 -> 1.0
                    // green: 1.f -> 0.f
                    r = 1, g = 1 - (ts - 0.75) / 0.25, b = 0;
                else if (ts > 0.5)
                    // 0.5 -> 0.75
                    // red: 0.f -> 1.f
                    // green: 0.5 -> 1.f
                    // blue: 1.f -> 0.f
                    r = (ts - 0.5) / 0.25, g = 0.5 + (ts - 0.5) * 2.f, b = 1 - (ts - 0.5) / 0.25;
                else
                    // 0.25 -> 0.5
                    // red: 1.f -> 0.f
                    // green: 1.f -> 0.5
                    // blue: 0.f -> 1.f
                    r = 1 - (ts - 0.25) / 0.25, g = 1.f - (ts * 2.f - .5f), b = (ts - 0.25) / 0.25;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME_REVERSE:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (!(vu->value < ts) || vu->value >= 1.0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME_CENTER:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            }
            GdkColor sc2 = { 0, (guint16)(65535 * r + 0.2), (guint16)(65535 * g), (guint16)(65535 * b) };
            GdkColor sc3 = { 0, (guint16)(65535 * r * 0.7), (guint16)(65535 * g * 0.7), (guint16)(65535 * b * 0.7) };
            gdk_cairo_set_source_color(cache_cr, &sc2);
            cairo_move_to(cache_cr, x + 0.5, led_y);
            cairo_line_to(cache_cr, x + 0.5, led_y + led_h);
            cairo_stroke(cache_cr);
            gdk_cairo_set_source_color(cache_cr, &sc3);
            cairo_move_to(cache_cr, x + 1.5, led_y + led_h);
            cairo_line_to(cache_cr, x + 1.5, led_y);
            cairo_stroke(cache_cr);
        }
        // create blinder pattern
        cairo_pattern_t *pat = cairo_pattern_create_linear (led_x, led_y, led_x, led_y + led_h);
        cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 0.25);
        cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.5, 0.5, 0.5, 0.0);
        cairo_pattern_add_color_stop_rgba (pat, 1, 0.0, 0.0, 0.0, 0.25);
        cairo_rectangle(cache_cr, led_x, led_y, led_w, led_h);
        cairo_set_source(cache_cr, pat);
        cairo_fill(cache_cr);

        // create overlay
        vu->cache_overlay = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
        cairo_t *over_cr = cairo_create(vu->cache_overlay);

        // copy surface to overlay
        cairo_set_source_surface(over_cr, vu->cache_surface, 0, 0);
        cairo_rectangle(over_cr, 0, 0, width, height);
        cairo_fill(over_cr);

        // create blinder pattern
        pat = cairo_pattern_create_linear (led_x, led_y, led_x, led_y + led_h);
        cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.2, 0.7);
        cairo_pattern_add_color_stop_rgba (pat, 0.4, 0.05, 0.05, 0.05, 0.7);
        cairo_pattern_add_color_stop_rgba (pat, 0.401, 0.05, 0.05, 0.05, 0.9);
        cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 0.75);

        // draw on top of overlay
        cairo_set_source(over_cr, pat);
        cairo_rectangle(over_cr, 0, 0, width, height);
        cairo_paint(over_cr);

        // clean up
        cairo_destroy(cache_cr);
        cairo_destroy(over_cr);
    } else {
        led_x += space_x;
        led_y += space_y;
        led_w -= 2 * space_x;
        led_h -= 2 * space_y;
    }
    led_x += x;
    led_y += y;
    text_x += x;
    text_y += y;
    // draw LED blinder
    cairo_set_source_surface( c, vu->cache_surface, x, y );
    cairo_paint( c );
    cairo_set_source_surface( c, vu->cache_overlay, x, y );

    // get microseconds
    timeval tv;
    gettimeofday(&tv, 0);
    long time = tv.tv_sec * 1000 * 1000 + tv.tv_usec;

    // limit to 1.f
    float value_orig = std::max(std::min(vu->value, 1.f), 0.f);
    float value = 0.f;

    // falloff?
    if(vu->vumeter_falloff > 0.f and vu->mode != VU_MONOCHROME_REVERSE) {
        // fall off a bit
        float s = ((float)(time - vu->last_falltime) / 1000000.0);
        float m = vu->last_falloff * s * vu->vumeter_falloff;
        vu->last_falloff -= m;
        // new max value?
        if(value_orig > vu->last_falloff) {
            vu->last_falloff = value_orig;
        }
        value = vu->last_falloff;
        vu->last_falltime = time;
        vu->falling = vu->last_falloff > 0.00000001;
    } else {
        // falloff disabled
        vu->last_falloff = 0.f;
        vu->last_falltime = 0.f;
        value = value_orig;
        vu->falling = false;
    }

    float draw = 0.f;
    float draw_last = 0.f;

    if(vu->vumeter_hold > 0.0) {
        // peak hold timer
        if(time - (long)(vu->vumeter_hold * 1000 * 1000) > vu->last_hold) {
            // time's up, reset
            vu->last_value = value;
            vu->last_hold = time;
            vu->holding = false;
            vu->disp_value = value_orig;
        }
        if( vu->mode == VU_MONOCHROME_REVERSE ) {
            if(value < vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            draw_last = log10(1 + vu->last_value * 9);

            // blinder left -> hold LED
            int hold_x = round((draw_last) * (led_w + led_m)); // add last led_m removed earlier
            hold_x -= hold_x % led_s + led_m;
            hold_x = std::max(0, hold_x);
            cairo_rectangle( c, led_x, led_y, hold_x, led_h);

            // blinder hold LED -> value
            int val_x = round((1 - draw) * (led_w + led_m)); // add last led_m removed earlier
            val_x -= val_x % led_s;
            int blind_x = std::min(hold_x + led_s, led_w);
            int blind_w = std::min(std::max(led_w - val_x - hold_x - led_s, 0), led_w);
            cairo_rectangle(c, led_x + blind_x, led_y, blind_w, led_h);
        } else  if( vu->mode == VU_STANDARD_CENTER ) {
            if(value > vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            int val_x = round((1 - draw) / 2.f * (led_w + led_m)); // add last led_m removed earlier
            cairo_rectangle(c, led_x, led_y, val_x, led_h);
            cairo_rectangle(c, led_x + led_w - val_x, led_y, val_x, led_h);

        } else {
            if(value > vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            draw_last = log10(1 + vu->last_value * 9);

            int hold_x = round((1 - draw_last) * (led_w + led_m)); // add last led_m removed earlier
            hold_x -= hold_x % led_s;
            int val_x = round(draw * (led_w + led_m)); // add last led_m removed earlier
            val_x -= val_x % led_s;
            int blind_w = led_w - hold_x - led_s - val_x;
            blind_w = std::min(std::max(blind_w, 0), led_w);
            cairo_rectangle(c, led_x + val_x, led_y, blind_w, led_h);
            cairo_rectangle( c, led_x + led_w - hold_x, led_y, hold_x, led_h);
        }
    } else {
        // darken normally
        float draw = log10(1 + value * 9);
        if( vu->mode == VU_MONOCHROME_REVERSE )
            cairo_rectangle( c, led_x, led_y, draw * led_w, led_h);
        else if( vu->mode == VU_STANDARD_CENTER ) {
            int val_x = round((1 - draw) / 2.f * (led_w + led_m)); // add last led_m removed earlier
            cairo_rectangle(c, led_x, led_y, val_x, led_h);
            cairo_rectangle(c, led_x + led_w - val_x, led_y, val_x, led_h);
        } else
            cairo_rectangle( c, led_x + draw * led_w, led_y, led_w * (1 - draw), led_h);
    }
    cairo_fill( c );

    if (vu->vumeter_position)
    {
        char str[32];
        if((vu->value > vu->disp_value and vu->mode != VU_MONOCHROME_REVERSE)
                or (vu->value < vu->disp_value and vu->mode == VU_MONOCHROME_REVERSE))
            vu->disp_value = vu->value;
        if (vu->disp_value < 1.0 / 32768.0)
            snprintf(str, sizeof(str), "-inf");
        else
            snprintf(str, sizeof(str), "%0.2f", dsp::amp2dB(vu->disp_value));
        // draw value as number
        cairo_text_extents(c, str, &extents);
        cairo_move_to(c, text_x + (text_w - extents.width) / 2.0, text_y);
        GtkStateType state;
        if(vu->disp_value > 1.f and vu->mode != VU_MONOCHROME_REVERSE)
            state = GTK_STATE_ACTIVE;
        else
            state = GTK_STATE_NORMAL;
        get_fg_color(widget, &state, &r, &g, &b);
        cairo_set_source_rgba (c, r, g, b, 1);
        cairo_show_text(c, str);
        cairo_fill(c);
    }
    cairo_destroy(c);
    //gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, widget, NULL, ox - 2, oy - 2, sx + 4, sy + 4);
    //printf("exposed %p %d+%d\n", widget->window, widget->allocation.x, widget->allocation.y);

    return TRUE;
}