Rect Image::GetCoverageBounds () { // FIXME: SL3 final only supports PixelFormatPbgra32 which makes this optimization // obsolete - unless we keep an "has_alpha" flag with each image ?!? return Rect (); #if FALSE ImageSource *source = GetSource (); if (!source || source->GetPixelFormat () == PixelFormatPbgra32) return Rect (); Stretch stretch = GetStretch (); if (stretch == StretchFill || stretch == StretchUniformToFill) return bounds; cairo_matrix_t matrix; Rect image = Rect (0, 0, source->GetPixelWidth (), source->GetPixelHeight ()); Rect paint = Rect (0, 0, GetActualWidth (), GetActualHeight ()); image_brush_compute_pattern_matrix (&matrix, paint.width, paint.height, image.width, image.height, stretch, AlignmentXCenter, AlignmentYCenter, NULL, NULL); cairo_matrix_invert (&matrix); cairo_matrix_multiply (&matrix, &matrix, &absolute_xform); image = image.Transform (&matrix); image = image.Intersection (bounds); return image; #endif }
Size Image::MeasureOverrideWithError (Size availableSize, MoonError *error) { Size desired = availableSize; Rect shape_bounds = Rect (); ImageSource *source = GetSource (); double sx = 0.0; double sy = 0.0; if (source) shape_bounds = Rect (0,0,source->GetPixelWidth (),source->GetPixelHeight ()); /* don't stretch to infinite size */ if (isinf (desired.width)) desired.width = shape_bounds.width; if (isinf (desired.height)) desired.height = shape_bounds.height; /* compute the scaling */ if (shape_bounds.width > 0) sx = desired.width / shape_bounds.width; if (shape_bounds.height > 0) sy = desired.height / shape_bounds.height; /* don't use infinite dimensions as constraints */ if (isinf (availableSize.width)) sx = sy; if (isinf (availableSize.height)) sy = sx; switch (GetStretch ()) { case StretchUniform: sx = sy = MIN (sx, sy); break; case StretchUniformToFill: sx = sy = MAX (sx, sy); break; case StretchFill: if (isinf (availableSize.width)) sx = sy; if (isinf (availableSize.height)) sy = sx; break; case StretchNone: sx = sy = 1.0; break; } desired = Size (shape_bounds.width * sx, shape_bounds.height * sy); return desired; }
void Image::OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error) { if (args->GetProperty ()->GetOwnerType() != Type::IMAGE) { MediaBase::OnPropertyChanged (args, error); return; } if (args->GetId () == Image::SourceProperty) { ImageSource *source = args->GetNewValue () ? args->GetNewValue ()->AsImageSource () : NULL; ImageSource *old = args->GetOldValue () ? args->GetOldValue ()->AsImageSource () : NULL; if (old) { if (old->Is(Type::BITMAPSOURCE)) { old->RemoveHandler (BitmapSource::PixelDataChangedEvent, source_pixel_data_changed, this); } if (old->Is(Type::BITMAPIMAGE)) { old->RemoveHandler (BitmapImage::DownloadProgressEvent, download_progress, this); old->RemoveHandler (BitmapImage::ImageOpenedEvent, image_opened, this); old->RemoveHandler (BitmapImage::ImageFailedEvent, image_failed, this); } } if (source) { if (source->Is(Type::BITMAPSOURCE)) { source->AddHandler (BitmapSource::PixelDataChangedEvent, source_pixel_data_changed, this); } if (source->Is(Type::BITMAPIMAGE)) { source->AddHandler (BitmapImage::DownloadProgressEvent, download_progress, this); source->AddHandler (BitmapImage::ImageOpenedEvent, image_opened, this); source->AddHandler (BitmapImage::ImageFailedEvent, image_failed, this); } if (source->GetPixelWidth () > 0 && source->GetPixelHeight () > 0) { RoutedEventArgs *args = MoonUnmanagedFactory::CreateRoutedEventArgs (); ImageOpened (args); args->unref (); } } else { UpdateBounds (); Invalidate (); } InvalidateMeasure (); } // we need to notify attachees if our DownloadProgress changed. NotifyListenersOfPropertyChange (args, error); }
Size Image::ArrangeOverrideWithError (Size finalSize, MoonError *error) { Size arranged = finalSize; Rect shape_bounds = Rect (); ImageSource *source = GetSource (); double sx = 1.0; double sy = 1.0; if (source) shape_bounds = Rect (0, 0, source->GetPixelWidth (), source->GetPixelHeight ()); /* compute the scaling */ if (shape_bounds.width == 0) shape_bounds.width = arranged.width; if (shape_bounds.height == 0) shape_bounds.height = arranged.height; if (shape_bounds.width != arranged.width) sx = arranged.width / shape_bounds.width; if (shape_bounds.height != arranged.height) sy = arranged.height / shape_bounds.height; switch (GetStretch ()) { case StretchUniform: sx = sy = MIN (sx, sy); break; case StretchUniformToFill: sx = sy = MAX (sx, sy); break; case StretchNone: sx = sy = 1.0; default: break; } arranged = Size (shape_bounds.width * sx, shape_bounds.height * sy); return arranged; }
void Image::Render (cairo_t *cr, Region *region, bool path_only) { ImageSource *source = GetSource (); cairo_pattern_t *pattern = NULL; cairo_matrix_t matrix; if (!source) return; source->Lock (); cairo_save (cr); Size specified (GetActualWidth (), GetActualHeight ()); Size stretched = ApplySizeConstraints (specified); bool adjust = specified != GetRenderSize (); if (GetStretch () != StretchUniformToFill) specified = specified.Min (stretched); Rect paint = Rect (0, 0, specified.width, specified.height); if (!path_only) { Rect image = Rect (0, 0, source->GetPixelWidth (), source->GetPixelHeight ()); if (GetStretch () == StretchNone) paint = paint.Union (image); if (image.width == 0.0 && image.height == 0.0) goto cleanup; pattern = cairo_pattern_create_for_surface (source->GetSurface (cr)); image_brush_compute_pattern_matrix (&matrix, paint.width, paint.height, image.width, image.height, GetStretch (), AlignmentXCenter, AlignmentYCenter, NULL, NULL); cairo_pattern_set_matrix (pattern, &matrix); #if MAKE_EVERYTHING_SLOW_AND_BUGGY cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); #endif if (cairo_pattern_status (pattern) == CAIRO_STATUS_SUCCESS) { cairo_set_source (cr, pattern); } cairo_pattern_destroy (pattern); } if (adjust) { // FIXME: Propagate error properly MoonError error; specified = MeasureOverrideWithError (specified, &error); paint = Rect ((stretched.width - specified.width) * 0.5, (stretched.height - specified.height) * 0.5, specified.width, specified.height); } if (!path_only) RenderLayoutClip (cr); paint = paint.Intersection (Rect (0, 0, stretched.width, stretched.height)); paint.Draw (cr); if (!path_only) cairo_fill (cr); cleanup: cairo_restore (cr); source->Unlock (); }