// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things. void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& providedTileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dstRect, solidColor(), op); return; } // FIXME: We do not support 'space' yet. For now just map it to 'repeat'. if (hRule == SpaceTile) hRule = RepeatTile; if (vRule == SpaceTile) vRule = RepeatTile; // FIXME: if this code is used for background-repeat: round (in addition to // border-image-repeat), then add logic to deal with the background-size: auto // special case. The aspect ratio should be maintained in this case. FloatSize tileScaleFactor = providedTileScaleFactor; bool useLowInterpolationQuality = false; if (hRule == RoundTile) { float hRepetitions = std::max(1.0f, roundf(dstRect.width() / (tileScaleFactor.width() * srcRect.width()))); tileScaleFactor.setWidth(dstRect.width() / (srcRect.width() * hRepetitions)); } if (vRule == RoundTile) { float vRepetitions = std::max(1.0f, roundf(dstRect.height() / (tileScaleFactor.height() * srcRect.height()))); tileScaleFactor.setHeight(dstRect.height() / (srcRect.height() * vRepetitions)); } if (hRule == RoundTile || vRule == RoundTile) { // High interpolation quality rounds the scaled tile to an integer size (see Image::drawPattern). // To avoid causing a visual problem, linear interpolation must be used instead. // FIXME: Allow using high-quality interpolation in this case, too. useLowInterpolationQuality = true; } // We want to construct the phase such that the pattern is centered (when stretch is not // set for a particular rule). float hPhase = tileScaleFactor.width() * srcRect.x(); float vPhase = tileScaleFactor.height() * srcRect.y(); float scaledTileWidth = tileScaleFactor.width() * srcRect.width(); float scaledTileHeight = tileScaleFactor.height() * srcRect.height(); if (hRule == Image::RepeatTile) hPhase -= (dstRect.width() - scaledTileWidth) / 2; if (vRule == Image::RepeatTile) vPhase -= (dstRect.height() - scaledTileHeight) / 2; FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); if (useLowInterpolationQuality) { InterpolationQuality previousInterpolationQuality = ctxt->imageInterpolationQuality(); ctxt->setImageInterpolationQuality(InterpolationLow); drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); ctxt->setImageInterpolationQuality(previousInterpolationQuality); } else { drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); } startAnimation(); }
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things. void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dstRect, solidColor(), op); return; } // FIXME: We do not support 'round' yet. For now just map it to 'repeat'. if (hRule == RoundTile) hRule = RepeatTile; if (vRule == RoundTile) vRule = RepeatTile; FloatSize scale = calculatePatternScale(dstRect, srcRect, hRule, vRule); AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height()); // We want to construct the phase such that the pattern is centered (when stretch is not // set for a particular rule). float hPhase = scale.width() * srcRect.x(); float vPhase = scale.height() * srcRect.y(); if (hRule == Image::RepeatTile) hPhase -= fmodf(dstRect.width(), scale.width() * srcRect.width()) / 2.0f; if (vRule == Image::RepeatTile) vPhase -= fmodf(dstRect.height(), scale.height() * srcRect.height()) / 2.0f; FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); drawPattern(ctxt, srcRect, patternTransform, patternPhase, op, dstRect); startAnimation(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, SkXfermode::Mode op, const IntSize& repeatSpacing) { FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatSize actualTileSize(scaledTileSize.width() + repeatSpacing.width(), scaledTileSize.height() + repeatSpacing.height()); FloatRect oneTileRect; oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect)) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); ctxt->drawImage(this, destRect, visibleSrcRect, op, DoNotRespectImageOrientation); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, repeatSpacing); startAnimation(); }
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, SkBlendMode op, const FloatSize& repeatSpacing) { FloatSize intrinsicTileSize = FloatSize(size()); if (hasRelativeSize()) { intrinsicTileSize.setWidth(scaledTileSize.width()); intrinsicTileSize.setHeight(scaledTileSize.height()); } FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); const FloatRect oneTileRect = computeTileContaining( destRect.location(), scaledTileSize, srcPoint, repeatSpacing); // Check and see if a single draw of the image can cover the entire area we // are supposed to tile. if (oneTileRect.contains(destRect)) { const FloatRect visibleSrcRect = computeSubsetForTile(oneTileRect, destRect, intrinsicTileSize); ctxt.drawImage(this, destRect, &visibleSrcRect, op, DoNotRespectImageOrientation); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, repeatSpacing); startAnimation(); }
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things. void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, op); return; } // FIXME: We do not support 'round' or 'space' yet. For now just map them to 'repeat'. if (hRule == RoundTile || hRule == SpaceTile) hRule = RepeatTile; if (vRule == RoundTile || vRule == SpaceTile) vRule = RepeatTile; AffineTransform patternTransform = AffineTransform().scaleNonUniform(tileScaleFactor.width(), tileScaleFactor.height()); // We want to construct the phase such that the pattern is centered (when stretch is not // set for a particular rule). float hPhase = tileScaleFactor.width() * srcRect.x(); float vPhase = tileScaleFactor.height() * srcRect.y(); float scaledTileWidth = tileScaleFactor.width() * srcRect.width(); float scaledTileHeight = tileScaleFactor.height() * srcRect.height(); if (hRule == Image::RepeatTile) hPhase -= (dstRect.width() - scaledTileWidth) / 2; if (vRule == Image::RepeatTile) vPhase -= (dstRect.height() - scaledTileHeight) / 2; FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); drawPattern(ctxt, srcRect, patternTransform, patternPhase, styleColorSpace, op, dstRect); startAnimation(); }
void yeseulWhitneyScene::draw(){ ofPushMatrix(); ofTranslate(dimensions.width/2, dimensions.height/2); drawPattern(); diffusion(); ofPopMatrix(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, ColorSpace styleColorSpace, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, op); return; } // See <https://webkit.org/b/59043>. #if !PLATFORM(WX) ASSERT(!isBitmapImage() || notSolidColor()); #endif FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatRect oneTileRect; oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect)) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, styleColorSpace, op); return; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect); startAnimation(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op, WebBlendMode blendMode, const IntSize& repeatSpacing) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } // See <https://webkit.org/b/59043>. ASSERT(!isBitmapImage() || notSolidColor()); FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatSize actualTileSize(scaledTileSize.width() + repeatSpacing.width(), scaledTileSize.height() + repeatSpacing.height()); FloatRect oneTileRect; oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect)) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, blendMode); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, blendMode, repeatSpacing); startAnimation(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, ColorSpace styleColorSpace, CompositeOperator op, BlendMode blendMode) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, op); return; } ASSERT(!isBitmapImage() || notSolidColor()); FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatRect oneTileRect; FloatSize actualTileSize(scaledTileSize.width() + spaceSize().width(), scaledTileSize.height() + spaceSize().height()); oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect) && !ctxt->drawLuminanceMask()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, styleColorSpace, op, blendMode, ImageOrientationDescription()); return; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect, blendMode); startAnimation(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height()); FloatRect oneTileRect; oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect)) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPatternCounter.startCounting(); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect); drawPatternCounter.stopCounting(); startAnimation(); }
void CharacterBase::drawAction(const Vec2f & pos_, const int & action_index_, const int & frame_index_, const Texture & tex_) { int pattern_index = actions[action_index_].frame[frame_index_].x(); drawPattern(pos_, pattern_index, tex_); }
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } ASSERT(!isBitmapImage() || notSolidColor()); #if PLATFORM(IOS) FloatSize intrinsicTileSize = originalSize(); #else FloatSize intrinsicTileSize = size(); #endif if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatRect oneTileRect; FloatSize actualTileSize(scaledTileSize.width() + spacing.width(), scaledTileSize.height() + spacing.height()); oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect) && !ctxt.drawLuminanceMask()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, blendMode, ImageOrientationDescription()); return; } #if PLATFORM(IOS) // When using accelerated drawing on iOS, it's faster to stretch an image than to tile it. if (ctxt.isAcceleratedContext()) { if (size().width() == 1 && intersection(oneTileRect, destRect).height() == destRect.height()) { FloatRect visibleSrcRect; visibleSrcRect.setX(0); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(1); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } if (size().height() == 1 && intersection(oneTileRect, destRect).width() == destRect.width()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY(0); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(1); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } } #endif // Patterned images and gradients can use lots of memory for caching when the // tile size is large (<rdar://problem/4691859>, <rdar://problem/6239505>). // Memory consumption depends on the transformed tile size which can get // larger than the original tile if user zooms in enough. #if PLATFORM(IOS) const float maxPatternTilePixels = 512 * 512; #else const float maxPatternTilePixels = 2048 * 2048; #endif FloatRect transformedTileSize = ctxt.getCTM().mapRect(FloatRect(FloatPoint(), scaledTileSize)); float transformedTileSizePixels = transformedTileSize.width() * transformedTileSize.height(); FloatRect currentTileRect = oneTileRect; if (transformedTileSizePixels > maxPatternTilePixels) { GraphicsContextStateSaver stateSaver(ctxt); ctxt.clip(destRect); currentTileRect.shiftYEdgeTo(destRect.y()); float toY = currentTileRect.y(); while (toY < destRect.maxY()) { currentTileRect.shiftXEdgeTo(destRect.x()); float toX = currentTileRect.x(); while (toX < destRect.maxX()) { FloatRect toRect(toX, toY, currentTileRect.width(), currentTileRect.height()); FloatRect fromRect(toFloatPoint(currentTileRect.location() - oneTileRect.location()), currentTileRect.size()); fromRect.scale(1 / scale.width(), 1 / scale.height()); draw(ctxt, toRect, fromRect, op, BlendModeNormal, ImageOrientationDescription()); toX += currentTileRect.width(); currentTileRect.shiftXEdgeTo(oneTileRect.x()); } toY += currentTileRect.height(); currentTileRect.shiftYEdgeTo(oneTileRect.y()); } return; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), spacing, op, destRect, blendMode); #if PLATFORM(IOS) startAnimation(DoNotCatchUp); #else startAnimation(); #endif }
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things. void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dstRect, solidColor(), op); return; } FloatSize tileScale = tileScaleFactor; FloatSize spacing; // FIXME: These rules follow CSS border-image rules, but they should not be down here in Image. bool centerOnGapHorizonally = false; bool centerOnGapVertically = false; switch (hRule) { case RoundTile: { int numItems = std::max<int>(floorf(dstRect.width() / srcRect.width()), 1); tileScale.setWidth(dstRect.width() / (srcRect.width() * numItems)); break; } case SpaceTile: { int numItems = floorf(dstRect.width() / srcRect.width()); if (!numItems) return; spacing.setWidth((dstRect.width() - srcRect.width() * numItems) / (numItems + 1)); tileScale.setWidth(1); centerOnGapHorizonally = !(numItems & 1); break; } case StretchTile: case RepeatTile: break; } switch (vRule) { case RoundTile: { int numItems = std::max<int>(floorf(dstRect.height() / srcRect.height()), 1); tileScale.setHeight(dstRect.height() / (srcRect.height() * numItems)); break; } case SpaceTile: { int numItems = floorf(dstRect.height() / srcRect.height()); if (!numItems) return; spacing.setHeight((dstRect.height() - srcRect.height() * numItems) / (numItems + 1)); tileScale.setHeight(1); centerOnGapVertically = !(numItems & 1); break; } case StretchTile: case RepeatTile: break; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(tileScale.width(), tileScale.height()); // We want to construct the phase such that the pattern is centered (when stretch is not // set for a particular rule). float hPhase = tileScale.width() * srcRect.x(); float vPhase = tileScale.height() * srcRect.y(); float scaledTileWidth = tileScale.width() * srcRect.width(); float scaledTileHeight = tileScale.height() * srcRect.height(); if (centerOnGapHorizonally) hPhase -= spacing.width(); else if (hRule == Image::RepeatTile || hRule == Image::SpaceTile) hPhase -= (dstRect.width() - scaledTileWidth) / 2; if (centerOnGapVertically) vPhase -= spacing.height(); else if (vRule == Image::RepeatTile || vRule == Image::SpaceTile) vPhase -= (dstRect.height() - scaledTileHeight) / 2; FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); drawPattern(ctxt, srcRect, patternTransform, patternPhase, spacing, op, dstRect); #if PLATFORM(IOS) startAnimation(DoNotCatchUp); #else startAnimation(); #endif }
int main(int argc, char* argv[]) { signal(SIGSEGV, segFault); if (argc < 2) { printUsage(); return 0; } #ifdef DEPRECATED printf("*Deprecation warning*\n"); fflush(0); #endif randomizer.timeSeed(); Scene& scene = *Scene::getInstance(); Texture screen; int w = 300, h = 300; bool threads_changed = 0; std::string filename, output = "out.bmp"; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--no-preview")) { settings.show_preview = 0; } else if (!strcmp(argv[i], "--size")) { sscanf(argv[++i], "%d", &w); sscanf(argv[++i], "%d", &h); } else if (!strcmp(argv[i], "--renders")) { sscanf(argv[++i], "%d", &settings.nrenders); } else if (!strcmp(argv[i], "--samples")) { sscanf(argv[++i], "%d", &settings.nsamples); } else if (!strcmp(argv[i], "--shadows")) { sscanf(argv[++i], "%d", &settings.nshadows); } else if (!strcmp(argv[i], "--coherent")) { settings.coherence = 1; } else if (!strcmp(argv[i], "--point-lights")) { settings.point_lights = 1; } else if (!strcmp(argv[i], "--dof-degrees")) { sscanf(argv[++i], "%f", &settings.dof_range); settings.dof_range *= PI / 180.0; } else if (!strcmp(argv[i], "--no-aa")) { settings.aa_enabled = 0; } else if (!strcmp(argv[i], "--aa-threshold")) { sscanf(argv[++i], "%f", &settings.aa_threshold); } else if (!strcmp(argv[i], "--threads")) { threads_changed = 1; sscanf(argv[++i], "%d", &settings.nworkers); } else if (!strcmp(argv[i], "--output") || !strcmp(argv[i], "-o")) { output = argv[++i]; } else if (!strcmp(argv[i], "--no-output")) { output = ""; } else { if (filename.empty()) { filename = argv[i]; } else { printf("Unrecognized token \"%s\".\n", argv[i]); exit(0); } } } if (settings.show_preview) { if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; } else { if (SDL_Init(0) < 0) return -1; } atexit(SDL_Quit); if (!threads_changed) { settings.nworkers = SDL_GetCPUCount(); if (settings.nworkers > 1) settings.nworkers--; //Use n threads (counting this one) on n-core machines, but 2 threads for single-core machines } try { Parser parser; parser.parseInto(filename.c_str(), &scene); } catch (std::exception& e) { fprintf(stderr, "%s\n", e.what()); return 1; } scene.init(); /* * Set up scene */ scene.camera.setScreen(w, h, (float)w / h, 1, PI / 2); screen.setDimensions(scene.camera.pxw, scene.camera.pxh); drawPattern(screen); if (settings.show_preview) { window = SDL_CreateWindow(TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scene.camera.pxw, scene.camera.pxh, 0); px = new PixelRenderer(SDL_CreateRenderer(window, -1, 0), scene.camera.pxw, scene.camera.pxh); redraw(screen); } Uint32 started = SDL_GetTicks(); std::vector<Texture> screens; for (int i = 0; i < settings.nrenders; i++) { render(scene, screen, i + 1, settings.nrenders); screens.push_back(screen); randomizer.advanceSeed(); } screen = Texture(screens); #ifndef SHOW_AA if (settings.show_preview) redraw(screen); #endif printf("Tracing complete:\n"); printf("\tTotal time elapsed: %.3fs\n", 0.001 * (SDL_GetTicks() - started)); fflush(0); if (output != "") screen.save_filename(output); if (settings.show_preview) { SDL_Event event; bool exitflag = 0; while (!exitflag) { while (SDL_PollEvent(&event)) if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) exitflag = 1; SDL_Delay(100); } SDL_DestroyRenderer(px->getRenderer()); delete px; SDL_DestroyWindow(window); } return 0; }
// TODO(cavalcantii): see crbug.com/662504. void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& providedTileScaleFactor, TileRule hRule, TileRule vRule, SkBlendMode op) { // TODO(cavalcantii): see crbug.com/662513. FloatSize tileScaleFactor = providedTileScaleFactor; if (vRule == RoundTile) { float vRepetitions = std::max(1.0f, roundf(dstRect.height() / (tileScaleFactor.height() * srcRect.height()))); tileScaleFactor.setHeight(dstRect.height() / (srcRect.height() * vRepetitions)); } if (hRule == RoundTile) { float hRepetitions = std::max( 1.0f, roundf(dstRect.width() / (tileScaleFactor.width() * srcRect.width()))); tileScaleFactor.setWidth(dstRect.width() / (srcRect.width() * hRepetitions)); } // We want to construct the phase such that the pattern is centered (when // stretch is not set for a particular rule). float vPhase = tileScaleFactor.height() * srcRect.y(); float hPhase = tileScaleFactor.width() * srcRect.x(); if (vRule == Image::RepeatTile) { float scaledTileHeight = tileScaleFactor.height() * srcRect.height(); vPhase -= (dstRect.height() - scaledTileHeight) / 2; } if (hRule == Image::RepeatTile) { float scaledTileWidth = tileScaleFactor.width() * srcRect.width(); hPhase -= (dstRect.width() - scaledTileWidth) / 2; } FloatSize spacing; auto calculateSpaceNeeded = []( const float destination, const float source) -> std::tuple<bool, float> { DCHECK_GT(source, 0); DCHECK_GT(destination, 0); float repeatTilesCount = floorf(destination / source); if (!repeatTilesCount) return std::make_tuple(false, -1); float space = destination; space -= source * repeatTilesCount; space /= repeatTilesCount + 1.0; return std::make_tuple(true, space); }; if (vRule == SpaceTile) { std::tuple<bool, float> space = calculateSpaceNeeded(dstRect.height(), srcRect.height()); if (!std::get<0>(space)) return; spacing.setHeight(std::get<1>(space)); tileScaleFactor.setHeight(1.0); vPhase = srcRect.y(); vPhase -= spacing.height(); } if (hRule == SpaceTile) { std::tuple<bool, float> space = calculateSpaceNeeded(dstRect.width(), srcRect.width()); if (!std::get<0>(space)) return; spacing.setWidth(std::get<1>(space)); tileScaleFactor.setWidth(1.0); hPhase = srcRect.x(); hPhase -= spacing.width(); } FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); // TODO(cavalcantii): see crbug.com/662507. if ((hRule == RoundTile || vRule == RoundTile)) { InterpolationQuality previousInterpolationQuality = ctxt.imageInterpolationQuality(); ctxt.setImageInterpolationQuality(InterpolationLow); drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); ctxt.setImageInterpolationQuality(previousInterpolationQuality); } else { drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect, spacing); } startAnimation(); }