├── LICENSE └── aricolor.php /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /aricolor.php: -------------------------------------------------------------------------------- 1 | color = $color; 193 | 194 | if ( is_array( $color ) && isset( $color['fallback'] ) ) { 195 | $this->fallback = $color['fallback']; 196 | $this->fallback_obj = self::newColor( $this->fallback ); 197 | } 198 | 199 | if ( ! method_exists( $this, 'from_' . $mode ) ) { 200 | $mode = $this->get_mode( $color ); 201 | } 202 | 203 | $this->mode = $mode; 204 | 205 | if ( ! $mode ) { 206 | return; 207 | } 208 | 209 | $this->mode = $mode; 210 | $method = 'from_' . $mode; 211 | // Call the from_{$color_mode} method. 212 | $this->$method(); 213 | } 214 | 215 | /** 216 | * Gets an instance for this color. 217 | * We use a separate instance per color 218 | * because there's no need to create a completely new instance each time we call this class. 219 | * Instead using instances helps us improve performance & footprint. 220 | * 221 | * @static 222 | * @access public 223 | * @since 1.0.0 224 | * @param string|array $color The color. 225 | * @param string $mode Mode to be used. 226 | * @return ariColor (object) 227 | */ 228 | public static function newColor( $color, $mode = 'auto' ) { 229 | 230 | // Get an md5 for this color. 231 | $color_md5 = ( is_array( $color ) ) ? md5( json_encode( $color ) . $mode ) : md5( $color . $mode ); 232 | // Set the instance if it does not already exist. 233 | if ( ! isset( self::$instances[ $color_md5 ] ) ) { 234 | self::$instances[ $color_md5 ] = new self( $color, $mode ); 235 | } 236 | return self::$instances[ $color_md5 ]; 237 | } 238 | 239 | /** 240 | * Alias of the newColor method. 241 | * 242 | * @static 243 | * @access public 244 | * @since 1.1 245 | * @param string|array $color The color. 246 | * @param string $mode Mode to be used. 247 | * @return ariColor (object) 248 | */ 249 | public static function new_color( $color, $mode = 'auto' ) { 250 | return self::newColor( $color, $mode ); 251 | } 252 | 253 | /** 254 | * Allows us to get a new instance by modifying a property of the existing one. 255 | * 256 | * @access public 257 | * @since 1.0.0 258 | * @param string $property Can be one of the following: 259 | * red, 260 | * green, 261 | * blue, 262 | * alpha, 263 | * hue, 264 | * saturation, 265 | * lightness, 266 | * brightness. 267 | * @param int|float|string $value The new value. 268 | * @return ariColor|null 269 | */ 270 | public function getNew( $property = '', $value = '' ) { 271 | 272 | if ( in_array( $property, array( 'red', 'green', 'blue', 'alpha' ), true ) ) { 273 | // Check if we're changing any of the rgba values. 274 | $value = max( 0, min( 255, $value ) ); 275 | if ( 'red' === $property ) { 276 | return self::new_color( 'rgba(' . $value . ',' . $this->green . ',' . $this->blue . ',' . $this->alpha . ')', 'rgba' ); 277 | } elseif ( 'green' === $property ) { 278 | return self::new_color( 'rgba(' . $this->red . ',' . $value . ',' . $this->blue . ',' . $this->alpha . ')', 'rgba' ); 279 | } elseif ( 'blue' === $property ) { 280 | return self::new_color( 'rgba(' . $this->red . ',' . $this->green . ',' . $value . ',' . $this->alpha . ')', 'rgba' ); 281 | } elseif ( 'alpha' === $property ) { 282 | return self::new_color( 'rgba(' . $this->red . ',' . $this->green . ',' . $this->blue . ',' . $value . ')', 'rgba' ); 283 | } 284 | } elseif ( in_array( $property, array( 'hue', 'saturation', 'lightness' ), true ) ) { 285 | // Check if we're changing any of the hsl values. 286 | $value = ( 'hue' === $property ) ? max( 0, min( 360, $value ) ) : max( 0, min( 100, $value ) ); 287 | 288 | if ( 'hue' === $property ) { 289 | return self::new_color( 'hsla(' . $value . ',' . $this->saturation . '%,' . $this->lightness . '%,' . $this->alpha . ')', 'hsla' ); 290 | } elseif ( 'saturation' === $property ) { 291 | return self::new_color( 'hsla(' . $this->hue . ',' . $value . '%,' . $this->lightness . '%,' . $this->alpha . ')', 'hsla' ); 292 | } elseif ( 'lightness' === $property ) { 293 | return self::new_color( 'hsla(' . $this->hue . ',' . $this->saturation . '%,' . $value . '%,' . $this->alpha . ')', 'hsla' ); 294 | } 295 | } elseif ( 'brightness' === $property ) { 296 | // Check if we're changing the brightness. 297 | if ( $value < $this->brightness['total'] ) { 298 | $red = max( 0, min( 255, $this->red - ( $this->brightness['total'] - $value ) ) ); 299 | $green = max( 0, min( 255, $this->green - ( $this->brightness['total'] - $value ) ) ); 300 | $blue = max( 0, min( 255, $this->blue - ( $this->brightness['total'] - $value ) ) ); 301 | } elseif ( $value > $this->brightness['total'] ) { 302 | $red = max( 0, min( 255, $this->red + ( $value - $this->brightness['total'] ) ) ); 303 | $green = max( 0, min( 255, $this->green + ( $value - $this->brightness['total'] ) ) ); 304 | $blue = max( 0, min( 255, $this->blue + ( $value - $this->brightness['total'] ) ) ); 305 | } else { 306 | // If it's not smaller and it's not greater, then it's equal. 307 | return $this; 308 | } 309 | return self::new_color( 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $this->alpha . ')', 'rgba' ); 310 | } 311 | return null; 312 | } 313 | 314 | /** 315 | * Allias for the getNew method. 316 | * 317 | * @access public 318 | * @since 1.1.0 319 | * @param string $property Can be one of the following: 320 | * red, 321 | * green, 322 | * blue, 323 | * alpha, 324 | * hue, 325 | * saturation, 326 | * lightness, 327 | * brightness. 328 | * @param int|float|string $value The new value. 329 | * @return ariColor|null 330 | */ 331 | public function get_new( $property = '', $value = '' ) { 332 | return $this->getNew( $property, $value ); 333 | } 334 | 335 | /** 336 | * Figure out what mode we're using. 337 | * 338 | * @access public 339 | * @since 1.0.0 340 | * @param string|array $color The color we're querying. 341 | * @return string 342 | */ 343 | public function get_mode( $color ) { 344 | 345 | // Check if value is an array. 346 | if ( is_array( $color ) ) { 347 | // Does the array have an 'rgba' key? 348 | if ( isset( $color['rgba'] ) ) { 349 | $this->color = $color['rgba']; 350 | return 'rgba'; 351 | } elseif ( isset( $color['color'] ) ) { 352 | // Does the array have a 'color' key? 353 | $this->color = $color['color']; 354 | if ( is_string( $color['color'] ) && false !== strpos( $color['color'], 'rgba' ) ) { 355 | return 'rgba'; 356 | } 357 | return 'hex'; 358 | } 359 | // Is this a simple array with 4 items? 360 | if ( 4 === count( $color ) && isset( $color[0] ) && isset( $color[1] ) && isset( $color[2] ) && isset( $color[3] ) ) { 361 | $this->color = 'rgba(' . intval( $color[0] ) . ',' . intval( $color[1] ) . ',' . intval( $color[2] ) . ',' . intval( $color[3] ) . ')'; 362 | return 'rgba'; 363 | } elseif ( 3 === count( $color ) && isset( $color[0] ) && isset( $color[1] ) && isset( $color[2] ) ) { 364 | // Is this a simple array with 3 items? 365 | $this->color = 'rgba(' . intval( $color[0] ) . ',' . intval( $color[1] ) . ',' . intval( $color[2] ) . ',1)'; 366 | return 'rgba'; 367 | } 368 | 369 | // Check for other keys in the array and get values from there. 370 | $finders_keepers = array( 371 | 'r' => 'red', 372 | 'g' => 'green', 373 | 'b' => 'blue', 374 | 'a' => 'alpha', 375 | 'red' => 'red', 376 | 'green' => 'green', 377 | 'blue' => 'blue', 378 | 'alpha' => 'alpha', 379 | 'opacity' => 'alpha', 380 | ); 381 | $found = false; 382 | foreach ( $finders_keepers as $finder => $keeper ) { 383 | if ( isset( $color[ $finder ] ) ) { 384 | $found = true; 385 | $this->$keeper = $color[ $finder ]; 386 | } 387 | } 388 | 389 | // We failed, use fallback. 390 | if ( ! $found ) { 391 | $this->from_fallback(); 392 | return $this->mode; 393 | } 394 | 395 | // We did not fail, so use rgba values recovered above. 396 | $this->color = 'rgba(' . $this->red . ',' . $this->green . ',' . $this->blue . ',' . $this->alpha . ')'; 397 | return 'rgba'; 398 | } 399 | 400 | $color = trim( strtolower( $color ) ); 401 | 402 | if ( 'transparent' === $color ) { 403 | $color = 'rgba(255,255,255,0)'; 404 | $this->color = $color; 405 | } 406 | 407 | // If the color contains 3 or 6 hex numbers, prepend #. 408 | if ( preg_match( '|^([0-9a-f]{3}){1,2}$|', $color ) ) { 409 | $color = '#' . $color; 410 | $this->color = $color; 411 | } 412 | 413 | // If we got this far, it's not an array. 414 | // Check for key identifiers in the value. 415 | $finders_keepers = array( 416 | '#' => 'hex', 417 | 'rgba' => 'rgba', 418 | 'rgb' => 'rgb', 419 | 'hsla' => 'hsla', 420 | 'hsl' => 'hsl', 421 | ); 422 | foreach ( $finders_keepers as $finder => $keeper ) { 423 | if ( false !== strrpos( $color, $finder ) ) { 424 | 425 | // Make sure hex colors have 6 digits and not more. 426 | if ( '#' === $finder && 7 < strlen( $color ) ) { 427 | $this->color = substr( $color, 0, 7 ); 428 | } 429 | 430 | return $keeper; 431 | } 432 | } 433 | // Perhaps we're using a word like "orange"? 434 | $wordcolors = $this->get_word_colors(); 435 | if ( array_key_exists( $color, $wordcolors ) ) { 436 | $this->color = '#' . $wordcolors[ $color ]; 437 | return 'hex'; 438 | } 439 | // Fallback to hex. 440 | 441 | $this->color = $this->fallback; 442 | return 'hex'; 443 | } 444 | 445 | /** 446 | * Sanitize a hex color. 447 | * 448 | * @param string $color The color we want to sanitize. 449 | * @return string 450 | */ 451 | protected function sanitize_hex_color( $color ) { 452 | $color = '#' . ltrim( $color, '#' ); 453 | if ( '#' === $color ) { 454 | return ''; 455 | } 456 | // 3 or 6 hex digits, or the empty string. 457 | if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) { 458 | return $color; 459 | } 460 | return ''; 461 | } 462 | 463 | /** 464 | * Starts with a HEX color and calculates all other properties. 465 | * 466 | * @access protected 467 | * @since 1.0.0 468 | * @return void 469 | */ 470 | protected function from_hex() { 471 | 472 | // Is this perhaps a word-color? 473 | $word_colors = $this->get_word_colors(); 474 | if ( array_key_exists( $this->color, $word_colors ) ) { 475 | $this->color = '#' . $word_colors[ $this->color ]; 476 | } 477 | // Sanitize color. 478 | $this->hex = $this->sanitize_hex_color( $this->color ); 479 | $hex = ltrim( $this->hex, '#' ); 480 | 481 | // Fallback if needed. 482 | if ( ! $hex || 3 > strlen( $hex ) ) { 483 | $this->from_fallback(); 484 | return; 485 | } 486 | // Make sure we have 6 digits for the below calculations. 487 | if ( 3 === strlen( $hex ) ) { 488 | $hex = ltrim( $this->hex, '#' ); 489 | $hex = substr( $hex, 0, 1 ) . substr( $hex, 0, 1 ) . substr( $hex, 1, 1 ) . substr( $hex, 1, 1 ) . substr( $hex, 2, 1 ) . substr( $hex, 2, 1 ); 490 | } 491 | 492 | // Set red, green, blue. 493 | $this->red = hexdec( substr( $hex, 0, 2 ) ); 494 | $this->green = hexdec( substr( $hex, 2, 2 ) ); 495 | $this->blue = hexdec( substr( $hex, 4, 2 ) ); 496 | $this->alpha = 1; 497 | // Set other color properties. 498 | $this->set_brightness(); 499 | $this->set_hsl(); 500 | $this->set_luminance(); 501 | 502 | } 503 | 504 | /** 505 | * Starts with an RGB color and calculates all other properties. 506 | * 507 | * @access protected 508 | * @since 1.0.0 509 | * @return void 510 | */ 511 | protected function from_rgb() { 512 | $value = explode( ',', str_replace( array( ' ', 'rgb', '(', ')' ), '', $this->color ) ); 513 | // Set red, green, blue. 514 | $this->red = ( isset( $value[0] ) ) ? intval( $value[0] ) : 255; 515 | $this->green = ( isset( $value[1] ) ) ? intval( $value[1] ) : 255; 516 | $this->blue = ( isset( $value[2] ) ) ? intval( $value[2] ) : 255; 517 | $this->alpha = 1; 518 | // Set the hex. 519 | $this->hex = $this->rgb_to_hex( $this->red, $this->green, $this->blue ); 520 | // Set other color properties. 521 | $this->set_brightness(); 522 | $this->set_hsl(); 523 | $this->set_luminance(); 524 | } 525 | 526 | /** 527 | * Starts with an RGBA color and calculates all other properties. 528 | * 529 | * @access protected 530 | * @since 1.0.0 531 | * @return void 532 | */ 533 | protected function from_rgba() { 534 | // Set r, g, b, a properties. 535 | $value = explode( ',', str_replace( array( ' ', 'rgba', '(', ')' ), '', $this->color ) ); 536 | $this->red = ( isset( $value[0] ) ) ? intval( $value[0] ) : 255; 537 | $this->green = ( isset( $value[1] ) ) ? intval( $value[1] ) : 255; 538 | $this->blue = ( isset( $value[2] ) ) ? intval( $value[2] ) : 255; 539 | $this->alpha = ( isset( $value[3] ) ) ? filter_var( $value[3], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION ) : 1; 540 | // Limit values in the range of 0 - 255. 541 | $this->red = max( 0, min( 255, $this->red ) ); 542 | $this->green = max( 0, min( 255, $this->green ) ); 543 | $this->blue = max( 0, min( 255, $this->blue ) ); 544 | // Limit values 0 - 1. 545 | $this->alpha = max( 0, min( 1, $this->alpha ) ); 546 | // Set hex. 547 | $this->hex = $this->rgb_to_hex( $this->red, $this->green, $this->blue ); 548 | // Set other color properties. 549 | $this->set_brightness(); 550 | $this->set_hsl(); 551 | $this->set_luminance(); 552 | } 553 | 554 | /** 555 | * Starts with an HSL color and calculates all other properties. 556 | * 557 | * @access protected 558 | * @since 1.0.0 559 | * @return void 560 | */ 561 | protected function from_hsl() { 562 | $value = explode( ',', str_replace( array( ' ', 'hsl', '(', ')', '%' ), '', $this->color ) ); 563 | $this->hue = $value[0]; 564 | $this->saturation = $value[1]; 565 | $this->lightness = $value[2]; 566 | $this->from_hsl_array(); 567 | } 568 | 569 | /** 570 | * Starts with an HSLA color and calculates all other properties. 571 | * 572 | * @access protected 573 | * @since 1.0.0 574 | * @return void 575 | */ 576 | protected function from_hsla() { 577 | $value = explode( ',', str_replace( array( ' ', 'hsla', '(', ')', '%' ), '', $this->color ) ); 578 | $this->hue = $value[0]; 579 | $this->saturation = $value[1]; 580 | $this->lightness = $value[2]; 581 | $this->alpha = $value[3]; 582 | $this->from_hsl_array(); 583 | } 584 | 585 | /** 586 | * Generates the HEX value of a color given values for $red, $green, $blue. 587 | * 588 | * @access protected 589 | * @since 1.0.0 590 | * @param int|string $red The red value of this color. 591 | * @param int|string $green The green value of this color. 592 | * @param int|string $blue The blue value of this color. 593 | * @return string 594 | */ 595 | protected function rgb_to_hex( $red, $green, $blue ) { 596 | // Get hex values properly formatted. 597 | $hex_red = $this->dexhex_double_digit( $red ); 598 | $hex_green = $this->dexhex_double_digit( $green ); 599 | $hex_blue = $this->dexhex_double_digit( $blue ); 600 | return '#' . $hex_red . $hex_green . $hex_blue; 601 | } 602 | 603 | /** 604 | * Convert a decimal value to hex and make sure it's 2 characters. 605 | * 606 | * @access protected 607 | * @since 1.0.0 608 | * @param int|string $value The value to convert. 609 | * @return string 610 | */ 611 | protected function dexhex_double_digit( $value ) { 612 | $value = dechex( $value ); 613 | if ( 1 === strlen( $value ) ) { 614 | $value = '0' . $value; 615 | } 616 | return $value; 617 | } 618 | 619 | /** 620 | * Calculates the red, green, blue values of an HSL color. 621 | * 622 | * @access protected 623 | * @since 1.0.0 624 | * @see https://gist.github.com/brandonheyer/5254516 625 | */ 626 | protected function from_hsl_array() { 627 | $h = $this->hue / 360; 628 | $s = $this->saturation / 100; 629 | $l = $this->lightness / 100; 630 | 631 | $r = $l; 632 | $g = $l; 633 | $b = $l; 634 | $v = ( $l <= 0.5 ) ? ( $l * ( 1.0 + $s ) ) : ( $l + $s - $l * $s ); 635 | if ( $v > 0 ) { 636 | $m = $l + $l - $v; 637 | $sv = ( $v - $m ) / $v; 638 | $h *= 6.0; 639 | $sextant = floor( $h ); 640 | $fract = $h - $sextant; 641 | $vsf = $v * $sv * $fract; 642 | $mid1 = $m + $vsf; 643 | $mid2 = $v - $vsf; 644 | switch ( $sextant ) { 645 | case 0: 646 | $r = $v; 647 | $g = $mid1; 648 | $b = $m; 649 | break; 650 | case 1: 651 | $r = $mid2; 652 | $g = $v; 653 | $b = $m; 654 | break; 655 | case 2: 656 | $r = $m; 657 | $g = $v; 658 | $b = $mid1; 659 | break; 660 | case 3: 661 | $r = $m; 662 | $g = $mid2; 663 | $b = $v; 664 | break; 665 | case 4: 666 | $r = $mid1; 667 | $g = $m; 668 | $b = $v; 669 | break; 670 | case 5: 671 | $r = $v; 672 | $g = $m; 673 | $b = $mid2; 674 | break; 675 | } 676 | } 677 | $this->red = round( $r * 255, 0 ); 678 | $this->green = round( $g * 255, 0 ); 679 | $this->blue = round( $b * 255, 0 ); 680 | 681 | $this->hex = $this->rgb_to_hex( $this->red, $this->green, $this->blue ); 682 | $this->set_luminance(); 683 | } 684 | 685 | /** 686 | * Returns a CSS-formatted value for colors. 687 | * 688 | * @access public 689 | * @since 1.0.0 690 | * @param string $mode The mode we're using. 691 | * @return string 692 | */ 693 | public function toCSS( $mode = 'hex' ) { 694 | 695 | $value = ''; 696 | 697 | switch ( $mode ) { 698 | case 'hex': 699 | $value = strtolower( $this->hex ); 700 | break; 701 | case 'rgba': 702 | $value = 'rgba(' . $this->red . ',' . $this->green . ',' . $this->blue . ',' . $this->alpha . ')'; 703 | break; 704 | case 'rgb': 705 | $value = 'rgb(' . $this->red . ',' . $this->green . ',' . $this->blue . ')'; 706 | break; 707 | case 'hsl': 708 | $value = 'hsl(' . $this->hue . ',' . round( $this->saturation ) . '%,' . round( $this->lightness ) . '%)'; 709 | break; 710 | case 'hsla': 711 | $value = 'hsla(' . $this->hue . ',' . round( $this->saturation ) . '%,' . round( $this->lightness ) . '%,' . $this->alpha . ')'; 712 | break; 713 | } 714 | return $value; 715 | } 716 | 717 | /** 718 | * Alias for the toCSS method. 719 | * 720 | * @access public 721 | * @since 1.1 722 | * @param string $mode The mode we're using. 723 | * @return string 724 | */ 725 | public function to_css( $mode = 'hex' ) { 726 | return $this->toCSS( $mode ); 727 | } 728 | 729 | /** 730 | * Sets the HSL values of a color based on the values of red, green, blue. 731 | * 732 | * @access public 733 | * @since 1.0.0 734 | */ 735 | protected function set_hsl() { 736 | $red = $this->red / 255; 737 | $green = $this->green / 255; 738 | $blue = $this->blue / 255; 739 | 740 | $max = max( $red, $green, $blue ); 741 | $min = min( $red, $green, $blue ); 742 | 743 | $lightness = ( $max + $min ) / 2; 744 | $difference = $max - $min; 745 | 746 | if ( ! $difference ) { 747 | $hue = $saturation = 0; // Achromatic. 748 | } else { 749 | $saturation = $difference / ( 1 - abs( 2 * $lightness - 1 ) ); 750 | switch ( $max ) { 751 | case $red: 752 | $hue = 60 * fmod( ( ( $green - $blue ) / $difference ), 6 ); 753 | if ( $blue > $green ) { 754 | $hue += 360; 755 | } 756 | break; 757 | case $green: 758 | $hue = 60 * ( ( $blue - $red ) / $difference + 2 ); 759 | break; 760 | case $blue: 761 | $hue = 60 * ( ( $red - $green ) / $difference + 4 ); 762 | break; 763 | } 764 | } 765 | 766 | $this->hue = round( $hue ); 767 | $this->saturation = round( $saturation * 100 ); 768 | $this->lightness = round( $lightness * 100 ); 769 | } 770 | 771 | /** 772 | * Sets the brightness of a color based on the values of red, green, blue. 773 | * 774 | * @access protected 775 | * @since 1.0.0 776 | */ 777 | protected function set_brightness() { 778 | $this->brightness = array( 779 | 'red' => round( $this->red * .299 ), 780 | 'green' => round( $this->green * .587 ), 781 | 'blue' => round( $this->blue * .114 ), 782 | 'total' => intval( ( $this->red * .299 ) + ( $this->green * .587 ) + ( $this->blue * .114 ) ), 783 | ); 784 | } 785 | 786 | /** 787 | * Sets the luminance of a color (range:0-255) based on the values of red, green, blue. 788 | * 789 | * @access protected 790 | * @since 1.0.0 791 | */ 792 | protected function set_luminance() { 793 | $lum = ( 0.2126 * $this->red ) + ( 0.7152 * $this->green ) + ( 0.0722 * $this->blue ); 794 | $this->luminance = round( $lum ); 795 | } 796 | 797 | /** 798 | * Gets an array of all the wordcolors. 799 | * 800 | * @access protected 801 | * @since 1.0.0 802 | * @return array 803 | */ 804 | protected function get_word_colors() { 805 | return array( 806 | 'aliceblue' => 'F0F8FF', 807 | 'antiquewhite' => 'FAEBD7', 808 | 'aqua' => '00FFFF', 809 | 'aquamarine' => '7FFFD4', 810 | 'azure' => 'F0FFFF', 811 | 'beige' => 'F5F5DC', 812 | 'bisque' => 'FFE4C4', 813 | 'black' => '000000', 814 | 'blanchedalmond' => 'FFEBCD', 815 | 'blue' => '0000FF', 816 | 'blueviolet' => '8A2BE2', 817 | 'brown' => 'A52A2A', 818 | 'burlywood' => 'DEB887', 819 | 'cadetblue' => '5F9EA0', 820 | 'chartreuse' => '7FFF00', 821 | 'chocolate' => 'D2691E', 822 | 'coral' => 'FF7F50', 823 | 'cornflowerblue' => '6495ED', 824 | 'cornsilk' => 'FFF8DC', 825 | 'crimson' => 'DC143C', 826 | 'cyan' => '00FFFF', 827 | 'darkblue' => '00008B', 828 | 'darkcyan' => '008B8B', 829 | 'darkgoldenrod' => 'B8860B', 830 | 'darkgray' => 'A9A9A9', 831 | 'darkgreen' => '006400', 832 | 'darkgrey' => 'A9A9A9', 833 | 'darkkhaki' => 'BDB76B', 834 | 'darkmagenta' => '8B008B', 835 | 'darkolivegreen' => '556B2F', 836 | 'darkorange' => 'FF8C00', 837 | 'darkorchid' => '9932CC', 838 | 'darkred' => '8B0000', 839 | 'darksalmon' => 'E9967A', 840 | 'darkseagreen' => '8FBC8F', 841 | 'darkslateblue' => '483D8B', 842 | 'darkslategray' => '2F4F4F', 843 | 'darkslategrey' => '2F4F4F', 844 | 'darkturquoise' => '00CED1', 845 | 'darkviolet' => '9400D3', 846 | 'deeppink' => 'FF1493', 847 | 'deepskyblue' => '00BFFF', 848 | 'dimgray' => '696969', 849 | 'dimgrey' => '696969', 850 | 'dodgerblue' => '1E90FF', 851 | 'firebrick' => 'B22222', 852 | 'floralwhite' => 'FFFAF0', 853 | 'forestgreen' => '228B22', 854 | 'fuchsia' => 'FF00FF', 855 | 'gainsboro' => 'DCDCDC', 856 | 'ghostwhite' => 'F8F8FF', 857 | 'gold' => 'FFD700', 858 | 'goldenrod' => 'DAA520', 859 | 'gray' => '808080', 860 | 'green' => '008000', 861 | 'greenyellow' => 'ADFF2F', 862 | 'grey' => '808080', 863 | 'honeydew' => 'F0FFF0', 864 | 'hotpink' => 'FF69B4', 865 | 'indianred' => 'CD5C5C', 866 | 'indigo' => '4B0082', 867 | 'ivory' => 'FFFFF0', 868 | 'khaki' => 'F0E68C', 869 | 'lavender' => 'E6E6FA', 870 | 'lavenderblush' => 'FFF0F5', 871 | 'lawngreen' => '7CFC00', 872 | 'lemonchiffon' => 'FFFACD', 873 | 'lightblue' => 'ADD8E6', 874 | 'lightcoral' => 'F08080', 875 | 'lightcyan' => 'E0FFFF', 876 | 'lightgoldenrodyellow' => 'FAFAD2', 877 | 'lightgray' => 'D3D3D3', 878 | 'lightgreen' => '90EE90', 879 | 'lightgrey' => 'D3D3D3', 880 | 'lightpink' => 'FFB6C1', 881 | 'lightsalmon' => 'FFA07A', 882 | 'lightseagreen' => '20B2AA', 883 | 'lightskyblue' => '87CEFA', 884 | 'lightslategray' => '778899', 885 | 'lightslategrey' => '778899', 886 | 'lightsteelblue' => 'B0C4DE', 887 | 'lightyellow' => 'FFFFE0', 888 | 'lime' => '00FF00', 889 | 'limegreen' => '32CD32', 890 | 'linen' => 'FAF0E6', 891 | 'magenta' => 'FF00FF', 892 | 'maroon' => '800000', 893 | 'mediumaquamarine' => '66CDAA', 894 | 'mediumblue' => '0000CD', 895 | 'mediumorchid' => 'BA55D3', 896 | 'mediumpurple' => '9370D0', 897 | 'mediumseagreen' => '3CB371', 898 | 'mediumslateblue' => '7B68EE', 899 | 'mediumspringgreen' => '00FA9A', 900 | 'mediumturquoise' => '48D1CC', 901 | 'mediumvioletred' => 'C71585', 902 | 'midnightblue' => '191970', 903 | 'mintcream' => 'F5FFFA', 904 | 'mistyrose' => 'FFE4E1', 905 | 'moccasin' => 'FFE4B5', 906 | 'navajowhite' => 'FFDEAD', 907 | 'navy' => '000080', 908 | 'oldlace' => 'FDF5E6', 909 | 'olive' => '808000', 910 | 'olivedrab' => '6B8E23', 911 | 'orange' => 'FFA500', 912 | 'orangered' => 'FF4500', 913 | 'orchid' => 'DA70D6', 914 | 'palegoldenrod' => 'EEE8AA', 915 | 'palegreen' => '98FB98', 916 | 'paleturquoise' => 'AFEEEE', 917 | 'palevioletred' => 'DB7093', 918 | 'papayawhip' => 'FFEFD5', 919 | 'peachpuff' => 'FFDAB9', 920 | 'peru' => 'CD853F', 921 | 'pink' => 'FFC0CB', 922 | 'plum' => 'DDA0DD', 923 | 'powderblue' => 'B0E0E6', 924 | 'purple' => '800080', 925 | 'red' => 'FF0000', 926 | 'rosybrown' => 'BC8F8F', 927 | 'royalblue' => '4169E1', 928 | 'saddlebrown' => '8B4513', 929 | 'salmon' => 'FA8072', 930 | 'sandybrown' => 'F4A460', 931 | 'seagreen' => '2E8B57', 932 | 'seashell' => 'FFF5EE', 933 | 'sienna' => 'A0522D', 934 | 'silver' => 'C0C0C0', 935 | 'skyblue' => '87CEEB', 936 | 'slateblue' => '6A5ACD', 937 | 'slategray' => '708090', 938 | 'slategrey' => '708090', 939 | 'snow' => 'FFFAFA', 940 | 'springgreen' => '00FF7F', 941 | 'steelblue' => '4682B4', 942 | 'tan' => 'D2B48C', 943 | 'teal' => '008080', 944 | 'thistle' => 'D8BFD8', 945 | 'tomato' => 'FF6347', 946 | 'turquoise' => '40E0D0', 947 | 'violet' => 'EE82EE', 948 | 'wheat' => 'F5DEB3', 949 | 'white' => 'FFFFFF', 950 | 'whitesmoke' => 'F5F5F5', 951 | 'yellow' => 'FFFF00', 952 | 'yellowgreen' => '9ACD32', 953 | ); 954 | 955 | } 956 | 957 | /** 958 | * Use fallback object. 959 | * 960 | * @access protected 961 | * @since 1.2.0 962 | */ 963 | protected function from_fallback() { 964 | $this->color = $this->fallback; 965 | 966 | if ( ! $this->fallback_obj ) { 967 | $this->fallback_obj = self::newColor( $this->fallback ); 968 | } 969 | $this->color = $this->fallback_obj->color; 970 | $this->mode = $this->fallback_obj->mode; 971 | $this->red = $this->fallback_obj->red; 972 | $this->green = $this->fallback_obj->green; 973 | $this->blue = $this->fallback_obj->blue; 974 | $this->alpha = $this->fallback_obj->alpha; 975 | $this->hue = $this->fallback_obj->hue; 976 | $this->saturation = $this->fallback_obj->saturation; 977 | $this->lightness = $this->fallback_obj->lightness; 978 | $this->luminance = $this->fallback_obj->luminance; 979 | $this->hex = $this->fallback_obj->hex; 980 | } 981 | 982 | /** 983 | * Handle non-existing public methods. 984 | * 985 | * @access public 986 | * @since 1.1.0 987 | * @param string $name The method name. 988 | * @param mixed $arguments The method arguments. 989 | * @return mixed 990 | */ 991 | public function __call( $name, $arguments ) { 992 | if ( method_exists( $this, $name ) ) { 993 | call_user_func( array( $this, $name ), $arguments ); 994 | } else { 995 | return $arguments; 996 | } 997 | } 998 | 999 | /** 1000 | * Handle non-existing public static methods. 1001 | * 1002 | * @static 1003 | * @access public 1004 | * @since 1.1.0 1005 | * @param string $name The method name. 1006 | * @param mixed $arguments The method arguments. 1007 | * @return mixed 1008 | */ 1009 | public static function __callStatic( $name, $arguments ) { 1010 | if ( method_exists( __CLASS__, $name ) ) { 1011 | call_user_func( array( __CLASS__, $name ), $arguments ); 1012 | } else { 1013 | return $arguments; 1014 | } 1015 | } 1016 | } 1017 | } 1018 | --------------------------------------------------------------------------------