static VALUE
cr_get_source (VALUE self)
{
  VALUE rb_source = Qnil;
  cairo_pattern_t *source;
  source = cairo_get_source (_SELF);

  if (source)
    {
      rb_cairo_check_status (cairo_pattern_status (source));
      rb_source = rb_ivar_get (self, cr_id_source);
      if (NIL_P (rb_source) || RVAL2CRPATTERN (rb_source) != source)
        {
          rb_source = CRPATTERN2RVAL (source);
          rb_ivar_set (self, cr_id_source, rb_source);
        }
    }
  else
    {
      rb_source = Qnil;
      rb_ivar_set (self, cr_id_source, rb_source);
    }

  return rb_source;
}
Exemple #2
0
bool GlyphLayerBitmap::render(
	cairo_t*       c,
	cairo_glyph_t* glyph,
	unsigned int   width,
	unsigned int   height
) {
	if(cairo_status(c) || !glyph || !_bitmap || cairo_pattern_status(_pattern)) return false;

	double bw = _bitmap->getSurfaceWidth();
	double bh = _bitmap->getSurfaceHeight();

	if(_repeatX > 1 || _repeatY > 1) cairo_pattern_set_extend(_pattern, CAIRO_EXTEND_REPEAT);
	
	else cairo_pattern_set_extend(_pattern, CAIRO_EXTEND_PAD);
	
	cairo_matrix_t matrix;

	cairo_matrix_init_scale(&matrix, bw / width * _repeatX, bh / height * _repeatY);
	cairo_pattern_set_matrix(_pattern, &matrix);

	cairo_set_source(c, _pattern);

	cairo_glyph_path(c, glyph, 1);
	cairo_fill(c);

	return true;
}
Exemple #3
0
static JSBool
gjs_cairo_surface_pattern_constructor(JSContext *context,
                                      JSObject  *obj,
                                      uintN      argc,
                                      jsval     *argv,
                                      jsval     *retval)
{
    JSObject *surface_wrapper;
    cairo_surface_t *surface;
    cairo_pattern_t *pattern;

    if (!gjs_check_constructing(context))
        return JS_FALSE;

    if (!gjs_parse_args(context, "SurfacePattern", "o", argc, argv,
                        "surface", &surface_wrapper))
        return JS_FALSE;

    surface = gjs_cairo_surface_get_surface(context, surface_wrapper);
    if (!surface) {
        gjs_throw(context, "first argument to SurfacePattern() should be a surface");
        return JS_FALSE;
    }

    pattern = cairo_pattern_create_for_surface(surface);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    gjs_cairo_pattern_construct(context, obj, pattern);
    cairo_pattern_destroy(pattern);

    return JS_TRUE;
}
Exemple #4
0
gboolean
gxps_brush_solid_color_parse (const gchar      *data,
                              GXPSArchive      *zip,
                              gdouble           alpha,
                              cairo_pattern_t **pattern)
{
        GXPSColor        color;
        cairo_pattern_t *retval;

        if (!gxps_color_parse (data, zip, &color))
                return FALSE;

        retval = cairo_pattern_create_rgba (color.red,
                                            color.green,
                                            color.blue,
                                            color.alpha * alpha);
        if (cairo_pattern_status (retval)) {
                cairo_pattern_destroy (retval);

                return FALSE;
        }

        if (pattern)
                *pattern = retval;

        return TRUE;
}
Exemple #5
0
static JSBool
getFilter_func(JSContext *context,
               JSObject  *object,
               uintN      argc,
               jsval     *argv,
               jsval     *retval)
{
    cairo_filter_t filter;
    cairo_pattern_t *pattern;

    if (argc > 0) {
        gjs_throw(context, "SurfacePattern.getFilter() requires no arguments");
        return JS_FALSE;
    }

    pattern = gjs_cairo_pattern_get_pattern(context, object);
    filter = cairo_pattern_get_filter(pattern);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    *retval = INT_TO_JSVAL(filter);

    return JS_TRUE;
}
/* Draw the gradient rectangle for the greyramp tool */
static void drawGradient(GdkDrawable *drawable, GtkWidget *greyramp)
{
  GreyrampProperties *properties = greyrampGetProperties(greyramp);
  GdkRectangle *rect = &properties->gradientRect;

  /* Create a gradient */
  cairo_pattern_t *pattern = cairo_pattern_create_linear(rect->x, rect->y, rect->x + rect->width, rect->y);

  /* If the positions are the same, make the black pos slightly smaller (to emulate historic behaviour) */
  int whitePoint = properties->whitePoint;
  int blackPoint = properties->blackPoint;
  
  if (whitePoint == blackPoint)
    {
      if (blackPoint <= 1)
        {
          whitePoint += 1;
        }
      else
        {
          blackPoint -= 1;
        }
    }

  /* Get the white and black points as fractions of 1.0 */
  gdouble blackPos = blackPoint / ((gdouble)GREYRAMP_MAX);
  gdouble whitePos = whitePoint / ((gdouble)GREYRAMP_MAX);
  
  /* Add a stop at the start and end. The start is white if the whitePos is less than blackPos */
  const int whiteEnd = whitePos < blackPos ? 0 : 1;
  const int blackEnd = whitePos < blackPos ? 1 : 0;
  cairo_pattern_add_color_stop_rgb(pattern, whiteEnd, 1.0, 1.0, 1.0);
  cairo_pattern_add_color_stop_rgb(pattern, blackEnd, 0.0, 0.0, 0.0);
  
  /* Add stop points at the black/white positions */
  cairo_pattern_add_color_stop_rgb(pattern, whitePos, 1.0, 1.0, 1.0);
  cairo_pattern_add_color_stop_rgb(pattern, blackPos, 0.0, 0.0, 0.0);
  
  if (cairo_pattern_status(pattern) == CAIRO_STATUS_SUCCESS)
    {
      cairo_t *cr = gdk_cairo_create(drawable);
      
      gdk_cairo_rectangle(cr, rect);
      cairo_set_source(cr, pattern);
      cairo_fill(cr);
      
      cairo_destroy(cr);
    }
  
  cairo_pattern_destroy(pattern);
}
Exemple #7
0
static cairo_pattern_t *mkbrush(uiDrawBrush *b)
{
	cairo_pattern_t *pat;
	size_t i;

	switch (b->Type) {
	case uiDrawBrushTypeSolid:
		pat = cairo_pattern_create_rgba(b->R, b->G, b->B, b->A);
		break;
	case uiDrawBrushTypeLinearGradient:
		pat = cairo_pattern_create_linear(b->X0, b->Y0, b->X1, b->Y1);
		break;
	case uiDrawBrushTypeRadialGradient:
		// make the start circle radius 0 to make it a point
		pat = cairo_pattern_create_radial(
			b->X0, b->Y0, 0,
			b->X1, b->Y1, b->OuterRadius);
		break;
//	case uiDrawBrushTypeImage:
	}
	if (cairo_pattern_status(pat) != CAIRO_STATUS_SUCCESS)
		implbug("error creating pattern in mkbrush(): %s",
			cairo_status_to_string(cairo_pattern_status(pat)));
	switch (b->Type) {
	case uiDrawBrushTypeLinearGradient:
	case uiDrawBrushTypeRadialGradient:
		for (i = 0; i < b->NumStops; i++)
			cairo_pattern_add_color_stop_rgba(pat,
				b->Stops[i].Pos,
				b->Stops[i].R,
				b->Stops[i].G,
				b->Stops[i].B,
				b->Stops[i].A);
	}
	return pat;
}
Exemple #8
0
/* PycairoPattern_FromPattern
 * Create a new
 *   PycairoSolidPattern,
 *   PycairoSurfacePattern,
 *   PycairoLinearGradient, or
 *   PycairoRadialGradient from a cairo_pattern_t.
 * pattern - a cairo_pattern_t to 'wrap' into a Python object.
 *   It is unreferenced if the PycairoPattern creation fails, or if the
 *   pattern has an error status.
 * base - the base object used to create the pattern, or NULL.
 *   It is referenced to keep it alive while the cairo_pattern_t is being used.
 *   For PycairoSurfacePattern base should be the PycairoSurface, for other
 #   patterns it should be NULL.
 * Return value: New reference or NULL on failure
 */
