43 #ifndef SDL_BIG_ENDIAN
44 #error missing SDL_endian.h
47 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
48 static unsigned int *
cR =
nullptr;
49 static unsigned int *
cG =
nullptr;
50 static unsigned int *
cB =
nullptr;
53 #define defRectFromArea(rect, area) \
54 const SDL_Rect rect = \
58 CAST_S32(area.width), \
59 CAST_S32(area.height) \
62 SDL2SoftwareGraphics::SDL2SoftwareGraphics() :
64 mRendererFlags(SDL_RENDERER_SOFTWARE),
73 SDL2SoftwareGraphics::~SDL2SoftwareGraphics()
79 const int desiredWidth,
84 if (!mSurface || !image || !image->mSDLSurface)
87 Image *const tmpImage = image->SDLgetScaledImage(
88 desiredWidth, desiredHeight);
90 if (!tmpImage || !tmpImage->mSDLSurface)
94 const SDL_Rect &bounds = image->mBounds;
112 SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, mSurface, &dstRect);
127 if (!mSurface || !image || !image->mSDLSurface)
131 const SDL_Rect &bounds = image->mBounds;
133 SDL_Surface *const src = image->mSDLSurface;
148 const int maxw = src->w - srcX;
158 const int maxh = src->h - srcY;
162 const SDL_Rect *
const clip = &mSurface->clip_rect;
163 const int clipX = clip->x;
164 const int clipY = clip->y;
165 int dx = clipX - dstX;
172 dx = dstX + w - clipX - clip->w;
176 int dy = clipY - dstY;
183 dy = dstY + h - clipY - clip->h;
205 SDL_LowerBlit(src, &srcRect, mSurface, &dstRect);
220 if (!mSurface || !image || !image->mSDLSurface)
224 const SDL_Rect &bounds = image->mBounds;
226 SDL_Surface *const src = image->mSDLSurface;
241 const int maxw = src->w - srcX;
251 const int maxh = src->h - srcY;
255 const SDL_Rect *
const clip = &mSurface->clip_rect;
256 const int clipX = clip->x;
257 const int clipY = clip->y;
265 dx =
x + w - clipX - clip->w;
276 dy =
y + h - clipY - clip->h;
298 SDL_LowerBlit(src, &srcRect, mSurface, &dstRect);
310 if (!mSurface || !image)
312 if (!image->mSDLSurface)
315 const SDL_Rect &bounds = image->mBounds;
316 const
int iw = bounds.w;
317 const
int ih = bounds.h;
318 if (iw == 0 || ih == 0)
322 const
int xOffset =
top.xOffset +
x;
323 const
int yOffset =
top.yOffset +
y;
324 const
int srcX = bounds.
x;
325 const
int srcY = bounds.
y;
326 SDL_Surface *const src = image->mSDLSurface;
327 const SDL_Rect *const clip = &mSurface->clip_rect;
328 const
int clipX = clip->
x;
329 const
int clipY = clip->
y;
331 for (
int py = 0; py < h; py += ih)
333 const int dh = (py + ih >= h) ? h - py : ih;
334 int dstY = py + yOffset;
343 const int maxh = src->h - y2;
347 int dy = clipY - dstY;
354 dy = dstY + h2 - clipY - clip->h;
360 for (
int px = 0; px < w; px += iw)
362 const int dw = (px + iw >= w) ? w - px : iw;
363 int dstX = px + xOffset;
372 const int maxw = src->w - x2;
376 int dx = clipX - dstX;
383 dx = dstX + w2 - clipX - clip->w;
405 SDL_LowerBlit(src, &srcRect, mSurface, &dstRect);
419 const int x,
const int y,
433 if (!mSurface || !image)
435 if (!image->mSDLSurface)
438 const SDL_Rect &bounds = image->mBounds;
439 const
int iw = bounds.w;
440 const
int ih = bounds.h;
441 if (iw == 0 || ih == 0)
445 const
int xOffset =
top.xOffset +
x;
446 const
int yOffset =
top.yOffset +
y;
447 const
int srcX = bounds.
x;
448 const
int srcY = bounds.
y;
449 SDL_Surface *const src = image->mSDLSurface;
450 const SDL_Rect *const clip = &mSurface->clip_rect;
451 const
int clipX = clip->
x;
452 const
int clipY = clip->
y;
454 for (
int py = 0; py < h; py += ih)
456 const int dh = (py + ih >= h) ? h - py : ih;
457 int dstY = py + yOffset;
466 const int maxh = src->h - y2;
470 int dy = clipY - dstY;
477 dy = dstY + h2 - clipY - clip->h;
483 for (
int px = 0; px < w; px += iw)
485 const int dw = (px + iw >= w) ? w - px : iw;
486 int dstX = px + xOffset;
495 const int maxw = src->w - x2;
499 int dx = clipX - dstX;
506 dx = dstX + w2 - clipX - clip->w;
528 SDL_LowerBlit(src, &srcRect, mSurface, &dstRect);
539 const int x,
const int y,
540 const int w,
const int h,
541 const int scaledWidth,
542 const int scaledHeight)
546 if (!mSurface || !image)
548 if (!image->mSDLSurface)
551 if (scaledHeight == 0 || scaledWidth == 0)
554 Image *
const tmpImage = image->SDLgetScaledImage(
555 scaledWidth, scaledHeight);
559 const SDL_Rect &bounds = tmpImage->mBounds;
560 const int iw = bounds.w;
561 const int ih = bounds.h;
562 if (iw == 0 || ih == 0)
566 const int xOffset =
top.xOffset +
x;
567 const int yOffset =
top.yOffset +
y;
568 const int srcX = bounds.x;
569 const int srcY = bounds.y;
571 for (
int py = 0; py < h; py += ih)
573 const int dh = (py + ih >= h) ? h - py : ih;
574 const int dstY = py + yOffset;
576 for (
int px = 0; px < w; px += iw)
578 const int dw = (px + iw >= w) ? w - px : iw;
579 const int dstX = px + xOffset;
597 SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect,
624 if (!vert || !mSurface || !image || !image->mSDLSurface)
627 const SDL_Rect &bounds = image->mBounds;
628 const int iw = bounds.w;
629 const int ih = bounds.h;
630 if (iw == 0 || ih == 0)
634 const int xOffset =
top.xOffset +
x;
635 const int yOffset =
top.yOffset +
y;
636 const int srcX = bounds.x;
637 const int srcY = bounds.y;
639 for (
int py = 0; py < h; py += ih)
641 const int dh = (py + ih >= h) ? h - py : ih;
642 const int dstY = py + yOffset;
644 for (
int px = 0; px < w; px += iw)
646 const int dw = (px + iw >= w) ? w - px : iw;
647 const int dstX = px + xOffset;
650 SDL_Rect &srcRect = r->
src;
655 SDL_Rect &dstRect = r->
dst;
659 if (SDL_FakeUpperBlit(image->mSDLSurface, &srcRect,
660 mSurface, &dstRect) == 1)
662 vert->sdl.push_back(r);
680 if (vertCol->currentImage != image)
683 vertCol->currentImage = image;
684 vertCol->currentVert = vert;
686 vertCol->draws.push_back(vert);
690 vert = vertCol->currentVert;
718 if (!vert || !vert->
image || !vert->
image->mSDLSurface)
723 const SDL_Rect &bounds = image->mBounds;
732 if (SDL_FakeUpperBlit(image->mSDLSurface, &rect->
src,
733 mSurface, &rect->
dst) == 1)
735 vert->
sdl.push_back(rect);
751 if (vertCol->currentImage != image)
754 vertCol->currentImage = image;
755 vertCol->currentVert = vert;
757 vertCol->draws.push_back(vert);
777 DoubleRects::const_iterator it2 = rects->begin();
778 const DoubleRects::const_iterator it2_end = rects->end();
779 while (it2 != it2_end)
781 SDL_LowerBlit(img->mSDLSurface, &(*it2)->src,
782 mSurface, &(*it2)->dst);
796 DoubleRects::const_iterator it = rects->begin();
797 const DoubleRects::const_iterator it_end = rects->end();
800 SDL_LowerBlit(img->mSDLSurface, &(*it)->src, mSurface, &(*it)->dst);
808 SDL_UpdateWindowSurfaceRects(mWindow, &mRect, 1);
813 const
int x, const
int y,
814 const
int w, const
int h,
819 Image *
const image = imgRect.grid[4];
822 if (vertCol->currentImage != image)
825 vertCol->currentImage = image;
826 vertCol->currentVert = vert;
828 vertCol->draws.push_back(vert);
832 vert = vertCol->currentVert;
837 int SDL2SoftwareGraphics::SDL_FakeUpperBlit(
const SDL_Surface *
restrict const
854 if (!srcrect || !dstrect)
865 int maxw = src->w - srcx;
877 int maxh = src->h - srcy;
881 const SDL_Rect *
const clip = &dst->clip_rect;
882 const int clipX = clip->x;
883 const int clipY = clip->y;
884 int dx = clipX - dstrect->x;
891 dx = dstrect->x + w - clipX - clip->w;
895 int dy = clipY - dstrect->y;
902 dy = dstrect->y + h - clipY - clip->h;
921 dstrect->w = dstrect->h = 0;
934 Rect area = rectangle;
935 area.
x +=
top.xOffset;
936 area.
y +=
top.yOffset;
938 if (!area.isIntersecting(
top))
943 const int x1 = area.x >
top.x ? area.x :
top.x;
944 const int y1 = area.y >
top.y ? area.y :
top.y;
945 const int x2 = area.x + area.width <
top.x +
top.width ?
946 area.x + area.width :
top.x +
top.width;
947 const int y2 = area.y + area.height <
top.y +
top.height ?
948 area.y + area.height :
top.y +
top.height;
952 SDL_LockSurface(mSurface);
954 const int bpp = mSurface->format->BytesPerPixel;
955 const uint32_t pixel = SDL_MapRGB(mSurface->format,
962 for (
y = y1;
y < y2;
y++)
964 uint8_t *
const p =
static_cast<uint8_t *
>(mSurface->pixels)
965 +
y * mSurface->pitch;
966 for (
x = x1;
x < x2;
x++)
971 for (
y = y1;
y < y2;
y++)
973 uint8_t *
const p0 =
static_cast<uint8_t *
>(
974 mSurface->pixels) +
y * mSurface->pitch;
975 for (
x = x1;
x < x2;
x++)
977 uint8_t *
const p = p0 +
x * 2;
978 *
reinterpret_cast<uint16_t *
>(p) =
SDLAlpha16(
980 *
reinterpret_cast<uint16_t *
>(p),
981 CAST_U8(mColor.a), mSurface->format);
987 const int ca = 255 - mColor.a;
988 const int cr = mColor.r * mColor.a;
989 const int cg = mColor.g * mColor.a;
990 const int cb = mColor.b * mColor.a;
992 for (
y = y1;
y < y2;
y++)
994 uint8_t *
const p0 =
static_cast<uint8_t *
>(
995 mSurface->pixels) +
y * mSurface->pitch;
996 for (
x = x1;
x < x2;
x++)
998 uint8_t *
const p = p0 +
x * 3;
999 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1000 p[2] =
CAST_U8((p[2] * ca + cb) >> 8);
1001 p[1] =
CAST_U8((p[1] * ca + cg) >> 8);
1002 p[0] =
CAST_U8((p[0] * ca + cr) >> 8);
1005 p[0] =
CAST_U8((p[0] * ca + cb) >> 8);
1006 p[1] =
CAST_U8((p[1] * ca + cg) >> 8);
1007 p[2] =
CAST_U8((p[2] * ca + cr) >> 8);
1015 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1016 const unsigned pb = (pixel & 0xff) * mColor.a;
1017 const unsigned pg = (pixel & 0xff00) * mColor.a;
1018 const unsigned pr = (pixel & 0xff0000) * mColor.a;
1019 const unsigned a1 = (255 - mColor.a);
1021 for (
y = y1;
y < y2;
y++)
1023 uint8_t *
const p0 =
static_cast<uint8_t *
>(
1024 mSurface->pixels) +
y * mSurface->pitch;
1025 for (
x = x1;
x < x2;
x++)
1027 uint8_t *p = p0 +
x * 4;
1028 uint32_t dst = *
reinterpret_cast<uint32_t *
>(p);
1029 const unsigned int b = (pb + (dst & 0xff) * a1) >> 8;
1030 const unsigned int g = (pg + (dst & 0xff00) * a1) >> 8;
1031 const unsigned int r = (pr
1032 + (dst & 0xff0000) * a1) >> 8;
1034 *
reinterpret_cast<uint32_t *
>(p) = ((b & 0xff)
1035 | (g & 0xff00) | (r & 0xff0000));
1042 cR =
new unsigned int[0x100];
1043 cG =
new unsigned int[0x100];
1044 cB =
new unsigned int[0x100];
1046 mOldAlpha = mColor.a;
1049 const SDL_PixelFormat *
const format = mSurface->format;
1050 const unsigned rMask = format->Rmask;
1051 const unsigned gMask = format->Gmask;
1052 const unsigned bMask = format->Bmask;
1054 unsigned rShift = rMask / 0xff;
1055 unsigned gShift = gMask / 0xff;
1056 unsigned bShift = bMask / 0xff;
1063 if (pixel != mOldPixel || mColor.a != mOldAlpha)
1065 const unsigned pb = (pixel & bMask) * mColor.a;
1066 const unsigned pg = (pixel & gMask) * mColor.a;
1067 const unsigned pr = (pixel & rMask) * mColor.a;
1068 const unsigned a0 = (255 - mColor.a);
1070 const unsigned int a1 = a0 * bShift;
1071 const unsigned int a2 = a0 * gShift;
1072 const unsigned int a3 = a0 * rShift;
1074 for (
int f = 0; f <= 0xff; f ++)
1076 cB[f] = ((pb + f * a1) >> 8) & bMask;
1077 cG[f] = ((pg + f * a2) >> 8) & gMask;
1078 cR[f] = ((pr + f * a3) >> 8) & rMask;
1082 mOldAlpha = mColor.a;
1085 for (
y = y1;
y < y2;
y++)
1087 uint32_t *
const p0 =
reinterpret_cast<uint32_t*
>(
1088 static_cast<uint8_t*
>(mSurface->pixels)
1089 +
y * mSurface->pitch);
1090 for (
x = x1;
x < x2;
x++)
1092 uint32_t *
const p = p0 +
x;
1093 const uint32_t dst = *p;
1094 *p =
cB[dst & bMask / bShift]
1095 |
cG[(dst & gMask) / gShift]
1096 |
cR[(dst & rMask) / rShift];
1107 SDL_UnlockSurface(mSurface);
1111 defRectFromArea(rect, area);
1112 const uint32_t color = SDL_MapRGBA(mSurface->format,
1117 SDL_FillRect(mSurface, &rect, color);
1135 const ClipRect &carea = mClipStack.top();
1136 defRectFromArea(rect, carea);
1137 SDL_SetClipRect(mSurface, &rect);
1144 if (mClipStack.empty())
1147 const ClipRect &carea = mClipStack.top();
1148 defRectFromArea(rect, carea);
1149 SDL_SetClipRect(mSurface, &rect);
1154 if (mClipStack.empty())
1162 if (!
top.isPointInRect(
x,
y))
1171 void SDL2SoftwareGraphics::drawHLine(
int x1,
int y,
int x2)
restrict2
1173 if (mClipStack.empty())
1178 const int xOffset =
top.xOffset;
1183 const int topY =
top.y;
1184 if (y < topY || y >= topY +
top.height)
1194 const int topX =
top.x;
1203 const int sumX = topX +
top.width;
1212 const int bpp = mSurface->format->BytesPerPixel;
1214 SDL_LockSurface(mSurface);
1216 uint8_t *p =
static_cast<uint8_t*
>(mSurface->pixels)
1217 +
y * mSurface->pitch + x1 * bpp;
1219 const uint32_t pixel = SDL_MapRGB(mSurface->format,
1226 for (; x1 <= x2; ++x1)
1232 uint16_t* q =
reinterpret_cast<uint16_t*
>(p);
1233 const uint16_t pixel1 =
CAST_U16(pixel);
1234 for (; x1 <= x2; ++x1)
1241 const uint8_t b0 =
CAST_U8((pixel >> 16) & 0xff);
1242 const uint8_t b1 =
CAST_U8((pixel >> 8) & 0xff);
1243 const uint8_t b2 =
CAST_U8(pixel & 0xff);
1244 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1245 for (; x1 <= x2; ++x1)
1254 for (; x1 <= x2; ++x1)
1268 uint32_t *q =
reinterpret_cast<uint32_t*
>(p);
1271 unsigned char a =
CAST_U8(mColor.a);
1272 unsigned char a1 =
CAST_U8(255U - a);
1273 const int b0 = (pixel & 0xff) * a;
1274 const int g0 = (pixel & 0xff00) * a;
1275 const int r0 = (pixel & 0xff0000) * a;
1276 for (; x1 <= x2; ++x1)
1278 const unsigned int b = (b0 + (*q & 0xff) * a1) >> 8;
1279 const unsigned int g = (g0 + (*q & 0xff00) * a1) >> 8;
1280 const unsigned int r = (r0 + (*q & 0xff0000) * a1) >> 8;
1281 *q = (b & 0xff) | (g & 0xff00) | (r & 0xff0000);
1288 for (; x1 <= x2; ++x1)
1297 SDL_UnlockSurface(mSurface);
1300 void SDL2SoftwareGraphics::drawVLine(
int x,
int y1,
int y2)
restrict2
1302 if (mClipStack.empty())
1307 const int yOffset =
top.yOffset;
1312 if (x < top.x || x >=
top.x +
top.width)
1330 const int sumY =
top.y +
top.height;
1339 const int bpp = mSurface->format->BytesPerPixel;
1341 SDL_LockSurface(mSurface);
1343 uint8_t *p =
static_cast<uint8_t*
>(mSurface->pixels)
1344 + y1 * mSurface->pitch +
x * bpp;
1346 const uint32_t pixel = SDL_MapRGB(mSurface->format,
1351 const int pitch = mSurface->pitch;
1355 for (; y1 <= y2; ++y1)
1363 for (; y1 <= y2; ++ y1)
1365 *
reinterpret_cast<uint16_t*
>(p)
1373 const uint8_t b0 =
CAST_U8((pixel >> 16) & 0xff);
1374 const uint8_t b1 =
CAST_U8((pixel >> 8) & 0xff);
1375 const uint8_t b2 =
CAST_U8(pixel & 0xff);
1376 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1377 for (; y1 <= y2; ++y1)
1386 for (; y1 <= y2; ++y1)
1402 unsigned char a =
CAST_U8(mColor.a);
1403 unsigned char a1 =
CAST_U8(255U - a);
1404 const int b0 = (pixel & 0xff) * a;
1405 const int g0 = (pixel & 0xff00) * a;
1406 const int r0 = (pixel & 0xff0000) * a;
1407 for (; y1 <= y2; ++y1)
1409 const unsigned int dst = *
reinterpret_cast<uint32_t*
>(p);
1410 const unsigned int b = (b0 + (dst & 0xff) * a1) >> 8;
1411 const unsigned int g = (g0 + (dst & 0xff00) * a1) >> 8;
1412 const unsigned int r = (r0 + (dst & 0xff0000) * a1) >> 8;
1413 *
reinterpret_cast<uint32_t*
>(p) =
1414 (b & 0xff) | (g & 0xff00) | (r & 0xff0000);
1421 for (; y1 <= y2; ++y1)
1423 *
reinterpret_cast<uint32_t*
>(p) = pixel;
1434 SDL_UnlockSurface(mSurface);
1440 const int x1 = rectangle.x;
1441 const int x2 = x1 + rectangle.width - 1;
1442 const int y1 = rectangle.y;
1443 const int y2 = y1 + rectangle.height - 1;
1445 drawHLine(x1, y1, x2);
1446 drawHLine(x1, y2, x2);
1448 drawVLine(x1, y1, y2);
1449 drawVLine(x2, y1, y2);
1457 drawVLine(x1, y1, y2);
1462 drawHLine(x1, y1, x2);
1486 getSoftwareFlags())))
1494 mSurface = SDL_GetWindowSurface(mWindow);
1496 SDL2SoftwareImageHelper::setFormat(mSurface->format);
1500 SDL_GetWindowSize(mWindow, &w1, &h1);
1508 bool SDL2SoftwareGraphics::resizeScreen(
const int width,
1513 mSurface = SDL_GetWindowSurface(mWindow);
1514 SDL2SoftwareImageHelper::setFormat(mSurface->format);
1519 const int w,
const int h,
1527 const int x,
const int y,
1528 const int w,
const int h,
static SDL_Surface * createWindow(const int w, const int h, const int bpp, const int flags)
virtual void popClipArea()
virtual bool resizeScreen(const int width, const int height)
virtual void pushClipArea(const Rect &area)
static void dumpSurfaceFormat(const SDL_Surface *const image)
const Image *restrict const top
void calcPatternInline(ImageVertexes *restrict const vert, const Image *restrict const image, const int x, const int y, const int w, const int h) const restrict2 A_INLINE
void calcTileVertexes(ImageVertexes *restrict const vert, const Image *restrict const image, int x, int y) const restrict2 override final A_NONNULL(2
void calcWindow(ImageCollection *restrict const vertCol, const int x, const int y, const int w, const int h, const ImageRect &restrict imgRect) restrict2 override final A_NONNULL(2)
void drawPatternInline(const Image *restrict const image, const int x, const int y, const int w, const int h) restrict2 A_INLINE
void drawRectangle(const Rect &restrict rect) restrict2 override final
void drawRescaledPattern(const Image *restrict const image, const int x, const int y, const int w, const int h, const int scaledWidth, const int scaledHeight) restrict2 override final
void copyImage(const Image *restrict const image, int dstX, int dstY) restrict2 override final
void calcPattern(ImageVertexes *restrict const vert, const Image *restrict const image, const int x, const int y, const int w, const int h) const restrict2 override final
bool setVideoMode(const int w, const int h, const int scalle, const int bpp, const bool fs, const bool hwaccel, const bool resize, const bool noFrame, const bool allowHighDPI) restrict2 override final
void drawPoint(int x, int y) restrict2 override final
void drawRescaledImage(const Image *restrict const image, int dstX, int dstY, const int desiredWidth, const int desiredHeight) restrict2 override final
void endDraw() restrict2 override final
void drawTileVertexes(const ImageVertexes *restrict const vert) restrict2 override final
void void drawImageInline(const Image *restrict const image, int dstX, int dstY) restrict2 A_INLINE
void calcTileVertexesInline(ImageVertexes *restrict const vert, const Image *restrict const image, int x, int y) const restrict2 A_INLINE A_NONNULL(2
void drawImageRect(int x, int y, int w, int h, const ImageRect &restrict imgRect) restrict2 override final
void fillRectangle(const Rect &restrict rect) restrict2 override final
void drawLine(int x1, int y1, int x2, int y2) restrict2 override final
void popClipArea() restrict2 override final
void drawTileCollection(const ImageCollection *restrict const vertCol) restrict2 override final A_NONNULL(2)
void drawImage(const Image *restrict const image, int dstX, int dstY) restrict2 override final
void updateScreen() restrict2 override final
void void calcTileCollection(ImageCollection *restrict const vertCol, const Image *restrict const image, int x, int y) restrict2 override final
void drawPattern(const Image *restrict const image, const int x, const int y, const int w, const int h) restrict2 override final
void calcImageRect(ImageVertexes *restrict const vert, int x, int y, int w, int h, const ImageRect &restrict imgRect) restrict2 A_INLINE
void pushClipArea(const Rect &restrict area) restrict2 override final
void drawImageCached(const Image *restrict const image, int x, int y) restrict2 override final
void completeCache() restrict2 override final
void beginDraw() restrict2 override final
void drawPatternCached(const Image *restrict const image, const int x, const int y, const int w, const int h) restrict2 override final
GraphicsManager graphicsManager
std::vector< ImageVertexes * > ImageVertexesVector
std::vector< DoubleRect * > DoubleRects
ImageVertexesVector::const_iterator ImageCollectionCIter
#define FUNC_BLOCK(name, id)
#define BLOCK_START(name)
void SDLputPixelAlpha(SDL_Surface *surface, int x, int y, const Color &color)
void SDLputPixel(SDL_Surface *surface, int x, int y, const Color &color)
unsigned short SDLAlpha16(const unsigned short src, const unsigned short dst, const unsigned char a, const SDL_PixelFormat *const f)
void calcTileSDL(ImageVertexes *restrict const vert, int x, int y) const restrict2 override final