diff options
Diffstat (limited to 'engines/sci/gfx/gfx_widgets.cpp')
-rw-r--r-- | engines/sci/gfx/gfx_widgets.cpp | 1775 |
1 files changed, 0 insertions, 1775 deletions
diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp deleted file mode 100644 index d260e66cfc..0000000000 --- a/engines/sci/gfx/gfx_widgets.cpp +++ /dev/null @@ -1,1775 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "sci/sci.h" // for INCLUDE_OLDGFX -#ifdef INCLUDE_OLDGFX - -#include "sci/gfx/gfx_gui.h" // for kWindowAutoRestore -#include "sci/gfx/gfx_widgets.h" -#include "sci/gfx/gfx_state_internal.h" - -namespace Sci { - -#undef GFXW_DEBUG_DIRTY // Enable to debug dirty rectangle propagation (writes to stderr) - -#ifdef GFXW_DEBUG_DIRTY -# define DDIRTY fprintf(stderr, "%s:%5d| ", __FILE__, __LINE__); fprintf -#else -# define DDIRTY if (0) fprintf -#endif - -Common::Point gfxw_point_zero(0, 0); - -#define MAX_SERIAL_NUMBER 0x7fffffff -static int widget_serial_number_counter = 0x10000; // Avoid confusion with IDs - -#ifdef GFXW_DEBUG_WIDGETS - -GfxWidget *debug_widgets[GFXW_DEBUG_WIDGETS]; -int debug_widget_pos = 0; - -static void _gfxw_debug_add_widget(GfxWidget *widget) { - if (debug_widget_pos == GFXW_DEBUG_WIDGETS) - error("WIDGET DEBUG: Allocated the maximum number of %d widgets- Aborting!\n", GFXW_DEBUG_WIDGETS); - debug_widgets[debug_widget_pos++] = widget; -} - -static void _gfxw_debug_remove_widget(GfxWidget *widget) { - int i; - int found = 0; - for (i = 0; i < debug_widget_pos; i++) { - if (debug_widgets[i] == widget) { - memmove(debug_widgets + i, debug_widgets + i + 1, (sizeof(GfxWidget *)) * (debug_widget_pos - i - 1)); - debug_widgets[debug_widget_pos--] = NULL; - found++; - } - } - - if (found > 1) { - error("While removing widget: Found it %d times!\n", found); - } - - if (found == 0) { - error("Attempted removal of unregistered widget!\n"); - } -} -#else // !GFXW_DEBUG_WIDGETS -#define _gfxw_debug_add_widget(a) -#define _gfxw_debug_remove_widget(a) -#endif - - -static void indent(int indentation) { - for (int i = 0; i < indentation; i++) - printf(" "); -} - -void GfxWidget::printIntern(int indentation) const { - unsigned int i; - char flags_list[] = "VOCDTMI"; - - indent(indentation); - - if (_magic == GFXW_MAGIC_VALID) { - if (_visual) - printf("v "); - else - printf("NoVis "); - } else if (_magic == GFXW_MAGIC_INVALID) - printf("INVALID "); - - printf("S%08x", _serial); - - if (_ID != GFXW_NO_ID) { - printf("#%x", _ID); - - if (_subID != GFXW_NO_ID) - printf(":%x ", _subID); - else - printf(" "); - } - - printf("[(%d,%d)(%dx%d)]", _bounds.x, _bounds.y, _bounds.width, _bounds.height); - - for (i = 0; i < strlen(flags_list); i++) - if (_flags & (1 << i)) - printf("%c", flags_list[i]); - - printf(" "); -} - -void GfxWidget::print(int indentation) const { - printIntern(indentation); - printf("<untyped #%d>", _type); -} - -GfxWidget::GfxWidget(gfxw_widget_type_t type_) { - _magic = GFXW_MAGIC_VALID; - - _serial = widget_serial_number_counter++; - widget_serial_number_counter &= MAX_SERIAL_NUMBER; - - _flags = GFXW_FLAG_DIRTY; - _type = type_; - _bounds = gfx_rect(0, 0, 0, 0); - _next = NULL; - _ID = GFXW_NO_ID; - _subID = GFXW_NO_ID; - _parent = NULL; - _visual = NULL; - _widgetPriority = -1; - - compare_to = NULL; - equals = NULL; - should_replace = NULL; - superarea_of = NULL; - - _gfxw_debug_add_widget(this); -} - -static int verify_widget(GfxWidget *widget) { - if (!widget) { - warning("Attempt to use NULL widget"); - return 1; - } else if (widget->_magic != GFXW_MAGIC_VALID) { - if (widget->_magic == GFXW_MAGIC_INVALID) { - warning("Attempt to use invalidated widget"); - } else { - warning("Attempt to use non-widget"); - } - return 1; - } - return 0; -} - -#define VERIFY_WIDGET(w) \ - if (verify_widget((GfxWidget *)(w))) { error("Error occured while validating widget"); } - -//********** Widgets ************* - -// Base class operations and common stuff - -// Assertion for drawing -#define DRAW_ASSERT(widget, exp_type) \ - if (!(widget)) { \ - printf("L%d: NULL widget", __LINE__); \ - return 1; \ - } \ - if ((widget)->_type != (exp_type)) { \ - printf("L%d: Error in widget: Expected type " # exp_type "(%d) but got %d\n", __LINE__, exp_type, (widget)->_type); \ - printf("Erroneous widget: "); \ - widget->print(4); \ - printf("\n"); \ - return 1; \ - } \ - if (!(widget->_flags & GFXW_FLAG_VISIBLE)) \ - return 0; \ - if (!(widget->_type == GFXW_VISUAL || widget->_visual)) { \ - printf("L%d: Error while drawing widget: Widget has no visual\n", __LINE__); \ - printf("Erroneous widget: "); \ - widget->print(1); \ - printf("\n"); \ - return 1; \ - } - -int GfxWidget::setVisual(GfxVisual *visual) { - _visual = visual; - - if (_parent) { - DDIRTY(stderr, "GfxWidget::setVisual: DOWNWARDS rel(%d,%d,%d,%d, 1)\n", GFX_PRINT_RECT(_bounds)); - _parent->add_dirty_rel(_parent, _bounds, 1); - } - - return 0; -} - -static int _gfxwop_basic_should_replace(GfxWidget *widget, GfxWidget *other) { - return 0; -} - -static void _gfxw_set_ops(GfxWidget *widget, - gfxw_bin_op *compare_to, gfxw_bin_op *equals, gfxw_bin_op *superarea_of) { - widget->compare_to = compare_to; - widget->equals = equals; - widget->superarea_of = superarea_of; - - widget->should_replace = _gfxwop_basic_should_replace; -} - -void gfxw_remove_widget_from_container(GfxContainer *container, GfxWidget *widget) { - GfxWidget **seekerp; - - if (!container) { - error("Attempt to remove widget from NULL container!\n"); - } - - seekerp = &(container->_contents); - - if (GFXW_IS_LIST(widget) && GFXW_IS_PORT(container)) { - GfxPort *port = (GfxPort *) container; - if (port->_decorations == (GfxList *) widget) { - port->_decorations = NULL; - return; - } - } - - while (*seekerp && *seekerp != widget) - seekerp = &((*seekerp)->_next); - - if (!*seekerp) { - printf("Internal error: Attempt to remove widget from container it was not contained in!\n"); - printf("Widget:"); - widget->print(1); - printf("Container:"); - widget->print(1); - error("gfxw_remove_widget_from_container() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - return; - } - - if (container->_nextpp == &(widget->_next)) - container->_nextpp = seekerp; - - *seekerp = widget->_next; // Remove it - widget->_parent = NULL; - widget->_next = NULL; -} - -GfxWidget::~GfxWidget() { - DDIRTY(stderr, "BASIC-FREE: SomeAddDirty\n"); // FIXME: What is this? - - if (_parent) { - if (GFXW_IS_CONTAINER(this)) - _parent->add_dirty_abs(_parent, _bounds, 1); - else - _parent->add_dirty_rel(_parent, _bounds, 1); - - gfxw_remove_widget_from_container(_parent, this); - } - - _magic = GFXW_MAGIC_INVALID; - _gfxw_debug_remove_widget(this); -} - -static int _gfxwop_basic_compare_to(GfxWidget *widget, GfxWidget *other) { - return 1; -} - -static int _gfxwop_basic_equals(GfxWidget *widget, GfxWidget *other) { - return 0; -} - -static int _gfxwop_basic_superarea_of(GfxWidget *widget, GfxWidget *other) { - return (widget == other); -} - -//*** Boxes *** - -static rect_t _move_rect(rect_t rect, Common::Point point) { - return gfx_rect(rect.x + point.x, rect.y + point.y, rect.width, rect.height); -} - -static void _split_rect(rect_t rect, Common::Point *p1, Common::Point *p2) { - p1->x = rect.x; - p1->y = rect.y; - p2->x = rect.x + rect.width; - p2->y = rect.y + rect.height; -} - -static Common::Point _move_point(rect_t rect, Common::Point point) { - return Common::Point(rect.x + point.x, rect.y + point.y); -} - -int GfxBox::draw(const Common::Point &pos) { - DRAW_ASSERT(this, GFXW_BOX); - gfxop_draw_box(_visual->_gfxState, _move_rect(_bounds, pos), _color1, _color2, _shadeType); - return 0; -} - -void GfxBox::print(int indentation) const { - printIntern(indentation); - printf("BOX"); -} - -static int _gfxwop_box_superarea_of(GfxWidget *widget, GfxWidget *other) { - GfxBox *box = (GfxBox *) widget; - - if (box->_color1.alpha) - return 0; - - if (box->_shadeType != GFX_BOX_SHADE_FLAT && box->_color2.alpha) - return 0; - - // Note: the check for box->_bounds and other->_bounds is NOT the same as contains() - // in Common::Rect (this one includes equality too) - if (!(box->_bounds.x <= other->_bounds.x && box->_bounds.y <= other->_bounds.y && - box->_bounds.x + box->_bounds.width >= other->_bounds.x + other->_bounds.width && - box->_bounds.y + box->_bounds.height >= other->_bounds.y + other->_bounds.height)) - return 0; - - return 1; -} - -static int _gfxwop_box_equals(GfxWidget *widget, GfxWidget *other) { - GfxBox *wbox = (GfxBox *)widget, *obox; - if (other->_type != GFXW_BOX) - return 0; - - obox = (GfxBox *) other; - - if (!toCommonRect(wbox->_bounds).equals(toCommonRect(obox->_bounds))) - return 0; - - if (wbox->_color1 != obox->_color1) - return 0; - - if (wbox->_shadeType != obox->_shadeType) - return 0; - - if (wbox->_shadeType != GFX_BOX_SHADE_FLAT - && wbox->_color2 == obox->_color2) - return 0; - - return 1; -} - -void _gfxw_set_ops_BOX(GfxWidget *widget) { - _gfxw_set_ops(widget, _gfxwop_basic_compare_to, _gfxwop_box_equals, _gfxwop_box_superarea_of); -} - -static int _gfxw_color_get_priority(gfx_color_t color) { - return (color.mask & GFX_MASK_PRIORITY) ? color.priority : -1; -} - -GfxBox *gfxw_new_box(GfxState *state, rect_t area, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) { - return new GfxBox(state, area, color1, color2, shade_type); -} - -GfxBox::GfxBox(GfxState *state, rect_t area, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) - : GfxWidget(GFXW_BOX) { - - _widgetPriority = _gfxw_color_get_priority(color1); - _bounds = area; - _color1 = color1; - _color2 = color2; - _shadeType = shade_type; - - _flags |= GFXW_FLAG_VISIBLE; - - if ((_color1.mask & GFX_MASK_VISUAL) && ((state && (state->driver->getMode()->palette)) || (!_color1.alpha && !_color2.alpha))) - _flags |= GFXW_FLAG_OPAQUE; - - _gfxw_set_ops_BOX(this); -} - -GfxPrimitive::GfxPrimitive(rect_t area, gfx_color_t color_, gfx_line_mode_t mode, - gfx_line_style_t style, gfxw_widget_type_t type_) - : GfxWidget(type_) { - - _widgetPriority = _gfxw_color_get_priority(color_); - _bounds = area; - _color = color_; - _lineMode = mode; - _lineStyle = style; - - _flags |= GFXW_FLAG_VISIBLE; -} - -//*** Rectangles *** - -struct GfxRect : public GfxPrimitive { - GfxRect(rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); - - virtual int draw(const Common::Point &pos); - virtual void print(int indentation) const; -}; - -static int _gfxwop_primitive_equals(GfxWidget *widget, GfxWidget *other) { - GfxPrimitive *wprim = (GfxPrimitive *) widget, *oprim; - if (widget->_type != other->_type) - return 0; - - oprim = (GfxPrimitive *) other; - - // Check if the two primitives are equal (note: the primitives aren't always rectangles, so - // the "width" and the "height" here could be negative) - if (wprim->_bounds.x != oprim->_bounds.x || wprim->_bounds.y != oprim->_bounds.y || - wprim->_bounds.width != oprim->_bounds.width || wprim->_bounds.height != oprim->_bounds.height) - return 0; - - if (wprim->_color != oprim->_color) - return 0; - - if (wprim->_lineMode != oprim->_lineMode) - return 0; - - if (wprim->_lineStyle != oprim->_lineStyle) - return 0; - - return 1; -} - -int GfxRect::draw(const Common::Point &pos) { - DRAW_ASSERT(this, GFXW_RECT); - - gfxop_draw_rectangle(_visual->_gfxState, gfx_rect(_bounds.x + pos.x, _bounds.y + pos.y, - _bounds.width - 1, _bounds.height - 1), _color, _lineMode, _lineStyle); - return 0; -} - -void GfxRect::print(int indentation) const { - printIntern(indentation); - printf("RECT"); -} - -void _gfxw_set_ops_RECT(GfxWidget *prim) { - _gfxw_set_ops(prim, - _gfxwop_basic_compare_to, _gfxwop_primitive_equals, _gfxwop_basic_superarea_of); -} - -GfxPrimitive *gfxw_new_rect(rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) { - return new GfxRect(rect, color, line_mode, line_style); -} - -GfxRect::GfxRect(rect_t rect, gfx_color_t color_, gfx_line_mode_t line_mode_, gfx_line_style_t line_style_) - : GfxPrimitive(rect, color_, line_mode_, line_style_, GFXW_RECT) { - - _bounds.width++; - _bounds.height++; // Since it is actually one pixel bigger in each direction - - _gfxw_set_ops_RECT(this); -} - -//*** Lines *** - -struct GfxLine : public GfxPrimitive { - GfxLine(Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); - - virtual int draw(const Common::Point &pos); - virtual void print(int indentation) const; -}; - -int GfxLine::draw(const Common::Point &pos) { - rect_t linepos = _bounds; - Common::Point p1, p2; - - linepos.width--; - linepos.height--; - - DRAW_ASSERT(this, GFXW_LINE); - - _split_rect(_move_rect(linepos, pos), &p1, &p2); - gfxop_draw_line(_visual->_gfxState, p1, p2, _color, _lineMode, _lineStyle); - return 0; -} - -void GfxLine::print(int indentation) const { - printIntern(indentation); -// printf("LINE"); -} - -void _gfxw_set_ops_LINE(GfxWidget *prim) { - _gfxw_set_ops(prim, - _gfxwop_basic_compare_to, _gfxwop_primitive_equals, _gfxwop_basic_superarea_of); -} - -GfxPrimitive *gfxw_new_line(Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) { - return new GfxLine(start, end, color, line_mode, line_style); -} - -GfxLine::GfxLine(Common::Point start, Common::Point end, gfx_color_t color_, gfx_line_mode_t line_mode_, gfx_line_style_t line_style_) - : GfxPrimitive(gfx_rect(start.x, start.y, end.x - start.x + 1, end.y - start.y + 1), color_, line_mode_, line_style_, GFXW_LINE) { - _gfxw_set_ops_LINE(this); -} - -//*** Views and static views *** - - -GfxView::GfxView(GfxState *state, Common::Point pos_, int view_, int loop_, int cel_, int palette_, int priority, int control, - gfx_alignment_t halign, gfx_alignment_t valign, int flags_) - : GfxWidget((flags_ & GFXW_VIEW_FLAG_STATIC) ? GFXW_STATIC_VIEW : GFXW_VIEW) { - - int width, height; - Common::Point offset; - - if (!state) { - error("Attempt to create view widget with NULL state"); - } - - gfxop_get_cel_parameters(state, view_, loop_, cel_, &width, &height, &offset); - - _pos = pos_; - _color.mask = ((priority < 0) ? 0 : GFX_MASK_PRIORITY) | ((control < 0) ? 0 : GFX_MASK_CONTROL); - _widgetPriority = priority; - _color.priority = priority; - _color.control = control; - _view = view_; - _loop = loop_; - _cel = cel_; - _palette = palette_; - - if (halign == ALIGN_CENTER) - _pos.x -= width >> 1; - else if (halign == ALIGN_RIGHT) - _pos.x -= width; - - if (valign == ALIGN_CENTER) - _pos.y -= height >> 1; - else if (valign == ALIGN_BOTTOM) - _pos.y -= height; - - _bounds = gfx_rect(_pos.x - offset.x, _pos.y - offset.y, width, height); - - _flags |= GFXW_FLAG_VISIBLE; -} - -int GfxView::draw(const Common::Point &pos) { - if (_type == GFXW_VIEW) { - DRAW_ASSERT(this, GFXW_VIEW); - gfxop_draw_cel(_visual->_gfxState, _view, _loop, _cel, - Common::Point(_pos.x + pos.x, _pos.y + pos.y), _color, _palette); - } else { - // FIXME: _gfxwop_static_view_draw checked for GFXW_VIEW here, instead of GFXW_STATIC_VIEW. - //DRAW_ASSERT(this, GFXW_VIEW); - DRAW_ASSERT(this, GFXW_STATIC_VIEW); - gfxop_draw_cel_static(_visual->_gfxState, _view, _loop, _cel, - _move_point(_bounds, pos), _color, _palette); - } - return 0; -} - -void GfxView::print(int indentation) const { - printIntern(indentation); - - if (_type == GFXW_STATIC_VIEW) - printf("STATICVIEW"); - else if (_type == GFXW_VIEW) - printf("VIEW"); - else - error("GfxView::print: Invalid type %d", _type); - - printf("(%d/%d/%d)@(%d,%d)[p:%d,c:%d]", _view, _loop, _cel, _pos.x, _pos.y, - (_color.mask & GFX_MASK_PRIORITY) ? _color.priority : -1, - (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1); -} - -void _gfxw_set_ops_VIEW(GfxWidget *view, char stat) { - _gfxw_set_ops(view, _gfxwop_basic_compare_to, _gfxwop_basic_equals, _gfxwop_basic_superarea_of); -} - -GfxView *gfxw_new_view(GfxState *state, Common::Point pos, int view_nr, int loop, int cel, int palette, int priority, int control, - gfx_alignment_t halign, gfx_alignment_t valign, int flags) { - GfxView *view; - - if (flags & GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET) { - int foo; - Common::Point offset; - gfxop_get_cel_parameters(state, view_nr, loop, cel, &foo, &foo, &offset); - pos.x += offset.x; - pos.y += offset.y; - } - - view = new GfxView(state, pos, view_nr, loop, cel, palette, priority, control, halign, valign, - (flags & GFXW_VIEW_FLAG_STATIC) ? GFXW_STATIC_VIEW : GFXW_VIEW); - - _gfxw_set_ops_VIEW(view, (char)(flags & GFXW_VIEW_FLAG_STATIC)); - - return view; -} - -//*** Dynamic Views *** - -int GfxDynView::draw(const Common::Point &pos) { - if (_type == GFXW_DYN_VIEW) { - DRAW_ASSERT(this, GFXW_DYN_VIEW); - - gfxop_draw_cel(_visual->_gfxState, _view, _loop, _cel, - _move_point(draw_bounds, pos), _color, _palette); - - /* - gfx_color_t red; - red.visual.r = 0xff; - red.visual.g = red.visual.b = 0; - red.mask = GFX_MASK_VISUAL; - gfxop_draw_rectangle(view->visual->_gfxState, - gfx_rect(view->_bounds.x + pos.x, view->_bounds.y + pos.y, view->_bounds.width - 1, view->_bounds.height - 1), red, 0, 0); - */ - } else { - DRAW_ASSERT(this, GFXW_PIC_VIEW); - - if (_isDrawn) - return 0; - - gfxop_set_clip_zone(_visual->_gfxState, _parent->zone); - gfxop_draw_cel_static_clipped(_visual->_gfxState, _view, _loop, - _cel, _move_point(draw_bounds, pos), _color, _palette); - - // Draw again on the back buffer - gfxop_draw_cel(_visual->_gfxState, _view, _loop, _cel, - _move_point(draw_bounds, pos), _color, _palette); - - - _isDrawn = true; // No more drawing needs to be done - } - - return 0; -} - - void GfxDynView::print(int indentation) const { - printIntern(indentation); - - if (_type == GFXW_DYN_VIEW) - printf("DYNVIEW"); - else if (_type == GFXW_PIC_VIEW) - printf("PICVIEW"); - else - error("GfxDynView::print: Invalid type %d", _type); - - printf(" SORT=%d z=%d seq=%d (%d/%d/%d)@(%d,%d)[p:%d,c:%d]; sig[%04x@%04X:%04X[%d]]", force_precedence, _z, - sequence, _view, _loop, _cel, _pos.x, _pos.y, - (_color.mask & GFX_MASK_PRIORITY) ? _color.priority : -1, - (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1, signal, signalp.obj.segment, signalp.obj.offset, signalp.varindex); -} - -static int _gfxwop_dyn_view_equals(GfxWidget *widget, GfxWidget *other) { - GfxDynView *wview = (GfxDynView *)widget, *oview; - if (!GFXW_IS_DYN_VIEW(other)) - return 0; - - oview = (GfxDynView *)other; - - if (wview->_pos.x != oview->_pos.x || wview->_pos.y != oview->_pos.y || wview->_z != oview->_z) - return 0; - - if (wview->_view != oview->_view || wview->_loop != oview->_loop || wview->_cel != oview->_cel) - return 0; - - if (wview->_color != oview->_color) - return 0; - - if (wview->_flags != oview->_flags) - return 0; - - return 1; -} - -static int _gfxwop_dyn_view_compare_to(GfxWidget *widget, GfxWidget *other) { - int retval; - GfxDynView *wview = (GfxDynView *) widget, *oview; - if (!GFXW_IS_DYN_VIEW(other)) - return 1; - - oview = (GfxDynView *) other; - - retval = wview->force_precedence - oview->force_precedence; - if (retval) - return retval; - - retval = wview->_pos.y - oview->_pos.y; - if (retval) - return retval; - - retval = (wview->_z - oview->_z); - if (retval) - return retval; - - return -(wview->sequence - oview->sequence); -} - -void _gfxw_set_ops_DYNVIEW(GfxWidget *widget) { - _gfxw_set_ops(widget, _gfxwop_dyn_view_compare_to, _gfxwop_dyn_view_equals, _gfxwop_basic_superarea_of); -} - -void _gfxw_set_ops_PICVIEW(GfxWidget *widget) { - _gfxw_set_ops_DYNVIEW(widget); -} - -GfxDynView *gfxw_new_dyn_view(GfxState *state, Common::Point pos, int z, int view, int loop, int cel, int palette, int priority, int control, - gfx_alignment_t halign, gfx_alignment_t valign, int sequence) { - - return new GfxDynView(state, pos, z, view, loop, cel, palette, priority, control, halign, valign, sequence); -} - -GfxDynView::GfxDynView(GfxState *state, Common::Point pos_, int z_, int view_, int loop_, int cel_, int palette_, int priority, int control, - gfx_alignment_t halign, gfx_alignment_t valign, int sequence_) - : GfxView(state, pos_, view_, loop_, cel_, palette_, priority, control, halign, valign, 0) { - int width, height; - int xalignmod, yalignmod; - Common::Point offset; - - _type = GFXW_DYN_VIEW; - - if (!state) - error("Attempt to create view widget with NULL state"); - - gfxop_get_cel_parameters(state, view_, loop_, cel_, &width, &height, &offset); - - _pos = pos_; - _color.mask = ((priority < 0) ? 0 : GFX_MASK_PRIORITY) | ((control < 0) ? 0 : GFX_MASK_CONTROL); - _widgetPriority = priority; - _color.priority = priority; - _color.control = control; - _view = view_; - _loop = loop_; - _cel = cel_; - _palette = palette_; - - _color.alpha = 0; - _color.visual = PaletteEntry(0,0,0); // FIXME: black! - - if (halign == ALIGN_CENTER) - xalignmod = width >> 1; - else if (halign == ALIGN_RIGHT) - xalignmod = width; - else - xalignmod = 0; - - if (valign == ALIGN_CENTER) - yalignmod = height >> 1; - else if (valign == ALIGN_BOTTOM) - yalignmod = height; - else - yalignmod = 0; - - draw_bounds = gfx_rect(_pos.x - xalignmod, _pos.y - yalignmod - z_, width, height); - _bounds = gfx_rect(_pos.x - offset.x - xalignmod, _pos.y - offset.y - yalignmod - z_, width, height); - - under_bitsp.obj = NULL_REG; - under_bits = 0; - signalp.obj = NULL_REG; - signal = 0; - _z = z_; - sequence = sequence_; - force_precedence = 0; - - _isDrawn = false; - - _flags |= GFXW_FLAG_VISIBLE; - - _gfxw_set_ops_DYNVIEW(this); -} - -//*** Text *** - -GfxText::~GfxText() { - if (_textHandle) { - GfxState *state = _visual ? _visual->_gfxState : NULL; - if (!state) { - error("Attempt to free text without supplying mode to free it from!\n"); - } else { - delete _textHandle; - _textHandle = NULL; - } - } -} - -int GfxText::draw(const Common::Point &pos) { - DRAW_ASSERT(this, GFXW_TEXT); - - if (_textHandle == 0) { - _textHandle = gfxop_new_text(_visual->_gfxState, _font, _text, _bounds.width, - halign, valign, _color1, _color2, _bgcolor, _textFlags); - } - - gfxop_draw_text(_visual->_gfxState, _textHandle, _move_rect(_bounds, pos)); - return 0; -} - -void GfxText::print(int indentation) const { - printIntern(indentation); - printf("TEXT:'%s'", _text.c_str()); -} - -static int _gfxwop_text_equals(GfxWidget *widget, GfxWidget *other) { - GfxText *wtext = (GfxText *)widget, *otext; - if (other->_type != GFXW_TEXT) - return 0; - - otext = (GfxText *)other; - - if ((wtext->_bounds.x != otext->_bounds.x) || (wtext->_bounds.y != otext->_bounds.y)) - return 0; - - if (wtext->halign != otext->halign || wtext->valign != otext->valign) - return 0; - - if (wtext->_textFlags != otext->_textFlags) - return 0; - - if (wtext->_font != otext->_font) - return 0; - - /* if (!(wtext->_color1 == otext->_color1 && wtext->_color2 == otext->_color2 - && wtext->_bgcolor == otext->_bgcolor)) - return 0; */ - - return 1; -} - -static int _gfxwop_text_should_replace(GfxWidget *widget, GfxWidget *other) { - GfxText *wtext = (GfxText *)widget, *otext; - - if (other->_type != GFXW_TEXT) - return 0; - - otext = (GfxText *)other; - - return wtext->_text != otext->_text; -} - -static int _gfxwop_text_compare_to(GfxWidget *widget, GfxWidget *other) { - return 1; -} - -void _gfxw_set_ops_TEXT(GfxWidget *widget) { - _gfxw_set_ops(widget, - _gfxwop_text_compare_to, _gfxwop_text_equals, - _gfxwop_basic_superarea_of); - widget->should_replace = _gfxwop_text_should_replace; -} - -GfxText *gfxw_new_text(GfxState *state, rect_t area, int font, const char *text, gfx_alignment_t halign, - gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2, gfx_color_t bgcolor, int text_flags) { - return new GfxText(state, area, font, text, halign, valign, color1, color2, bgcolor, text_flags); -} - -GfxText::GfxText(GfxState *state, rect_t area, int font, const char *text, gfx_alignment_t halign_, - gfx_alignment_t valign_, gfx_color_t color1_, gfx_color_t color2_, gfx_color_t bgcolor_, int text_flags_) - : GfxWidget(GFXW_TEXT) { - - _widgetPriority = _gfxw_color_get_priority(color1_); - _font = font; - _text = text; - halign = halign_; - valign = valign_; - _color1 = color1_; - _color2 = color2_; - _bgcolor = bgcolor_; - _textFlags = text_flags_; - _textHandle = NULL; - - gfxop_get_text_params(state, font, text, area.width, &width, &height, _textFlags, - &lines_nr, &lineheight, &lastline_width); - - /* FIXME: Window is too big - area.x += _calc_needmove(halign, area.width, width); - area.y += _calc_needmove(valign, area.height, height); - */ - - if (halign == ALIGN_LEFT) - area.width = width; - if (valign == ALIGN_TOP) - area.height = height; - - _bounds = area; - - _flags |= GFXW_FLAG_VISIBLE; - - _gfxw_set_ops_TEXT(this); -} - -void gfxw_text_info(GfxState *state, GfxText *text, int *lines, int *lineheight, int *offset) { - if (lines) - *lines = text->lines_nr; - if (lineheight) - *lineheight = text->lineheight; - if (offset) - *offset = text->lastline_width; -} - -//-- Container types -- - -static int _gfxwop_container_add_dirty_rel(GfxContainer *cont, rect_t rect, int propagate) { - DDIRTY(stderr, "->container_add_dirty_rel(%d,%d,%d,%d, %d)\n", GFX_PRINT_RECT(rect), propagate); - return cont->add_dirty_abs(cont, _move_rect(rect, Common::Point(cont->zone.x, cont->zone.y)), propagate); -} - -static void _gfxw_set_container_ops(GfxContainer *container, - gfxw_bin_op *compare_to, gfxw_bin_op *equals, - gfxw_bin_op *superarea_of, - gfxw_unary_container_op *free_tagged, gfxw_unary_container_op *free_contents, - gfxw_rect_op *add_dirty, gfxw_container_op *add) { - _gfxw_set_ops(container, compare_to, equals, superarea_of); - - container->free_tagged = free_tagged; - container->free_contents = free_contents; - container->add_dirty_abs = add_dirty; - container->add_dirty_rel = _gfxwop_container_add_dirty_rel; - container->add = add; -} - -static int _w_gfxwop_container_print_contents(const char *name, GfxWidget *widget, int indentation) { - GfxWidget *seeker = widget; - - indent(indentation); - - printf("--%s:\n", name); - - while (seeker) { - seeker->print(indentation + 1); - printf("\n"); - seeker = seeker->_next; - } - - return 0; -} - -void GfxContainer::print(int indentation) const { - printf(" viszone=((%d,%d),(%dx%d))\n", zone.x, zone.y, zone.width, zone.height); - - indent(indentation); - printf("--dirty:\n"); - - for (DirtyRectList::const_iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) { - indent(indentation + 1); - printf("dirty(%d,%d, (%dx%d))\n", dirty->x, dirty->y, dirty->width, dirty->height); - } - - _w_gfxwop_container_print_contents("contents", _contents, indentation); -} - - -GfxContainer::GfxContainer(rect_t area, gfxw_widget_type_t type_) - : GfxWidget(type_) { - _bounds = zone = area; - _contents = NULL; - _nextpp = &_contents; - - free_tagged = NULL; - free_contents = NULL; - add_dirty_abs = NULL; - add_dirty_rel = NULL; - add = NULL; - - _flags |= GFXW_FLAG_VISIBLE | GFXW_FLAG_CONTAINER; -} - -static int _gfxw_dirty_rect_overlaps_normal_rect(rect_t port_zone, rect_t bounds, rect_t dirty) { - bounds.x += port_zone.x; - bounds.y += port_zone.y; - - return gfx_rects_overlap(bounds, dirty); -} - -static int _gfxwop_container_draw_contents(GfxWidget *widget, GfxWidget *contents) { - GfxContainer *container = (GfxContainer *)widget; - GfxState *gfx_state = (widget->_visual) ? widget->_visual->_gfxState : ((GfxVisual *) widget)->_gfxState; - int draw_ports; - rect_t nullzone = {0, 0, 0, 0}; - - if (!contents) - return 0; - - DirtyRectList::iterator dirty = container->_dirtyRects.begin(); - while (dirty != container->_dirtyRects.end()) { - GfxWidget *seeker = contents; - - while (seeker) { - if (_gfxw_dirty_rect_overlaps_normal_rect(GFXW_IS_CONTAINER(seeker) ? nullzone : container->zone, - // Containers have absolute coordinates, reflect this. - seeker->_bounds, *dirty)) { - - if (GFXW_IS_CONTAINER(seeker)) {// Propagate dirty rectangles /upwards/ - DDIRTY(stderr, "container_draw_contents: propagate upwards (%d,%d,%d,%d ,0)\n", GFX_PRINT_RECT(*dirty)); - ((GfxContainer *)seeker)->add_dirty_abs((GfxContainer *)seeker, *dirty, 0); - } - - seeker->_flags |= GFXW_FLAG_DIRTY; - } - - seeker = seeker->_next; - } - - ++dirty; - } - - // The draw loop is executed twice: Once for normal data, and once for ports. - for (draw_ports = 0; draw_ports < 2; draw_ports++) { - - dirty = container->_dirtyRects.begin(); - while (dirty != container->_dirtyRects.end()) { - GfxWidget *seeker = contents; - // FIXME: Ugly hack to check whether this is the last dirty rect or not - DirtyRectList::iterator next = dirty; - ++next; - const bool isLastDirtyRect = (next == container->_dirtyRects.end()); - - while (seeker && (draw_ports || !GFXW_IS_PORT(seeker))) { - rect_t small_rect = *dirty; - bool draw_noncontainers = !_gfxop_clip(&small_rect, container->_bounds); - - if (seeker->_flags & GFXW_FLAG_DIRTY) { - - if (!GFXW_IS_CONTAINER(seeker) && draw_noncontainers) { - gfxop_set_clip_zone(gfx_state, small_rect); - } - /* Clip zone must be reset after each element, because we might - ** descend into containers. - ** Doing this is relatively cheap, though. */ - if (draw_noncontainers || GFXW_IS_CONTAINER(seeker)) - seeker->draw(Common::Point(container->zone.x, container->zone.y)); - - if (isLastDirtyRect) - seeker->_flags &= ~GFXW_FLAG_DIRTY; - } - - seeker = seeker->_next; - } - ++dirty; - } - } - // Remember that the dirty rects should be freed afterwards! - - return 0; -} - -GfxContainer::~GfxContainer() { - GfxWidget *seeker = _contents; - - while (seeker) { - GfxWidget *next = seeker->_next; - delete seeker; - seeker = next; - } - - _dirtyRects.clear(); -} - -void GfxContainer::tag() { - // FIXME: Should we also tag this object itself? - GfxWidget *seeker = _contents; - while (seeker) { - seeker->tag(); - seeker = seeker->_next; - } -} - -int GfxContainer::setVisual(GfxVisual *visual) { - _visual = visual; - if (_parent) { - if (!(GFXW_IS_LIST(this) && !_contents)) { - DDIRTY(stderr, "set_visual::DOWNWARDS abs(%d,%d,%d,%d, 1)\n", GFX_PRINT_RECT(_bounds)); - _parent->add_dirty_abs(_parent, _bounds, 1); - } - } - - GfxWidget *seeker = _contents; - while (seeker) { - seeker->setVisual(visual); - seeker = seeker->_next; - } - return 0; -} - -static int _gfxwop_container_free_tagged(GfxContainer *container) { - GfxWidget *seeker = container->_contents; - - while (seeker) { - GfxWidget *next = seeker->_next; - if (seeker->_flags & GFXW_FLAG_TAGGED) - delete seeker; - seeker = next; - } - - return 0; -} - -static int _gfxwop_container_free_contents(GfxContainer *container) { - GfxWidget *seeker = container->_contents; - - while (seeker) { - GfxWidget *next = seeker->_next; - delete seeker; - seeker = next; - } - return 0; -} - -static void _gfxw_dirtify_container(GfxContainer *container, GfxWidget *widget) { - if (GFXW_IS_CONTAINER(widget)) - container->add_dirty_abs(container, widget->_bounds, 1); - else - container->add_dirty_rel(container, widget->_bounds, 1); -} - -static int _parentize_widget(GfxContainer *container, GfxWidget *widget) { - if (widget->_parent) { - printf("_parentize_widget(): Attempt to give second parent node to widget!\nWidget:"); - widget->print(3); - printf("\nContainer:"); - container->print(3); - error("Error in _parentize_widget()"); - return 1; - } - - widget->_parent = container; - - if (GFXW_IS_VISUAL(container)) - widget->setVisual((GfxVisual *)container); - else if (container->_visual) - widget->setVisual(container->_visual); - - return 0; -} - -static int _gfxw_container_id_equals(GfxContainer *container, GfxWidget *widget) { - GfxWidget **seekerp = &(container->_contents); - - if (GFXW_IS_PORT(widget)) - return 0; - - if (widget->_ID == GFXW_NO_ID) - return 0; - - while (*seekerp && ((*seekerp)->_ID != widget->_ID || (*seekerp)->_subID != widget->_subID)) - seekerp = &((*seekerp)->_next); - - if (!*seekerp) - return 0; - - if ((*seekerp)->equals(*seekerp, widget) && !(*seekerp)->should_replace(*seekerp, widget)) { - delete widget; - (*seekerp)->_flags &= ~GFXW_FLAG_TAGGED; - return 1; - } else { - if (!(widget->_flags & GFXW_FLAG_MULTI_ID)) - delete *seekerp; - return 0; - } -} - -static int _gfxwop_container_add_dirty(GfxContainer *container, rect_t dirty, int propagate) { -#if 0 - // This code has been disabled because containers may contain sub-containers with - // bounds greater than their own. - if (_gfxop_clip(&dirty, container->_bounds)) - return 0; -#endif - - DDIRTY(stderr, "Effectively adding dirty %d,%d,%d,%d %d to ID %d\n", GFX_PRINT_RECT(dirty), propagate, container->_ID); - gfxdr_add_dirty(container->_dirtyRects, dirty); - return 0; -} - -static int _gfxwop_container_add(GfxContainer *container, GfxWidget *widget) { - if (_gfxw_container_id_equals(container, widget)) - return 0; - - if (_parentize_widget(container, widget)) - return 1; - - if (!(GFXW_IS_LIST(widget) && (!((GfxContainer *)widget)->_contents))) { // Don't dirtify self on empty lists - DDIRTY(stderr, "container_add: dirtify DOWNWARDS (%d,%d,%d,%d, 1)\n", GFX_PRINT_RECT(widget->_bounds)); - _gfxw_dirtify_container(container, widget); - } - - *(container->_nextpp) = widget; - container->_nextpp = &(widget->_next); - - return 0; -} - -//*** Lists and sorted lists *** - -int GfxList::draw(const Common::Point &pos) { - if (_type == GFXW_LIST) { - DRAW_ASSERT(this, GFXW_LIST); - - _gfxwop_container_draw_contents(this, _contents); - _flags &= ~GFXW_FLAG_DIRTY; - } else { - DRAW_ASSERT(this, GFXW_SORTED_LIST); - - _gfxwop_container_draw_contents(this, _contents); - } - _dirtyRects.clear(); - - return 0; -} - - -void GfxList::print(int indentation) const { - printIntern(indentation); - - if (_type == GFXW_LIST) - printf("LIST"); - else if (_type == GFXW_SORTED_LIST) - printf("SORTED_LIST"); - else - error("GfxList::print: Invalid type %d", _type); - - GfxContainer::print(indentation); -} - -static int _gfxwop_list_equals(GfxWidget *widget, GfxWidget *other) { - // Requires identical order of list elements. - GfxList *wlist, *olist; - - if (widget->_type != other->_type) - return 0; - - if (!GFXW_IS_LIST(widget)) { - warning("[GFX] _gfxwop_list_equals(): Method called on non-list"); - widget->print(0); - printf("\n"); - return 0; - } - - wlist = (GfxList *)widget; - olist = (GfxList *)other; - - if (memcmp(&(wlist->_bounds), &(olist->_bounds), sizeof(rect_t))) - return 0; - - widget = wlist->_contents; - other = olist->_contents; - - while (widget && other) { - if (!(widget->equals(widget, other) && !widget->should_replace(widget, other))) - return 0; - - widget = widget->_next; - other = other->_next; - } - - return (!widget && !other); // True if both are finished now -} - -static int _gfxwop_list_add_dirty(GfxContainer *container, rect_t dirty, int propagate) { - // Lists add dirty boxes to both themselves and their parenting port/visual - - container->_flags |= GFXW_FLAG_DIRTY; - - DDIRTY(stderr, "list_add_dirty %d,%d,%d,%d %d\n", GFX_PRINT_RECT(dirty), propagate); - if (propagate) - if (container->_parent) { - DDIRTY(stderr, "->PROPAGATING\n"); - container->_parent->add_dirty_abs(container->_parent, dirty, 1); - } - - return _gfxwop_container_add_dirty(container, dirty, propagate); -} - -int _gfxwop_ordered_add(GfxContainer *container, GfxWidget *widget, int compare_all) { - // O(n) - GfxWidget **seekerp = &(container->_contents); - - if (widget->_next) { - printf("_gfxwop_ordered_add(): Attempt to add widget to two lists!\nWidget:"); - widget->print(3); - printf("\nList:"); - container->print(3); - error("Error in _gfxwop_ordered_add()"); - } - - if (_gfxw_container_id_equals(container, widget)) - return 0; - - while (*seekerp && (compare_all || (widget->compare_to(widget, *seekerp) >= 0))) { - - if (widget->equals(widget, *seekerp)) { - if (compare_all) { - if ((*seekerp)->_visual) - delete *seekerp; // If it's a fresh widget - else - gfxw_annihilate(*seekerp); - - return _gfxwop_ordered_add(container, widget, compare_all); // We might have destroyed the container's contents - } else { - widget->_next = (*seekerp)->_next; - delete *seekerp; - *seekerp = widget; - return (_parentize_widget(container, widget)); - } - } - - if (*seekerp) - seekerp = &((*seekerp)->_next); - } - - widget->_next = *seekerp; - *seekerp = widget; - - return _parentize_widget(container, widget); -} - -static int _gfxwop_sorted_list_add(GfxContainer *container, GfxWidget *widget) { - // O(n) - return _gfxwop_ordered_add(container, widget, 0); -} - -void _gfxw_set_ops_LIST(GfxContainer *list, char sorted) { - _gfxw_set_container_ops((GfxContainer *)list, - _gfxwop_basic_compare_to, sorted ? _gfxwop_basic_equals : _gfxwop_list_equals, - _gfxwop_basic_superarea_of, - _gfxwop_container_free_tagged, _gfxwop_container_free_contents, - _gfxwop_list_add_dirty, sorted ? _gfxwop_sorted_list_add : _gfxwop_container_add); -} - -GfxList *gfxw_new_list(rect_t area, int sorted) { - return new GfxList(area, sorted); -} - -GfxList::GfxList(rect_t area, bool sorted) - : GfxContainer(area, sorted ? GFXW_SORTED_LIST : GFXW_LIST) { - - _gfxw_set_ops_LIST(this, sorted); -} - - - -//*** Visuals *** - -int GfxVisual::draw(const Common::Point &pos) { - DRAW_ASSERT(this, GFXW_VISUAL); - - for (DirtyRectList::iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) { - gfxop_clear_box(_gfxState, *dirty); - } - - _gfxwop_container_draw_contents(this, _contents); - - _dirtyRects.clear(); - _flags &= ~GFXW_FLAG_DIRTY; - - return 0; -} - -void GfxVisual::print(int indentation) const { - printIntern(indentation); - printf("VISUAL; ports={"); - for (uint i = 0; i < _portRefs.size(); i++) { - if (_portRefs[i]) { - if (i != 0) - printf(","); - printf("%d", i); - } - } - printf("}\n"); - - GfxContainer::print(indentation); -} - -int GfxVisual::setVisual(GfxVisual *visual) { - if (this != visual) { - warning("Attempt to set a visual's parent visual to something else"); - } else { - warning("Attempt to set a visual's parent visual to itself"); - } - - return 1; -} - -void _gfxw_set_ops_VISUAL(GfxContainer *visual) { - _gfxw_set_container_ops((GfxContainer *)visual, - _gfxwop_basic_compare_to, - _gfxwop_basic_equals, _gfxwop_basic_superarea_of, - _gfxwop_container_free_tagged, _gfxwop_container_free_contents, - _gfxwop_container_add_dirty, _gfxwop_container_add); -} - -GfxVisual::GfxVisual(GfxState *state, int font) - : GfxContainer(gfx_rect(0, 0, 320, 200), GFXW_VISUAL) { - - _font = font; - _gfxState = state; - - _gfxw_set_ops_VISUAL(this); -} - -GfxVisual::~GfxVisual() { - // HACK: We must dispose all content *here* already, because our child widgets - // still may have references to this object, and will try to invoke methods - // of this object which try to access the already cleared _portRefs array - // when they are destroyed. - GfxWidget *seeker = _contents; - - while (seeker) { - GfxWidget *next = seeker->_next; - delete seeker; - seeker = next; - } - _contents = 0; -} - -static int _visual_find_free_ID(GfxVisual *visual) { - uint id = 0; - - while (id < visual->_portRefs.size() && visual->_portRefs[id]) - id++; - - if (id == visual->_portRefs.size()) { // Out of ports? - visual->_portRefs.push_back(0); - } - - return id; -} - -//*** Ports *** - -int GfxPort::draw(const Common::Point &pos) { - DRAW_ASSERT(this, GFXW_PORT); - - if (_decorations) { - DDIRTY(stderr, "Getting/applying deco dirty (multi)\n"); - - DDIRTY(stderr, "Adding multiple dirty to #%d\n", _decorations->_ID); - for (DirtyRectList::iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) { - gfxdr_add_dirty(_decorations->_dirtyRects, *dirty); - } - - if (_decorations->draw(gfxw_point_zero)) { - _decorations->_dirtyRects.clear(); - return 1; // error - } - _decorations->_dirtyRects.clear(); - } - - _gfxwop_container_draw_contents(this, _contents); - - _dirtyRects.clear(); - _flags &= ~GFXW_FLAG_DIRTY; - - return 0; -} - -GfxPort::~GfxPort() { - if (_visual) { - if (_ID < 0 || _ID >= (int)_visual->_portRefs.size()) { - error("Attempt to free port #%d; allowed: [0..%d]", _ID, _visual->_portRefs.size()); - } - - if (_visual->_portRefs[_ID] != this) { - warning("[GFX] While freeing port %d: Port is at %p, but port list indicates %p", _ID, (void *)this, (void *)_visual->_portRefs[_ID]); - } else - _visual->_portRefs[_ID] = NULL; - - } - - delete _decorations; -} - -void GfxPort::print(int indentation) const { - printIntern(indentation); - printf("PORT"); - printf(" font=%d drawpos=(%d,%d)", _font, draw_pos.x, draw_pos.y); - if (gray_text) - printf(" (gray)"); - - GfxContainer::print(indentation); - _w_gfxwop_container_print_contents("decorations", _decorations, indentation); -} - -static int _gfxwop_port_superarea_of(GfxWidget *self, GfxWidget *other) { - GfxPort *port = (GfxPort *) self; - - if (!port->port_bg) - return _gfxwop_basic_superarea_of(self, other); - - return port->port_bg->superarea_of(port->port_bg, other); -} - -int GfxPort::setVisual(GfxVisual *visual) { - _visual = visual; - - if (_decorations) - if (_decorations->setVisual(visual)) { - warning("[GFX] Setting the visual for decorations failed for port "); - this->print(1); - return 1; - } - - return GfxContainer::setVisual(visual); -} - -static int _gfxwop_port_add_dirty(GfxContainer *widget, rect_t dirty, int propagate) { - GfxPort *self = (GfxPort *) widget; - - self->_flags |= GFXW_FLAG_DIRTY; - - _gfxwop_container_add_dirty(widget, dirty, propagate); - - DDIRTY(stderr, "Added dirty to ID %d\n", widget->_ID); - DDIRTY(stderr, "dirty= (%d,%d,%d,%d) bounds (%d,%d,%d,%d)\n", dirty.x, dirty.x, dirty.width, dirty.height, - widget->_bounds.x, widget->_bounds.y, widget->_bounds.width, widget->_bounds.height); -#if 0 - // FIXME: This is a worthwhile optimization - if (self->port_bg) { - GfxWidget foo; - - foo.bounds = dirty; // Yeah, sub-elegant, I know - foo.bounds.x -= self->zone.x; - foo.bounds.y -= self->zone.y; - if (self->port_bg->superarea_of(self->port_bg, &foo)) { - GfxContainer *parent = self->_parent; - while (parent) { - fprintf(stderr, "Dirtifying parent id %d\n", parent->_ID); - parent->_flags |= GFXW_FLAG_DIRTY; - parent = parent->_parent; - } - return 0; - } - } // else propagate to the parent, since we're not 'catching' the dirty rect -#endif - - if (propagate) - if (self->_parent) { - DDIRTY(stderr, "PROPAGATE\n"); - return self->_parent->add_dirty_abs(self->_parent, dirty, 1); - } - - return 0; -} - -static int _gfxwop_port_add(GfxContainer *container, GfxWidget *widget) { - // O(n) - return _gfxwop_ordered_add(container, widget, 1); -} - -void _gfxw_set_ops_PORT(GfxContainer *widget) { - _gfxw_set_container_ops((GfxContainer *)widget, - _gfxwop_basic_compare_to, _gfxwop_basic_equals, _gfxwop_port_superarea_of, - _gfxwop_container_free_tagged, _gfxwop_container_free_contents, - _gfxwop_port_add_dirty, _gfxwop_port_add); -} - -GfxPort::GfxPort(GfxVisual *visual_, rect_t area, gfx_color_t fgcolor, gfx_color_t bgcolor_) - : GfxContainer(area, GFXW_PORT) { - VERIFY_WIDGET(visual_); - - port_bg = NULL; - _parent = NULL; - _decorations = NULL; - draw_pos = Common::Point(0, 0); - gray_text = 0; - _color = fgcolor; - _bgcolor = bgcolor_; - _font = visual_->_font; - _ID = _visual_find_free_ID(visual_); - visual_->_portRefs[_ID] = this; - - _gfxw_set_ops_PORT(this); -} - -void gfxw_port_auto_restore_background(GfxVisual *visual, GfxPort *window, rect_t auto_rect) { - window->port_flags |= kWindowAutoRestore; - window->restore_snap = gfxw_make_snapshot(visual, auto_rect); -} - -GfxPort *gfxw_remove_port(GfxVisual *visual, GfxPort *port) { - GfxPort *parent; - VERIFY_WIDGET(visual); - VERIFY_WIDGET(port); - - if (!visual->_contents) { - warning("[GFX] Attempt to remove port from empty visual"); - return NULL; - } - - parent = (GfxPort *)port->_parent; - if (port->port_flags & kWindowAutoRestore) - gfxw_restore_snapshot(visual, port->restore_snap); - - delete port; - - while (parent && !GFXW_IS_PORT(parent)) - parent = (GfxPort *)parent->_parent; // Ascend through ancestors - - return parent; -} - -GfxPort *gfxw_find_default_port(GfxVisual *visual) { - int id = visual->_portRefs.size(); - - while (id--) { - GfxPort *port = visual->_portRefs[id]; - - if (port) - return port; - } - - return NULL; -} - -// - other functions - - -GfxWidget *gfxw_set_id(GfxWidget *widget, int ID, int subID) { - if (widget) { - widget->_ID = ID; - widget->_subID = subID; - } - - return widget; -} - -GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, const ObjVarRef& under_bitsp, int signal, const ObjVarRef& signalp) { - if (!widget) - return NULL; - - widget->under_bits = under_bits; - widget->under_bitsp = under_bitsp; - widget->signal = signal; - widget->signalp = signalp; - - return widget; -} - -GfxWidget *gfxw_remove_id(GfxContainer *container, int ID, int subID) { - GfxWidget **wp = &(container->_contents); - - while (*wp) { - if ((*wp)->_ID == ID && (subID == GFXW_NO_ID || (*wp)->_subID == subID)) { - GfxWidget *widget = *wp; - - *wp = (*wp)->_next; - widget->_next = NULL; - widget->_parent = NULL; - widget->_visual = NULL; - - return widget; - } - - wp = &((*wp)->_next); - } - - return NULL; -} - -GfxWidget *gfxw_hide_widget(GfxWidget *widget) { - if (widget->_flags & GFXW_FLAG_VISIBLE) { - widget->_flags &= ~GFXW_FLAG_VISIBLE; - - if (widget->_parent) - widget->_parent->add_dirty_rel(widget->_parent, widget->_bounds, 1); - } - - return widget; -} - -GfxWidget *gfxw_show_widget(GfxWidget *widget) { - if (!(widget->_flags & GFXW_FLAG_VISIBLE)) { - widget->_flags |= GFXW_FLAG_VISIBLE; - - if (widget->_parent) - widget->_parent->add_dirty_rel(widget->_parent, widget->_bounds, 1); - } - - return widget; -} - -gfxw_snapshot_t *gfxw_make_snapshot(GfxVisual *visual, rect_t area) { - gfxw_snapshot_t *retval = (gfxw_snapshot_t*)malloc(sizeof(gfxw_snapshot_t)); - - retval->serial = widget_serial_number_counter++; - - retval->area = area; - - // Work around subset semantics in gfx_rect_subset. - // This fixes the help icon in LSL5. */ - if (retval->area.width == 320) - retval->area.width = 321; - - return retval; -} - -int gfxw_widget_matches_snapshot(gfxw_snapshot_t *snapshot, GfxWidget *widget) { - int free_below = (snapshot->serial < widget_serial_number_counter) ? 0 : widget_serial_number_counter; - int free_above_eq = snapshot->serial; - rect_t bounds = widget->_bounds; - - if (!GFXW_IS_CONTAINER(widget) && widget->_parent) { - bounds.x += widget->_parent->_bounds.x; - bounds.y += widget->_parent->_bounds.y; - } - - // Note: the check for snapshot->area and bounds is NOT the same as contains() in Common::Rect - // (this one includes equality too) - return ((widget->_serial >= free_above_eq || widget->_serial < free_below) && - (snapshot->area.x <= bounds.x && snapshot->area.y <= bounds.y && - snapshot->area.x + snapshot->area.width >= bounds.x + bounds.width && - snapshot->area.y + snapshot->area.height >= bounds.y + bounds.height)); -} - -#define MAGIC_FREE_NUMBER -42 - -void _gfxw_free_contents_appropriately(GfxContainer *container, gfxw_snapshot_t *snapshot, int priority) { - GfxWidget *widget = container->_contents; - - while (widget) { - GfxWidget *next = widget->_next; - - if (gfxw_widget_matches_snapshot(snapshot, widget) && !(widget->_flags & GFXW_FLAG_IMMUNE_TO_SNAPSHOTS) - && (priority == MAGIC_FREE_NUMBER || priority <= widget->_widgetPriority || widget->_widgetPriority == -1)) { - delete widget; - } else { - if (GFXW_IS_CONTAINER(widget)) - _gfxw_free_contents_appropriately((GfxContainer *)widget, snapshot, priority); - } - - widget = next; - } -} - -gfxw_snapshot_t *gfxw_restore_snapshot(GfxVisual *visual, gfxw_snapshot_t *snapshot) { - _gfxw_free_contents_appropriately((GfxContainer *)visual, snapshot, MAGIC_FREE_NUMBER); - - return snapshot; -} - -void gfxw_annihilate(GfxWidget *widget) { - GfxVisual *visual = widget->_visual; - int widget_priority = 0; - int free_overdrawn = 0; - - gfxw_snapshot_t snapshot; - if (!GFXW_IS_CONTAINER(widget) && widget->_parent && visual && (widget->_flags & GFXW_FLAG_VISIBLE)) { - snapshot.serial = 0; - snapshot.area = widget->_bounds; - snapshot.area.x += widget->_parent->zone.x; - snapshot.area.y += widget->_parent->zone.y; - free_overdrawn = 1; - widget_priority = widget->_widgetPriority; - } - - delete widget; - - if (free_overdrawn) - _gfxw_free_contents_appropriately((GfxContainer *)visual, &snapshot, widget_priority); -} - -GfxDynView *gfxw_picviewize_dynview(GfxDynView *dynview) { - dynview->_type = GFXW_PIC_VIEW; - dynview->_flags |= GFXW_FLAG_DIRTY; - - _gfxw_set_ops_PICVIEW(dynview); - - if (dynview->_parent) - _gfxw_dirtify_container(dynview->_parent, dynview); - - return dynview; -} - -} // End of namespace Sci - -#endif |