PyObject *
PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base) {
  PyTypeObject *type = NULL;
  PyObject *o;

  assert (pattern != NULL);

  if (Pycairo_Check_Status (cairo_pattern_status (pattern))) {
    cairo_pattern_destroy (pattern);
    return NULL;
  }

  switch (cairo_pattern_get_type (pattern)) {
  case CAIRO_PATTERN_TYPE_SOLID:
    type = &PycairoSolidPattern_Type;
    break;
  case CAIRO_PATTERN_TYPE_SURFACE:
    type = &PycairoSurfacePattern_Type;
    break;
  case CAIRO_PATTERN_TYPE_LINEAR:
    type = &PycairoLinearGradient_Type;
    break;
  case CAIRO_PATTERN_TYPE_RADIAL:
    type = &PycairoRadialGradient_Type;
    break;
  default:
    type = &PycairoPattern_Type;
    break;
  }

  o = type->tp_alloc(type, 0);
  if (o == NULL) {
    cairo_pattern_destroy (pattern);
  } else {
    ((PycairoPattern *)o)->pattern = pattern;
    Py_XINCREF(base);
    ((PycairoPattern *)o)->base = base;
  }
  return o;
}
Exemple #9
0
static JSBool
setExtend_func(JSContext *context,
               JSObject  *object,
               uintN      argc,
               jsval     *argv,
               jsval     *retval)
{
    cairo_extend_t extend;
    cairo_pattern_t *pattern;

    if (!gjs_parse_args(context, "setExtend", "i", argc, argv,
                        "extend", &extend))
        return JS_FALSE;

    pattern = gjs_cairo_pattern_get_pattern(context, object);
    cairo_pattern_set_extend(pattern, extend);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    return JS_TRUE;
}
Exemple #10
0
static JSBool
setFilter_func(JSContext *context,
               JSObject  *object,
               uintN      argc,
               jsval     *argv,
               jsval     *retval)
{
    cairo_filter_t filter;
    cairo_pattern_t *pattern;

    if (!gjs_parse_args(context, "setFilter", "i", argc, argv,
                        "filter", &filter))
        return JS_FALSE;

    pattern = gjs_cairo_pattern_get_pattern(context, object);
    cairo_pattern_set_filter(pattern, filter);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    return JS_TRUE;
}
Exemple #11
0
static void
progressbar_draw (kk_widget_t *widget, cairo_t *ctx)
{
  kk_progressbar_t *progressbar = (kk_progressbar_t *) widget;

  cairo_pattern_t *pat;

  pat = cairo_pattern_create_linear (
      (double) 0.0,
      (double) 0.0,
      (double) progressbar->widget.width,
      (double) 0.0);

  if (cairo_pattern_status (pat) != CAIRO_STATUS_SUCCESS)
    return;

  cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.75, 0.00, 0.98, 0.5);
  cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.92, 0.03, 0.41, 0.5);
  cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.18, 0.09, 0.21, 0.5);

  cairo_rectangle (ctx,
      (double) progressbar->widget.x,
      (double) progressbar->widget.y,
      (double) progressbar->widget.width,
      (double) progressbar->widget.height);

  cairo_set_source_rgb (ctx, 0.0, 0.0, 0.0);
  cairo_fill_preserve (ctx);
  cairo_set_source (ctx, pat);
  cairo_fill (ctx);
  cairo_pattern_destroy (pat);
  cairo_set_source_rgb (ctx, 0.0, 0.0, 0.0);
  cairo_rectangle (ctx,
      (double) progressbar->widget.x + ((double) progressbar->widget.width * progressbar->progress),
      (double) progressbar->widget.y,
      (double) progressbar->widget.width * 1.0 - (double) progressbar->progress,
      (double) progressbar->widget.height);
  cairo_fill (ctx);
}
/* PycairoPattern_FromPattern
 * Create a new
 *   PycairoSolidPattern,
 *   PycairoSurfacePattern,
 *   PycairoLinearGradient, or
 *   PycairoRadialGradient from a cairo_pattern_t.
 * pattern - a cairo_pattern_t to 'wrap' into a Python object.
 *           it is unreferenced if the PycairoPattern creation fails, or if the
 *           pattern has an error status.
 * Return value: New reference or NULL on failure
 */
