112 } |
117 } |
113 |
118 |
114 TAknLayoutRect layRect; |
119 TAknLayoutRect layRect; |
115 TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::scroll_bg_pane_g1( varietyIndex ); //top |
120 TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::scroll_bg_pane_g1( varietyIndex ); //top |
116 layRect.LayoutRect( rect, layout.LayoutLine() ); |
121 layRect.LayoutRect( rect, layout.LayoutLine() ); |
117 TSize newSize( layRect.Rect().Size() ); |
122 TSize newSize = layRect.Rect().Size(); |
118 iHeadItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth); |
123 iHeadItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth); |
119 |
124 |
120 layout = AknLayoutScalable_Avkon::scroll_bg_pane_g3(varietyIndex); // bottom |
125 layout = AknLayoutScalable_Avkon::scroll_bg_pane_g3(varietyIndex); // bottom |
121 layRect.LayoutRect(rect, layout.LayoutLine()); |
126 layRect.LayoutRect(rect, layout.LayoutLine()); |
122 newSize = layRect.Rect().Size(); |
127 newSize = layRect.Rect().Size(); |
123 iTailItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth); |
128 iTailItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth); |
|
129 |
|
130 layout = AknLayoutScalable_Avkon::scroll_bg_pane_g2(varietyIndex); //middle |
|
131 layRect.LayoutRect(rect, layout.LayoutLine()); |
|
132 newSize = layRect.Rect().Size(); |
|
133 // iMidItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth) * 5; |
124 } |
134 } |
125 |
135 |
126 void CAknDoubleSpanScrollIndicator::DrawTiled( |
136 void CAknDoubleSpanScrollIndicator::DrawTiled( |
127 CWindowGc& aGc, const TRect& aRect, |
137 CWindowGc& aGc, const TRect& aRect, |
128 CAknDoubleSpanScrollIndicatorItem *aIndicatorItem) const |
138 CAknDoubleSpanScrollIndicatorItem *aIndicatorItem) const |
148 tailRect.iTl.iY = tailRect.iBr.iY - headRect.Height(); |
158 tailRect.iTl.iY = tailRect.iBr.iY - headRect.Height(); |
149 } |
159 } |
150 midRect.iTl.iY += headRect.Height(); |
160 midRect.iTl.iY += headRect.Height(); |
151 midRect.iBr.iY -= tailRect.Height(); |
161 midRect.iBr.iY -= tailRect.Height(); |
152 midDrawLength = midRect.Height(); |
162 midDrawLength = midRect.Height(); |
153 midSize.SetSize(midRect.Width(), midDrawLength); |
163 midSize.SetSize(midRect.Width(), iMidItemSize); |
154 } |
164 } |
155 else |
165 else |
156 { |
166 { |
157 headRect.SetWidth( iHeadItemSize ); |
167 headRect.SetWidth( iHeadItemSize ); |
158 tailRect.iTl.iX = tailRect.iBr.iX - iTailItemSize; |
168 tailRect.iTl.iX = tailRect.iBr.iX - iTailItemSize; |
159 |
169 |
160 midRect.iTl.iX += iHeadItemSize; |
170 midRect.iTl.iX += iHeadItemSize; |
161 midRect.iBr.iX -= iTailItemSize; |
171 midRect.iBr.iX -= iTailItemSize; |
162 midDrawLength = midRect.Width(); |
172 midDrawLength = midRect.Width(); |
163 midSize.SetSize(midDrawLength, midRect.Height()); |
173 midSize.SetSize(iMidItemSize, midRect.Height()); |
164 } |
174 } |
165 |
175 |
166 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
176 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
167 |
177 |
168 CFbsBitmap *bmp = NULL; |
178 CFbsBitmap *bmp = NULL; |
169 CFbsBitmap *mask = NULL; |
179 CFbsBitmap *mask = NULL; |
170 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iTopId, bmp, mask); |
180 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iTopId, bmp, mask); |
171 AknIconUtils::SetSize(bmp, headRect.Size(), EAspectRatioNotPreserved); |
181 AknIconUtils::SetSize(bmp, headRect.Size(), EAspectRatioNotPreserved); |
172 AknIconUtils::SetSize(mask, headRect.Size(), EAspectRatioNotPreserved); |
182 AknIconUtils::SetSize(mask, headRect.Size(), EAspectRatioNotPreserved); |
173 aGc.BitBltMasked(headRect.iTl, bmp, TRect(headRect.Size()), mask, ETrue); |
183 aGc.BitBltMasked(headRect.iTl, bmp, TRect(TPoint(0, 0), headRect.Size()), mask, ETrue); |
174 |
184 |
175 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iMidId, bmp, mask); |
185 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iMidId, bmp, mask); |
176 AknIconUtils::SetSize(bmp, midSize, EAspectRatioNotPreserved); |
186 AknIconUtils::SetSize(bmp, midSize, EAspectRatioNotPreserved); |
177 AknIconUtils::SetSize(mask, midSize, EAspectRatioNotPreserved); |
187 AknIconUtils::SetSize(mask, midSize, EAspectRatioNotPreserved); |
178 |
188 |
|
189 TInt count = midDrawLength / iMidItemSize; |
179 TPoint destPos(midRect.iTl.iX, midRect.iTl.iY); |
190 TPoint destPos(midRect.iTl.iX, midRect.iTl.iY); |
180 TRect sourRect(bmp->SizeInPixels()); |
191 TRect sourRect(TPoint(0, 0), bmp->SizeInPixels()); |
|
192 for(TInt i = 0; i < count; i++) |
|
193 { |
|
194 aGc.BitBltMasked(destPos, bmp, sourRect, mask, ETrue); |
|
195 iOrientation == CEikScrollBar::EVertical?destPos.iY += iMidItemSize : destPos.iX += iMidItemSize; |
|
196 } |
|
197 iOrientation == CEikScrollBar::EVertical?sourRect.iBr.iY = midRect.Height() % iMidItemSize |
|
198 :sourRect.iBr.iX = midRect.Width() % iMidItemSize; |
181 aGc.BitBltMasked(destPos, bmp, sourRect, mask, ETrue); |
199 aGc.BitBltMasked(destPos, bmp, sourRect, mask, ETrue); |
182 |
200 |
183 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iBottomId, bmp, mask); |
201 AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iBottomId, bmp, mask); |
184 AknIconUtils::SetSize(bmp, tailRect.Size(), EAspectRatioNotPreserved); |
202 AknIconUtils::SetSize(bmp, tailRect.Size(), EAspectRatioNotPreserved); |
185 AknIconUtils::SetSize(mask, tailRect.Size(), EAspectRatioNotPreserved); |
203 AknIconUtils::SetSize(mask, tailRect.Size(), EAspectRatioNotPreserved); |
186 aGc.BitBltMasked(tailRect.iTl, bmp, TRect(tailRect.Size()), mask, ETrue); |
204 aGc.BitBltMasked(tailRect.iTl, bmp, TRect(TPoint(0, 0), tailRect.Size()), mask, ETrue); |
187 } |
205 } |
188 |
206 |
189 void CAknDoubleSpanScrollIndicator::CalculateRects() |
207 void CAknDoubleSpanScrollIndicator::CalculateRects() |
190 { |
208 { |
191 iBackgroundRect = Rect(); |
209 iBackgroundRect = Rect(); |
203 checkedFocusPosition, |
221 checkedFocusPosition, |
204 checkedWindowSize, |
222 checkedWindowSize, |
205 checkedFieldPosition, |
223 checkedFieldPosition, |
206 checkedFieldSize); |
224 checkedFieldSize); |
207 |
225 |
208 TBool wasEmpty = iBackgroundRect.IsEmpty(); |
|
209 TBool isEmpty = EFalse; |
|
210 |
|
211 // If span (max number of items) is zero, then draw only the background |
226 // If span (max number of items) is zero, then draw only the background |
212 if ( checkedScrollSpan == 0 || ( checkedScrollSpan <= checkedWindowSize ) ) |
227 if (checkedScrollSpan == 0) |
213 { |
228 { |
214 iBackgroundRect = TRect( 0, 0, 0, 0 ); |
|
215 iHandleBackgroundRect = TRect(0,0,0,0); |
229 iHandleBackgroundRect = TRect(0,0,0,0); |
216 iHandleRect = TRect(0,0,0,0); |
230 iHandleRect = TRect(0,0,0,0); |
217 iForceDrawBackground = ETrue; // to enable background drawing |
|
218 isEmpty = ETrue; |
|
219 } |
|
220 else |
|
221 { |
|
222 iForceDrawBackground = EFalse; |
|
223 } |
|
224 if ( wasEmpty != isEmpty || iForceDrawBackground ) |
|
225 { |
|
226 DrawDeferred(); |
|
227 } |
|
228 |
|
229 if ( isEmpty ) |
|
230 { |
|
231 return; |
231 return; |
232 } |
232 } |
233 |
233 |
234 // |
234 // |
235 // Transform values into pixels and rects. |
235 // Transform values into pixels and rects. |
262 roomForMovementInSpan; |
274 roomForMovementInSpan; |
263 } |
275 } |
264 |
276 |
265 // If window would cover whole scrollbar, then modify |
277 // If window would cover whole scrollbar, then modify |
266 // it to leave the thumb little short from bottom |
278 // it to leave the thumb little short from bottom |
267 TInt scrollBarHandleMaxSizeInPixels = iHandleMaxSize; |
279 TInt scrollBarHandleMaxSizeInPixels = ScrollHandleMaxVisibleSizeInPixels(); |
268 |
|
269 if (windowSizeInPixels >= scrollBarHeightInPixels) |
280 if (windowSizeInPixels >= scrollBarHeightInPixels) |
270 { |
281 { |
271 windowSizeInPixels = scrollBarHandleMaxSizeInPixels; |
282 windowSizeInPixels = scrollBarHandleMaxSizeInPixels; |
272 } |
283 } |
273 |
284 |
274 TBool doubleSpanInUse = (checkedFieldPosition >= 0) && (checkedFieldSize > 0); |
285 TBool doubleSpanInUse = (checkedFieldPosition >= 0) && (checkedFieldSize > 0); |
275 TInt minHandleBackgroundSize = iHandleMinSize; |
286 TInt minHandleBackgroundSize = 0; |
276 TInt fieldSizeInPixels = 0; // sub field size |
287 TInt fieldSizeInPixels = 0; // sub field size |
277 TInt fieldPositionInPixels = 0; |
288 TInt fieldPositionInPixels = 0; |
278 TInt handleMinSize = iHandleMinSize; |
|
279 |
|
280 if (doubleSpanInUse) |
289 if (doubleSpanInUse) |
281 { |
290 { |
282 fieldSizeInPixels = windowSizeInPixels/checkedFieldSize; |
291 fieldSizeInPixels = windowSizeInPixels/checkedFieldSize; |
283 fieldPositionInPixels = windowSizeInPixels*checkedFieldPosition/checkedFieldSize; |
292 fieldPositionInPixels = windowSizeInPixels*checkedFieldPosition/checkedFieldSize; |
284 } |
293 minHandleBackgroundSize = HandleBackgroundMinSizeInPixels(); |
285 |
294 } |
|
295 else |
|
296 { |
|
297 minHandleBackgroundSize = HandleMinSizeInPixels(); |
|
298 } |
|
299 |
|
300 TInt handleMinSize = HandleMinSizeInPixels(); |
286 // Similar compensation for handle if double span is in use |
301 // Similar compensation for handle if double span is in use |
287 if (doubleSpanInUse && (fieldSizeInPixels < handleMinSize)) |
302 if (doubleSpanInUse && (fieldSizeInPixels < handleMinSize)) |
288 { |
303 { |
289 TInt extraPixels = 0; |
304 TInt extraPixels = 0; |
290 TInt extraPixelCompensationInterval = 0; |
305 TInt extraPixelCompensationInterval = 0; |
648 return layRect.Rect().Height(); |
676 return layRect.Rect().Height(); |
649 else |
677 else |
650 return layRect.Rect().Width(); |
678 return layRect.Rect().Width(); |
651 } |
679 } |
652 |
680 |
653 |
681 TInt CAknDoubleSpanScrollIndicator::ScrollHandleMaxVisibleSizeInPixels() |
654 TInt CAknDoubleSpanScrollIndicator::HandleMaxSizeInPixels() |
682 { |
655 { |
683 TRect scbRect = Rect(); |
656 TRect scbRect( Rect() ); |
|
657 if ( iOrientation == CEikScrollBar::EHorizontal ) |
684 if ( iOrientation == CEikScrollBar::EHorizontal ) |
658 scbRect.SetRect(scbRect.iTl, TSize(scbRect.Height(), scbRect.Width())); |
685 scbRect.SetRect(scbRect.iTl, TSize(scbRect.Height(), scbRect.Width())); |
659 |
686 |
660 TAknLayoutRect layRect; |
687 TAknLayoutRect layRect; |
661 TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::aid_size_max_handle(); |
688 TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::aid_size_max_handle(); |
662 layRect.LayoutRect(scbRect, layout.LayoutLine()); |
689 layRect.LayoutRect(scbRect, layout.LayoutLine()); |
663 return layRect.Rect().Height(); |
690 return layRect.Rect().Height(); |
664 } |
691 } |
665 |
692 |
|
693 TInt CAknDoubleSpanScrollIndicator::HandleBackgroundMinSizeInPixels() |
|
694 { |
|
695 return HandleMinSizeInPixels(); |
|
696 } |
666 |
697 |
667 TInt CAknDoubleSpanScrollIndicator::HandleMinSizeInPixels() |
698 TInt CAknDoubleSpanScrollIndicator::HandleMinSizeInPixels() |
668 { |
699 { |
669 // We have the minimum size as aid value, do not layout to the handle layout as it is not correct |
700 // We have the minimum size as aid value, do not layout to the handle layout as it is not correct |
670 // on behalf of height argument (not set as maximum) |
701 // on behalf of height argument (not set as maximum) |
711 // Redraw the background to bitmap if the skin or the size is changed. |
747 // Redraw the background to bitmap if the skin or the size is changed. |
712 // Note that the indicator itself is not window owning but the actual window owning |
748 // Note that the indicator itself is not window owning but the actual window owning |
713 // component is the scrollbar class, therefore the window may be in different position |
749 // component is the scrollbar class, therefore the window may be in different position |
714 // and size than the indicator itself |
750 // and size than the indicator itself |
715 RWindow& win = Window(); |
751 RWindow& win = Window(); |
|
752 iDrawBackgroundBitmap = EFalse; |
716 TRect bmpRect(win.Position() + pos, rect.Size()); // There may be an arrow on top of scb |
753 TRect bmpRect(win.Position() + pos, rect.Size()); // There may be an arrow on top of scb |
717 |
754 if ( CAknEnv::Static()->TransparencyEnabled() ) |
718 AknsDrawUtils::DrawBackground( skin, cc, NULL, gc, |
755 { |
719 rect.iTl, bmpRect, KAknsDrawParamNoClearUnderImage ); |
756 AknsDrawUtils::DrawBackground( skin, cc, NULL, gc, |
|
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 } |
720 } |
766 } |
721 else //SB is non-window-owning |
767 else //SB is non-window-owning |
722 { |
768 { |
723 AknsDrawUtils::Background( skin, cc, this, gc, rect, |
769 if ( CAknEnv::Static()->TransparencyEnabled() ) |
724 KAknsDrawParamNoClearUnderImage ); |
770 { |
725 } |
771 AknsDrawUtils::Background( skin, cc, this, gc, rect, KAknsDrawParamNoClearUnderImage ); |
726 } |
772 } |
727 } |
773 else |
728 |
774 { |
|
775 AknsDrawUtils::Background( skin, cc, this, gc, rect ); |
|
776 } |
|
777 } |
|
778 } |
|
779 } |
|
780 |
|
781 void CAknDoubleSpanScrollIndicator::LayoutHandleGraphics() |
|
782 { |
|
783 |
|
784 // We layout the handle middle graphics here according to the given inidcator values |
|
785 TRect rect = Rect(); |
|
786 |
|
787 if (!iHandleBar || rect.IsEmpty()) |
|
788 return; |
|
789 |
|
790 TInt varietyIndex = 0; |
|
791 TInt varietyIndexForHandle = 0; |
|
792 if (iOrientation == CEikScrollBar::EHorizontal) |
|
793 { |
|
794 varietyIndex = 1; |
|
795 varietyIndexForHandle = 2; |
|
796 } |
|
797 |
|
798 TAknLayoutRect layRect; |
|
799 TAknWindowComponentLayout // layout handle bottom & top as they do not scale according to handle size |
|
800 layout = AknLayoutScalable_Avkon::scroll_handle_pane(varietyIndexForHandle); // handle (the shadow if two handles) |
|
801 layRect.LayoutRect(rect, layout.LayoutLine()); |
|
802 layout = AknLayoutScalable_Avkon::scroll_handle_focus_pane(varietyIndex); // focus handle |
|
803 // The horizontal data for focus handle is missing so switch the values from the vertical data |
|
804 TAknWindowLineLayout layoutLine = layout.LayoutLine(); |
|
805 if (iOrientation == CEikScrollBar::EHorizontal) |
|
806 { |
|
807 TInt height = layoutLine.iH; |
|
808 TInt width = layoutLine.iW; |
|
809 layoutLine.iW = height; |
|
810 layoutLine.iH = width; |
|
811 } |
|
812 layRect.LayoutRect(layRect.Rect(), layoutLine); |
|
813 rect = layRect.Rect(); // parent rect is now the focus handle |
|
814 |
|
815 // the retangle includes the variated length of the middle, |
|
816 // the top and bottom graphics must subtracted from the value |
|
817 |
|
818 // do not change the handle retangle, the full size is needed in drawing |
|
819 // set the width or height to be correct |
|
820 if (iOrientation == CEikScrollBar::EVertical) |
|
821 { |
|
822 iHandleRect.iTl.iX = rect.iTl.iX; |
|
823 iHandleRect.iBr.iX = rect.iBr.iX; |
|
824 } |
|
825 else |
|
826 { |
|
827 iHandleRect.iTl.iY = rect.iTl.iY; |
|
828 iHandleRect.iBr.iY = rect.iBr.iY; |
|
829 } |
|
830 |
|
831 |
|
832 } |
729 |
833 |
730 TInt CAknDoubleSpanScrollIndicator::GetCurrentThumbSpanInPixels() |
834 TInt CAknDoubleSpanScrollIndicator::GetCurrentThumbSpanInPixels() |
731 { |
835 { |
732 return ( iOrientation == CEikScrollBar::EVertical ? |
836 return ( iOrientation == CEikScrollBar::EVertical ? |
733 iHandleBackgroundRect.Height() : |
837 iHandleBackgroundRect.Height() : |
762 TBool CAknDoubleSpanScrollIndicator::HandleHighlight() const |
866 TBool CAknDoubleSpanScrollIndicator::HandleHighlight() const |
763 { |
867 { |
764 return iHandleHighlight; |
868 return iHandleHighlight; |
765 } |
869 } |
766 |
870 |
767 |
871 void CAknDoubleSpanScrollIndicator::SetTouchAreaControl( CCoeControl* aTouchAreaControl ) |
|
872 { |
|
873 iTouchAreaControl = aTouchAreaControl; |
|
874 } |
|
875 |
768 void CAknDoubleSpanScrollIndicator::SetBackgroudHighlight( TBool aBackgroudHighlight ) |
876 void CAknDoubleSpanScrollIndicator::SetBackgroudHighlight( TBool aBackgroudHighlight ) |
769 { |
877 { |
770 // This does nothing in non-touch |
878 // This does nothing in non-touch |
771 iBackgroundHighlight = aBackgroudHighlight; |
879 iBackgroundHighlight = aBackgroudHighlight; |
|
880 |
772 } |
881 } |
773 |
882 |
774 TBool CAknDoubleSpanScrollIndicator::BackgroudHighlight() const |
883 TBool CAknDoubleSpanScrollIndicator::BackgroudHighlight() const |
775 { |
884 { |
776 return iBackgroundHighlight; |
885 return iBackgroundHighlight; |
777 } |
886 } |
778 |
887 CFbsBitmap* CAknDoubleSpanScrollIndicator::CopyAndApplyEffectL( |
|
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 |