LexerTransition<nsIconDecoder::State> nsIconDecoder::ReadHeader(const char* aData) { // Grab the width and height. uint8_t width = uint8_t(aData[0]); uint8_t height = uint8_t(aData[1]); // The input is 32bpp, so we expect 4 bytes of data per pixel. mBytesPerRow = width * 4; // Post our size to the superclass. PostSize(width, height); // Icons have alpha. PostHasTransparency(); // If we're doing a metadata decode, we're done. if (IsMetadataDecode()) { return Transition::TerminateSuccess(); } MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(this, 0, Size(), OutputSize(), FullFrame(), SurfaceFormat::B8G8R8A8, SurfacePipeFlags()); if (!pipe) { return Transition::TerminateFailure(); } mPipe = Move(*pipe); MOZ_ASSERT(mImageData, "Should have a buffer now"); return Transition::To(State::ROW_OF_PIXELS, mBytesPerRow); }
void gprint(size_t num, genotype gtype) { extern int spd[]; extern double gain[], thr[], w[]; int i, j, position; size_t column, offset; column = HideSize(gtype[0]) + OutputSize(gtype[0]); printf("[Population Number] %ld\n", num); printf("[Number of Transition] %llu\n", TransitionSize(gtype[0])); draw_line(column); printf("| |"); for(i = 0; i < HideSize(gtype[0]); i++) printf(" H%2d |", i); for(i = 0; i < OutputSize(gtype[0]); i++) printf(" O%2d |", i); printf(" 0x%010llX\n", (genotype_t)gtype[0]); draw_line(column); printf("| Function |"); for(i = 0; i < column; i++) { position = (column - i - 1) * 4; printf(" %9s |", function_name((gtype[1] >> position) & 0x0F)); } printf(" 0x%010llX\n", (genotype_t)gtype[1]); printf("| Parameter |"); for(i = 0; i < column; i++) { position = (column - i - 1) * 4; printf(" %+.2f |", gain[(gtype[2] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[2]); printf("| Speed |"); for(i = 0; i < column; i++) { position = (column - i - 1) * 4; printf(" %3d |", spd[(gtype[3] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[3]); printf("| Threshold |"); for(i = 0; i < column; i++) { position = (column - i - 1) * 4; printf(" %+.2f |", thr[(gtype[4] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[4]); draw_line(column); offset = ParameterSize(gtype[0]) + 1; for(i = 0; i < InternalSize(gtype[0]); i++) { printf("| I%2d |", i); for(j = 0; j < column; j++) { position = (column - j - 1) * 4; printf(" %+.2f |", w[(gtype[offset + i] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[offset + i]); } draw_line(column); offset += InternalSize(gtype[0]); if(ExternalSize(gtype[0]) != 0) { for(i = 0; i < ExternalSize(gtype[0]); i++) { printf("| E%2d |", i); for(j = 0; j < column; j++) { position = (column - j - 1) * 4; printf(" %+.2f |", w[(gtype[offset + i] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[offset + i]); } draw_line(column); } offset += ExternalSize(gtype[0]); for(i = 0; i < HideSize(gtype[0]); i++) { printf("| H%2d |", i); for(j = 0; j < column; j++) { position = (column - j - 1) * 4; printf(" %+.2f |", w[(gtype[offset + i] >> position) & 0x0F]); } printf(" 0x%010llX\n", (genotype_t)gtype[offset + i]); } draw_line(column); putchar('\n'); }
LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData(const char* aData, size_t aLength) { mSegment = reinterpret_cast<const JOCTET*>(aData); mSegmentLen = aLength; // Return here if there is a fatal error within libjpeg. nsresult error_code; // This cast to nsresult makes sense because setjmp() returns whatever we // passed to longjmp(), which was actually an nsresult. if ((error_code = static_cast<nsresult>(setjmp(mErr.setjmp_buffer))) != NS_OK) { if (error_code == NS_ERROR_FAILURE) { // Error due to corrupt data. Make sure that we don't feed any more data // to libjpeg-turbo. mState = JPEG_SINK_NON_JPEG_TRAILER; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (setjmp returned NS_ERROR_FAILURE)")); } else { // Error for another reason. (Possibly OOM.) mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (setjmp returned an error)")); } return Transition::TerminateFailure(); } MOZ_LOG(sJPEGLog, LogLevel::Debug, ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this)); switch (mState) { case JPEG_HEADER: { LOG_SCOPE((mozilla::LogModule*)sJPEGLog, "nsJPEGDecoder::Write -- entering JPEG_HEADER" " case"); // Step 3: read file parameters with jpeg_read_header() if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (JPEG_SUSPENDED)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } // Post our size to the superclass PostSize(mInfo.image_width, mInfo.image_height, ReadOrientationFromEXIF()); if (HasError()) { // Setting the size led to an error. mState = JPEG_ERROR; return Transition::TerminateFailure(); } // If we're doing a metadata decode, we're done. if (IsMetadataDecode()) { return Transition::TerminateSuccess(); } // We're doing a full decode. if (mCMSMode != eCMSMode_Off && (mInProfile = GetICCProfile(mInfo)) != nullptr) { uint32_t profileSpace = qcms_profile_get_color_space(mInProfile); bool mismatch = false; #ifdef DEBUG_tor fprintf(stderr, "JPEG profileSpace: 0x%08X\n", profileSpace); #endif switch (mInfo.jpeg_color_space) { case JCS_GRAYSCALE: if (profileSpace == icSigRgbData) { mInfo.out_color_space = JCS_RGB; } else if (profileSpace != icSigGrayData) { mismatch = true; } break; case JCS_RGB: if (profileSpace != icSigRgbData) { mismatch = true; } break; case JCS_YCbCr: if (profileSpace == icSigRgbData) { mInfo.out_color_space = JCS_RGB; } else { // qcms doesn't support ycbcr mismatch = true; } break; case JCS_CMYK: case JCS_YCCK: // qcms doesn't support cmyk mismatch = true; break; default: mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (unknown colorpsace (1))")); return Transition::TerminateFailure(); } if (!mismatch) { qcms_data_type type; switch (mInfo.out_color_space) { case JCS_GRAYSCALE: type = QCMS_DATA_GRAY_8; break; case JCS_RGB: type = QCMS_DATA_RGB_8; break; default: mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (unknown colorpsace (2))")); return Transition::TerminateFailure(); } #if 0 // We don't currently support CMYK profiles. The following // code dealt with lcms types. Add something like this // back when we gain support for CMYK. // Adobe Photoshop writes YCCK/CMYK files with inverted data if (mInfo.out_color_space == JCS_CMYK) { type |= FLAVOR_SH(mInfo.saw_Adobe_marker ? 1 : 0); } #endif if (gfxPlatform::GetCMSOutputProfile()) { // Calculate rendering intent. int intent = gfxPlatform::GetRenderingIntent(); if (intent == -1) { intent = qcms_profile_get_rendering_intent(mInProfile); } // Create the color management transform. mTransform = qcms_transform_create(mInProfile, type, gfxPlatform::GetCMSOutputProfile(), QCMS_DATA_RGB_8, (qcms_intent)intent); } } else { #ifdef DEBUG_tor fprintf(stderr, "ICM profile colorspace mismatch\n"); #endif } } if (!mTransform) { switch (mInfo.jpeg_color_space) { case JCS_GRAYSCALE: case JCS_RGB: case JCS_YCbCr: // if we're not color managing we can decode directly to // MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB if (mCMSMode != eCMSMode_All) { mInfo.out_color_space = MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB; mInfo.out_color_components = 4; } else { mInfo.out_color_space = JCS_RGB; } break; case JCS_CMYK: case JCS_YCCK: // libjpeg can convert from YCCK to CMYK, but not to RGB mInfo.out_color_space = JCS_CMYK; break; default: mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (unknown colorpsace (3))")); return Transition::TerminateFailure(); } } // Don't allocate a giant and superfluous memory buffer // when not doing a progressive decode. mInfo.buffered_image = mDecodeStyle == PROGRESSIVE && jpeg_has_multiple_scans(&mInfo); /* Used to set up image size so arrays can be allocated */ jpeg_calc_output_dimensions(&mInfo); MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); nsresult rv = AllocateFrame(/* aFrameNum = */ 0, OutputSize(), FullOutputFrame(), SurfaceFormat::B8G8R8X8); if (NS_FAILED(rv)) { mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (could not initialize image frame)")); return Transition::TerminateFailure(); } MOZ_ASSERT(mImageData, "Should have a buffer now"); if (mDownscaler) { nsresult rv = mDownscaler->BeginFrame(Size(), Nothing(), mImageData, /* aHasAlpha = */ false); if (NS_FAILED(rv)) { mState = JPEG_ERROR; return Transition::TerminateFailure(); } } MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, (" JPEGDecoderAccounting: nsJPEGDecoder::" "Write -- created image frame with %ux%u pixels", mInfo.image_width, mInfo.image_height)); mState = JPEG_START_DECOMPRESS; MOZ_FALLTHROUGH; // to start decompressing. } case JPEG_START_DECOMPRESS: { LOG_SCOPE((mozilla::LogModule*)sJPEGLog, "nsJPEGDecoder::Write -- entering" " JPEG_START_DECOMPRESS case"); // Step 4: set parameters for decompression // FIXME -- Should reset dct_method and dither mode // for final pass of progressive JPEG mInfo.dct_method = JDCT_ISLOW; mInfo.dither_mode = JDITHER_FS; mInfo.do_fancy_upsampling = TRUE; mInfo.enable_2pass_quant = FALSE; mInfo.do_block_smoothing = TRUE; // Step 5: Start decompressor if (jpeg_start_decompress(&mInfo) == FALSE) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after jpeg_start_decompress())")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } // If this is a progressive JPEG ... mState = mInfo.buffered_image ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; MOZ_FALLTHROUGH; // to decompress sequential JPEG. } case JPEG_DECOMPRESS_SEQUENTIAL: { if (mState == JPEG_DECOMPRESS_SEQUENTIAL) { LOG_SCOPE((mozilla::LogModule*)sJPEGLog, "nsJPEGDecoder::Write -- " "JPEG_DECOMPRESS_SEQUENTIAL case"); bool suspend; OutputScanlines(&suspend); if (suspend) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after OutputScanlines() - SEQUENTIAL)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } // If we've completed image output ... NS_ASSERTION(mInfo.output_scanline == mInfo.output_height, "We didn't process all of the data!"); mState = JPEG_DONE; } MOZ_FALLTHROUGH; // to decompress progressive JPEG. } case JPEG_DECOMPRESS_PROGRESSIVE: { if (mState == JPEG_DECOMPRESS_PROGRESSIVE) { LOG_SCOPE((mozilla::LogModule*)sJPEGLog, "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case"); int status; do { status = jpeg_consume_input(&mInfo); } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); for (;;) { if (mInfo.output_scanline == 0) { int scan = mInfo.input_scan_number; // if we haven't displayed anything yet (output_scan_number==0) // and we have enough data for a complete scan, force output // of the last full scan if ((mInfo.output_scan_number == 0) && (scan > 1) && (status != JPEG_REACHED_EOI)) scan--; if (!jpeg_start_output(&mInfo, scan)) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after jpeg_start_output() -" " PROGRESSIVE)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } } if (mInfo.output_scanline == 0xffffff) { mInfo.output_scanline = 0; } bool suspend; OutputScanlines(&suspend); if (suspend) { if (mInfo.output_scanline == 0) { // didn't manage to read any lines - flag so we don't call // jpeg_start_output() multiple times for the same scan mInfo.output_scanline = 0xffffff; } MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after OutputScanlines() - PROGRESSIVE)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } if (mInfo.output_scanline == mInfo.output_height) { if (!jpeg_finish_output(&mInfo)) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after jpeg_finish_output() -" " PROGRESSIVE)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } if (jpeg_input_complete(&mInfo) && (mInfo.input_scan_number == mInfo.output_scan_number)) break; mInfo.output_scanline = 0; if (mDownscaler) { mDownscaler->ResetForNextProgressivePass(); } } } mState = JPEG_DONE; } MOZ_FALLTHROUGH; // to finish decompressing. } case JPEG_DONE: { LOG_SCOPE((mozilla::LogModule*)sJPEGLog, "nsJPEGDecoder::ProcessData -- entering" " JPEG_DONE case"); // Step 7: Finish decompression if (jpeg_finish_decompress(&mInfo) == FALSE) { MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, ("} (I/O suspension after jpeg_finish_decompress() - DONE)")); return Transition::ContinueUnbuffered(State::JPEG_DATA); // I/O suspension } // Make sure we don't feed any more data to libjpeg-turbo. mState = JPEG_SINK_NON_JPEG_TRAILER; // We're done. return Transition::TerminateSuccess(); } case JPEG_SINK_NON_JPEG_TRAILER: MOZ_LOG(sJPEGLog, LogLevel::Debug, ("[this=%p] nsJPEGDecoder::ProcessData -- entering" " JPEG_SINK_NON_JPEG_TRAILER case\n", this)); MOZ_ASSERT_UNREACHABLE("Should stop getting data after entering state " "JPEG_SINK_NON_JPEG_TRAILER"); return Transition::TerminateSuccess(); case JPEG_ERROR: MOZ_ASSERT_UNREACHABLE("Should stop getting data after entering state " "JPEG_ERROR"); return Transition::TerminateFailure(); } MOZ_ASSERT_UNREACHABLE("Escaped the JPEG decoder state machine"); return Transition::TerminateFailure(); }