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 "Outline.h"
10 
11 #include "Log.h"
12 #include "PixelTool.h"
13 #include "SurfaceTool.h"
14 #include "SurfaceLock.h"
15 
16 //-----------------------------------------------------------------
Outline(const SDL_Color & color,int width)17 Outline::Outline(const SDL_Color &color, int width)
18     : m_color(color)
19 {
20     m_width = width;
21     m_pixel = 0;
22 }
23 //-----------------------------------------------------------------
24 /**
25  * Draw outline, use surface colorkey as bg color.
26  */
27 void
drawOnColorKey(SDL_Surface * surface)28 Outline::drawOnColorKey(SDL_Surface *surface)
29 {
30     Uint32 bgKey = surface->format->colorkey;
31     drawOn(surface, bgKey);
32 }
33 //-----------------------------------------------------------------
34 /**
35  * Draw outline on bg color.
36  * @param surface picture with shape to outline
37  * @param bgKey color used for background
38  */
39 void
drawOn(SDL_Surface * surface,Uint32 bgKey)40 Outline::drawOn(SDL_Surface *surface, Uint32 bgKey)
41 {
42     SurfaceLock lock1(surface);
43 
44     precomputePixel(surface->format);
45     for (int i = 0; i < m_width; ++i) {
46         drawOneLayer(surface, bgKey);
47     }
48 }
49 //-----------------------------------------------------------------
50 void
precomputePixel(SDL_PixelFormat * format)51 Outline::precomputePixel(SDL_PixelFormat *format)
52 {
53     m_pixel = SDL_MapRGB(format, m_color.r, m_color.g, m_color.b);
54 }
55 //-----------------------------------------------------------------
56 /**
57  * Draw outline with width=1.
58  */
59 void
drawOneLayer(SDL_Surface * surface,Uint32 bgKey)60 Outline::drawOneLayer(SDL_Surface *surface, Uint32 bgKey)
61 {
62     SDL_Surface *copy = SurfaceTool::createClone(surface);
63     drawAlongCopy(surface, bgKey, copy);
64     SDL_FreeSurface(copy);
65 }
66 //-----------------------------------------------------------------
67 /**
68  * Draw outline with width=1.
69  * Cloned surface will be used as a model. It will not be modified.
70  * Destination surface must be locked.
71  */
72 void
drawAlongCopy(SDL_Surface * surface,Uint32 bgKey,SDL_Surface * copy)73 Outline::drawAlongCopy(SDL_Surface *surface, Uint32 bgKey, SDL_Surface *copy)
74 {
75     SurfaceLock lock1(copy);
76 
77     for (int py = 0; py < surface->h; ++py) {
78         for (int px = 0; px < surface->w; ++px) {
79             if (PixelTool::getPixel(copy, px, py) != bgKey) {
80                 fillNeighbourhood(surface, bgKey, px, py);
81             }
82         }
83     }
84 }
85 //-----------------------------------------------------------------
86 /**
87  * Fill neighboors around this point.
88  * Neighbours with bgKey will be filled.
89  * Surface must be locked.
90  * m_pixel must be precomputed.
91  */
92 void
fillNeighbourhood(SDL_Surface * surface,Uint32 bgKey,int x,int y)93 Outline::fillNeighbourhood(SDL_Surface *surface, Uint32 bgKey, int x, int y)
94 {
95     //TODO: optimize for speed
96     if (x > 0 && PixelTool::getPixel(surface, x - 1, y) == bgKey) {
97         PixelTool::putPixel(surface, x - 1, y, m_pixel);
98     }
99     if (y > 0 && PixelTool::getPixel(surface, x, y - 1) == bgKey) {
100         PixelTool::putPixel(surface, x, y - 1, m_pixel);
101     }
102 
103     if (x + 1 < surface->w &&
104             PixelTool::getPixel(surface, x + 1, y) == bgKey)
105     {
106         PixelTool::putPixel(surface, x + 1, y, m_pixel);
107     }
108     if (y + 1 < surface->h &&
109             PixelTool::getPixel(surface, x, y + 1) == bgKey)
110     {
111         PixelTool::putPixel(surface, x, y + 1, m_pixel);
112     }
113 }
114 
115 
116