OSDN Git Service

ライセンスをMIT-Styleに変更,DLL内にライセンス埋め込み
[kimikage-nscr/kimikage-nscr.git] / nsdfont / src / ColorBlender.h
1 /*\r
2  *      Kimikage NScripter Plugins Project\r
3  *\r
4  *      This software is distributed under a MIT-style license.\r
5  *      See license.txt for more information.\r
6  */\r
7 \r
8 #pragma once\r
9 #include "Color.h"\r
10 \r
11 namespace nsdfont\r
12 {\r
13         class ColorBlender\r
14         {\r
15         private:\r
16                 class Table\r
17                 {\r
18                 protected:\r
19                         unsigned char table[256*256];\r
20                 public:\r
21                         inline unsigned int operator[]( size_t i ) const\r
22                         {\r
23                                 return static_cast<unsigned int>( table[i] );\r
24                         }\r
25                 };\r
26                 \r
27                 /**\r
28                  *      \8fæ\8eZ\83e\81[\83u\83\8b.\r
29                  */\r
30                 class MulTable : public Table\r
31                 {\r
32                 public:\r
33                         MulTable();\r
34                 };\r
35                 /**\r
36                  *      \8f\9c\8eZ\83e\81[\83u\83\8b.\r
37                  */\r
38                 class DivTable : public Table\r
39                 {\r
40                 public:\r
41                         DivTable();\r
42                 };\r
43 \r
44                 static const MulTable mulTable;\r
45                 static const DivTable divTable;\r
46         public:\r
47                 ColorBlender( void );\r
48 \r
49                 ~ColorBlender( void );\r
50 \r
51                 /**\r
52                  *      \8fæ\8eZ\r
53                  */\r
54                 static inline unsigned int mul( const unsigned int v1, const unsigned int v2 )\r
55                 {\r
56                         const size_t i = v1 + (v2 << 8);\r
57                         return mulTable[i];\r
58                 }\r
59                 \r
60                 /**\r
61                  *      \83X\83N\83\8a\81[\83\93(\94½\93]\8fæ\8eZ)\r
62                  */\r
63                 static inline unsigned int scr( const unsigned int v1, const unsigned int v2 )\r
64                 {\r
65                         const size_t i = (v1 + (v2 << 8)) ^ 0xFFFF;\r
66                         return mulTable[i] ^ 0xFF;\r
67                 }\r
68 \r
69                 static inline unsigned int div( const unsigned int numerator, const unsigned int divider )\r
70                 {\r
71                         const size_t i = numerator + (divider << 8);\r
72                         return divTable[i];\r
73                 }\r
74                 \r
75                 static inline Color blend( const Color &c1, const Color &c2, unsigned int rate )\r
76                 {\r
77                         const unsigned int inv = 255 - rate;\r
78                         const unsigned int newA = mul( c1.getA(), inv ) + mul( c2.getA(), rate );\r
79                         const unsigned int newR = mul( c1.getR(), inv ) + mul( c2.getR(), rate );\r
80                         const unsigned int newG = mul( c1.getG(), inv ) + mul( c2.getG(), rate );\r
81                         const unsigned int newB = mul( c1.getB(), inv ) + mul( c2.getB(), rate );\r
82                         return Color( newR, newG, newB, newA );\r
83                 }\r
84                 \r
85                 static inline Color interpolate( const Color &c1, const Color &c2, double rate )\r
86                 {\r
87                         const unsigned int r = static_cast<unsigned int>( 255 * rate );\r
88                         return blend( c1, c2, r );\r
89                 }\r
90 \r
91                 static inline Color interpolateHsv( const Color &c1, const Color &c2, double rate )\r
92                 {\r
93                         const unsigned int r = static_cast<unsigned int>( 255 * rate );\r
94                         return blend( c1, c2, r );\r
95                 }\r
96 \r
97                 \r
98                 /**\r
99                  *      2\82Â\82Ì\90F\82ð\8fd\82Ë\8d\87\82í\82¹\82½\90F\82ð\90\90¬\82·\82é.\r
100                  *      @param back     \89º\91w\82Ì\90F\r
101                  *      @param fore \91O\96Ê\82Ì\90F\r
102                  *      @return \8fd\82Ë\8d\87\82í\82¹\82½\90F\r
103                  */\r
104                 static inline Color merge( const Color &back, const Color &fore )\r
105                 {\r
106                         // C = blend( blend( C0, C1, A1), C2, A2 )\r
107                         //   = blend( C0*(1-A1) + C1*A1, C2, A2 )\r
108                         //   = C0*(1-A1)*(1-A2) + C1*A1*(1-A2) + C2*A2\r
109                         //   = blend( C0, {C1*A1*(1-A2) + C2*A2}/{1-(1-A1)*(1-A2)}, 1-(1-A1)*(1-A2) )\r
110                         //       = blend( C0, {C1*A1 + C2*A2 - C1*A1*A2}/scr(A1,A2), scr(A1,A2) )\r
111                         const unsigned int backA = back.getA();\r
112                         if ( backA == 0 ) return Color( fore );\r
113                         const unsigned int foreA = fore.getA();\r
114                         if ( foreA == 0 ) return Color( back );\r
115                         const unsigned int mulA = mul( backA, foreA );\r
116 \r
117                         const unsigned int backR = back.getR();\r
118                         const unsigned int foreR = fore.getR();\r
119                         const unsigned int newR = mul( backR, backA ) + mul( foreR, foreA )\r
120                                                                                 - mul( backR, mulA );\r
121                         const unsigned int backG = back.getG();\r
122                         const unsigned int foreG = fore.getG();\r
123                         const unsigned int newG = mul( backG, backA ) + mul( foreG, foreA )\r
124                                                                                 - mul( backG, mulA ); \r
125                         const unsigned int backB = back.getB();\r
126                         const unsigned int foreB = fore.getB();\r
127                         const unsigned int newB = mul( backB, backA ) + mul( foreB, foreA )\r
128                                                                                 -mul(  backB, mulA );\r
129                         const unsigned int newA = scr( backA, foreA );\r
130                         return Color( div( newR, newA ), \r
131                                                   div( newG, newA ),\r
132                                                   div( newB, newA ), newA );\r
133                 }\r
134         };\r
135 }