/* Copyright (C) 2009 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "common.h" #include "red_drawable.h" #include "pixels_source_p.h" #include "utils.h" #include "threads.h" static const uint64_t lock_timout = 1000 * 1000 * 10; /*10ms*/ void RedDrawable::copy_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest) { PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque(); for (;;) { Lock lock(*dest_p_data->_mutex); Lock timed_lock(*src_p_data->_mutex, lock_timout); if (!timed_lock.is_locked()) { continue; } BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y, dest.right - dest.left, dest.bottom - dest.top, src_p_data->dc, src_x + src._origin.x, src_y + src._origin.y, SRCCOPY); return; } } void RedDrawable::blend_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest) { static BLENDFUNCTION blend_func = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA}; int width = dest.right - dest.left; int height = dest.bottom - dest.top; PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque(); for (;;) { Lock lock(*dest_p_data->_mutex); Lock timed_lock(*src_p_data->_mutex, lock_timout); if (!timed_lock.is_locked()) { continue; } AlphaBlend(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y, width, height, src_p_data->dc, src_x + src._origin.x, src_y + src._origin.y, width, height, blend_func); return; } } void RedDrawable::combine_pixels(const PixelsSource& src, int src_x, int src_y, const Rect& dest, CombineOP op) { DWORD rop; switch (op) { case OP_COPY: rop = SRCCOPY; break; case OP_AND: rop = SRCAND; break; case OP_XOR: rop = SRCINVERT; break; default: THROW("invalid op %d", op); } PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque(); for (;;) { Lock lock(*dest_p_data->_mutex); Lock timed_lock(*src_p_data->_mutex, lock_timout); if (!timed_lock.is_locked()) { continue; } BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y, dest.right - dest.left, dest.bottom - dest.top, src_p_data->dc, src_x + src._origin.x, src_y + src._origin.y, rop); return; } } void RedDrawable::erase_rect(const Rect& rect, rgb32_t color) { RECT r; r.left = rect.left + _origin.x; r.right = rect.right + _origin.x; r.top = rect.top + _origin.y; r.bottom = rect.bottom + _origin.y; PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); Lock lock(*dest_p_data->_mutex); FillRect(dest_p_data->dc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH)); } void RedDrawable::fill_rect(const Rect& rect, rgb32_t color) { RECT r; r.left = rect.left + _origin.x; r.right = rect.right + _origin.x; r.top = rect.top + _origin.y; r.bottom = rect.bottom + _origin.y; HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color), rgb32_get_green(color), rgb32_get_blue(color))); for (;;) { PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); Lock lock(*dest_p_data->_mutex); FillRect(dest_p_data->dc, &r, brush); break; } DeleteObject(brush); } void RedDrawable::frame_rect(const Rect& rect, rgb32_t color) { RECT r; r.left = rect.left + _origin.x; r.right = rect.right + _origin.x; r.top = rect.top + _origin.y; r.bottom = rect.bottom + _origin.y; HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color), rgb32_get_green(color), rgb32_get_blue(color))); for (;;) { PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque(); Lock lock(*dest_p_data->_mutex); FrameRect(dest_p_data->dc, &r, brush); break; } DeleteObject(brush); }