From ad4471f70cf5672aeef75ecbbbd8574b7a284602 Mon Sep 17 00:00:00 2001 From: MaximRussia Date: Wed, 7 Dec 2011 14:01:53 +0000 Subject: GUI: Improved pop up and scrollbar arrows look Previous triangle drawing was all wrong, rewrote it from the scratch. Added padding to drawsteps in stx files --- graphics/VectorRenderer.cpp | 28 ++- graphics/VectorRenderer.h | 2 + graphics/VectorRendererSpec.cpp | 337 ++++++++++++++++++++--------- gui/ThemeEngine.cpp | 2 +- gui/ThemeEngine.h | 2 +- gui/ThemeParser.cpp | 10 + gui/ThemeParser.h | 1 + gui/themes/scummclassic/THEMERC | 2 +- gui/themes/scummclassic/classic_gfx.stx | 226 +++++++++++++++++-- gui/themes/scummmodern/THEMERC | 2 +- gui/themes/scummmodern/scummmodern_gfx.stx | 254 +++++++++++++++++++--- 11 files changed, 703 insertions(+), 163 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 4dbcd9845f..30ef9eeeeb 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -78,27 +78,29 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & switch (step.xAlign) { case Graphics::DrawStep::kVectorAlignManual: - if (step.x >= 0) in_x = area.left + step.x; - else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. + if (step.x >= 0) + in_x = area.left + step.x + step.padding.left; + else + in_x = area.left + area.width() + step.x + step.padding.left; // value relative to the opposite corner. break; case Graphics::DrawStep::kVectorAlignCenter: - in_x = area.left + (area.width() / 2) - (in_w / 2); + in_x = area.left + (area.width() / 2) - (in_w / 2) + ((step.padding.left + step.padding.right ) / 2); break; case Graphics::DrawStep::kVectorAlignLeft: - in_x = area.left; + in_x = area.left + step.padding.left; break; case Graphics::DrawStep::kVectorAlignRight: - in_x = area.left + area.width() - in_w; + in_x = area.left + area.width() - in_w - step.padding.right; break; default: error("Vertical alignment in horizontal data"); } } else { - in_x = area.left; + in_x = area.left + step.padding.left; in_w = area.width(); } @@ -107,27 +109,29 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & switch (step.yAlign) { case Graphics::DrawStep::kVectorAlignManual: - if (step.y >= 0) in_y = area.top + step.y; - else in_y = area.top + area.height() + step.y; // relative + if (step.y >= 0) + in_y = area.top + step.y + step.padding.top; + else + in_y = area.top + area.height() + step.y + step.padding.top; // relative break; case Graphics::DrawStep::kVectorAlignCenter: - in_y = area.top + (area.height() / 2) - (in_h / 2); + in_y = area.top + (area.height() / 2) - (in_h / 2) + ((step.padding.top + step.padding.bottom ) / 2) ; break; case Graphics::DrawStep::kVectorAlignTop: - in_y = area.top; + in_y = area.top + step.padding.top; break; case Graphics::DrawStep::kVectorAlignBottom: - in_y = area.top + area.height() - in_h; + in_y = area.top + area.height() - in_h - step.padding.bottom; break; default: error("Horizontal alignment in vertical data"); } } else { - in_y = area.top; + in_y = area.top + step.padding.top; in_h = area.height(); } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index ec8a8f7245..87706a36f5 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -55,6 +55,8 @@ struct DrawStep { bool autoWidth, autoHeight; int16 x, y, w, h; /**< width, height and position, if not measured automatically. negative values mean counting from the opposite direction */ + + Common::Rect padding; enum VectorAlignment { kVectorAlignManual, diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 8bc7b5c164..1bd07af237 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -693,25 +693,49 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { if (Base::_dynamicData != 0) orient = (TriangleOrientation)Base::_dynamicData; - int newW = w / 2; - if (newW % 2) newW++; + if (w == h) { + int newW = w; - switch (orient) { + switch (orient) { case kTriangleUp: case kTriangleDown: - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), color, Base::_fillMode); + //drawTriangleFast(x, y, newW, (orient == kTriangleDown), color, Base::_fillMode); + drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode); break; case kTriangleLeft: case kTriangleRight: case kTriangleAuto: break; - } + } - if (Base::_strokeWidth > 0) - if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), _fgColor, kFillDisabled); + if (Base::_strokeWidth > 0) + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { + //drawTriangleFast(x, y, newW, (orient == kTriangleDown), _fgColor, kFillDisabled); + drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode); + } + } else { + int newW = w; + int newH = h; + + switch (orient) { + case kTriangleUp: + case kTriangleDown: + drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode); + break; + + case kTriangleLeft: + case kTriangleRight: + case kTriangleAuto: + break; } + + if (Base::_strokeWidth > 0) { + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { + drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled); + } + } + } } @@ -1005,130 +1029,249 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { } /** VERTICAL TRIANGLE DRAWING ALGORITHM **/ +/** + FIXED POINT ARITHMETIC +**/ + +#define FIXED_POINT 1 + +#if FIXED_POINT +#define ipart(x) ((x) & ~0xFF) +// This is not really correct since gradient is not percentage, but [0..255] +#define rfpart(x) ((0x100 - ((x) & 0xFF)) * 100 >> 8) +//#define rfpart(x) (0x100 - ((x) & 0xFF)) +#else +#define ipart(x) ((int)x) +#define round(x) (ipart(x + 0.5)) +#define fpart(x) (x - ipart(x)) +#define rfpart(x) (int)((1 - fpart(x)) * 100) +#endif + template void VectorRendererSpec:: drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { - int dx = w >> 1, dy = h, gradient_h = 0; int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - PixelType *ptr_right = 0, *ptr_left = 0; - - if (inverted) { - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); - } else { - ptr_right = ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + dx, y1); + int gradient_h = 0; + if (!inverted) { + pitch = -pitch; + y1 += h; } + + PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + PixelType *floor = ptr_right - 1; + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); + + int x2 = x1 + w / 2; + int y2 = y1 + h; + +#if FIXED_POINT + int dx = (x2 - x1) << 8; + int dy = (y2 - y1) << 8; + + if (abs(dx) > abs(dy)) { +#else + double dx = (double)x2 - (double)x1; + double dy = (double)y2 - (double)y1; - if (dx > dy) { - int ddy = dy * 2; - int dysub = ddy - (dx * 2); - int error_term = ddy - dx; + if (fabs(dx) > fabs(dy)) { +#endif + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dy << 8) / dx; + int intery = (y1 << 8) + gradient; +#else + double gradient = dy / dx; + double intery = y1 + gradient; +#endif - switch (fill_m) { - case kFillDisabled: - while (dx--) { - TRIANGLE_MAINX(); - *ptr_right = color; - *ptr_left = color; + for (int x = x1 + 1; x < x2; x++) { +#if FIXED_POINT + if (intery + gradient > ipart(intery) + 0x100) { +#else + if (intery + gradient > ipart(intery) + 1) { +#endif + ptr_right++; + ptr_left--; } - colorFill(ptr_left, ptr_right, color); - break; - case kFillForeground: - case kFillBackground: - while (dx--) { - TRIANGLE_MAINX(); - if (inverted) colorFill(ptr_right, ptr_left, color); - else colorFill(ptr_left, ptr_right, color); + ptr_left += pitch; + ptr_right += pitch; + + intery += gradient; + + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(intery)); + blendPixelPtr(ptr_left, color, rfpart(intery)); + break; + case kFillGradient: + colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(intery)); + blendPixelPtr(ptr_left, color, rfpart(intery)); + break; } - break; + } + + return; + } + +#if FIXED_POINT + if (abs(dx) < abs(dy)) { +#else + if (fabs(dx) < fabs(dy)) { +#endif + ptr_left--; + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dx << 8) / (dy + 0x100); + int interx = (x1 << 8) + gradient; +#else + double gradient = dx / (dy+1); + double interx = x1 + gradient; +#endif - case kFillGradient: - while (dx--) { - TRIANGLE_MAINX(); - if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + for (int y = y1 + 1; y < y2; y++) { +#if FIXED_POINT + if (interx + gradient > ipart(interx) + 0x100) { +#else + if (interx + gradient > ipart(interx) + 1) { +#endif + ptr_right++; + ptr_left--; + } + + ptr_left += pitch; + ptr_right += pitch; + + interx += gradient; + + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); + break; + case kFillGradient: + colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); + break; } - break; } - } else { - int ddx = dx * 2; - int dxsub = ddx - (dy * 2); - int error_term = ddx - dy; + + return; + } + + ptr_left--; + + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dx / dy) << 8; + int interx = (x1 << 8) + gradient; +#else + double gradient = dx / dy; + double interx = x1 + gradient; +#endif + for (int y = y1 + 1; y < y2; y++) { + ptr_right++; + ptr_left--; + + ptr_left += pitch; + ptr_right += pitch; + + interx += gradient; + switch (fill_m) { case kFillDisabled: - while (dy--) { - TRIANGLE_MAINY(); - *ptr_right = color; - *ptr_left = color; - } - colorFill(ptr_left, ptr_right, color); + *ptr_left = *ptr_right = color; break; - case kFillForeground: case kFillBackground: - while (dy--) { - TRIANGLE_MAINY(); - if (inverted) colorFill(ptr_right, ptr_left, color); - else colorFill(ptr_left, ptr_right, color); - } + colorFill(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); break; case kFillGradient: - while (dy--) { - TRIANGLE_MAINY(); - if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); - } + colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); break; } } + } - /** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */ template void VectorRendererSpec:: drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - int hstep = 0, dy = size; - bool grad = (fill_m == kFillGradient); - - PixelType *ptr_right = 0, *ptr_left = 0; - - if (x1 + size > Base::_activeSurface->w || x1 < 0 || - y1 + size > Base::_activeSurface->h || y1 < 0) - return; - - if (inverted) { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); - } else { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1 + size); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1 + size); + + if (!inverted) { pitch = -pitch; + y1 += size; } - - if (fill_m == kFillDisabled) { - while (ptr_left < ptr_right) { - *ptr_left = color; - *ptr_right = color; - ptr_left += pitch; - ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } + + int gradient_h = 0; + PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); + int x2 = x1 + size / 2; + int y2 = y1 + size; + int deltaX = abs(x2 - x1); + int deltaY = abs(y2 - y1); + int signX = x1 < x2 ? 1 : -1; + int signY = y1 < y2 ? 1 : -1; + int error = deltaX - deltaY; + + colorFill(ptr_right, ptr_left, color); + + while (1) { + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill(ptr_right, ptr_left, color); + break; + case kFillGradient: + colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, size)); + break; } - } else { - while (ptr_left < ptr_right) { - colorFill(ptr_left, ptr_right, grad ? calcGradient(dy--, size) : color); - ptr_left += pitch; + + if (x1 == x2 && y1 == y2) + break; + + int error2 = error * 2; + + if (error2 > -deltaY) { + error -= deltaY; + x1 += signX; + ptr_right += signX; + ptr_left += -signX; + } + + if (error2 < deltaX) { + error += deltaX; + y1 += signY; ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } + ptr_left += pitch; } } } diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 4952d0f2ef..6d95cab526 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -972,7 +972,7 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe r2.left += 1; r2.right -= 1; r2.top += sliderY; - r2.bottom = r2.top + sliderHeight - 1; + r2.bottom = r2.top + sliderHeight; r2.top += r.width() / 5; r2.bottom -= r.width() / 5; diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index d9b1f09f25..0029886de5 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -35,7 +35,7 @@ #include "graphics/pixelformat.h" -#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.4" +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.5" class OSystem; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 7279279598..ea50dcc061 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -544,6 +544,16 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst else return parserError("'" + stepNode->values["fill"] + "' is not a valid fill mode for a shape."); } + + if (stepNode->values.contains("padding")) { + val = stepNode->values["padding"]; + int pr, pt, pl, pb; + if (parseIntegerKey(val, 4, &pl, &pt, &pr, &pb)) + drawstep->padding.left = pl, + drawstep->padding.top = pt, + drawstep->padding.right = pr, + drawstep->padding.bottom = pb; + } #undef PARSER_ASSIGN_INT #undef PARSER_ASSIGN_RGB diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 39a951e007..1999850643 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -138,6 +138,7 @@ protected: XML_PROP(height, false) XML_PROP(xpos, false) XML_PROP(ypos, false) + XML_PROP(padding, false) XML_PROP(orientation, false) XML_PROP(file, false) KEY_END() diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC index b871dfe430..f6a46692a0 100644 --- a/gui/themes/scummclassic/THEMERC +++ b/gui/themes/scummclassic/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.8.4:ScummVM Classic Theme:No Author] +[SCUMMVM_STX0.8.5:ScummVM Classic Theme:No Author] diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx index c0fcc9f083..2f8f0a358a 100644 --- a/gui/themes/scummclassic/classic_gfx.stx +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -176,7 +176,7 @@ /> - + + + + + + - + + + + + + @@ -272,20 +308,70 @@ /> - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + - + + + + + + + + + + + @@ -393,7 +433,7 @@ - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + -- cgit v1.2.3