747 // Redraw the background to bitmap if the skin or the size is changed. |
729 // Redraw the background to bitmap if the skin or the size is changed. |
748 // Note that the indicator itself is not window owning but the actual window owning |
730 // Note that the indicator itself is not window owning but the actual window owning |
749 // component is the scrollbar class, therefore the window may be in different position |
731 // component is the scrollbar class, therefore the window may be in different position |
750 // and size than the indicator itself |
732 // and size than the indicator itself |
751 RWindow& win = Window(); |
733 RWindow& win = Window(); |
752 iDrawBackgroundBitmap = EFalse; |
|
753 TRect bmpRect(win.Position() + pos, rect.Size()); // There may be an arrow on top of scb |
734 TRect bmpRect(win.Position() + pos, rect.Size()); // There may be an arrow on top of scb |
754 if ( CAknEnv::Static()->TransparencyEnabled() ) |
735 |
755 { |
736 AknsDrawUtils::DrawBackground( skin, cc, NULL, gc, |
756 AknsDrawUtils::DrawBackground( skin, cc, NULL, gc, |
737 rect.iTl, bmpRect, KAknsDrawParamNoClearUnderImage ); |
757 rect.iTl, bmpRect, KAknsDrawParamNoClearUnderImage ); |
|
758 } |
|
759 else |
|
760 { |
|
761 AknsDrawUtils::DrawBackground( skin, cc, NULL, gc, |
|
762 TPoint(0,0), bmpRect , KAknsDrawParamNoClearUnderImage ); |
|
763 |
|
764 |
|
765 } |
|
766 } |
738 } |
767 else //SB is non-window-owning |
739 else //SB is non-window-owning |
768 { |
740 { |
769 if ( CAknEnv::Static()->TransparencyEnabled() ) |
741 AknsDrawUtils::Background( skin, cc, this, gc, rect, |
770 { |
742 KAknsDrawParamNoClearUnderImage ); |
771 AknsDrawUtils::Background( skin, cc, this, gc, rect, KAknsDrawParamNoClearUnderImage ); |
|
772 } |
|
773 else |
|
774 { |
|
775 AknsDrawUtils::Background( skin, cc, this, gc, rect ); |
|
776 } |
|
777 } |
743 } |
778 } |
744 } |
779 } |
745 } |
780 |
746 |
781 void CAknDoubleSpanScrollIndicator::LayoutHandleGraphics() |
747 void CAknDoubleSpanScrollIndicator::LayoutHandleGraphics() |
866 TBool CAknDoubleSpanScrollIndicator::HandleHighlight() const |
830 TBool CAknDoubleSpanScrollIndicator::HandleHighlight() const |
867 { |
831 { |
868 return iHandleHighlight; |
832 return iHandleHighlight; |
869 } |
833 } |
870 |
834 |
871 void CAknDoubleSpanScrollIndicator::SetTouchAreaControl( CCoeControl* aTouchAreaControl ) |
835 |
872 { |
|
873 iTouchAreaControl = aTouchAreaControl; |
|
874 } |
|
875 |
|
876 void CAknDoubleSpanScrollIndicator::SetBackgroudHighlight( TBool aBackgroudHighlight ) |
836 void CAknDoubleSpanScrollIndicator::SetBackgroudHighlight( TBool aBackgroudHighlight ) |
877 { |
837 { |
878 // This does nothing in non-touch |
838 // This does nothing in non-touch |
879 iBackgroundHighlight = aBackgroudHighlight; |
839 iBackgroundHighlight = aBackgroudHighlight; |
880 |
|
881 } |
840 } |
882 |
841 |
883 TBool CAknDoubleSpanScrollIndicator::BackgroudHighlight() const |
842 TBool CAknDoubleSpanScrollIndicator::BackgroudHighlight() const |
884 { |
843 { |
885 return iBackgroundHighlight; |
844 return iBackgroundHighlight; |
886 } |
845 } |
887 CFbsBitmap* CAknDoubleSpanScrollIndicator::CopyAndApplyEffectL( |
846 |
888 const CFbsBitmap* aSource, TBool aCopyOnly ) |
|
889 { |
|
890 CFbsBitmap* newBitmap = NULL; |
|
891 |
|
892 |
|
893 newBitmap = new ( ELeave ) CFbsBitmap; |
|
894 |
|
895 |
|
896 |
|
897 TInt err = newBitmap->Create( aSource->SizeInPixels(), aSource->DisplayMode() ); |
|
898 |
|
899 // We still have to return a dummy bitmap object, even if |
|
900 // the creation fails. |
|
901 if ( err == KErrNone ) |
|
902 { |
|
903 SEpocBitmapHeader header = aSource->Header(); |
|
904 |
|
905 // We support only 16-bit (5-6-5), since this is the default |
|
906 // display mode icons are created in. Otherwise just copy. |
|
907 if ( !aCopyOnly && aSource->DisplayMode() == EColor64K ) |
|
908 { |
|
909 // Don't modify header data. |
|
910 TInt size = ( header.iBitmapSize - header.iStructSize ) / |
|
911 sizeof( TUint16 ); |
|
912 |
|
913 aSource->BeginDataAccess(); |
|
914 |
|
915 TUint16* source = (TUint16*)aSource->DataAddress(); |
|
916 TUint16* dest = (TUint16*)newBitmap->DataAddress(); |
|
917 |
|
918 for ( TInt i = 0; i < size; ++i ) |
|
919 { |
|
920 *dest = *source++; |
|
921 TBitmapFx::PixelEffect( dest++ ); |
|
922 } |
|
923 |
|
924 aSource->EndDataAccess( ETrue ); |
|
925 } |
|
926 else |
|
927 { |
|
928 // This is probably faster than blitting it. Copy |
|
929 // the header data in the same run to minimize size |
|
930 // calculations, although it's already correct in the |
|
931 // new bitmap. |
|
932 TInt size = aSource->Header().iBitmapSize; |
|
933 |
|
934 aSource->BeginDataAccess(); |
|
935 |
|
936 Mem::Copy( newBitmap->DataAddress(), |
|
937 aSource->DataAddress(), |
|
938 size ); |
|
939 |
|
940 aSource->EndDataAccess( ETrue ); |
|
941 } |
|
942 } |
|
943 |
|
944 |
|
945 return newBitmap; |
|
946 } |
|
947 |
|
948 |
|
949 void TBitmapFx::PixelEffect( TUint16* aPixelData ) |
|
950 { |
|
951 // Note: the calculations in this function are based on |
|
952 // graphic designers' conception of what Photoshop does |
|
953 // to images with certain values. There might also be some |
|
954 // room for optimizations. |
|
955 |
|
956 TRGB rgb; |
|
957 |
|
958 rgb.iR = ( *aPixelData & 0xF800 ) >> 11; |
|
959 rgb.iG = ( *aPixelData & 0x7E0 ) >> 5; |
|
960 rgb.iB = ( *aPixelData & 0x1F ); |
|
961 |
|
962 // Scale to 65280 (0xFF00). Under no circumstances should these |
|
963 // values end up being > 0xFF00 or < 0x00 |
|
964 rgb.iR *= 2105.82f; |
|
965 rgb.iG *= 1036.20f; |
|
966 rgb.iB *= 2105.82f; |
|
967 |
|
968 // Convert RGB to HSL |
|
969 TInt min = Min( rgb.iR, Min( rgb.iG, rgb.iB ) ); |
|
970 TInt max = Max( rgb.iR, Max( rgb.iG, rgb.iB ) ); |
|
971 TInt delta = max - min; |
|
972 |
|
973 THSL hsl = { 0, 0, 0 } ; |
|
974 |
|
975 // Lightness |
|
976 hsl.iL = ( max + min ) >> 1; |
|
977 |
|
978 if ( delta == 0 ) |
|
979 { |
|
980 hsl.iH = 0; |
|
981 hsl.iS = 0; |
|
982 } |
|
983 else |
|
984 { |
|
985 // Hue |
|
986 if ( max == rgb.iR ) |
|
987 { |
|
988 hsl.iH = 10880 * ( rgb.iG - rgb.iB ) / delta; |
|
989 } |
|
990 else if ( max == rgb.iG ) |
|
991 { |
|
992 hsl.iH = 10880 * ( rgb.iB - rgb.iR ) / delta + 21760; |
|
993 } |
|
994 else if ( max == rgb.iB ) |
|
995 { |
|
996 hsl.iH = 10880 * ( rgb.iR - rgb.iG ) / delta + 43520; |
|
997 } |
|
998 |
|
999 // Saturation |
|
1000 if ( hsl.iL <= 32640 ) |
|
1001 { |
|
1002 hsl.iS = ( delta << KPrecision ) / ( ( max + min ) >> KPrecision ); |
|
1003 } |
|
1004 else |
|
1005 { |
|
1006 hsl.iS = ( delta << KPrecision ) / ( ( 0x1FE00 - ( max + min ) ) >> KPrecision ); |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 // Apply hue shift, moved to proper range in HueToRGB() |
|
1011 hsl.iH += 0x715; |
|
1012 |
|
1013 // Apply saturation |
|
1014 // +10 in -100..100 in Photoshop terms. According to related material |
|
1015 // corresponds to 0xCC0 when applied to 0x00..0xFF00 |
|
1016 hsl.iS += 0xCC0; |
|
1017 |
|
1018 if ( hsl.iS > 0xFF00 ) |
|
1019 { |
|
1020 hsl.iS = 0xFF00; |
|
1021 } |
|
1022 |
|
1023 // Convert back to RGB |
|
1024 TInt v1; |
|
1025 TInt v2; |
|
1026 |
|
1027 if ( hsl.iS == 0 ) |
|
1028 { |
|
1029 rgb.iR = ( hsl.iL * 255 ) >> KPrecision; |
|
1030 rgb.iG = ( hsl.iL * 255 ) >> KPrecision; |
|
1031 rgb.iB = ( hsl.iL * 255 ) >> KPrecision; |
|
1032 } |
|
1033 else |
|
1034 { |
|
1035 if ( hsl.iL < 32640 ) |
|
1036 { |
|
1037 v2 = ( hsl.iL * ( ( 0xFF00 + hsl.iS ) >> KPrecision ) ) >> KPrecision; |
|
1038 } |
|
1039 else |
|
1040 { |
|
1041 v2 = ( hsl.iL + hsl.iS ) - ( ( hsl.iS >> KPrecision ) * ( hsl.iL >> KPrecision ) ); |
|
1042 } |
|
1043 |
|
1044 v1 = 2 * hsl.iL - v2; |
|
1045 |
|
1046 rgb.iR = ( HueToRGB( v1, v2, hsl.iH + 0x54FF ) ); |
|
1047 rgb.iG = ( HueToRGB( v1, v2, hsl.iH ) ); |
|
1048 rgb.iB = ( HueToRGB( v1, v2, hsl.iH - 0x54FF ) ); |
|
1049 } |
|
1050 |
|
1051 rgb.iR /= 2105.82f; |
|
1052 rgb.iG /= 1036.20f; |
|
1053 rgb.iB /= 2105.82f; |
|
1054 |
|
1055 // Apply contrast.. However, the original req stated that the |
|
1056 // contrast value should be +6 in a range of -100..100. |
|
1057 // With 5 and 6 bit values and fixed point math such a small value has |
|
1058 // no effect, so it has been left out. The code is here in case |
|
1059 // the contrast value is updated at some point. |
|
1060 /* |
|
1061 const TInt contrast = ( 6 * 65536 / 200 ) + 65536; |
|
1062 |
|
1063 rgb.iR -= 15; |
|
1064 rgb.iG -= 31; |
|
1065 rgb.iB -= 15; |
|
1066 |
|
1067 rgb.iR *= contrast; |
|
1068 rgb.iG *= contrast; |
|
1069 rgb.iB *= contrast; |
|
1070 |
|
1071 rgb.iR /= 65536; |
|
1072 rgb.iG /= 65536; |
|
1073 rgb.iB /= 65536; |
|
1074 |
|
1075 rgb.iR += 15; |
|
1076 rgb.iG += 31; |
|
1077 rgb.iB += 15; |
|
1078 */ |
|
1079 |
|
1080 // Apply brightness, -40 in a range of -100..100 for |
|
1081 // 0..255 rgb values, which corresponds to -5 for 5 bit |
|
1082 // and -10 for 6 bit rgb values. |
|
1083 rgb.iR -= 5; |
|
1084 rgb.iG -= 10; |
|
1085 rgb.iB -= 5; |
|
1086 |
|
1087 if ( rgb.iR < 0 ) rgb.iR = 0; |
|
1088 if ( rgb.iG < 0 ) rgb.iG = 0; |
|
1089 if ( rgb.iB < 0 ) rgb.iB = 0; |
|
1090 |
|
1091 if ( rgb.iR > 31 ) rgb.iR = 31; |
|
1092 if ( rgb.iG > 63 ) rgb.iG = 63; |
|
1093 if ( rgb.iB > 31 ) rgb.iB = 31; |
|
1094 |
|
1095 *aPixelData = |
|
1096 ( rgb.iB | ( rgb.iG << 5 ) | ( rgb.iR << 11 ) ); |
|
1097 } |
|
1098 |
|
1099 TInt TBitmapFx::HueToRGB( TInt v1, TInt v2, TInt aH ) |
|
1100 { |
|
1101 while ( aH < 0 ) |
|
1102 { |
|
1103 aH += 0xFF00; |
|
1104 } |
|
1105 |
|
1106 while ( aH >= 0xFF00 ) |
|
1107 { |
|
1108 aH -= 0xFF00; |
|
1109 } |
|
1110 |
|
1111 if ( ( ( 6 * aH ) ) < 0xFF00 ) |
|
1112 { |
|
1113 return v1 + ( ( v2 - v1 ) * ( ( 6 * aH ) >> KPrecision ) >> KPrecision ); |
|
1114 } |
|
1115 |
|
1116 if ( ( ( 2 * aH ) ) < 0xFF00 ) |
|
1117 { |
|
1118 return v2; |
|
1119 } |
|
1120 |
|
1121 if ( ( ( 3 * aH ) ) < 0x1FE00 ) |
|
1122 { |
|
1123 return v1 + ( ( v2 - v1 ) * ( ( ( 0xA9FF - aH ) * 6 ) >> KPrecision ) >> KPrecision ); |
|
1124 } |
|
1125 |
|
1126 return v1; |
|
1127 } |
|
1128 |
|