PyObject *
PycairoPattern_FromPattern (cairo_pattern_t *pattern)
{
    PyTypeObject *type = NULL;
    PyObject *o;

    assert (pattern != NULL);

    if (Pycairo_Check_Status (cairo_pattern_status (pattern))) {
	cairo_pattern_destroy (pattern);
	return NULL;
    }

    switch (cairo_pattern_get_type (pattern)) {
    case CAIRO_PATTERN_TYPE_SOLID:
	type = &PycairoSolidPattern_Type;
	break;
    case CAIRO_PATTERN_TYPE_SURFACE:
	type = &PycairoSurfacePattern_Type;
	break;
    case CAIRO_PATTERN_TYPE_LINEAR:
	type = &PycairoLinearGradient_Type;
	break;
    case CAIRO_PATTERN_TYPE_RADIAL:
	type = &PycairoRadialGradient_Type;
	break;
    default:
	PyErr_SetString(CairoError, "Unsupported Pattern type");
	return NULL;
    }

    o = type->tp_alloc(type, 0);
    if (o == NULL)
	cairo_pattern_destroy (pattern);
    else
	((PycairoPattern *)o)->pattern = pattern;
    return o;
}
Exemple #13
0
void GlyphLayerBitmap::setBitmap(const std::string& path) {
	if(_path == path || path.empty()) return;

	_path   = path;
	_bitmap = osgCairo::readImageFile(_path);

	if(!_bitmap || !_bitmap->valid())  {
		osg::notify(osg::WARN)
			<< "osgPango::GlyphLayerBitmap::setBitmap: Can't load image: "
			<< _path
			<< std::endl
		; 
		
		return;
	}

	// TODO: Consider if we can flip in osgCairo::readImageFile
	_bitmap->flipVertical();

	_pattern = cairo_pattern_create_for_surface(_bitmap->getSurface());
	
	if(cairo_pattern_status(_pattern)) return;
}
static JSBool
setExtend_func(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    jsval *argv = JS_ARGV(context, vp);
    JSObject *obj = JS_THIS_OBJECT(context, vp);
    cairo_extend_t extend;
    cairo_pattern_t *pattern;

    if (!gjs_parse_args(context, "setExtend", "i", argc, argv,
                        "extend", &extend))
        return JS_FALSE;

    pattern = gjs_cairo_pattern_get_pattern(context, obj);
    cairo_pattern_set_extend(pattern, extend);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}
