SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit) : fScaleToFit(scaleToFit) { SkASSERT(intervals); SkASSERT(count > 1 && SkAlign2(count) == count); fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); fCount = count; SkScalar len = 0; for (int i = 0; i < count; i++) { SkASSERT(intervals[i] >= 0); fIntervals[i] = intervals[i]; len += intervals[i]; } fIntervalLength = len; // watch out for values that might make us go out of bounds if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) { // Adjust phase to be between 0 and len, "flipping" phase if negative. // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80 if (phase < 0) { phase = -phase; if (phase > len) { phase = SkScalarMod(phase, len); } phase = len - phase; // Due to finite precision, it's possible that phase == len, // even after the subtract (if len >>> phase), so fix that here. // This fixes http://crbug.com/124652 . SkASSERT(phase <= len); if (phase == len) { phase = 0; } } else if (phase >= len) { phase = SkScalarMod(phase, len); } SkASSERT(phase >= 0 && phase < len); fInitialDashLength = FindFirstInterval(intervals, phase, &fInitialDashIndex, count); SkASSERT(fInitialDashLength >= 0); SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount); } else { fInitialDashLength = -1; // signal bad dash intervals } }
SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) { SkASSERT(intervals); SkASSERT(count > 1 && SkAlign2(count) == count); fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); fCount = count; for (int i = 0; i < count; i++) { SkASSERT(intervals[i] >= 0); fIntervals[i] = intervals[i]; } this->setInternalMembers(phase); }
SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) : fPhase(0) , fInitialDashLength(-1) , fInitialDashIndex(0) , fIntervalLength(0) { SkASSERT(intervals); SkASSERT(count > 1 && SkAlign2(count) == count); fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); fCount = count; for (int i = 0; i < count; i++) { fIntervals[i] = intervals[i]; } // set the internal data members SkDashPath::CalcDashParameters(phase, fIntervals, fCount, &fInitialDashLength, &fInitialDashIndex, &fIntervalLength, &fPhase); }
SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit) : fScaleToFit(scaleToFit) { SkASSERT(intervals); SkASSERT(count > 1 && SkAlign2(count) == count); fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); fCount = count; SkScalar len = 0; for (int i = 0; i < count; i++) { SkASSERT(intervals[i] >= 0); fIntervals[i] = intervals[i]; len += intervals[i]; } fIntervalLength = len; if (len > 0) // we don't handle 0 length dash arrays { if (phase < 0) { phase = -phase; if (phase > len) phase = SkScalarMod(phase, len); phase = len - phase; } else if (phase >= len) phase = SkScalarMod(phase, len); SkASSERT(phase >= 0 && phase < len); fInitialDashLength = FindFirstInterval(intervals, phase, &fInitialDashIndex); SkASSERT(fInitialDashLength >= 0); SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount); } else fInitialDashLength = -1; // signal bad dash intervals }
/* * Performs the bitmap decoding for RLE input format * RLE decoding is performed all at once, rather than a one row at a time */ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts) { // Set RLE flags static const uint8_t RLE_ESCAPE = 0; static const uint8_t RLE_EOL = 0; static const uint8_t RLE_EOF = 1; static const uint8_t RLE_DELTA = 2; // Set constant values const int width = dstInfo.width(); const int height = dstInfo.height(); // Destination parameters int x = 0; int y = 0; // Set the background as transparent. Then, if the RLE code skips pixels, // the skipped pixels will be transparent. // Because of the need for transparent pixels, kN32 is the only color // type that makes sense for the destination format. SkASSERT(kN32_SkColorType == dstInfo.colorType()); if (kNo_ZeroInitialized == opts.fZeroInitialized) { SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL); } while (true) { // If we have reached a row that is beyond the requested height, we have // succeeded. if (y >= height) { // It would be better to check for the EOF marker before returning // success, but we may be performing a scanline decode, which // may require us to stop before decoding the full height. return kSuccess; } // Every entry takes at least two bytes if ((int) fRLEBytes - fCurrRLEByte < 2) { SkCodecPrintf("Warning: might be incomplete RLE input.\n"); if (this->checkForMoreData() < 2) { return kIncompleteInput; } } // Read the next two bytes. These bytes have different meanings // depending on their values. In the first interpretation, the first // byte is an escape flag and the second byte indicates what special // task to perform. const uint8_t flag = fStreamBuffer.get()[fCurrRLEByte++]; const uint8_t task = fStreamBuffer.get()[fCurrRLEByte++]; // Perform decoding if (RLE_ESCAPE == flag) { switch (task) { case RLE_EOL: x = 0; y++; break; case RLE_EOF: return kSuccess; case RLE_DELTA: { // Two bytes are needed to specify delta if ((int) fRLEBytes - fCurrRLEByte < 2) { SkCodecPrintf("Warning: might be incomplete RLE input.\n"); if (this->checkForMoreData() < 2) { return kIncompleteInput; } } // Modify x and y const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; x += dx; y += dy; if (x > width || y > height) { SkCodecPrintf("Warning: invalid RLE input.\n"); return kInvalidInput; } break; } default: { // If task does not match any of the above signals, it // indicates that we have a sequence of non-RLE pixels. // Furthermore, the value of task is equal to the number // of pixels to interpret. uint8_t numPixels = task; const size_t rowBytes = compute_row_bytes(numPixels, this->bitsPerPixel()); // Abort if setting numPixels moves us off the edge of the // image. if (x + numPixels > width) { SkCodecPrintf("Warning: invalid RLE input.\n"); return kInvalidInput; } // Also abort if there are not enough bytes // remaining in the stream to set numPixels. if ((int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) { SkCodecPrintf("Warning: might be incomplete RLE input.\n"); if (this->checkForMoreData() < SkAlign2(rowBytes)) { return kIncompleteInput; } } // Set numPixels number of pixels while (numPixels > 0) { switch(this->bitsPerPixel()) { case 4: { SkASSERT(fCurrRLEByte < fRLEBytes); uint8_t val = fStreamBuffer.get()[fCurrRLEByte++]; setPixel(dst, dstRowBytes, dstInfo, x++, y, val >> 4); numPixels--; if (numPixels != 0) { setPixel(dst, dstRowBytes, dstInfo, x++, y, val & 0xF); numPixels--; } break; } case 8: SkASSERT(fCurrRLEByte < fRLEBytes); setPixel(dst, dstRowBytes, dstInfo, x++, y, fStreamBuffer.get()[fCurrRLEByte++]); numPixels--; break; case 24: { SkASSERT(fCurrRLEByte + 2 < fRLEBytes); uint8_t blue = fStreamBuffer.get()[fCurrRLEByte++]; uint8_t green = fStreamBuffer.get()[fCurrRLEByte++]; uint8_t red = fStreamBuffer.get()[fCurrRLEByte++]; setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, green, blue); numPixels--; } default: SkASSERT(false); return kInvalidInput; } } // Skip a byte if necessary to maintain alignment if (!SkIsAlign2(rowBytes)) { fCurrRLEByte++; } break; } } } else { // If the first byte read is not a flag, it indicates the number of // pixels to set in RLE mode. const uint8_t numPixels = flag; const int endX = SkTMin<int>(x + numPixels, width); if (24 == this->bitsPerPixel()) { // In RLE24, the second byte read is part of the pixel color. // There are two more required bytes to finish encoding the // color. if ((int) fRLEBytes - fCurrRLEByte < 2) { SkCodecPrintf("Warning: might be incomplete RLE input.\n"); if (this->checkForMoreData() < 2) { return kIncompleteInput; } } // Fill the pixels up to endX with the specified color uint8_t blue = task; uint8_t green = fStreamBuffer.get()[fCurrRLEByte++]; uint8_t red = fStreamBuffer.get()[fCurrRLEByte++]; while (x < endX) { setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, green, blue); } } else { // In RLE8 or RLE4, the second byte read gives the index in the // color table to look up the pixel color. // RLE8 has one color index that gets repeated // RLE4 has two color indexes in the upper and lower 4 bits of // the bytes, which are alternated uint8_t indices[2] = { task, task }; if (4 == this->bitsPerPixel()) { indices[0] >>= 4; indices[1] &= 0xf; } // Set the indicated number of pixels for (int which = 0; x < endX; x++) { setPixel(dst, dstRowBytes, dstInfo, x, y, indices[which]); which = !which; } } }