mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-21 19:51:49 +00:00
GUI: Add VectorRendererSpec::drawTriangleClip()
This commit is contained in:
parent
5868d6d471
commit
559ca37daf
@ -187,6 +187,7 @@ public:
|
||||
* @param orient Orientation of the triangle.
|
||||
*/
|
||||
virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0;
|
||||
virtual void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping) = 0;
|
||||
|
||||
/**
|
||||
* Draws a beveled square like the ones in the Classic GUI themes.
|
||||
@ -390,7 +391,7 @@ public:
|
||||
void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
|
||||
uint16 x, y, w, h;
|
||||
stepGetPositions(step, area, x, y, w, h);
|
||||
drawTriangle(x, y, w, h, (TriangleOrientation)step.extraData);
|
||||
drawTriangleClip(x, y, w, h, (TriangleOrientation)step.extraData, clip);
|
||||
}
|
||||
|
||||
void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
|
||||
|
@ -870,6 +870,13 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelType>
|
||||
inline void VectorRendererSpec<PixelType>::
|
||||
blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y) {
|
||||
if (IS_IN_CLIP(x, y))
|
||||
blendPixelPtr(ptr, color, alpha);
|
||||
}
|
||||
|
||||
template<typename PixelType>
|
||||
inline void VectorRendererSpec<PixelType>::
|
||||
blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) {
|
||||
@ -1263,8 +1270,88 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelType>
|
||||
void VectorRendererSpec<PixelType>::
|
||||
drawTriangleClip(int x, int y, int w, int h, TriangleOrientation orient, Common::Rect clipping) {
|
||||
if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
|
||||
return;
|
||||
|
||||
PixelType color = 0;
|
||||
|
||||
if (Base::_strokeWidth <= 1) {
|
||||
if (Base::_fillMode == kFillForeground)
|
||||
color = _fgColor;
|
||||
else if (Base::_fillMode == kFillBackground)
|
||||
color = _bgColor;
|
||||
} else {
|
||||
if (Base::_fillMode == kFillDisabled)
|
||||
return;
|
||||
color = _fgColor;
|
||||
}
|
||||
|
||||
if (Base::_dynamicData != 0)
|
||||
orient = (TriangleOrientation)Base::_dynamicData;
|
||||
|
||||
Common::Rect backup = _clippingArea;
|
||||
_clippingArea = clipping;
|
||||
bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
|
||||
|
||||
if (w == h) {
|
||||
int newW = w;
|
||||
|
||||
switch (orient) {
|
||||
case kTriangleUp:
|
||||
case kTriangleDown:
|
||||
if (useClippingVersions)
|
||||
drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
|
||||
else
|
||||
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) {
|
||||
if (useClippingVersions)
|
||||
drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
|
||||
else
|
||||
drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
|
||||
}
|
||||
} else {
|
||||
int newW = w;
|
||||
int newH = h;
|
||||
|
||||
switch (orient) {
|
||||
case kTriangleUp:
|
||||
case kTriangleDown:
|
||||
if (useClippingVersions)
|
||||
drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
|
||||
else
|
||||
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) {
|
||||
if (useClippingVersions)
|
||||
drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
|
||||
else
|
||||
drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_clippingArea = backup;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
@ -1821,6 +1908,212 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
|
||||
|
||||
}
|
||||
|
||||
/////////////
|
||||
|
||||
template<typename PixelType>
|
||||
void VectorRendererSpec<PixelType>::
|
||||
drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
|
||||
// Don't draw anything for empty rects. This assures dy is always different
|
||||
// from zero.
|
||||
if (w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||
int gradient_h = 0;
|
||||
int y_pitch_sign = 1;
|
||||
if (!inverted) {
|
||||
pitch = -pitch;
|
||||
y1 += h;
|
||||
y_pitch_sign = -1;
|
||||
}
|
||||
|
||||
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;
|
||||
int x_right = x1;
|
||||
int y_right = y1;
|
||||
int x_left = x1 + w;
|
||||
int y_left = y1;
|
||||
int x_floor = x_right - 1;
|
||||
int y_floor = y_right;
|
||||
|
||||
#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 (fabs(dx) > fabs(dy)) {
|
||||
#endif
|
||||
while (floor++ != ptr_left)
|
||||
blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
|
||||
|
||||
#if FIXED_POINT
|
||||
// In this branch dx is always different from zero. This is because
|
||||
// abs(dx) is strictly greater than abs(dy), and abs returns zero
|
||||
// as minimal value.
|
||||
int gradient = (dy << 8) / dx;
|
||||
int intery = (y1 << 8) + gradient;
|
||||
#else
|
||||
double gradient = dy / dx;
|
||||
double intery = y1 + gradient;
|
||||
#endif
|
||||
|
||||
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--;
|
||||
++x_right;
|
||||
--x_left;
|
||||
}
|
||||
|
||||
ptr_left += pitch;
|
||||
ptr_right += pitch;
|
||||
y_right += y_pitch_sign;
|
||||
y_left += y_pitch_sign;
|
||||
|
||||
intery += gradient;
|
||||
|
||||
switch (fill_m) {
|
||||
case kFillDisabled:
|
||||
if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
|
||||
if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
|
||||
break;
|
||||
case kFillForeground:
|
||||
case kFillBackground:
|
||||
colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
|
||||
break;
|
||||
case kFillGradient:
|
||||
colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if FIXED_POINT
|
||||
if (abs(dx) < abs(dy)) {
|
||||
#else
|
||||
if (fabs(dx) < fabs(dy)) {
|
||||
#endif
|
||||
ptr_left--;
|
||||
--x_left;
|
||||
while (floor++ != ptr_left)
|
||||
blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
|
||||
|
||||
#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
|
||||
|
||||
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--;
|
||||
++x_right;
|
||||
--x_left;
|
||||
}
|
||||
|
||||
ptr_left += pitch;
|
||||
ptr_right += pitch;
|
||||
y_right += y_pitch_sign;
|
||||
y_left += y_pitch_sign;
|
||||
|
||||
interx += gradient;
|
||||
|
||||
switch (fill_m) {
|
||||
case kFillDisabled:
|
||||
if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
|
||||
if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
|
||||
break;
|
||||
case kFillForeground:
|
||||
case kFillBackground:
|
||||
colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
|
||||
break;
|
||||
case kFillGradient:
|
||||
colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_left--;
|
||||
--x_left;
|
||||
while (floor++ != ptr_left)
|
||||
blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
|
||||
|
||||
#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--;
|
||||
++x_right;
|
||||
--x_left;
|
||||
|
||||
ptr_left += pitch;
|
||||
ptr_right += pitch;
|
||||
y_right += y_pitch_sign;
|
||||
y_left += y_pitch_sign;
|
||||
|
||||
interx += gradient;
|
||||
|
||||
switch (fill_m) {
|
||||
case kFillDisabled:
|
||||
if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
|
||||
if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
|
||||
break;
|
||||
case kFillForeground:
|
||||
case kFillBackground:
|
||||
colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
|
||||
break;
|
||||
case kFillGradient:
|
||||
colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
|
||||
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
|
||||
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////
|
||||
|
||||
/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */
|
||||
template<typename PixelType>
|
||||
void VectorRendererSpec<PixelType>::
|
||||
|
@ -50,14 +50,15 @@ class VectorRendererSpec : public VectorRenderer {
|
||||
public:
|
||||
VectorRendererSpec(PixelFormat format);
|
||||
|
||||
void drawLine(int x1, int y1, int x2, int y2);
|
||||
void drawCircle(int x, int y, int r);
|
||||
void drawSquare(int x, int y, int w, int h);
|
||||
void drawLine(int x1, int y1, int x2, int y2); //TODO
|
||||
void drawCircle(int x, int y, int r); //TODO
|
||||
void drawSquare(int x, int y, int w, int h); //TODO
|
||||
void drawRoundedSquare(int x, int y, int r, int w, int h);
|
||||
void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
|
||||
void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
|
||||
void drawTab(int x, int y, int r, int w, int h);
|
||||
void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
|
||||
void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); //TODO
|
||||
void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
|
||||
void drawTab(int x, int y, int r, int w, int h); //TODO
|
||||
void drawBeveledSquare(int x, int y, int w, int h, int bevel) { //TODO
|
||||
drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
|
||||
}
|
||||
void drawString(const Graphics::Font *font, const Common::String &text,
|
||||
@ -122,6 +123,7 @@ protected:
|
||||
* @param alpha Alpha intensity of the pixel (0-255)
|
||||
*/
|
||||
inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha);
|
||||
inline void blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y);
|
||||
|
||||
/**
|
||||
* Blends a single pixel on the surface in the given pixel pointer, using supplied color
|
||||
@ -182,6 +184,9 @@ protected:
|
||||
virtual void drawTriangleVertAlg(int x, int y, int w, int h,
|
||||
bool inverted, PixelType color, FillMode fill_m);
|
||||
|
||||
virtual void drawTriangleVertAlgClip(int x, int y, int w, int h,
|
||||
bool inverted, PixelType color, FillMode fill_m);
|
||||
|
||||
virtual void drawTriangleFast(int x, int y, int size,
|
||||
bool inverted, PixelType color, FillMode fill_m);
|
||||
|
||||
|
@ -1127,6 +1127,29 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe
|
||||
queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2);
|
||||
}
|
||||
|
||||
void ThemeEngine::drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
|
||||
if (!ready())
|
||||
return;
|
||||
|
||||
queueDDClip(kDDScrollbarBase, r, clippingRect);
|
||||
|
||||
Common::Rect r2 = r;
|
||||
const int buttonExtra = (r.width() * 120) / 100;
|
||||
|
||||
r2.bottom = r2.top + buttonExtra;
|
||||
queueDDClip(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleUp);
|
||||
|
||||
r2.translate(0, r.height() - r2.height());
|
||||
queueDDClip(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleDown);
|
||||
|
||||
r2 = r;
|
||||
r2.left += 1;
|
||||
r2.right -= 1;
|
||||
r2.top += sliderY;
|
||||
r2.bottom = r2.top + sliderHeight;
|
||||
queueDDClip(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2, clippingRect);
|
||||
}
|
||||
|
||||
void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) {
|
||||
if (!ready())
|
||||
return;
|
||||
@ -1199,7 +1222,7 @@ void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect
|
||||
else if (state == kStateDisabled)
|
||||
dd = kDDPopUpDisabled;
|
||||
|
||||
queueDDClip(dd, r, clip);
|
||||
queueDDClip(dd, r, clip);
|
||||
|
||||
if (!sel.empty()) {
|
||||
Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
|
||||
|
@ -368,6 +368,8 @@ public:
|
||||
|
||||
void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
|
||||
ScrollbarState, WidgetStateInfo state = kStateEnabled);
|
||||
void drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight,
|
||||
ScrollbarState scrollState, WidgetStateInfo state = kStateEnabled);
|
||||
|
||||
void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
|
||||
int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "gui/widgets/scrollbar.h"
|
||||
#include "gui/gui-manager.h"
|
||||
#include "gui/ThemeEngine.h"
|
||||
#include "gui/widgets/scrollcontainer.h"
|
||||
|
||||
namespace GUI {
|
||||
|
||||
@ -202,7 +203,11 @@ void ScrollBarWidget::drawWidget() {
|
||||
state = ThemeEngine::kScrollbarStateSlider;
|
||||
}
|
||||
|
||||
g_gui.theme()->drawScrollbar(Common::Rect(_x, _y, _x+_w, _y+_h), _sliderPos, _sliderHeight, state, _state);
|
||||
Common::Rect clipRect = getBossClipRect();
|
||||
//scrollbar is not a usual child of ScrollContainerWidget, so it gets this special treatment
|
||||
if (dynamic_cast<ScrollContainerWidget *>(_boss))
|
||||
clipRect.right += _w;
|
||||
g_gui.theme()->drawScrollbarClip(Common::Rect(_x, _y, _x+_w, _y+_h), clipRect, _sliderPos, _sliderHeight, state, _state);
|
||||
}
|
||||
|
||||
} // End of namespace GUI
|
||||
|
Loading…
x
Reference in New Issue
Block a user