Exemple #15
0
static JSBool
getType_func(JSContext *context,
             unsigned   argc,
             jsval     *vp)
{
    JSObject *obj = JS_THIS_OBJECT(context, vp);
    cairo_pattern_t *pattern;
    cairo_pattern_type_t type;

    if (argc > 1) {
        gjs_throw(context, "Pattern.getType() takes no arguments");
        return JS_FALSE;
    }

    pattern = gjs_cairo_pattern_get_pattern(context, obj);
    type = cairo_pattern_get_type(pattern);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    JS_SET_RVAL(context, vp, INT_TO_JSVAL(type));
    return JS_TRUE;
}
static JSBool
getFilter_func(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    JSObject *obj = JS_THIS_OBJECT(context, vp);
    cairo_filter_t filter;
    cairo_pattern_t *pattern;

    if (argc > 0) {
        gjs_throw(context, "SurfacePattern.getFilter() requires no arguments");
        return JS_FALSE;
    }

    pattern = gjs_cairo_pattern_get_pattern(context, obj);
    filter = cairo_pattern_get_filter(pattern);

    if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
        return JS_FALSE;

    JS_SET_RVAL(context, vp, INT_TO_JSVAL(filter));

    return JS_TRUE;
}
Exemple #17
0
static void
brush_end_element (GMarkupParseContext  *context,
                   const gchar          *element_name,
                   gpointer              user_data,
                   GError              **error)
{
        GXPSBrush *brush = (GXPSBrush *)user_data;

        if (strcmp (element_name, "SolidColorBrush") == 0) {
        } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
                g_markup_parse_context_pop (context);
        } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
                g_markup_parse_context_pop (context);
        } else if (strcmp (element_name, "ImageBrush") == 0) {
                GXPSBrushImage  *brush_image;
                GXPSImage       *image;
                GError          *err = NULL;

                brush_image = g_markup_parse_context_pop (context);

                GXPS_DEBUG (g_message ("set_fill_pattern (image)"));
                image = gxps_page_get_image (brush->ctx->page, brush_image->image_uri, &err);
                if (image) {
                        cairo_matrix_t   matrix;
                        gdouble          x_scale, y_scale;
                        cairo_surface_t *clip_surface;

                        /* viewbox units is 1/96 inch, convert to pixels */
                        brush_image->viewbox.x *= image->res_x / 96;
                        brush_image->viewbox.y *= image->res_y / 96;
                        brush_image->viewbox.width *= image->res_x / 96;
                        brush_image->viewbox.height *= image->res_y / 96;

                        clip_surface = cairo_surface_create_for_rectangle (image->surface,
                                                                           brush_image->viewbox.x,
                                                                           brush_image->viewbox.y,
                                                                           brush_image->viewbox.width,
                                                                           brush_image->viewbox.height);
                        brush_image->brush->pattern = cairo_pattern_create_for_surface (clip_surface);
                        cairo_pattern_set_extend (brush_image->brush->pattern, brush_image->extend);

                        x_scale = brush_image->viewport.width / brush_image->viewbox.width;
                        y_scale = brush_image->viewport.height / brush_image->viewbox.height;
                        cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
                                           brush_image->viewport.x, brush_image->viewport.y);
                        cairo_matrix_multiply (&matrix, &matrix, &brush_image->matrix);
                        cairo_matrix_invert (&matrix);
                        cairo_pattern_set_matrix (brush_image->brush->pattern, &matrix);

                        if (brush->opacity != 1.0) {
                                cairo_push_group (brush->ctx->cr);
                                cairo_set_source (brush->ctx->cr, brush_image->brush->pattern);
                                cairo_pattern_destroy (brush_image->brush->pattern);
                                cairo_paint_with_alpha (brush->ctx->cr, brush->opacity);
                                brush_image->brush->pattern = cairo_pop_group (brush->ctx->cr);
                        }

                        if (cairo_pattern_status (brush_image->brush->pattern)) {
                                GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (brush_image->brush->pattern))));
                                cairo_pattern_destroy (brush_image->brush->pattern);
                                brush_image->brush->pattern = NULL;
                        }
                        cairo_surface_destroy (clip_surface);
                } else if (err) {
                        GXPS_DEBUG (g_debug ("%s", err->message));
                        g_error_free (err);
                }
                gxps_brush_image_free (brush_image);
        } else if (strcmp (element_name, "VisualBrush") == 0) {
                GXPSRenderContext *sub_ctx;
                GXPSBrushVisual   *visual;
                cairo_matrix_t     matrix;

                sub_ctx = g_markup_parse_context_pop (context);
                visual = sub_ctx->visual;
                g_slice_free (GXPSRenderContext, sub_ctx);

                GXPS_DEBUG (g_message ("set_fill_pattern (visual)"));
                visual->brush->pattern = cairo_pop_group (brush->ctx->cr);
                /* Undo the clip */
                cairo_restore (brush->ctx->cr);
                cairo_pattern_set_extend (visual->brush->pattern, visual->extend);
                cairo_pattern_get_matrix (visual->brush->pattern, &matrix);
                cairo_matrix_multiply (&matrix, &visual->matrix, &matrix);
                cairo_pattern_set_matrix (visual->brush->pattern, &matrix);
                if (cairo_pattern_status (visual->brush->pattern)) {
                        GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (visual->brush->pattern))));
                        cairo_pattern_destroy (visual->brush->pattern);
                        visual->brush->pattern = NULL;
                }

                gxps_brush_visual_free (visual);
        } else {
                gxps_parse_error (context,
                                  brush->ctx->page->priv->source,
                                  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                                  element_name, NULL, NULL, error);

        }
}
static void _make_bar_surface (ProgressBar *pProgressBar)
{
	CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pProgressBar);
	int iWidth = pRenderer->iWidth;
	
	if (pProgressBar->cImageGradation != NULL)  // an image is provided
	{
		pProgressBar->pBarSurface = cairo_dock_create_surface_from_image_simple (
			pProgressBar->cImageGradation,
			iWidth,
			pProgressBar->iBarThickness);
	}
	
	if (pProgressBar->pBarSurface == NULL)  // no image was provided, or it was not valid.
	{
		// create a surface to bufferize the pattern.
		pProgressBar->pBarSurface = cairo_dock_create_blank_surface (iWidth, pProgressBar->iBarThickness);
		
		cairo_t *ctx = cairo_create (pProgressBar->pBarSurface);
		cairo_pattern_t *pGradationPattern = NULL;
		if (myIndicatorsParam.bBarUseDefaultColors)
		{
			gldi_style_colors_set_selected_bg_color (ctx);
		}
		else
		{
			// create the pattern.
			pGradationPattern = cairo_pattern_create_linear (0.,
				0.,
				iWidth,
				0.);  // de gauche a droite.
			g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS);
			
			cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
			
			gdouble *fColorGradation = pProgressBar->fColorGradation;
			int iNbColors = 2;
			int i;
			for (i = 0; i < iNbColors; i ++)
			{
				cairo_pattern_add_color_stop_rgba (pGradationPattern,
					(double)i / (iNbColors-1),
					fColorGradation[4*i+0],
					fColorGradation[4*i+1],
					fColorGradation[4*i+2],
					fColorGradation[4*i+3]);
			}
			cairo_set_source (ctx, pGradationPattern);
		}
		
		// draw the pattern on the surface.
		cairo_set_operator (ctx, CAIRO_OPERATOR_OVER);
		
		cairo_set_line_width (ctx, pProgressBar->iBarThickness);
		
		double r = .5*pProgressBar->iBarThickness;  // radius
		cairo_move_to (ctx, 0, r);
		cairo_rel_line_to (ctx, iWidth, 0);
		
		cairo_stroke (ctx);
		
		if (pGradationPattern)
			cairo_pattern_destroy (pGradationPattern);
		cairo_destroy (ctx);
	}
	pProgressBar->iBarTexture = cairo_dock_create_texture_from_surface (pProgressBar->pBarSurface);
}
Exemple #19
0
static inline void
cr_pattern_check_status (cairo_pattern_t *pattern)
{
  rb_cairo_check_status (cairo_pattern_status (pattern));
}
JNIEXPORT jint JNICALL Java_org_jclutter_cairo_CairoPattern_status(JNIEnv *env, jobject obj){
return (jint)cairo_pattern_status();
}
Exemple #21
0
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 ();
}
Exemple #22
0
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte,
	long ix1, long ix2, long x1DC, long x2DC,
	long iy1, long iy2, long y1DC, long y2DC,
	double minimum, double maximum,
	long clipx1, long clipx2, long clipy1, long clipy2, int interpolate)
{
	/*long t=clock();*/
	long nx = ix2 - ix1 + 1;   /* The number of cells along the horizontal axis. */
	long ny = iy2 - iy1 + 1;   /* The number of cells along the vertical axis. */
	double dx = (double) (x2DC - x1DC) / (double) nx;   /* Horizontal pixels per cell. Positive. */
	double dy = (double) (y2DC - y1DC) / (double) ny;   /* Vertical pixels per cell. Negative. */
	double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale;
	if (x2DC <= x1DC || y1DC <= y2DC) return;
	trace ("scale %f", scale);
	/* Clip by the intersection of the world window and the outline of the cells. */
	//Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2);
	if (clipx1 < x1DC) clipx1 = x1DC;
	if (clipx2 > x2DC) clipx2 = x2DC;
	if (clipy1 > y1DC) clipy1 = y1DC;
	if (clipy2 < y2DC) clipy2 = y2DC;
	/*
	 * The first decision is whether we are going to use the standard rectangle drawing
	 * (cellArray only), or whether we are going to write into a bitmap.
	 * The standard drawing is best for small numbers of cells,
	 * provided that some cells are larger than a pixel.
	 */
	if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) {
		try {
			/*unsigned int cellWidth = (unsigned int) dx + 1;*/
			unsigned int cellHeight = (unsigned int) (- (int) dy) + 1;
			long ix, iy;
			#if cairo
				cairo_pattern_t *grey [256];
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) {
					double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0);
					grey [igrey] = cairo_pattern_create_rgb (v, v, v);
				}
			#elif win
				static HBRUSH greyBrush [256];
				RECT rect;
				if (! greyBrush [0])
					for (int igrey = 0; igrey <= 255; igrey ++)
						greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey));   // once
			#elif mac
				GraphicsQuartz_initDraw (me);
				CGContextSetAlpha (my d_macGraphicsContext, 1.0);
				CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal);
			#endif
			autoNUMvector <long> lefts (ix1, ix2 + 1);
			for (ix = ix1; ix <= ix2 + 1; ix ++)
				lefts [ix] = x1DC + (long) ((ix - ix1) * dx);
			for (iy = iy1; iy <= iy2; iy ++) {
				long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight;
				if (top > clipy1 || bottom < clipy2) continue;
				if (top < clipy2) top = clipy2;
				if (bottom > clipy1) bottom = clipy1;
				#if win
					rect. bottom = bottom; rect. top = top;
				#endif
				for (ix = ix1; ix <= ix2; ix ++) {
					long left = lefts [ix], right = lefts [ix + 1];
					if (right < clipx1 || left > clipx2) continue;
					if (left < clipx1) left = clipx1;
					if (right > clipx2) right = clipx2;
					if (z_rgbt) {
						#if cairo
							// NYI
						#elif win
							// NYI
						#elif mac
							double red          = z_rgbt [iy] [ix]. red;
							double green        = z_rgbt [iy] [ix]. green;
							double blue         = z_rgbt [iy] [ix]. blue;
							double transparency = z_rgbt [iy] [ix]. transparency;
							red =   ( red   <= 0.0 ? 0.0 : red   >= 1.0 ? 1.0 : red   );
							green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green );
							blue =  ( blue  <= 0.0 ? 0.0 : blue  >= 1.0 ? 1.0 : blue  );
							CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					} else {
						#if cairo
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]);
							cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top);
							cairo_fill (my d_cairoGraphicsContext);
						#elif win
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							rect. left = left; rect. right = right;
							FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]);
						#elif mac
							double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0;
							CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					}
				}
			}
			
			#if cairo
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++)
					cairo_pattern_destroy (grey [igrey]);
			#elif mac
				CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0);
				GraphicsQuartz_exitDraw (me);
			#endif
		} catch (MelderError) { }
	} else {
		long xDC, yDC;
		long undersampling = 1;
		/*
		 * Prepare for off-screen bitmap drawing.
		 */
		#if cairo
			long arrayWidth = clipx2 - clipx1;
			long arrayHeight = clipy1 - clipy2;
			trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight);
			cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight);
			unsigned char *bits = cairo_image_surface_get_data (sfc);
			int scanLineLength = cairo_image_surface_get_stride (sfc);
			unsigned char grey [256];
			trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey));
			for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++)
				grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1));
		#elif win
			long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2;
			int igrey;
			/*
			 * Create a device-independent bitmap, 32 bits deep.
			 */
			struct { BITMAPINFOHEADER header; } bitmapInfo;
			long scanLineLength = bitmapWidth * 4;   // for 24 bits: (bitmapWidth * 3 + 3) & ~3L;
			HBITMAP bitmap;
			unsigned char *bits;   // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection ()
			bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER);
			bitmapInfo. header.biWidth = bitmapWidth;   // scanLineLength;
			bitmapInfo. header.biHeight = bitmapHeight;
			bitmapInfo. header.biPlanes = 1;
			bitmapInfo. header.biBitCount = 32;
			bitmapInfo. header.biCompression = 0;
			bitmapInfo. header.biSizeImage = 0;
			bitmapInfo. header.biXPelsPerMeter = 0;
			bitmapInfo. header.biYPelsPerMeter = 0;
			bitmapInfo. header.biClrUsed = 0;
			bitmapInfo. header.biClrImportant = 0;
			bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo,
				DIB_RGB_COLORS, (VOID **) & bits, NULL, 0);
		#elif mac
			long bytesPerRow = (clipx2 - clipx1) * 4;
			Melder_assert (bytesPerRow > 0);
			long numberOfRows = clipy1 - clipy2;
			Melder_assert (numberOfRows > 0);
			unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows);
		#endif
		/*
		 * Draw into the bitmap.
		 */
		#if cairo
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif win
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif mac
			#define ROW_START_ADDRESS  (imageData + (clipy1 - 1 - yDC) * bytesPerRow)
			#define PUT_PIXEL \
				if (my colourScale == kGraphics_colourScale_GREY) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				} else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \
					if (value < 0.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
					} else if (value < 64.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = (int) (value * 3 + 63.999); \
						*pixelAddress ++ = 0; \
					} else if (value < 128.0) { \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = 0; \
					} else if (value < 192.0) { \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = 0; \
					} else if (value < 256.0) { \
						*pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} else { \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} \
				}
		#else
			#define ROW_START_ADDRESS  NULL
			#define PUT_PIXEL
		#endif
		if (interpolate) {
			try {
				autoNUMvector <long> ileft (clipx1, clipx2);
				autoNUMvector <long> iright (clipx1, clipx2);
				autoNUMvector <double> rightWeight (clipx1, clipx2);
				autoNUMvector <double> leftWeight (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
					double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC);
					ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1;
					rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC];
					if (ileft [xDC] < ix1) ileft [xDC] = ix1;
					if (iright [xDC] > ix2) iright [xDC] = ix2;
				}
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC);
					long itop = ceil (iy_real), ibottom = itop - 1;
					double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight;
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					if (itop > iy2) itop = iy2;
					if (ibottom < iy1) ibottom = iy1;
					if (z_float) {
						double *ztop = z_float [itop], *zbottom = z_float [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					} else if (z_rgbt) {
						double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double red =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. red + bottomWeight * zbottom [ileft  [xDC]]. red);
							double green =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. green + bottomWeight * zbottom [ileft  [xDC]]. green);
							double blue =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. blue + bottomWeight * zbottom [ileft  [xDC]]. blue);
							double transparency =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. transparency + bottomWeight * zbottom [ileft  [xDC]]. transparency);
							if (red          < 0.0) red          = 0.0; else if (red          > 1.0) red          = 1.0;
							if (green        < 0.0) green        = 0.0; else if (green        > 1.0) green        = 1.0;
							if (blue         < 0.0) blue         = 0.0; else if (blue         > 1.0) blue         = 1.0;
							if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0;
							#if win
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = 0;
							#elif mac
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#elif cairo
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#endif
						}
					} else {
						unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		} else {
			try {
				autoNUMvector <long> ix (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling)
					ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC));
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC));
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					Melder_assert (iy >= iy1 && iy <= iy2);
					if (z_float) {
						double *ziy = z_float [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					} else {
						unsigned char *ziy = z_byte [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		}
		/*
		 * Copy the bitmap to the screen.
		 */
		#if cairo
			cairo_matrix_t clip_trans;
			cairo_matrix_init_identity (& clip_trans);
			cairo_matrix_scale (& clip_trans, 1, -1);		// we painted in the reverse y-direction
			cairo_matrix_translate (& clip_trans, - clipx1, - clipy1);
			cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc);
			trace ("bitmap pattern %p", bitmap_pattern);
			if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) {
				Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status));
			} else {
				cairo_pattern_set_matrix (bitmap_pattern, & clip_trans);
				cairo_save (my d_cairoGraphicsContext);
				cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern);
				cairo_paint (my d_cairoGraphicsContext);
				cairo_restore (my d_cairoGraphicsContext);
			}
			cairo_pattern_destroy (bitmap_pattern);
		#elif win
			SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
				bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS);
			//StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
			//	bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
		#elif mac
			CGImageRef image;
			static CGColorSpaceRef colourSpace = NULL;
			if (colourSpace == NULL) {
				colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);   // used to be kCGColorSpaceUserRGB
				Melder_assert (colourSpace != NULL);
			}
			if (1) {
				CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL,
					imageData,
					bytesPerRow * numberOfRows,
					_mac_releaseDataCallback   // we need this because we cannot release the image data immediately after drawing,
						// because in PDF files the imageData has to stay available through EndPage
				);
				Melder_assert (dataProvider != NULL);
				image = CGImageCreate (clipx2 - clipx1, numberOfRows,
					8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault);
				CGDataProviderRelease (dataProvider);
			} else if (0) {
				Melder_assert (CGBitmapContextCreate != NULL);
				CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100,
					8, 800, colourSpace, 0);
				Melder_assert (bitmaptest != NULL);
				CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows,
					8, bytesPerRow, colourSpace, kCGImageAlphaLast);
				Melder_assert (bitmap != NULL);
				image = CGBitmapContextCreateImage (bitmap);
				// release bitmap?
			}
			Melder_assert (image != NULL);
			GraphicsQuartz_initDraw (me);
			CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image);
			GraphicsQuartz_exitDraw (me);
			//CGColorSpaceRelease (colourSpace);
			CGImageRelease (image);
		#endif
		/*
		 * Clean up.
		 */
		#if cairo
			cairo_surface_destroy (sfc);
		#elif win
			DeleteBitmap (bitmap);
		#endif
	}
