diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h index f8dffa3a0..2a9315dc8 100644 --- a/include/views/SkWindow.h +++ b/include/views/SkWindow.h @@ -32,8 +32,8 @@ public: const SkBitmap& getBitmap() const { return fBitmap; } - void setConfig(SkBitmap::Config); - void resize(int width, int height, SkBitmap::Config config = SkBitmap::kNo_Config); + void setColorType(SkColorType); + void resize(int width, int height, SkColorType = kUnknown_SkColorType); bool isDirty() const { return !fDirtyRgn.isEmpty(); } bool update(SkIRect* updateArea); @@ -81,7 +81,7 @@ protected: virtual bool onSetFocusView(SkView* focus); private: - SkBitmap::Config fConfig; + SkColorType fColorType; SkBitmap fBitmap; SkRegion fDirtyRgn; diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 15e56a3bb..5b37662dc 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -442,39 +442,6 @@ static void SkGMRegistyToSampleRegistry() { } } -#if 0 -#include -#include - -static void testpdf() { - CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf", - kCFStringEncodingUTF8); - CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, - kCFURLPOSIXPathStyle, - false); - CFRelease(path); - CGRect box = CGRectMake(0, 0, 8*72, 10*72); - CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL); - CFRelease(url); - - CGContextBeginPage(cg, &box); - CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5); - CGContextFillEllipseInRect(cg, r); - CGContextEndPage(cg); - CGContextRelease(cg); - - if (false) { - SkBitmap bm; - bm.setConfig(SkBitmap::kA8_Config, 64, 64); - bm.allocPixels(); - bm.eraseColor(SK_ColorTRANSPARENT); - - SkCanvas canvas(bm); - - } -} -#endif - ////////////////////////////////////////////////////////////////////////////// enum FlipAxisEnum { @@ -991,8 +958,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev fSlideMenu = new SkOSMenu; this->addMenu(fSlideMenu); -// this->setConfig(SkBitmap::kRGB_565_Config); - this->setConfig(SkBitmap::kARGB_8888_Config); + this->setColorType(kPMColor_SkColorType); this->setVisibleP(true); this->setClipToBounds(false); @@ -1600,17 +1566,18 @@ void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) { canvas->setDrawFilter(NULL); } -static SkBitmap::Config gConfigCycle[] = { - SkBitmap::kNo_Config, // none -> none - SkBitmap::kNo_Config, // a8 -> none - SkBitmap::kNo_Config, // index8 -> none - SkBitmap::kARGB_4444_Config, // 565 -> 4444 - SkBitmap::kARGB_8888_Config, // 4444 -> 8888 - SkBitmap::kRGB_565_Config // 8888 -> 565 +static SkColorType gColorTypeCycle[] = { + kUnknown_SkColorType, // none -> none + kUnknown_SkColorType, // a8 -> none + kARGB_4444_SkColorType, // 565 -> 4444 + kPMColor_SkColorType, // 4444 -> 8888 + kRGB_565_SkColorType, // 8888 -> 565 + kRGB_565_SkColorType, // 8888 -> 565 + kUnknown_SkColorType, // index8 -> none }; -static SkBitmap::Config cycle_configs(SkBitmap::Config c) { - return gConfigCycle[c]; +static SkColorType cycle_configs(SkColorType c) { + return gColorTypeCycle[c]; } void SampleWindow::changeZoomLevel(float delta) { @@ -2007,7 +1974,7 @@ bool SampleWindow::onHandleKey(SkKey key) { if (USE_ARROWS_FOR_ZOOM) { this->changeZoomLevel(-1.f / 32.f); } else { - this->setConfig(cycle_configs(this->getBitmap().config())); + this->setColorType(cycle_configs(this->getBitmap().colorType())); this->updateTitle(); } return true; diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp index 6b55fdf90..1163f67b2 100644 --- a/src/effects/SkAlphaThresholdFilter.cpp +++ b/src/effects/SkAlphaThresholdFilter.cpp @@ -306,9 +306,9 @@ void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const { bool SkAlphaThresholdFilterImpl::onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix& matrix, SkBitmap* dst, SkIPoint* offset) const { - SkASSERT(src.config() == SkBitmap::kARGB_8888_Config); + SkASSERT(src.colorType() == kPMColor_SkColorType); - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp index cf71435cd..887e2b8ee 100644 --- a/src/effects/SkBicubicImageFilter.cpp +++ b/src/effects/SkBicubicImageFilter.cpp @@ -92,7 +92,7 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy, return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index a08b9c567..f946f87c1 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -143,7 +143,7 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy, return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 21731c4a3..f4d399b80 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -195,10 +195,9 @@ static bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) { // FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a // clean way to share more code? SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kA8_Config, - mask->fBounds.width(), mask->fBounds.height(), - mask->fRowBytes); - bitmap.setPixels(mask->fImage); + bitmap.installPixels(SkImageInfo::MakeA8(mask->fBounds.width(), + mask->fBounds.height()), + mask->fImage, mask->fRowBytes, NULL, NULL); SkCanvas canvas(bitmap); canvas.translate(-SkIntToScalar(mask->fBounds.left()), @@ -216,10 +215,11 @@ static bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask) } SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kA8_Config, - mask->fBounds.width(), mask->fBounds.height(), - mask->fRowBytes); - bitmap.setPixels(mask->fImage); + bitmap.installPixels(SkImageInfo::Make(mask->fBounds.width(), + mask->fBounds.height(), + kAlpha_8_SkColorType, + kPremul_SkAlphaType), + mask->fImage, mask->fRowBytes, NULL, NULL); SkCanvas canvas(bitmap); canvas.translate(-SkIntToScalar(mask->fBounds.left()), diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index a563a6ef8..cffadb2e6 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -204,8 +204,8 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, (displInput && !displInput->filterImage(proxy, src, ctm, &displ, &displOffset))) { return false; } - if ((displ.config() != SkBitmap::kARGB_8888_Config) || - (color.config() != SkBitmap::kARGB_8888_Config)) { + if ((displ.colorType() != kPMColor_SkColorType) || + (color.colorType() != kPMColor_SkColorType)) { return false; } diff --git a/src/effects/SkLayerRasterizer.cpp b/src/effects/SkLayerRasterizer.cpp index 6381c4d69..65ebd8ad1 100644 --- a/src/effects/SkLayerRasterizer.cpp +++ b/src/effects/SkLayerRasterizer.cpp @@ -122,8 +122,9 @@ bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), -SkIntToScalar(mask->fBounds.fTop)); - device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes); - device.setPixels(mask->fImage); + device.installPixels(SkImageInfo::MakeA8(mask->fBounds.width(), + mask->fBounds.height()), + mask->fImage, mask->fRowBytes, NULL, NULL); draw.fBitmap = &device; draw.fMatrix = &drawMatrix; diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index f4f1ae170..f4d0ea26a 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -933,7 +933,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } SkAutoLockPixels alp(src); @@ -1026,7 +1026,7 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } SkAutoLockPixels alp(src); diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index 2fed24dc7..4ab3fa174 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -282,11 +282,11 @@ void SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { bool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, SkBitmap* dst, SkIPoint* offset) const { - SkASSERT(src.config() == SkBitmap::kARGB_8888_Config); + SkASSERT(src.colorType() == kPMColor_SkColorType); SkASSERT(fSrcRect.width() < src.width()); SkASSERT(fSrcRect.height() < src.height()); - if ((src.config() != SkBitmap::kARGB_8888_Config) || + if ((src.colorType() != kPMColor_SkColorType) || (fSrcRect.width() >= src.width()) || (fSrcRect.height() >= src.height())) { return false; diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp index 43ebc6ce6..79b8e2781 100644 --- a/src/effects/SkMatrixConvolutionImageFilter.cpp +++ b/src/effects/SkMatrixConvolutionImageFilter.cpp @@ -260,7 +260,7 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy, return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index f2eeb2d6f..351042bd8 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -150,7 +150,7 @@ bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p return false; } - if (src.config() != SkBitmap::kARGB_8888_Config) { + if (src.colorType() != kPMColor_SkColorType) { return false; } diff --git a/src/effects/SkTransparentShader.cpp b/src/effects/SkTransparentShader.cpp index 1d7e80877..9de4a0cc2 100644 --- a/src/effects/SkTransparentShader.cpp +++ b/src/effects/SkTransparentShader.cpp @@ -23,13 +23,13 @@ bool SkTransparentShader::setContext(const SkBitmap& device, uint32_t SkTransparentShader::getFlags() { uint32_t flags = this->INHERITED::getFlags(); - switch (fDevice->config()) { - case SkBitmap::kRGB_565_Config: + switch (fDevice->colorType()) { + case kRGB_565_SkColorType: flags |= kHasSpan16_Flag; if (fAlpha == 255) flags |= kOpaqueAlpha_Flag; break; - case SkBitmap::kARGB_8888_Config: + case kPMColor_SkColorType: if (fAlpha == 255 && fDevice->isOpaque()) flags |= kOpaqueAlpha_Flag; break; @@ -42,8 +42,8 @@ uint32_t SkTransparentShader::getFlags() { void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { unsigned scale = SkAlpha255To256(fAlpha); - switch (fDevice->config()) { - case SkBitmap::kARGB_8888_Config: + switch (fDevice->colorType()) { + case kPMColor_SkColorType: if (scale == 256) { SkPMColor* src = fDevice->getAddr32(x, y); if (src != span) { @@ -56,7 +56,7 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { } } break; - case SkBitmap::kRGB_565_Config: { + case kRGB_565_SkColorType: { const uint16_t* src = fDevice->getAddr16(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { @@ -78,10 +78,7 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { } break; } - case SkBitmap::kIndex8_Config: - SkDEBUGFAIL("index8 not supported as a destination device"); - break; - case SkBitmap::kA8_Config: { + case kAlpha_8_SkColorType: { const uint8_t* src = fDevice->getAddr8(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { @@ -94,13 +91,14 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { } break; } - default: // to avoid warnings + default: + SkDEBUGFAIL("colorType not supported as a destination device"); break; } } void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { - SkASSERT(fDevice->config() == SkBitmap::kRGB_565_Config); + SkASSERT(fDevice->colorType() == kRGB_565_SkColorType); uint16_t* src = fDevice->getAddr16(x, y); if (src != span) { diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 1da259afe..5b0b9c763 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -583,7 +583,7 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (fMapper) { // force our cahce32pixelref to be built (void)this->getCache32(); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); + bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); bitmap->setPixelRef(fCache32PixelRef); return; } @@ -624,7 +624,7 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (!gCache->find(storage.get(), size, bitmap)) { // force our cahce32pixelref to be built (void)this->getCache32(); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); + bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); bitmap->setPixelRef(fCache32PixelRef); gCache->add(storage.get(), size, *bitmap); @@ -1043,7 +1043,7 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, desc.fHeight = 32; desc.fRowHeight = bitmap.height(); desc.fContext = ctx; - desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); + desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.colorType(), bitmap.alphaType()); fAtlas = GrTextureStripAtlas::GetAtlas(desc); SkASSERT(NULL != fAtlas); diff --git a/src/utils/SkCanvasStateUtils.cpp b/src/utils/SkCanvasStateUtils.cpp index 77b0e20c2..4b8868b02 100644 --- a/src/utils/SkCanvasStateUtils.cpp +++ b/src/utils/SkCanvasStateUtils.cpp @@ -221,11 +221,11 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) { layerState->width = bitmap.width(); layerState->height = bitmap.height(); - switch (bitmap.config()) { - case SkBitmap::kARGB_8888_Config: + switch (bitmap.colorType()) { + case kPMColor_SkColorType: layerState->raster.config = kARGB_8888_RasterConfig; break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: layerState->raster.config = kRGB_565_RasterConfig; break; default: @@ -279,25 +279,24 @@ static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layer SkASSERT(kRaster_CanvasBackend == layerState.type); SkBitmap bitmap; - SkBitmap::Config config = - layerState.raster.config == kARGB_8888_RasterConfig ? SkBitmap::kARGB_8888_Config : - layerState.raster.config == kRGB_565_RasterConfig ? SkBitmap::kRGB_565_Config : - SkBitmap::kNo_Config; + SkColorType colorType = + layerState.raster.config == kARGB_8888_RasterConfig ? kPMColor_SkColorType : + layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType : + kUnknown_SkColorType; - if (config == SkBitmap::kNo_Config) { + if (colorType == kUnknown_SkColorType) { return NULL; } - bitmap.setConfig(config, layerState.width, layerState.height, - layerState.raster.rowBytes); - bitmap.setPixels(layerState.raster.pixels); + bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height, + colorType, kPremul_SkAlphaType), + layerState.raster.pixels, layerState.raster.rowBytes, + NULL, NULL); SkASSERT(!bitmap.empty()); SkASSERT(!bitmap.isNull()); - // create a device & canvas - SkAutoTUnref device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); - SkAutoTUnref canvas(SkNEW_ARGS(SkCanvas, (device.get()))); + SkAutoTUnref canvas(SkNEW_ARGS(SkCanvas, (bitmap))); // setup the matrix and clip setup_canvas_from_MC_state(layerState.mcState, canvas.get()); diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp index 1b52ba31a..01f2dacdd 100644 --- a/src/utils/mac/SkCreateCGImageRef.cpp +++ b/src/utils/mac/SkCreateCGImageRef.cpp @@ -22,13 +22,19 @@ static bool getBitmapInfo(const SkBitmap& bm, *upscaleTo32 = false; } - switch (bm.config()) { - case SkBitmap::kRGB_565_Config: + switch (bm.colorType()) { + case kRGB_565_SkColorType: +#if 0 + // doesn't see quite right. Are they thinking 1555? + *bitsPerComponent = 5; + *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; + break; +#endif if (upscaleTo32) { *upscaleTo32 = true; } // fall through - case SkBitmap::kARGB_8888_Config: + case kPMColor_SkColorType: *bitsPerComponent = 8; #if SK_PMCOLOR_BYTE_ORDER(R,G,B,A) *info = kCGBitmapByteOrder32Big; @@ -60,14 +66,7 @@ This will probably not work. } #endif break; -#if 0 - case SkBitmap::kRGB_565_Config: - // doesn't see quite right. Are they thinking 1555? - *bitsPerComponent = 5; - *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; - break; -#endif - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: *bitsPerComponent = 4; *info = kCGBitmapByteOrder16Little; if (bm.isOpaque()) { diff --git a/src/views/SkWidgets.cpp b/src/views/SkWidgets.cpp index e4547ec0e..fb16f1ec0 100644 --- a/src/views/SkWidgets.cpp +++ b/src/views/SkWidgets.cpp @@ -507,7 +507,7 @@ bool SkBitmapView::getBitmap(SkBitmap* bitmap) const { if (bitmap) *bitmap = fBitmap; - return fBitmap.getConfig() != SkBitmap::kNo_Config; + return fBitmap.colorType() != kUnknown_SkColorType; } void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels) @@ -534,7 +534,7 @@ bool SkBitmapView::loadBitmapFromFile(const char path[]) void SkBitmapView::onDraw(SkCanvas* canvas) { - if (fBitmap.getConfig() != SkBitmap::kNo_Config && + if (fBitmap.colorType() != kUnknown_SkColorType && fBitmap.width() && fBitmap.height()) { SkAutoCanvasRestore restore(canvas, true); diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp index 5451fca07..cca291a4e 100644 --- a/src/views/SkWindow.cpp +++ b/src/views/SkWindow.cpp @@ -51,9 +51,9 @@ SkWindow::SkWindow() : fFocusView(NULL) { fWaitingOnInval = false; #ifdef SK_BUILD_FOR_WINCE - fConfig = SkBitmap::kRGB_565_Config; + fColorType = kRGB_565_SkColorType; #else - fConfig = SkBitmap::kARGB_8888_Config; + fColorType = kPMColor_SkColorType; #endif fMatrix.reset(); @@ -87,18 +87,18 @@ void SkWindow::postConcat(const SkMatrix& matrix) { this->setMatrix(m); } -void SkWindow::setConfig(SkBitmap::Config config) { - this->resize(fBitmap.width(), fBitmap.height(), config); +void SkWindow::setColorType(SkColorType ct) { + this->resize(fBitmap.width(), fBitmap.height(), ct); } -void SkWindow::resize(int width, int height, SkBitmap::Config config) { - if (config == SkBitmap::kNo_Config) - config = fConfig; +void SkWindow::resize(int width, int height, SkColorType ct) { + if (ct == kUnknown_SkColorType) + ct = fColorType; - if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig) { - fConfig = config; - fBitmap.setConfig(config, width, height, 0, kOpaque_SkAlphaType); - fBitmap.allocPixels(); + if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) { + fColorType = ct; + fBitmap.allocPixels(SkImageInfo::Make(width, height, + ct, kPremul_SkAlphaType)); this->setSize(SkIntToScalar(width), SkIntToScalar(height)); this->inval(NULL); diff --git a/src/views/mac/SkNSView.mm b/src/views/mac/SkNSView.mm index 209aecad7..1014ffe04 100644 --- a/src/views/mac/SkNSView.mm +++ b/src/views/mac/SkNSView.mm @@ -57,7 +57,7 @@ SK_COMPILE_ASSERT(SK_SUPPORT_GPU, not_implemented_for_non_gpu_build); size = [self convertSizeToBacking:self.frame.size]; #endif fWind->resize((int) size.width, (int) size.height, - SkBitmap::kARGB_8888_Config); + kPMColor_SkColorType); } }