123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /* GCSx
- ** WPREVIEW.CPP
- **
- ** Widget that previews an image (tile, map, etc.)
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- WPreview::WPreview(int pId, SDL_Surface* const* src, int myWidth, int myHeight, int pShowMultiple, int pAllowDistort) : Widget(pId, blankString, NULL) { start_func
- assert(src);
- showMultiple = pShowMultiple;
- allowDistort = pAllowDistort;
-
- source = src;
- scaled = NULL;
- scaledIsSource = 1;
- changeSize(myWidth, myHeight);
- }
- WPreview::~WPreview() { start_func
- if (scaled) SDL_FreeSurface(scaled);
- }
- void WPreview::changeSize(int newWidth, int newHeight) { start_func
- displayW = newWidth;
- displayH = newHeight;
- if ((newWidth <= 0) || (newHeight <= 0)) {
- resize(0, 0);
- }
- else {
- resize(newWidth + PREVIEW_BORDER_SIZE * 2, newHeight + PREVIEW_BORDER_SIZE * 2);
- }
- }
- int WPreview::event(int hasFocus, const SDL_Event* event) { start_func
- // Currently doesn't do any events
- return 0;
- }
- int WPreview::refuseAll() const { start_func
- // Currently doesn't do any events
- return 1;
- }
- void WPreview::load() { start_func
- if ((*source == NULL) || (displayW <= 0) || (displayH <= 0)) {
- if (scaled) SDL_FreeSurface(scaled);
- scaled = NULL;
- scaledIsSource = 1;
- }
- else {
- SDL_Surface* src= *source;
- int actualW = src->w;
- int actualH = src->h;
-
- // Scaling required?
- if (actualW <= displayW) {
- imageFullX = 1;
- imageScaleX = 1.0;
- }
- else {
- imageFullX = 0;
- imageScaleX = (float)(displayW) / (float)(actualW);
- }
-
- if (actualH <= displayH) {
- imageFullY = 1;
- imageScaleY = 1.0;
- }
- else {
- imageFullY = 0;
- imageScaleY = (float)(displayH) / (float)(actualH);
- }
-
- // Prevent distortion?
- if ((!allowDistort) && ((!imageFullX) || (!imageFullY))) {
- imageFullX = imageFullY = 0;
-
- if (imageScaleX > imageScaleY) imageScaleX = imageScaleY;
- else imageScaleY = imageScaleX;
- }
-
- // Calculate actual w/h (round up; limit to display size max)
- actualW = min(displayW, (int)ceil(actualW * imageScaleX));
- actualH = min(displayH, (int)ceil(actualH * imageScaleY));
-
- // Multiple copies? (only if not scaled)
- int copies = 1;
- int gutters = 0;
- if ((showMultiple) && (imageFullX) && (imageFullY)) {
- // Non-tiled copies must have at least one pixel between them
- // Room for at least two copies?
- if (displayW >= actualW * 2 + 1) {
- copies = 2;
- gutters = 1;
- }
-
- // Room for two copies and 2x? tiled?
- if (displayW >= actualW * 4 + 2) {
- // Room for two copies and 3x? tiled?
- if (displayW >= actualW * 5 + 2) copies = 5;
- else copies = 4;
- gutters = 2;
- }
- }
-
- // Size of gutters and l/r margins; gutters get twice as much space
- int gutterSize = (displayW - actualW * copies) / (gutters + 1);
- int marginSize = (displayW - actualW * copies) / (gutters * 2 + 2);
- // Margins can be 0, gutters must be at least 1
- if (gutterSize < 1) gutterSize = 1;
-
- // Position of primary image
- // Offset x/y by border amount
- imageX = marginSize + PREVIEW_BORDER_SIZE;
- imageY = (displayH - actualH) / 2 + PREVIEW_BORDER_SIZE;
-
- // Secondary image
- if (copies > 1) {
- imageWhiteX = marginSize + actualW + gutterSize + PREVIEW_BORDER_SIZE;
- imageWhiteY = (displayH - actualH) / 2 + PREVIEW_BORDER_SIZE;
- }
- else {
- imageWhiteX = imageWhiteY = 0;
- }
-
- // Tiled image
- if (copies > 2) {
- imageTiledQty = copies - 2;
- imageTiledX = marginSize + actualW * 2 + gutterSize * 2 + PREVIEW_BORDER_SIZE;
- // (can be negative, but if so, ensure rounds in right direction)
- if (actualH * imageTiledQty > displayH) imageTiledY = (displayH - actualH * imageTiledQty - 1) / 2 + PREVIEW_BORDER_SIZE;
- else imageTiledY = (displayH - actualH * imageTiledQty) / 2 + PREVIEW_BORDER_SIZE;
- }
- else {
- imageTiledX = imageTiledY = imageTiledQty = 0;
- }
-
- // Need to redraw actual image? Always redraw if scaled at all
- if ((!imageFullX) || (!imageFullY)) {
- // Deallocate
- if (scaled) SDL_FreeSurface(scaled);
- scaled = NULL;
- scaledIsSource = 1;
-
- // If scaling fails to allocate surface, we won't throw an error-
- // we'll just stick to the original source version
- scaled = sge_transform_surface(src, SDL_MapRGBA(src->format, 0, 0, 0, 0), 0, imageScaleX, imageScaleY, SGE_TAA|SGE_TSAFE);
- if (scaled) {
- scaledIsSource = 0;
- }
- else {
- // (ptr already NULL)
- scaledIsSource = 1;
- }
- }
- // Stick with copy of source if not really scaled
- else {
- // Deallocate?
- if (scaled) SDL_FreeSurface(scaled);
- scaled = NULL;
- scaledIsSource = 1;
- }
- }
-
- setDirty();
- }
- void WPreview::apply() { start_func
- // Doesn't apply anything
- }
- void WPreview::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
- assert(destSurface);
- if (visible) {
- // If dirty, redraw all
- if (dirty) {
- getRect(toDisplay);
- toDisplay.x += xOffset;
- toDisplay.y += yOffset;
- dirty = 0;
- intersectRects(toDisplay, clipArea);
- }
-
- // Anything to draw?
- if (toDisplay.w) {
- SDL_SetClipRect(destSurface, &toDisplay);
- xOffset += x;
- yOffset += y;
-
- // We specifically use black, except for "white" copy
- SDL_FillRect(destSurface, &toDisplay, SDL_MapRGB(destSurface->format, 0, 0, 0));
- // @TODO: Corners of inverted box aren't grey
- if (PREVIEW_BORDER_SIZE) drawGuiBoxInvert(xOffset, yOffset, width, height, PREVIEW_BORDER_SIZE, destSurface);
-
- // Just one copy?
- if (!imageWhiteX) {
- // (scaled images have a 1-pixel border we want to discard)
- if (scaled) blit(1, 1, scaled, xOffset + imageX, yOffset + imageY, destSurface, scaled->w - 2, scaled->h - 2);
- else if ((scaledIsSource) && (*source)) blit(0, 0, *source, xOffset + imageX, yOffset + imageY, destSurface);
- }
- else {
- int tileW = (*source)->w;
- int tileH = (*source)->h;
- SDL_SetAlpha(*source, SDL_SRCALPHA, 255);
- // Multiple copies- never scaled
- // Black copy
- blit(0, 0, *source, xOffset + imageX, yOffset + imageY, destSurface);
-
- // White copy, with alpha
- drawRect(xOffset + imageWhiteX, yOffset + imageWhiteY, tileW, tileH, SDL_MapRGB(destSurface->format, 255, 255, 255), destSurface);
- blit(0, 0, *source, xOffset + imageWhiteX, yOffset + imageWhiteY, destSurface);
-
- // Tiles
- if (imageTiledX) {
- // Reduce clip rectangle to within border vertically, tiled copy may go out
- Rect newClip = toDisplay;
- if (newClip.y == yOffset) {
- ++newClip.y;
- --newClip.h;
- }
- if (newClip.y + newClip.h == yOffset + height) --newClip.h;
- SDL_SetClipRect(destSurface, &newClip);
- for (int tX = 0; tX < imageTiledQty; ++tX)
- for (int tY = 0; tY < imageTiledQty; ++tY)
- blit(0, 0, *source, xOffset + imageTiledX + tileW * tX, yOffset + imageTiledY + tileH * tY, destSurface);
- }
- SDL_SetAlpha(*source, 0, 255);
- }
- }
- }
- }
|