gboolean cd_drop_indicator_render (gpointer pUserData, CairoDock *pDock, cairo_t *pCairoContext)
{
	CDDropIndicatorData *pData = CD_APPLET_GET_MY_DOCK_DATA (pDock);
	if (pData == NULL)
		return GLDI_NOTIFICATION_LET_PASS;
	
	if (pCairoContext != NULL)
	{
		if (pData->fAlpha > 0)
		{
			cairo_save (pCairoContext);
			double fX = pDock->container.iMouseX - myData.dropIndicator.iWidth / 2;
			if (pDock->container.bIsHorizontal)
				cairo_rectangle (pCairoContext,
					(int) pDock->container.iMouseX - myData.dropIndicator.iWidth/2,
					(int) (pDock->container.bDirectionUp ? 0 : pDock->iActiveHeight - 2*myData.dropIndicator.iHeight),
					(int) myData.dropIndicator.iWidth,
					(int) (pDock->container.bDirectionUp ? 2*myData.dropIndicator.iHeight : pDock->iActiveHeight));
			else
				cairo_rectangle (pCairoContext,
					(int) (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->iActiveHeight : pDock->iActiveHeight - 2*myData.dropIndicator.iHeight),
					(int) pDock->container.iMouseX - myData.dropIndicator.iWidth/2,
					(int) (pDock->container.bDirectionUp ? 2*myData.dropIndicator.iHeight : pDock->iActiveHeight),
					(int) myData.dropIndicator.iWidth);
			cairo_clip (pCairoContext);
			
			if (pDock->container.bIsHorizontal)
				cairo_translate (pCairoContext, fX, (pDock->container.bDirectionUp ? 0 : pDock->iActiveHeight));
			else
				cairo_translate (pCairoContext, (pDock->container.bDirectionUp ? 0 : pDock->iActiveHeight), fX);
			double fRotationAngle = (pDock->container.bIsHorizontal ? (pDock->container.bDirectionUp ? 0 : G_PI) : (pDock->container.bDirectionUp ? -G_PI/2 : G_PI/2));
			cairo_rotate (pCairoContext, fRotationAngle);
			
			cairo_translate (pCairoContext, 0, pData->iDropIndicatorOffset);
			cairo_pattern_t* pPattern = cairo_pattern_create_for_surface (myData.dropIndicator.pSurface);
			g_return_val_if_fail (cairo_pattern_status (pPattern) == CAIRO_STATUS_SUCCESS, GLDI_NOTIFICATION_LET_PASS);
			cairo_pattern_set_extend (pPattern, CAIRO_EXTEND_REPEAT);
			cairo_set_source (pCairoContext, pPattern);
			
			cairo_translate (pCairoContext, 0, - pData->iDropIndicatorOffset);
			cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (0.,
				0.,
				0.,
				2*myData.dropIndicator.iHeight);  // de haut en bas.
			g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, GLDI_NOTIFICATION_LET_PASS);
		
			cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
			cairo_pattern_add_color_stop_rgba (pGradationPattern,
				0.,
				0.,
				0.,
				0.,
				0.);
			cairo_pattern_add_color_stop_rgba (pGradationPattern,
				0.4,
				0.,
				0.,
				0.,
				pData->fAlpha);
			cairo_pattern_add_color_stop_rgba (pGradationPattern,
				0.5,
				0.,
				0.,
				0.,
				pData->fAlpha);
			cairo_pattern_add_color_stop_rgba (pGradationPattern,
				1.,
				0.,
				0.,
				0.,
				0.);
		
			cairo_mask (pCairoContext, pGradationPattern);
			
			cairo_pattern_destroy (pPattern);
			cairo_pattern_destroy (pGradationPattern);
			cairo_restore (pCairoContext);
		}
		
		if (pData->fAlphaHover > 0 && myData.hoverIndicator.pSurface != NULL)
		{
			Icon *pIcon = cairo_dock_get_pointed_icon (pDock->icons);
			if (pIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			{
				cairo_save (pCairoContext);
				if (pDock->container.bIsHorizontal)
				{
					cairo_translate (pCairoContext,
						pIcon->fDrawX + 2./3*pIcon->fWidth*pIcon->fScale,
						pIcon->fDrawY);  // top right corner
					cairo_scale (pCairoContext,
						pIcon->fWidth*pIcon->fScale/3 / myData.hoverIndicator.iWidth,
						pIcon->fHeight*pIcon->fScale/3 / myData.hoverIndicator.iHeight);
				}
				else
				{
					cairo_translate (pCairoContext,
						pIcon->fDrawY + 2./3*pIcon->fWidth*pIcon->fScale,
						pIcon->fDrawX);
					cairo_scale (pCairoContext,
						pIcon->fHeight*pIcon->fScale/3 / myData.hoverIndicator.iWidth,
						pIcon->fWidth*pIcon->fScale/3 / myData.hoverIndicator.iHeight);
				}
				cairo_set_source_surface (pCairoContext, myData.hoverIndicator.pSurface, 0., 0.);
				cairo_paint_with_alpha (pCairoContext, pData->fAlphaHover);
				cairo_restore (pCairoContext);
			}
		}
	}
	else
	{
		if (pData->fAlpha > 0)
		{
			double fX = pDock->container.iMouseX;
			double fY = (pDock->container.bDirectionUp ? pDock->iActiveHeight - myData.dropIndicator.iHeight : myData.dropIndicator.iHeight);
			glPushMatrix();
			glLoadIdentity();
			
			if (pDock->container.bIsHorizontal)
			{
				fX = pDock->container.iMouseX;
				fY = (pDock->container.bDirectionUp ? pDock->iActiveHeight - myData.dropIndicator.iHeight : myData.dropIndicator.iHeight);
				glTranslatef (fX, fY, - myData.dropIndicator.iWidth-1.);
				if (! pDock->container.bDirectionUp)
					glScalef (1., -1., 1.);
			}
			else
			{
				fX = pDock->container.iWidth - pDock->container.iMouseX;
				fY = (! pDock->container.bDirectionUp ? pDock->iActiveHeight - myData.dropIndicator.iHeight : pDock->container.iHeight - pDock->iActiveHeight + myData.dropIndicator.iHeight);
				glTranslatef (fY, fX, - myData.dropIndicator.iWidth-1.);
				glRotatef ((pDock->container.bDirectionUp ? 90. : -90.), 0., 0., 1.);
			}
			
			glRotatef (pData->iDropIndicatorRotation, 0., 1., 0.);
			
			//\_________________ On decale la texture vers le bas.
			glMatrixMode(GL_TEXTURE); // On selectionne la matrice des textures
			glPushMatrix();
			glLoadIdentity(); // On la reset
			glTranslatef(.0, - (double)pData->iDropIndicatorOffset / myData.dropIndicator.iHeight, 0.);
			glScalef (1., -2., 1.);
			glMatrixMode(GL_MODELVIEW); // On revient sur la matrice d'affichage
			
			//\_________________ On dessine l'indicateur.
			glEnable (GL_BLEND);
			if (pData->fAlpha != 1)
				_cairo_dock_set_blend_alpha ();
			else
				_cairo_dock_set_blend_over();
			
			//glEnable(GL_DEPTH_TEST);
			glScalef (myData.dropIndicator.iWidth, myData.dropIndicator.iHeight, myData.dropIndicator.iWidth);
			glColor4f(1.0f, 1.0f, 1.0f, pData->fAlpha);
			glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
			
			glEnable(GL_TEXTURE);
			glActiveTextureARB(GL_TEXTURE0_ARB); // Go pour le multitexturing 1ere passe
			glEnable(GL_TEXTURE_2D); // On active le texturing sur cette passe
			glBindTexture(GL_TEXTURE_2D, myData.dropIndicator.iTexture);
			glActiveTextureARB(GL_TEXTURE1_ARB); // Go pour le texturing 2eme passe
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, myData.iBilinearGradationTexture);
			glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Le mode de combinaison des textures
			///glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);  // multiplier les alpha.
			//glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
			
			glBegin(GL_QUADS);
			glNormal3f(0,0,1);
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,0., 0.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,0., 0.); glVertex3f(-0.5, -1., 0.);  // Bottom Left Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,1., 0.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,1., 0.); glVertex3f( 0.5, -1., 0.);  // Bottom Right Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,1., 1.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,1., 1.); glVertex3f( 0.5, 1., 0.);  // Top Right Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,0., 1.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,0., 1.); glVertex3f(-0.5, 1., 0.);  // Top Left Of The Texture and Quad
			glNormal3f(1,0,0);
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,0., 0.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,0., 0.); glVertex3f(0., -1., -0.5);  // Bottom Left Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,1., 0.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,1., 0.); glVertex3f(0., -1.,  0.5);  // Bottom Right Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,1., 1.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,1., 1.); glVertex3f(0.,  1.,  0.5);  // Top Right Of The Texture and Quad
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB,0., 1.); glMultiTexCoord2fARB( GL_TEXTURE1_ARB,0., 1.); glVertex3f(0.,  1., -0.5);  // Top Left Of The Texture and Quad
			glEnd();
			
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);
			glDisable (GL_BLEND);
			_cairo_dock_set_blend_alpha ();
			glPopMatrix();
			
			//\_________________ On remet la matrice des textures.
			glMatrixMode(GL_TEXTURE);
			glPopMatrix();
			glMatrixMode(GL_MODELVIEW);
		}
		
		if (pData->fAlphaHover > 0 && myData.hoverIndicator.iTexture != 0)
		{
			Icon *pIcon = cairo_dock_get_pointed_icon (pDock->icons);
			if (pIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			{
				_cairo_dock_enable_texture ();
				_cairo_dock_set_blend_alpha ();
				glPushMatrix ();
				if (pDock->container.bIsHorizontal)
					glTranslatef (pIcon->fDrawX + 5./6*pIcon->fWidth*pIcon->fScale,
						pDock->iActiveHeight - pIcon->fDrawY - 1./6*pIcon->fHeight*pIcon->fScale,
						0.);
				else
					glTranslatef (pIcon->fDrawY + 5./6*pIcon->fHeight*pIcon->fScale,
						pDock->container.iWidth - (pIcon->fDrawX + 1./6*pIcon->fWidth*pIcon->fScale),
						0.);
				_cairo_dock_apply_texture_at_size_with_alpha (myData.hoverIndicator.iTexture,
					myData.hoverIndicator.iWidth,
					myData.hoverIndicator.iHeight,
					pData->fAlphaHover);
				glPopMatrix ();
				_cairo_dock_disable_texture ();
			}
		}
	}
	return GLDI_NOTIFICATION_LET_PASS;
}
void
draw_shadow (cairo_t* cr,
	     gdouble  width,
	     gdouble  height,
	     gint     shadow_radius,
	     gint     corner_radius)
{
	cairo_surface_t* tmp_surface = NULL;
	cairo_surface_t* new_surface = NULL;
	cairo_pattern_t* pattern     = NULL;
	cairo_t*         cr_surf     = NULL;
	cairo_matrix_t   matrix;
	raico_blur_t*    blur        = NULL;

	tmp_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
						  4 * shadow_radius,
						  4 * shadow_radius);
	if (cairo_surface_status (tmp_surface) != CAIRO_STATUS_SUCCESS)
		return;

	cr_surf = cairo_create (tmp_surface);
	if (cairo_status (cr_surf) != CAIRO_STATUS_SUCCESS)
	{
		cairo_surface_destroy (tmp_surface);
		return;
	}

	cairo_scale (cr_surf, 1.0f, 1.0f);
	cairo_set_operator (cr_surf, CAIRO_OPERATOR_CLEAR);
	cairo_paint (cr_surf);
	cairo_set_operator (cr_surf, CAIRO_OPERATOR_OVER);
	cairo_set_source_rgba (cr_surf, 0.0f, 0.0f, 0.0f, 0.75f);
	cairo_arc (cr_surf,
		   2 * shadow_radius,
		   2 * shadow_radius,
		   2.0f * corner_radius,
		   0.0f,
		   360.0f * (G_PI / 180.f));
	cairo_fill (cr_surf);
	cairo_destroy (cr_surf);

	// create and setup blur
	blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
	raico_blur_set_radius (blur, shadow_radius);

	// now blur it
	raico_blur_apply (blur, tmp_surface);

	// blur no longer needed
	raico_blur_destroy (blur);

	new_surface = cairo_image_surface_create_for_data (
			cairo_image_surface_get_data (tmp_surface),
			cairo_image_surface_get_format (tmp_surface),
			cairo_image_surface_get_width (tmp_surface) / 2,
			cairo_image_surface_get_height (tmp_surface) / 2,
			cairo_image_surface_get_stride (tmp_surface));
	pattern = cairo_pattern_create_for_surface (new_surface);
	if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS)
	{
		cairo_surface_destroy (tmp_surface);
		cairo_surface_destroy (new_surface);
		return;
	}

	// top left
	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
	cairo_set_source (cr, pattern);
	cairo_rectangle (cr,
			 0.0f,
			 0.0f,
			 width - 2 * shadow_radius,
			 2 * shadow_radius);
	cairo_fill (cr);

	// bottom left
	cairo_matrix_init_scale (&matrix, 1.0f, -1.0f);
	cairo_matrix_translate (&matrix, 0.0f, -height);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 0.0f,
			 2 * shadow_radius,
			 2 * shadow_radius,
			 height - 2 * shadow_radius);
	cairo_fill (cr);

	// top right
	cairo_matrix_init_scale (&matrix, -1.0f, 1.0f);
	cairo_matrix_translate (&matrix, -width, 0.0f);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 width - 2 * shadow_radius,
			 0.0f,
			 2 * shadow_radius,
			 height - 2 * shadow_radius);
	cairo_fill (cr);

	// bottom right
	cairo_matrix_init_scale (&matrix, -1.0f, -1.0f);
	cairo_matrix_translate (&matrix, -width, -height);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 2 * shadow_radius,
			 height - 2 * shadow_radius,
			 width - 2 * shadow_radius,
			 2 * shadow_radius);
	cairo_fill (cr);

	// clean up
	cairo_pattern_destroy (pattern);
	cairo_surface_destroy (tmp_surface);
	cairo_surface_destroy (new_surface);
}