559 | * var same = PixelFormat.convert(argb, PixelFormat.ARGB, PixelFormat.ARGB); // 0xAA2266BB
560 | * var rgba = PixelFormat.convert(same, PixelFormat.ARGB, PixelFormat.RGBA); // 0x2266BBAA
561 | * var bgra = PixelFormat.convert(rgba, PixelFormat.RGBA, PixelFormat.BGRA); // 0xBB6622AA
562 | * var back = PixelFormat.convert(bgra, PixelFormat.BGRA, PixelFormat.ARGB); // 0xAA2266BB
563 | * var rgba2 = PixelFormat.convert(bgra, PixelFormat.BGRA, PixelFormat.RGBA); // 0x2266BBAA`
564 | *
565 | */
566 | static public function convert(px:Pixel, fromFormat:PixelFormat, toFormat:PixelFormat):Pixel {
567 | return
568 | (((px >> (8 * (Pixels.CHANNEL_MASK - fromFormat.A))) & 0xFF) << (8 * (Pixels.CHANNEL_MASK - toFormat.A))) |
569 | (((px >> (8 * (Pixels.CHANNEL_MASK - fromFormat.R))) & 0xFF) << (8 * (Pixels.CHANNEL_MASK - toFormat.R))) |
570 | (((px >> (8 * (Pixels.CHANNEL_MASK - fromFormat.G))) & 0xFF) << (8 * (Pixels.CHANNEL_MASK - toFormat.G))) |
571 | (((px >> (8 * (Pixels.CHANNEL_MASK - fromFormat.B))) & 0xFF) << (8 * (Pixels.CHANNEL_MASK - toFormat.B)));
572 | }
573 |
574 | inline static public function getNativeFormatFor(target:TargetType):PixelFormat {
575 | return switch (target) {
576 | case FORMAT:
577 | BGRA;
578 | case FLASH, NME_FLASH, NME_DESKTOP, OPENFL_FLASH, FLAMBE_FLASH:
579 | ARGB;
580 | case OPENFL_DESKTOP:
581 | BGRA;
582 | case JS, OPENFL_JS, LUXE, FLAMBE_WEB:
583 | RGBA;
584 | case JAVA:
585 | RGBA;
586 | default:
587 | throw "Unhandled target!";
588 | }
589 | }
590 |
591 | inline public function new(a:Channel, r:Channel, g:Channel, b:Channel, name:String = "PixelFormat"):Void {
592 | this.channelMap = [a, r, g, b];
593 | this.ch0 = a;
594 | this.ch1 = r;
595 | this.ch2 = g;
596 | this.ch3 = b;
597 | this.name = name;
598 | }
599 |
600 | public var A(get, null):Channel;
601 | inline private function get_A():Channel {
602 | return ch0;
603 | }
604 |
605 | public var R(get, null):Channel;
606 | inline private function get_R():Channel {
607 | return ch1;
608 | }
609 |
610 | public var G(get, null):Channel;
611 | inline private function get_G():Channel {
612 | return ch2;
613 | }
614 |
615 | public var B(get, null):Channel;
616 | inline private function get_B():Channel {
617 | return ch3;
618 | }
619 |
620 | public function toString():String {
621 | return name;
622 | }
623 | }
624 |
625 | @:enum abstract Channel(Int) to Int {
626 |
627 | static public var MASK = [0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF];
628 |
629 | var CH_0 = 0;
630 | var CH_1 = 1;
631 | var CH_2 = 2;
632 | var CH_3 = 3;
633 |
634 | @:op(A + B) static function add(a:Int, b:Channel):Int;
635 | }
636 |
637 | /**
638 | * Abstracts an ARGB pixel over Int.
639 | *
640 | * NOTE: it's just a convenience class to easily access ARGB channels' values (wrapping bit math).
641 | * Since it's built on top of a primitive (value) type, be careful with what you expect when
642 | * assigning to it. In particular consider that:
643 | *
644 | * `pixels.getPixel32(10, 10).R = 0xFF;`
645 | *
646 | * will NOT modify the actual pixel (but just an Int copy/representation of it!)
647 | *
648 | * What you really want is probably:
649 | *
650 | * `var pixel = pixels.getPixel32(10, 10);
651 | * pixel.R = 0xFF; // or pixel.fR = 1.0;
652 | * pixels.setPixel32(10, 10, pixel);`
653 | *
654 | * Also note that, for performance reasons, no clamping is performed when setting values, i.e.:
655 | *
656 | * `pixel.B = 0xFFFF;`
657 | *
658 | * is perfectly valid, but will probably result in unwanted behaviour.
659 | */
660 | @:expose
661 | @:forward
662 | @:native("Pixel")
663 | abstract Pixel(Int) from Int to Int
664 | {
665 | inline static public function fclamp(value:Float):Float {
666 | if (value <= 0.) return 0.;
667 | else if (value >= 1.) return 1.;
668 | else return value;
669 | }
670 |
671 | inline static public function iclamp(value:Int):Int {
672 | if (value <= 0) return 0;
673 | else if (value >= 255) return 255;
674 | else return value;
675 | }
676 |
677 | inline static public function iround(value:Float):Int {
678 | return Std.int(value + .5);
679 | }
680 |
681 | inline public function multiplyAlpha():Pixel {
682 | var fA = (this:Pixel).fA;
683 | return
684 | (this & 0xFF000000) |
685 | (iclamp(iround(fA * (this:Pixel).R)) << 16) |
686 | (iclamp(iround(fA * (this:Pixel).G)) << 8) |
687 | (iclamp(iround(fA * (this:Pixel).B)));
688 | }
689 |
690 | inline public function unmultiplyAlpha():Pixel {
691 | var inv_fA = 1. / ((this:Pixel).fA + 0.00000001); // inc fA to avoid divide_by_zero special case
692 | return
693 | (this & 0xFF000000) |
694 | (iclamp(iround(inv_fA * (this:Pixel).R)) << 16) |
695 | (iclamp(iround(inv_fA * (this:Pixel).G)) << 8) |
696 | (iclamp(iround(inv_fA * (this:Pixel).B)));
697 | }
698 |
699 | inline static public function create(a:Int, r:Int, g:Int, b:Int):Pixel {
700 | return ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | b;
701 | }
702 |
703 | inline static public function fcreate(a:Float, r:Float, g:Float, b:Float):Pixel {
704 | return create(Std.int(a * 255.), Std.int(r * 255.), Std.int(g * 255.), Std.int(b * 255.));
705 | }
706 |
707 | inline public function getChannel(ch:Channel):Int {
708 | return (this >> (8 * (Pixels.CHANNEL_MASK - ch))) & 0xFF;
709 | }
710 |
711 | inline public function setChannel(ch:Channel, value:Int):Int {
712 | this = (this & ~Channel.MASK[ch]) | (value << (8 * (Pixels.CHANNEL_MASK - ch)));
713 | return value;
714 | }
715 |
716 | public var A(get, set):Int;
717 | inline private function get_A():Int {
718 | return (this >> 24) & 0xFF;
719 | }
720 | inline private function set_A(a:Int):Int {
721 | this = (this & 0x00FFFFFF) | (a << 24);
722 | return a;
723 | }
724 |
725 | public var R(get, set):Int;
726 | inline private function get_R():Int {
727 | return (this >> 16) & 0xFF;
728 | }
729 | inline private function set_R(r:Int):Int {
730 | this = (this & 0xFF00FFFF) | (r << 16);
731 | return r;
732 | }
733 |
734 | public var G(get, set):Int;
735 | inline private function get_G():Int {
736 | return (this >> 8) & 0xFF;
737 | }
738 | inline private function set_G(g:Int):Int {
739 | this = (this & 0xFFFF00FF) | (g << 8);
740 | return g;
741 | }
742 |
743 | public var B(get, set):Int;
744 | inline private function get_B():Int {
745 | return this & 0xFF;
746 | }
747 | inline private function set_B(b:Int):Int {
748 | this = (this & 0xFFFFFF00) | b;
749 | return b;
750 | }
751 |
752 | // channels as floats (expected range is [0...1])
753 | public var fA(get, set):Float;
754 | inline private function get_fA():Float {
755 | return (this : Pixel).A / 255.;
756 | }
757 | inline private function set_fA(a:Float):Float {
758 | this = (this & 0x00FFFFFF) | (Std.int(a * 255) << 24);
759 | return a;
760 | }
761 |
762 | public var fR(get, set):Float;
763 | inline private function get_fR():Float {
764 | return (this : Pixel).R / 255.;
765 | }
766 | inline private function set_fR(r:Float):Float {
767 | this = (this & 0xFF00FFFF) | (Std.int(r * 255) << 16);
768 | return r;
769 | }
770 |
771 | public var fG(get, set):Float;
772 | inline private function get_fG():Float {
773 | return (this : Pixel).G / 255.;
774 | }
775 | inline private function set_fG(g:Float):Float {
776 | this = (this & 0xFFFF00FF) | (Std.int(g * 255) << 8);
777 | return g;
778 | }
779 |
780 | public var fB(get, set):Float;
781 | inline private function get_fB():Float {
782 | return (this : Pixel).B / 255.;
783 | }
784 | inline private function set_fB(b:Float):Float {
785 | this = (this & 0xFFFFFF00) | (Std.int(b * 255));
786 | return b;
787 | }
788 |
789 | // forward operators from Int (same order used in std/Int32)
790 | @:op(-A) function negate():Pixel;
791 | @:op(++A) function preIncrement():Pixel;
792 | @:op(A++) function postIncrement():Pixel;
793 | @:op(--A) function preDecrement():Pixel;
794 | @:op(A--) function postDecrement():Pixel;
795 |
796 | @:op(A + B) static function add(a:Pixel, b:Pixel):Pixel;
797 | @:op(A + B) @:commutative static function addInt(a:Pixel, b:Int):Pixel;
798 | @:op(A + B) @:commutative static function addFloat(a:Pixel, b:Float):Float;
799 | @:op(A - B) static function sub(a:Pixel, b:Pixel):Pixel;
800 | @:op(A - B) static function subInt(a:Pixel, b:Int):Pixel;
801 | @:op(A - B) static function intSub(a:Int, b:Pixel):Pixel;
802 | @:op(A - B) static function subFloat(a:Pixel, b:Float):Float;
803 | @:op(A - B) static function floatSub(a:Float, b:Pixel):Float;
804 | @:op(A * B) static function mul(a:Pixel, b:Pixel):Pixel;
805 | @:op(A * B) @:commutative static function mulInt(a:Pixel, b:Int):Pixel;
806 | @:op(A * B) static function mul(a:Pixel, b:Pixel):Pixel;
807 | @:op(A * B) @:commutative static function mulInt(a:Pixel, b:Int):Pixel;
808 | @:op(A * B) @:commutative static function mulFloat(a:Pixel, b:Float):Float;
809 | @:op(A / B) static function div(a:Pixel, b:Pixel):Float;
810 | @:op(A / B) static function divInt(a:Pixel, b:Int):Float;
811 | @:op(A / B) static function intDiv(a:Int, b:Pixel):Float;
812 | @:op(A / B) static function divFloat(a:Pixel, b:Float):Float;
813 | @:op(A / B) static function floatDiv(a:Float, b:Pixel):Float;
814 |
815 | @:op(A % B) static function mod(a:Pixel, b:Pixel):Pixel;
816 | @:op(A % B) static function modInt(a:Pixel, b:Int):Int;
817 | @:op(A % B) static function intMod(a:Int, b:Pixel):Int;
818 | @:op(A % B) static function modFloat(a:Pixel, b:Float):Float;
819 | @:op(A % B) static function floatMod(a:Float, b:Pixel):Float;
820 |
821 | @:op(A == B) static function eq(a:Pixel, b:Pixel):Bool;
822 | @:op(A == B) @:commutative static function eqInt(a:Pixel, b:Int):Bool;
823 | @:op(A == B) @:commutative static function eqFloat(a:Pixel, b:Float):Bool;
824 |
825 | @:op(A != B) static function neq(a:Pixel, b:Pixel):Bool;
826 | @:op(A != B) @:commutative static function neqInt(a:Pixel, b:Int):Bool;
827 | @:op(A != B) @:commutative static function neqFloat(a:Pixel, b:Float):Bool;
828 |
829 | @:op(A < B) static function lt(a:Pixel, b:Pixel):Bool;
830 | @:op(A < B) static function ltInt(a:Pixel, b:Int):Bool;
831 | @:op(A < B) static function intLt(a:Int, b:Pixel):Bool;
832 | @:op(A < B) static function ltFloat(a:Pixel, b:Float):Bool;
833 | @:op(A < B) static function floatLt(a:Float, b:Pixel):Bool;
834 |
835 | @:op(A <= B) static function lte(a:Pixel, b:Pixel):Bool;
836 | @:op(A <= B) static function lteInt(a:Pixel, b:Int):Bool;
837 | @:op(A <= B) static function intLte(a:Int, b:Pixel):Bool;
838 | @:op(A <= B) static function lteFloat(a:Pixel, b:Float):Bool;
839 | @:op(A <= B) static function floatLte(a:Float, b:Pixel):Bool;
840 |
841 | @:op(A > B) static function gt(a:Pixel, b:Pixel):Bool;
842 | @:op(A > B) static function gtInt(a:Pixel, b:Int):Bool;
843 | @:op(A > B) static function intGt(a:Int, b:Pixel):Bool;
844 | @:op(A > B) static function gtFloat(a:Pixel, b:Float):Bool;
845 | @:op(A > B) static function floatGt(a:Float, b:Pixel):Bool;
846 |
847 | @:op(A >= B) static function gte(a:Pixel, b:Pixel):Bool;
848 | @:op(A >= B) static function gteInt(a:Pixel, b:Int):Bool;
849 | @:op(A >= B) static function intGte(a:Int, b:Pixel):Bool;
850 | @:op(A >= B) static function gteFloat(a:Pixel, b:Float):Bool;
851 | @:op(A >= B) static function floatGte(a:Float, b:Pixel):Bool;
852 |
853 | @:op(~A) function complement():Pixel;
854 |
855 | @:op(A & B) static function and(a:Pixel, b:Pixel):Pixel;
856 | @:op(A & B) @:commutative static function andInt(a:Pixel, b:Int):Pixel;
857 |
858 | @:op(A | B) static function or(a:Pixel, b:Pixel):Pixel;
859 | @:op(A | B) @:commutative static function orInt(a:Pixel, b:Int):Pixel;
860 |
861 | @:op(A ^ B) static function xor(a:Pixel, b:Pixel):Pixel;
862 | @:op(A ^ B) @:commutative static function xorInt(a:Pixel, b:Int):Pixel;
863 |
864 |
865 | @:op(A >> B) static function shr(a:Pixel, b:Pixel):Pixel;
866 | @:op(A >> B) static function shrInt(a:Pixel, b:Int):Pixel;
867 | @:op(A >> B) static function intShr(a:Int, b:Pixel):Pixel;
868 |
869 | @:op(A >>> B) static function ushr(a:Pixel, b:Pixel):Pixel;
870 | @:op(A >>> B) static function ushrInt(a:Pixel, b:Int):Pixel;
871 | @:op(A >>> B) static function intUshr(a:Int, b:Pixel):Pixel;
872 |
873 | @:op(A << B) static function shl(a:Pixel, b:Pixel):Pixel;
874 | @:op(A << B) static function shlInt(a:Pixel, b:Int):Pixel;
875 | @:op(A << B) static function intShl(a:Int, b:Pixel):Pixel;
876 | }
877 |
878 | @:enum abstract TargetType(String) {
879 | var FLASH = "flash";
880 | var FORMAT = "format";
881 | var FLAMBE_FLASH = "flambe flash";
882 | var FLAMBE_WEB = "flambe web";
883 | var LUXE = "luxe";
884 | var OPENFL_JS = "openfl js";
885 | var OPENFL_DESKTOP = "openfl desktop";
886 | var OPENFL_FLASH = "openfl flash";
887 | var NME_DESKTOP = "nme desktop";
888 | var NME_FLASH = "nme flash";
889 | var JAVA = "java";
890 | var JS = "js";
891 | var UNKNOWN = "unknown";
892 |
893 | static public inline function getCurrent():TargetType {
894 | #if (flash && !(openfl || nme || flambe))
895 | return FLASH;
896 | #elseif (luxe || snow)
897 | return LUXE;
898 | #elseif flambe
899 | #if (flash)
900 | return FLAMBE_FLASH;
901 | #else
902 | return FLAMBE_WEB;
903 | #end
904 | #elseif (openfl && !nme)
905 | #if (js)
906 | return OPENFL_JS;
907 | #elseif (neko || cpp)
908 | return OPENFL_DESKTOP;
909 | #elseif flash
910 | return OPENFL_FLASH;
911 | #else
912 | return UNKNOWN;
913 | #end
914 | #elseif (nme)
915 | #if (neko || cpp)
916 | return NME_DESKTOP;
917 | #elseif flash
918 | return NME_FLASH;
919 | #else
920 | return UNKNOWN;
921 | #end
922 | #elseif java
923 | return JAVA;
924 | #elseif js
925 | return JS;
926 | #else
927 | return UNKNOWN;
928 | #end
929 | }
930 | }
931 |
932 | @:enum abstract Endianness(Int) to Int {
933 | var BIG = 0;
934 | var LITTLE = 1;
935 |
936 | static public var names = ["BIG_ENDIAN", "LITTLE_ENDIAN"];
937 |
938 | /**
939 | * Get system endianness.
940 | *
941 | * NOTE: It _might_ differ from actual texture bytes implementation
942 | * (e.g. flash usually uses BIG_ENDIAN even though the host system is LITTLE_ENDIAN).
943 | */
944 | static public function getCurrent():Endianness {
945 | var a:UInt32Array = UInt32Array.fromArray([0xDDCCBBAA]);
946 | var b:UInt8Array = UInt8Array.fromBytes(a.view.buffer);
947 | if (b[0] == 0xDD) return BIG;
948 | else /*if (b[0] == 0xAA)*/ return LITTLE;
949 | }
950 |
951 | inline static public function getName(endian:Endianness) {
952 | return names[endian];
953 | }
954 | }
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 | This folder is needed by flambe.
--------------------------------------------------------------------------------
/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azrafe7/hxPixels/d5292060d2a31f34b21d3c5089b9c1502d741b3e/web/favicon.ico
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Your Game
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
69 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------