/*********************************************************************** * 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 ); }
/* ---------------------------------------------------------------------------- * 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); } }
/*********************************************************************** * 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 ); }
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; }