First public contribution.
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #include "tcompressed.h"
20 CTCompressed::CTCompressed(CTestStep* aStep) :
25 void CTCompressed::BlankBitmap(CFbsBitmapEx& aBitmap)
27 TSize size = aBitmap.SizeInPixels();
28 TInt dataLength = CFbsBitmap::ScanLineLength(size.iWidth,aBitmap.DisplayMode()) * size.iHeight;
30 Mem::FillZ((TUint8*)aBitmap.DataAddress(),dataLength);
34 void CTCompressed::RunTestCaseL(TInt aCurTestCase)
36 ((CTCompressedStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
40 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0571"));
41 TRAPD(err, RunTestL());
42 TEST(err == KErrNone);
45 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0572"));
46 TRAP(err, DefectFix_EXT5DXGK6_L());
47 TEST(err == KErrNone);
51 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0500"));
52 // Set size of bitmap large enough to warrant compression
53 const TSize KBitmapSize(200,200);
54 INFO_PRINTF1(_L("Test case for INC082713\r\n"));
55 TRAP(err, DefectFix_INC082713_L(EColor16MU, KBitmapSize));
56 TEST(err == KErrNone);
57 TRAP(err, DefectFix_INC082713_L(EColor16MA, KBitmapSize));
58 TEST(err == KErrNone);
62 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0573"));
63 TRAPD(err1, INC088856_TestL());
64 TEST(err1 == KErrNone);
67 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0615"));
68 TestDestroyBitmapWhileBeingBackgroundCompressedL();
71 ((CTCompressedStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0616"));
72 TestBackgroundCompressionThreadPriorityInheritanceL();
75 ((CTCompressedStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
76 ((CTCompressedStep*)iStep)->CloseTMSGraphicsStep();
80 ((CTCompressedStep*)iStep)->RecordTestResultL();
88 Tests compression of bitmaps in RAM and ROM.
91 Four bitmaps are loaded. One compressed and one
92 uncompressed from ROM and from RAM. The bitmap
93 in RAM is tested if it can be compressed successfully.
94 The bitmap in ROM should fail when tried to be compressed.
95 All of the bitmaps are then tried to be BitBlt.
97 @SYMTestExpectedResults
100 void CTCompressed::RunTestL()
102 TInt skipRomBitmapTests = EFalse;
103 TUint32* romAddress = NULL;
104 if(!CFbsBitmap::IsFileInRom(KRomNotCompressed, romAddress)) //any ROM bitmap
106 INFO_PRINTF2(_L("Skipping ROM bitmap tests since file \"%S\" is reported to not be a ROM bitmap."),
108 INFO_PRINTF1(_L("This should only occur on non-XIP ROMs, e.g. NAND ROMs, where ROM bitmaps aren't supported."));
109 skipRomBitmapTests = ETrue;
112 TBuf<64> romNotCompressed(KRomNotCompressed);
113 TBuf<64> romCompressed(KRomCompressed);
114 TBuf<64> fileNotCompressed(KFileNotCompressed);
115 TBuf<64> fileCompressed(KFileCompressed);
121 if(!skipRomBitmapTests)
123 TEST(rom.Load(romNotCompressed, 0, EFalse)== KErrNone);
124 TEST(romcomp.Load(romCompressed, 0, EFalse)== KErrNone);
126 INFO_PRINTF1(_L("Check compressing of ROM bitmaps causes error.\r\n"));
127 ret = rom.Compress();
128 TEST(ret == KErrAccessDenied); //cannot compress bitmaps in ROM
129 TEST(rom.IsCompressedInRAM());
134 TEST(file.Load(fileNotCompressed, 0, EFalse)== KErrNone);
135 TEST(filecomp.Load(fileCompressed, 0, EFalse)== KErrNone);
137 INFO_PRINTF1(_L("Check compressing of RAM files is OK.\r\n"));
139 ret=ram.Load(fileNotCompressed,0,EFalse);
140 TEST(ret == KErrNone);
141 ret = ram.Compress();
142 TEST(ret == KErrNone); //can compress bitmaps in RAM
143 TEST(ram.IsCompressedInRAM());
145 INFO_PRINTF1(_L("Check compressing a created EColor256 bitmap.\r\n"));
146 CFbsBitmapEx created;
147 ret=created.Create(TSize(200,200),EColor256);
150 // This makes sure we can compress it...
151 BlankBitmap(created);
153 ret = created.Compress();
155 TEST(created.IsCompressedInRAM());
157 INFO_PRINTF1(_L("Check compressing a created EColor24MU bitmap.\r\n"));
158 CFbsBitmapEx created24MU;
159 ret=created24MU.Create(TSize(200,200),EColor16MU);
162 // This makes sure we can compress it...
163 BlankBitmap(created24MU);
165 ret = created24MU.Compress();
167 TEST(created24MU.IsCompressedInRAM());
169 INFO_PRINTF1(_L("Try bitblt on all bitmaps"));
170 for (TInt mode = EGray2; mode < EColorLast; mode++)
172 if(!skipRomBitmapTests)
174 INFO_PRINTF2(_L("BitBlt rom with %d display mode.\r\n"), mode);
175 TestBitBltL(rom, TDisplayMode(mode));
176 INFO_PRINTF2(_L("BitBlt romcomp with %d display mode.\r\n"), mode);
177 TestBitBltL(romcomp, TDisplayMode(mode));
179 INFO_PRINTF2(_L("BitBlt file with %d display mode.\r\n"), mode);
180 TestBitBltL(file, TDisplayMode(mode));
181 INFO_PRINTF2(_L("BitBlt filecomp with %d display mode.\r\n"), mode);
182 TestBitBltL(filecomp, TDisplayMode(mode));
183 INFO_PRINTF2(_L("BitBlt ram with %d display mode.\r\n"), mode);
184 TestBitBltL(ram, TDisplayMode(mode));
185 INFO_PRINTF2(_L("BitBlt created with %d display mode.\r\n"), mode);
186 TestBitBltL(created, TDisplayMode(mode));
187 INFO_PRINTF2(_L("BitBlt 24MU created bitmap with %d display mode.\r\n"), mode);
188 TestBitBltL(created24MU, TDisplayMode(mode));
199 Testcode to check for fix to defect EXT-5DXGK6 Bitmap
200 compression causes crash when loading skins.
201 Its not a conclusive test as it depends on where the
202 bitmap is loaded into memory and if there is
203 memory allocated at the end of the bitmap.
207 @SYMTestExpectedResults
210 void CTCompressed::DefectFix_EXT5DXGK6_L()
214 TInt ret=bmp1.Create(size,EGray2);
218 // calculate the size of the destination scan line in bytes
219 // + 31 to pad to 4 byte boundary; 8 bits in a byte
220 TInt source_buffer_size = (size.iWidth + 31) / 8 ;
221 TUint8* buffer = new(ELeave) TUint8[source_buffer_size];
222 TPtr8 source_ptr(buffer,source_buffer_size,source_buffer_size);
224 for(TInt ii = 0; ii<source_buffer_size; ++ii)
232 source_ptr[source_buffer_size-1] = 5;
233 source_ptr[source_buffer_size-2] = 5;
234 source_ptr[source_buffer_size-3] = 5;
235 source_ptr[source_buffer_size-4] = 4;
236 bmp1.SetScanLine(source_ptr,0);
243 * @SYMTestCaseID GRAPHICS-FBSERV-0500
247 * @SYMTestCaseDesc Test RLE compression algorithm of EColor16MU and EColor16MA bitmaps.
249 * @SYMTestPriority Critical
251 * @SYMTestStatus Implemented
253 * @SYMTestActions The following test checks a corner-case of the algorithm triggered by a specific pixel pattern.
255 * The corner case is triggered when the input to the compression function ends in a run of equal pixels,
256 * terminated by a single pixel that is different i.e. ...rrrrrrrrrrrrrrrg
257 * where we have a run of equal (red) pixels followed by a green pixel, which is the last pixel in the
258 * bitmap (or the scanline, depending on how the data is being compressed).
260 * This test case performs the following:
261 * 1) Creates a bitmap in the display mode and of size specified in function args.
262 * This size must be large enough to trigger the compression when requested.
263 * 2) Creates a scanline the width of this bitmap, which is a run of equal pixels, and
264 * then sets the last pixel to be different.
265 * 3) Sets the last scanline of the bitmap to the scanline we have just created.
266 * This means that the last scanline of the bitmap conforms to the corner-case pattern.
267 * 4) Compresses the bitmap
268 * 5) Checks the compression has been successful
269 * 6) Retrieves the last scanline of the bitmap and compares it with the original one
270 * to verify that the compression of data has been successful.
272 * @SYMTestExpectedResults
273 * The compression should occur successfully without panicking.
274 * The scanline retrieved from the compressed version of the bitmap should match
275 * the original scanline created.
277 void CTCompressed::DefectFix_INC082713_L(const TDisplayMode aDispMode, const TSize aBitmapSize)
279 // *** This function assumes that pixels are stored as 32 bit words ***
280 // *** for EColor16MU and EColor16MA bitmaps ***
284 INFO_PRINTF1(_L("Check compression algorithm corner case for EColor16MU bitmap.\r\n"));
287 INFO_PRINTF1(_L("Check compression algorithm corner case for EColor16MA bitmap.\r\n"));
290 INFO_PRINTF1(_L("Unsupported display mode for test"));
295 TInt ret=bitmap.Create(aBitmapSize,aDispMode);
298 TInt widthInPixels = bitmap.SizeInPixels().iWidth;
299 TInt heightInPixels = bitmap.SizeInPixels().iHeight;
300 TInt scanLineByteLength = bitmap.ScanLineLength(widthInPixels, aDispMode);
301 TUint32* buffer = (TUint32*)User::AllocLC(scanLineByteLength);
303 // Breaking from a run of equal pixels
304 // i.e. rrrrrrr...rrrrrrrrg
305 for (TInt ii = 0; ii < widthInPixels; ii++)
307 buffer[ii] = 0xc6ebff;
309 // Last pixel differs - must be able to re-enter loop when at last pixel
310 buffer[widthInPixels - 1] = 0xcee7ff;
312 TPtr8 scanline((TUint8*)buffer ,scanLineByteLength,scanLineByteLength);
314 bitmap.SetScanLine(scanline, heightInPixels - 1);
316 INFO_PRINTF1(_L("Compressing bitmap"));
317 ret = bitmap.Compress();
319 TEST(bitmap.IsCompressedInRAM());
321 // Retrieve the scanline from the compressed bitmap and compare with original
322 // in order to test whether the scanline is correctly compressed
323 INFO_PRINTF1(_L("Retrieving scanline from compressed bitmap"));
325 TUint32* readbackbuffer = (TUint32*)User::AllocLC(scanLineByteLength);
326 TPtr8 readbackscanline((TUint8*)readbackbuffer ,scanLineByteLength,scanLineByteLength);
327 readbackscanline.Fill(0xff);
328 bitmap.GetScanLine(readbackscanline,TPoint(0,heightInPixels - 1),widthInPixels, aDispMode);
330 INFO_PRINTF1(_L("Comparing scanlines\r\n"));
331 // Compare the original scanline with the one retrieved from the compressed version
336 TBool result = ETrue;
337 for (TInt ii = 0; ii < widthInPixels; ii++)
339 // Must mask off top bits (as we can ignore them, since we have no alpha channel)
340 TUint32 original = buffer[ii] & 0x00ffffff;
341 TUint32 readback = readbackbuffer[ii] & 0x00ffffff;
342 result = result && (original == readback);
348 ret = Mem::Compare((TUint8*)buffer, scanLineByteLength, (TUint8*)readbackbuffer, scanLineByteLength);
349 // Mem::Compare returns 0 if the two scanlines are equal
353 INFO_PRINTF1(_L("Unsupported display mode for test"));
357 CleanupStack::PopAndDestroy(2, buffer);
360 void CTCompressed::TestBitBltL(CFbsBitmap& aBmp, TDisplayMode aDispMode)
362 CFbsScreenDevice* scd = 0;
363 TRAPD(ret, scd = CFbsScreenDevice::NewL(_L("scdv"),aDispMode));
366 WARN_PRINTF3(_L("Could not create screen device in %d mode, reason=%d.\r\n"), aDispMode, ret);
369 CleanupStack::PushL(scd);
371 scd->ChangeScreenDevice(NULL);
373 if (scd->CreateContext((CGraphicsContext*&)sgc)==KErrNone)
375 CleanupStack::PushL(sgc);
377 TSize halfScreen = scd->SizeInPixels();
378 halfScreen.iWidth /= 2;
380 INFO_PRINTF1(_L("BitBlt..."));
381 sgc->BitBlt(TPoint(halfScreen.iWidth,0),&aBmp);
382 INFO_PRINTF1(_L("worked\r\n"));
384 CleanupStack::PopAndDestroy(sgc);
388 INFO_PRINTF2(_L("Could not create context in %d mode.\r\n"), aDispMode);
390 CleanupStack::PopAndDestroy(scd);
400 Verifies defect INC088856. Checks the
401 updated padding value before compression for
402 256 gray scale and 64k colour.
405 Creates a bitmap. Gets the bitmaps scanline length.
406 Locks the heap. Retrieves the bitmaps data address.
407 Unlocks the heap. Then for both 256 gray scale and 64k colour
408 it checks the padding after compression matches before compression.
411 @SYMTestExpectedResults
414 void CTCompressed::INC088856_TestL()
416 INFO_PRINTF1(_L("Check updated Padding value in before compression \r\n"));
418 INFO_PRINTF1(_L("Check updated Padding value for EGray256 \r\n"));
419 DoUpdateOnPadding(TSize(5,3),EGray256);
420 DoUpdateOnPadding(TSize(25,43),EGray256);
422 INFO_PRINTF1(_L("Check updated Padding value for EColor64K \r\n"));
423 DoUpdateOnPadding(TSize(5,3),EColor64K);
424 DoUpdateOnPadding(TSize(25,43),EColor64K);
427 void CTCompressed::DoUpdateOnPadding(const TSize aSize, const TDisplayMode aDispMode)
430 TInt ret=bmp1.Create(aSize,aDispMode);
433 TInt dataLength = CFbsBitmap::ScanLineLength(aSize.iWidth, bmp1.DisplayMode()) * aSize.iHeight;
436 TUint8* srcBits = (TUint8*)bmp1.DataAddress();
443 TUint8* bmpBits = srcBits;
444 TUint8* bmpBitsLimit = srcBits + dataLength;
445 while(bmpBits<bmpBitsLimit)
447 if(pos++ < aSize.iWidth)
462 TUint16* bmpBits = (TUint16*)srcBits;
463 TUint16* bmpBitsLimit = (TUint16*)(srcBits + dataLength);
464 while(bmpBits<bmpBitsLimit)
466 if(pos++ < aSize.iWidth)
484 TInt stride = bmp1.DataStride();
485 TUint8* dataPtr = (TUint8*)bmp1.DataAddress();
490 for (TInt row = 0; row < aSize.iHeight - 1; ++row)
492 TEST(*dataPtr++ == stride - 1);
493 TEST(*dataPtr++ == row + 1);
499 for (TInt row = 0; row < aSize.iHeight - 1; ++row)
501 TEST(*dataPtr++ == stride / 2 - 1);
502 TEST(*dataPtr++ == row + 1);
503 TEST(*dataPtr++ == 0);
513 * @SYMTestCaseID GRAPHICS-FBSERV-0615
518 * Test Fbserv robustness when bitmaps are destroyed while they are being background compressed
520 * @SYMTestPriority High
522 * @SYMTestStatus Implemented
525 * Preform various scenarios to create bitmaps, compress them in background and then destroy the
526 * bitmaps without waiting the compression to complete.
528 * @SYMTestExpectedResults
529 * Fbserv does not crash because of misfirig its background compression active object
531 void CTCompressed::TestDestroyBitmapWhileBeingBackgroundCompressedL()
533 const TInt KNumOfBitmaps = 1000;
534 const TSize KSize(1,1);
535 const TDisplayMode KMode = EColor64K;
536 CFbsBitmap* bitmaps[KNumOfBitmaps];
539 // Create N bitmap instances, compress them in background and destroy them in-reverse order
540 // without waiting compression to complete
541 INFO_PRINTF2(_L("Create %d bitmaps,compress them in background and destroy in reverse order"), KNumOfBitmaps);
543 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
545 bitmaps[idx] = new(ELeave) CFbsBitmap;
546 CleanupStack::PushL(bitmaps[idx]);
547 User::LeaveIfError(bitmaps[idx]->Create(KSize, KMode));
550 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
552 User::LeaveIfError(bitmaps[idx]->CompressInBackground());
555 // Delete bitmaps in reverse order
556 CleanupStack::PopAndDestroy(KNumOfBitmaps, bitmaps[0]);
559 // Create N bitmap instances, compress them in background and destroy them in the compression order
560 // without waiting compression to complete
561 INFO_PRINTF2(_L("Create %d bitmaps,compress them in background and destroy in forward order"), KNumOfBitmaps);
563 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
565 bitmaps[idx] = new(ELeave) CFbsBitmap;
566 CleanupStack::PushL(bitmaps[idx]);
567 User::LeaveIfError(bitmaps[idx]->Create(KSize, KMode));
570 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
572 User::LeaveIfError(bitmaps[idx]->CompressInBackground());
575 // Delete bitmaps in compression order
576 CleanupStack::Pop(KNumOfBitmaps, bitmaps[0]);
577 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
583 // Create N bitmap instances, compress them in background and destroy them in random order
584 // without waiting compression to complete
585 INFO_PRINTF2(_L("Create %d bitmaps,compress them in background and destroy in random order"), KNumOfBitmaps);
587 TInt randomOrder[KNumOfBitmaps];
588 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
590 bitmaps[idx] = new(ELeave) CFbsBitmap;
591 CleanupStack::PushL(bitmaps[idx]);
592 User::LeaveIfError(bitmaps[idx]->Create(KSize, KMode));
593 randomOrder[idx] = idx;
595 // Randomise deletion order
596 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
598 TInt swap = Math::Random()%KNumOfBitmaps;
599 TInt tmp = randomOrder[idx];
600 randomOrder[idx] = randomOrder[swap];
601 randomOrder[swap] = tmp;
604 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
606 User::LeaveIfError(bitmaps[idx]->CompressInBackground());
609 // Delete bitmaps in random order
610 CleanupStack::Pop(KNumOfBitmaps, bitmaps[0]);
611 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
613 delete bitmaps[randomOrder[idx]];
614 bitmaps[randomOrder[idx]] = NULL;
616 // Test all bitmaps has been destroyed
617 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
619 TEST(bitmaps[idx]==NULL);
623 // Create bitmap, compress it in background and immediately destroyed without waiting compression
625 INFO_PRINTF2(_L("Create bitmap,compress in background and immediately destroyed. Repeat %d times"), KNumOfBitmaps);
627 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
629 CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
630 CleanupStack::PushL(bitmap);
631 User::LeaveIfError(bitmap->Create(KSize, KMode));
632 User::LeaveIfError(bitmap->CompressInBackground());
633 CleanupStack::PopAndDestroy(bitmap);
637 // Similar from #4 but executed from two different threads
638 INFO_PRINTF2(_L("Create bitmap,compress in background and immediately destroyed from 2 different threads. Repeat %d times"), KNumOfBitmaps);
640 const TInt KStackSize = 4096;
641 const TInt KMinHeapSize = 4096;
642 const TInt KMaxHeapSize = 1024*1024;
644 User::LeaveIfError(t1.Create(_L("bgCompThreadFunc#1"), CTCompressed::BgCompThreadFunc, KStackSize, KMinHeapSize, KMaxHeapSize, NULL));
646 User::LeaveIfError(t2.Create(_L("bgCompThreadFunc#2"), CTCompressed::BgCompThreadFunc, KStackSize, KMinHeapSize, KMaxHeapSize, NULL));
655 User::WaitForRequest(s1);
656 User::WaitForRequest(s2);
662 TInt CTCompressed::BgCompThreadFunc(TAny*)
664 const TInt KNumOfBitmaps = 1000;
665 const TSize KSize(1,1);
666 const TDisplayMode KMode = EColor64K;
668 // No need to worries with cleanup stack and trap as resources will be freed if the thread
669 // running this functions dies, panics or leaves.
671 RFbsSession::Connect();
673 for (TInt idx=0; idx<KNumOfBitmaps; ++idx)
675 CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
676 User::LeaveIfError(bitmap->Create(KSize, KMode));
677 User::LeaveIfError(bitmap->CompressInBackground());
681 RFbsSession::Disconnect();
687 * @SYMTestCaseID GRAPHICS-FBSERV-0616
692 * Test Fbserv bitmap's priority inversion when we use background compression against a long running thread
694 * @SYMTestPriority High
696 * @SYMTestStatus Implemented
699 * Create a thread which creates a bitmap and makes a call to background compression. Once this thread resumed,
700 * make the current thread as busy by doing some long running task and test the exit status of the bitmap compression thread.
702 * @SYMTestExpectedResults
703 * Fbserv does priority inheritance and therefore protect against priority inversion, so the thread function will
704 * do backgroud compression and the thread will exit successfully, which will pass the test. If it is not protect
705 * against priority inversion with in 30 seconds(approximately) the test will fail without doing background compression.
707 void CTCompressed::TestBackgroundCompressionThreadPriorityInheritanceL()
709 const TInt KStackSize = 4096;
710 const TInt KMinHeapSize = 4096;
711 const TInt KMaxHeapSize = 1024*1024;
712 const TInt KMaxViewChangeTime = 2000;
714 INFO_PRINTF1(_L("Test case for Background Compression Thread Priority Inheritance\r\n"));
715 //Create and start a thread which create a bitmap and calls CompressInBackground
717 User::LeaveIfError(thread1.Create(_L("CompressBgThreadFunc"), CTCompressed::CompressBgThreadFunc, KStackSize, KMinHeapSize, KMaxHeapSize, NULL));
719 TUint startTime = User::TickCount();
721 //Start a infinite running loop to make current thread as a busy and long running thread...
724 TExitType exitType = thread1.ExitType();
725 if(exitType != EExitPending)
727 TInt exitReason = thread1.ExitReason();
728 TEST(exitType == EExitKill);
729 TEST(exitReason == KErrNone);
732 TUint stopTime = User::TickCount();
733 if((stopTime - startTime) > KMaxViewChangeTime) //Check for the busy task is running for more than 30 seconds...
736 thread1.Terminate(KErrGeneral);
744 Thread function used from the test case TestBackgroundCompressionThreadPriorityInheritanceL
746 TInt CTCompressed::CompressBgThreadFunc(TAny*)
748 const TSize KSize(100, 100);
749 const TDisplayMode KMode = EColor64K;
751 TInt err = RFbsSession::Connect();
754 CFbsBitmap* bitmap = new CFbsBitmap;
757 err = bitmap->Create(KSize, KMode);
760 err = bitmap->CompressInBackground();
765 RFbsSession::Disconnect();
770 __CONSTRUCT_STEP__(Compressed)