1 /*
2  * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 #include "LayeredPicture.h"
10 
11 #include "Path.h"
12 #include "ResImagePack.h"
13 #include "ResourceException.h"
14 #include "SurfaceLock.h"
15 #include "PixelTool.h"
16 
17 //-----------------------------------------------------------------
18 /**
19  * Create picture with two layers and color mask to select
20  * active areas.
21  *
22  * @throws ResourceException when lowerLayer and colorMask have
23  * different proportions
24  */
LayeredPicture(const Path & bg_file,const V2 & loc,const Path & lowerLayer,const Path & colorMask)25 LayeredPicture::LayeredPicture(const Path &bg_file, const V2 &loc,
26         const Path &lowerLayer, const Path &colorMask)
27 : Picture(bg_file, loc)
28 {
29     m_lowerLayer = ResImagePack::loadImage(lowerLayer);
30     m_colorMask = ResImagePack::loadImage(colorMask);
31     if (m_lowerLayer->w != m_colorMask->w
32             || m_lowerLayer->h != m_colorMask->h) {
33         SDL_FreeSurface(m_lowerLayer);
34         SDL_FreeSurface(m_colorMask);
35         SDL_FreeSurface(m_surface);
36 
37         throw ResourceException(ExInfo(
38                     "lowerLayer and colorMask have different proportions")
39                 .addInfo("lowerLayer", lowerLayer.getNative())
40                 .addInfo("colorMask", colorMask.getNative()));
41     }
42 
43     setNoActive();
44 }
45 //-----------------------------------------------------------------
~LayeredPicture()46 LayeredPicture::~LayeredPicture()
47 {
48     SDL_FreeSurface(m_lowerLayer);
49     SDL_FreeSurface(m_colorMask);
50 }
51 //-----------------------------------------------------------------
52 /**
53  * Return pixel at worldLoc.
54  * Translates world coordinates to local coordinates.
55  */
56     Uint32
getMaskAtWorld(const V2 & worldLoc)57 LayeredPicture::getMaskAtWorld(const V2 &worldLoc)
58 {
59     V2 localLoc = worldLoc.minus(m_loc);
60     return getMaskAt(localLoc);
61 }
62 //-----------------------------------------------------------------
63 /**
64  * Return pixel at position from left top image corner.
65  */
66     Uint32
getMaskAt(const V2 & loc)67 LayeredPicture::getMaskAt(const V2 &loc)
68 {
69     Uint32 result = MASK_NO;
70 
71     if ((0 <= loc.getX() && loc.getX() < m_colorMask->w)
72             && (0 <= loc.getY() && loc.getY() < m_colorMask->h))
73     {
74         SurfaceLock lock1(m_colorMask);
75         result = PixelTool::getPixel(m_colorMask,
76                 loc.getX(), loc.getY());
77     }
78     return result;
79 }
80 //-----------------------------------------------------------------
81     void
drawOn(SDL_Surface * screen)82 LayeredPicture::drawOn(SDL_Surface *screen)
83 {
84     Picture::drawOn(screen);
85     if (m_activeColor == MASK_NO) {
86         return;
87     }
88 
89     SurfaceLock lock1(screen);
90     SurfaceLock lock2(m_lowerLayer);
91     SurfaceLock lock3(m_colorMask);
92 
93     //TODO: support alpha channels
94     for (int py = 0; py < m_colorMask->h; ++py) {
95         int world_y = m_loc.getY() + py;
96         for (int px = 0; px < m_colorMask->w; ++px) {
97             Uint32 sample = PixelTool::getPixel(m_colorMask, px, py);
98 
99             if (sample == m_activeColor) {
100                 SDL_Color lower = PixelTool::getColor(m_lowerLayer, px, py);
101                 if (lower.unused == 255) {
102                     PixelTool::putColor(screen,
103                             m_loc.getX() + px, world_y, lower);
104                 }
105             }
106         }
107     }
108 }
109 
110