void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace, const FontDescription& fontDescription)
{
    cairo_font_options_t* options = getDefaultFontOptions();

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    // Scaling a font with width zero size leads to a failed cairo_scaled_font_t instantiations.
    // Instead we scale we scale the font to a very tiny size and just abort rendering later on.
    float realSize = m_size ? m_size : 1;

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, realSize, realSize);
    else {
        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
        int actualFontSlant;
        if (fontDescription.italic() && FcPatternGetInteger(m_pattern.get(), FC_SLANT, 0, &actualFontSlant) == FcResultMatch)
            m_syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;

        // The matrix from FontConfig does not include the scale. 
        cairo_matrix_scale(&fontMatrix, realSize, realSize);
    }

    if (syntheticOblique()) {
        static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
        cairo_matrix_t skew = {1, 0, syntheticObliqueSkew, 1, 0, 0};
        cairo_matrix_multiply(&fontMatrix, &skew, &fontMatrix);
    }

    m_horizontalOrientationMatrix = fontMatrix;
    if (m_orientation == Vertical)
        rotateCairoMatrixForVerticalOrientation(&fontMatrix);

    m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
    cairo_font_options_destroy(options);
}
Exemple #2
0
static PyObject *
matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
  static char *kwlist[] = { "xx", "yx", "xy", "yy", "x0", "y0", NULL };
  double xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0;

  if (!PyArg_ParseTupleAndKeywords(args, kwds,
				   "|dddddd:Matrix.__init__", kwlist,
				   &xx, &yx, &xy, &yy, &x0, &y0))
    return NULL;

  cairo_matrix_t mx;
  cairo_matrix_init (&mx, xx, yx, xy, yy, x0, y0);
  return PycairoMatrix_FromMatrix (&mx);
}
static void
rsvg_cairo_clip_apply_affine (RsvgCairoClipRender *render, cairo_matrix_t *affine)
{
    RsvgCairoRender *cairo_render = &render->super;
    cairo_matrix_t matrix;
    gboolean nest = cairo_render->cr != cairo_render->initial_cr;

    cairo_matrix_init (&matrix,
                       affine->xx, affine->yx,
                       affine->xy, affine->yy,
                       affine->x0 + (nest ? 0 : render->parent->offset_x),
                       affine->y0 + (nest ? 0 : render->parent->offset_y));
    cairo_set_matrix (cairo_render->cr, &matrix);
}
Exemple #4
0
static void cmd_flip_x (struct document *doc)
{
	int width = (doc->flags & NO_GENERIC_SCALE) ?
		doc->width : ceil(doc->scale * doc->width);
	cairo_matrix_t flipx;
	cairo_matrix_init (&flipx, -1, 0, 0, 1, width, 0);

	/*
	 * .y        y.
	 *  │   ->   │
	 *  └─x    x─┘
	 */
	cairo_matrix_multiply (&doc->transform, &doc->transform, &flipx);
}
Exemple #5
0
void Drawer::RotationOLD(double aAngle)
{
    mAngle = aAngle * M_PI / 180;

    double CentreX = 0.0;
    double CentreY = 0.0;
    cairo_matrix_t Matrice;

    cairo_get_current_point(mCairoDC, &CentreX, &CentreY);

    cairo_matrix_init (&Matrice, cos (mAngle), sin (mAngle), -sin (mAngle), cos(mAngle), CentreX * (1 - cos (mAngle)) + sin (mAngle) * CentreY, CentreY * ( 1 - cos (mAngle)) - sin (mAngle) * CentreX);

    cairo_transform (mCairoDC, &Matrice);
}
Exemple #6
0
void dtgtk_cairo_paint_solid_triangle(cairo_t *cr, gint x,int y,gint w,gint h, gint flags)
{
  /* initialize rotation and flip matrices */
  cairo_matrix_t hflip_matrix;
  cairo_matrix_init(&hflip_matrix,-1,0,0,1,1,0);

  double C=cos(-(M_PI/2.0)),S=sin(-(M_PI/2.0));  // -90 degrees
  C=flags&CPF_DIRECTION_DOWN?cos(-(M_PI*1.5)):C;
  S=flags&CPF_DIRECTION_DOWN?sin(-(M_PI*1.5)):S;
  cairo_matrix_t rotation_matrix;
  cairo_matrix_init(&rotation_matrix,C,S,-S,C,0.5-C*0.5+S*0.5,0.5-S*0.5-C*0.5);

  /* scale and transform*/
  gint s=w<h?w:h;
  cairo_translate(cr, x+(w/2.0)-(s/2.0), y+(h/2.0)-(s/2.0));
  cairo_scale(cr,s,s);
  cairo_set_line_width(cr,0.1);
  cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);

  if( flags&CPF_DIRECTION_UP || flags &CPF_DIRECTION_DOWN)
    cairo_transform(cr,&rotation_matrix);
  else if(flags&CPF_DIRECTION_LEFT)	// Flip x transformation
    cairo_transform(cr,&hflip_matrix);


  cairo_move_to(cr, 0.2, 0.2);
  cairo_line_to(cr, 0.7, 0.5);
  cairo_line_to(cr, 0.2, 0.8);
  cairo_line_to(cr, 0.2, 0.2);
  cairo_stroke(cr);
  cairo_move_to(cr, 0.2, 0.2);
  cairo_line_to(cr, 0.7, 0.5);
  cairo_line_to(cr, 0.2, 0.8);
  cairo_line_to(cr, 0.2, 0.2);
  cairo_fill(cr);
  cairo_identity_matrix(cr);
}
Exemple #7
0
/**
 * cairo_matrix_init_rotate:
 * @matrix: a #cairo_matrix_t
 * @radians: angle of rotation, in radians. The direction of rotation
 * is defined such that positive angles rotate in the direction from
 * the positive X axis toward the positive Y axis. With the default
 * axis orientation of cairo, positive angles rotate in a clockwise
 * direction.
 *
 * Initialized @matrix to a transformation that rotates by @radians.
 **/
void
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
			  double radians)
{
    double  s;
    double  c;

    s = sin (radians);
    c = cos (radians);

    cairo_matrix_init (matrix,
		       c, s,
		       -s, c,
		       0, 0);
}
Exemple #8
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
int o_text_get_rendered_bounds (void *user_data, OBJECT *o_current,
                                int *min_x, int *min_y,
                                int *max_x, int *max_y)
{
  GschemToplevel *w_current = (GschemToplevel *) user_data;
  TOPLEVEL *toplevel;
  EdaRenderer *renderer;
  cairo_t *cr;
  cairo_matrix_t render_mtx;
  int result, render_flags = 0;
  double t, l, r, b;

  g_return_val_if_fail ((w_current != NULL), FALSE);
  toplevel = gschem_toplevel_get_toplevel (w_current);

  cr = gdk_cairo_create (w_current->drawable);

  /* Set up renderer based on configuration in w_current. Note that we
   * *don't* enable hinting, because if its enabled the calculated
   * bounds are zoom-level-dependent. */
  if (toplevel->show_hidden_text)
    render_flags |= EDA_RENDERER_FLAG_TEXT_HIDDEN;
  renderer = g_object_ref (w_current->renderer);
  g_object_set (G_OBJECT (renderer),
                "cairo-context", cr,
                "render-flags", render_flags,
                NULL);

  /* We need to transform the cairo context to approximate world
   * coordinates. */
  cairo_matrix_init (&render_mtx, 1, 0, 0, -1, -1, 1);
  cairo_set_matrix (cr, &render_mtx);

  /* Use the renderer to calculate text bounds */
  result = eda_renderer_get_user_bounds (renderer, o_current, &l, &t, &r, &b);

  /* Clean up */
  eda_renderer_destroy (renderer);
  cairo_destroy (cr);

  /* Round bounds to nearest integer */
  *min_x = lrint (fmin (l, r));
  *min_y = lrint (fmin (t, b));
  *max_x = lrint (fmax (l, r));
  *max_y = lrint (fmax (t, b));

  return result;
}
Exemple #9
0
static cairo_pattern_t *
_pattern_build_for_cairo (DiaPattern *pattern, const Rectangle *ext)
{
  cairo_pattern_t *pat;
  gsize i;
  real x, y;
  DiaPatternType type;
  guint flags;
  Point p1, p2;
  real r;

  g_return_val_if_fail (pattern != NULL, NULL);

  dia_pattern_get_settings (pattern, &type, &flags);
  dia_pattern_get_points (pattern, &p1, &p2);
  dia_pattern_get_radius (pattern, &r);

  switch (type ) {
  case DIA_LINEAR_GRADIENT :
    pat = cairo_pattern_create_linear (p1.x, p1.y, p2.x, p2.y);
    break;
  case DIA_RADIAL_GRADIENT :
    pat = cairo_pattern_create_radial (p2.x, p2.y, 0.0, p1.x, p1.y, r);
    break;
  default :
    g_warning ("_pattern_build_for_cairo non such.");
    return NULL;
  }
  /* this must only be optionally done */
  if ((flags & DIA_PATTERN_USER_SPACE)==0) {
    cairo_matrix_t matrix;
    real w = ext->right - ext->left;
    real h = ext->bottom - ext->top;
    cairo_matrix_init (&matrix, w, 0.0, 0.0, h, ext->left, ext->top);
    cairo_matrix_invert (&matrix);
    cairo_pattern_set_matrix (pat, &matrix);
  }
  if (flags & DIA_PATTERN_EXTEND_PAD)
    cairo_pattern_set_extend (pat, CAIRO_EXTEND_PAD);
  else if (flags & DIA_PATTERN_EXTEND_REPEAT)
    cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);
  else if (flags & DIA_PATTERN_EXTEND_REFLECT)
    cairo_pattern_set_extend (pat, CAIRO_EXTEND_REFLECT);

  dia_pattern_foreach (pattern, _add_color_stop, pat);

  return pat;
}
Exemple #10
0
/* This function isn't a correct adjoint in that the implicit 1 in the
   homogeneous result should actually be ad-bc instead. But, since this
   adjoint is only used in the computation of the inverse, which
   divides by det (A)=ad-bc anyway, everything works out in the end. */
static void
_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
{
    /* adj (A) = transpose (C:cofactor (A,i,j)) */
    double a, b, c, d, tx, ty;

    _cairo_matrix_get_affine (matrix,
			      &a,  &b,
			      &c,  &d,
			      &tx, &ty);

    cairo_matrix_init (matrix,
		       d, -b,
		       -c, a,
		       c*ty - d*tx, b*tx - a*ty);
}
Exemple #11
0
static void cmd_flip_y (struct document *doc)
{
	int height = (doc->flags & NO_GENERIC_SCALE) ?
		doc->height : ceil(doc->scale * doc->height);
	cairo_matrix_t flipy;
	cairo_matrix_init (&flipy, 1, 0, 0, -1, 0, height);

	/* .y      .
	 *  │  
	 *  └─x ->
	 *          ┌─x
	 *          │
	 *          y
	 */
	cairo_matrix_multiply (&doc->transform, &doc->transform, &flipy);
}
Exemple #12
0
static void do_drawing(cairo_t *cr) {
	cairo_matrix_t matrix;

	cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
	cairo_rectangle(cr, 20, 30, 80, 50);
	cairo_fill(cr);
	cairo_matrix_init(&matrix,
		1.0, 0.5,
		0.0, 1.0,
		0.0, 0.0
	);

	cairo_transform(cr, &matrix);
	cairo_rectangle(cr, 130, 30, 80, 50);
	cairo_fill(cr);
}
HBITMAP allocImage(HDC dc, IntSize size, CairoContextRef* targetRef)
{
    BITMAPINFO bmpInfo = {0};
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = size.width();
    bmpInfo.bmiHeader.biHeight = size.height(); // Must be positive!
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 32;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biClrUsed = 0; // unused
    bmpInfo.bmiHeader.biClrImportant = 0;

    LPVOID bits;
    HBITMAP hbmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0);

    // At this point, we have a Cairo surface that points to a Windows DIB.  The DIB interprets
    // with the opposite meaning of positive Y axis, so everything we draw into this cairo
    // context is going to be upside down.
    if (!targetRef)
        return hbmp;

    cairo_surface_t* bitmapContext = cairo_image_surface_create_for_data((unsigned char*)bits,
                                               CAIRO_FORMAT_ARGB32,
                                               bmpInfo.bmiHeader.biWidth,
                                               bmpInfo.bmiHeader.biHeight,
                                               bmpInfo.bmiHeader.biWidth * 4);

    if (!bitmapContext) {
        DeleteObject(hbmp);
        return 0;
    }

    *targetRef = cairo_create (bitmapContext);
    cairo_surface_destroy (bitmapContext);

    // At this point, we have a Cairo surface that points to a Windows DIB.  The DIB interprets
    // with the opposite meaning of positive Y axis, so everything we draw into this cairo
    // context is going to be upside down.
    //
    // So, we must invert the CTM for the context so that drawing commands will be flipped
    // before they get written to the internal buffer.
    cairo_matrix_t matrix;
    cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, size.height());
    cairo_set_matrix(*targetRef, &matrix);

    return hbmp;
}
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
		       cairo_rectangle_int_t     *rect)
{
    double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
    double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
    int x, y, width, height;
    cairo_status_t status;
    cairo_surface_t *image;
    cairo_surface_pattern_t pattern;
    cairo_clip_t *clip;

    x = rect->x;
    y = rect->y;
    width = rect->width;
    height = rect->height;
    image = _cairo_paginated_surface_create_image_surface (surface,
							   ceil (width  * x_scale),
							   ceil (height * y_scale));
    _cairo_surface_set_device_scale (image, x_scale, y_scale);
    /* set_device_offset just sets the x0/y0 components of the matrix;
     * so we have to do the scaling manually. */
    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);

    status = _cairo_recording_surface_replay (surface->recording_surface, image);
    if (unlikely (status))
	goto CLEANUP_IMAGE;

    _cairo_pattern_init_for_surface (&pattern, image);
    cairo_matrix_init (&pattern.base.matrix,
		       x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
    /* the fallback should be rendered at native resolution, so disable
     * filtering (if possible) to avoid introducing potential artifacts. */
    pattern.base.filter = CAIRO_FILTER_NEAREST;

    clip = _cairo_clip_intersect_rectangle (NULL, rect);
    status = _cairo_surface_paint (surface->target,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, clip);
    _cairo_clip_destroy (clip);
    _cairo_pattern_fini (&pattern.base);

CLEANUP_IMAGE:
    cairo_surface_destroy (image);

    return (cairo_int_status_t)status;
}
Exemple #15
0
static void matrix_init(cairo_matrix_t *mat, double width, double height, OGREnvelope *bounds){
  cairo_matrix_init(mat, 1, 0, 0, -1, 0, 0);
  cairo_matrix_translate(mat, 0, height * -1.0);

  double w,
    bWidth  = fabs(bounds->MaxX - bounds->MinX),
    bHeight = fabs(bounds->MaxY - bounds->MinY);

  if(bWidth > bHeight){
    w = width / bWidth;
  } else {
    w = height / bHeight;
  }

  cairo_matrix_scale(mat, w, w);
  cairo_matrix_translate(mat, -bounds->MinX, -bounds->MinY);
}
/**
 * goo_canvas_item_model_skew_y:
 * @model: an item model.
 * @degrees: the skew angle.
 * @cx: the x coordinate of the origin of the skew transform.
 * @cy: the y coordinate of the origin of the skew transform.
 * 
 * Skews the model's coordinate system along the y axis by the given amount,
 * about the given origin.
 **/
void
goo_canvas_item_model_skew_y         (GooCanvasItemModel *model,
				      gdouble             degrees,
				      gdouble             cx,
				      gdouble             cy)
{
  GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
  cairo_matrix_t tmp, new_matrix = { 1, 0, 0, 1, 0, 0 };
  double radians = degrees * (M_PI / 180);

  iface->get_transform (model, &new_matrix);
  cairo_matrix_translate (&new_matrix, cx, cy);
  cairo_matrix_init (&tmp, 1, tan (radians), 0, 1, 0, 0);
  cairo_matrix_multiply (&new_matrix, &tmp, &new_matrix);
  cairo_matrix_translate (&new_matrix, -cx, -cy);
  iface->set_transform (model, &new_matrix);
}
Exemple #17
0
static PyObject *
matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
  PyObject *o;
  static char *kwlist[] = { "xx", "yx", "xy", "yy", "x0", "y0", NULL };
  double xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0;

  if (!PyArg_ParseTupleAndKeywords(args, kwds,
				   "|dddddd:Matrix.__init__", kwlist,
				   &xx, &yx, &xy, &yy, &x0, &y0))
    return NULL;

  o = type->tp_alloc(type, 0);
  if (o)
    cairo_matrix_init (&((PycairoMatrix *)o)->matrix,
		       xx, yx, xy, yy, x0, y0);
  return o;
}
Exemple #18
0
void cairo_context::add_image(agg::trans_affine const& tr, image_rgba8 const& data, double opacity)
{
    cairo_pattern pattern(data);
    if (!tr.is_identity())
    {
        double m[6];
        tr.store_to(m);
        cairo_matrix_t cairo_matrix;
        cairo_matrix_init(&cairo_matrix,m[0],m[1],m[2],m[3],m[4],m[5]);
        cairo_matrix_invert(&cairo_matrix);
        pattern.set_matrix(cairo_matrix);
    }
    cairo_save(cairo_.get());
    cairo_set_source(cairo_.get(), const_cast<cairo_pattern_t*>(pattern.pattern()));
    cairo_paint_with_alpha(cairo_.get(), opacity);
    cairo_restore(cairo_.get());
    check_object_status_and_throw_exception(*this);
}
Exemple #19
0
cairo_scaled_font_t *
gfxDWriteFont::CairoScaledFont()
{
    if (!mCairoScaledFont) {
        cairo_matrix_t sizeMatrix;
        cairo_matrix_t identityMatrix;

        cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);
        cairo_matrix_init_identity(&identityMatrix);

        cairo_font_options_t *fontOptions = cairo_font_options_create();
        if (mNeedsOblique) {
            double skewfactor = OBLIQUE_SKEW_FACTOR;

            cairo_matrix_t style;
            cairo_matrix_init(&style,
                              1,                //xx
                              0,                //yx
                              -1 * skewfactor,  //xy
                              1,                //yy
                              0,                //x0
                              0);               //y0
            cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
        }

        if (mAntialiasOption != kAntialiasDefault) {
            cairo_font_options_set_antialias(fontOptions,
                GetCairoAntialiasOption(mAntialiasOption));
        }

        mCairoScaledFont = cairo_scaled_font_create(CairoFontFace(),
                                                    &sizeMatrix,
                                                    &identityMatrix,
                                                    fontOptions);
        cairo_font_options_destroy(fontOptions);
    }

    NS_ASSERTION(mAdjustedSize == 0.0 ||
                 cairo_scaled_font_status(mCairoScaledFont) 
                   == CAIRO_STATUS_SUCCESS,
                 "Failed to make scaled font");

    return mCairoScaledFont;
}
void
_pango_cairo_font_private_initialize (PangoCairoFontPrivate      *cf_priv,
				      PangoCairoFont             *cfont,
				      PangoGravity                gravity,
				      const cairo_font_options_t *font_options,
				      const PangoMatrix          *pango_ctm,
				      const cairo_matrix_t       *font_matrix)
{
  cairo_matrix_t gravity_matrix;

  cf_priv->cfont = cfont;
  cf_priv->gravity = gravity;

  cf_priv->data = _pango_cairo_font_private_scaled_font_data_create (); 

  /* first apply gravity rotation, then font_matrix, such that
   * vertical italic text comes out "correct".  we don't do anything
   * like baseline adjustment etc though.  should be specially
   * handled when we support italic correction. */
  cairo_matrix_init_rotate(&gravity_matrix,
			   pango_gravity_to_rotation (cf_priv->gravity));
  cairo_matrix_multiply (&cf_priv->data->font_matrix,
			 font_matrix,
			 &gravity_matrix);

  if (pango_ctm)
    cairo_matrix_init (&cf_priv->data->ctm,
		       pango_ctm->xx,
		       pango_ctm->yx,
		       pango_ctm->xy,
		       pango_ctm->yy,
		       0., 0.);
  else
    cairo_matrix_init_identity (&cf_priv->data->ctm);

  cf_priv->data->options = cairo_font_options_copy (font_options);
  cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF;

  cf_priv->scaled_font = NULL;
  cf_priv->hbi = NULL;
  cf_priv->glyph_extents_cache = NULL;
  cf_priv->metrics_by_lang = NULL;
}
HBITMAP allocImage(HDC dc, IntSize size, PlatformContextCairo** targetRef)
{
    BitmapInfo bmpInfo = BitmapInfo::create(size);

    LPVOID bits;
    HBITMAP hbmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0);

    // At this point, we have a Cairo surface that points to a Windows DIB.  The DIB interprets
    // with the opposite meaning of positive Y axis, so everything we draw into this cairo
    // context is going to be upside down.
    if (!targetRef)
        return hbmp;

    cairo_surface_t* bitmapContext = cairo_image_surface_create_for_data((unsigned char*)bits,
                                               CAIRO_FORMAT_ARGB32,
                                               bmpInfo.bmiHeader.biWidth,
                                               bmpInfo.bmiHeader.biHeight,
                                               bmpInfo.bmiHeader.biWidth * 4);

    if (!bitmapContext) {
        DeleteObject(hbmp);
        return 0;
    }

    cairo_t* cr = cairo_create(bitmapContext);
    cairo_surface_destroy(bitmapContext);

    // At this point, we have a Cairo surface that points to a Windows DIB.  The DIB interprets
    // with the opposite meaning of positive Y axis, so everything we draw into this cairo
    // context is going to be upside down.
    //
    // So, we must invert the CTM for the context so that drawing commands will be flipped
    // before they get written to the internal buffer.
    cairo_matrix_t matrix;
    cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, size.height());
    cairo_set_matrix(cr, &matrix);

    *targetRef = new PlatformGraphicsContext(cr);
    cairo_destroy(cr);

    return hbmp;
}
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
		       cairo_box_int_t           *box)
{
    double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
    double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
    cairo_matrix_t matrix;
    int x, y, width, height;
    cairo_status_t status;
    cairo_surface_t *image;
    cairo_pattern_t *pattern;

    x = box->p1.x;
    y = box->p1.y;
    width = box->p2.x - x;
    height = box->p2.y - y;
    image = _cairo_paginated_surface_create_image_surface (surface,
							   ceil (width  * x_scale),
							   ceil (height * y_scale));
    _cairo_surface_set_device_scale (image, x_scale, y_scale);
    /* set_device_offset just sets the x0/y0 components of the matrix;
     * so we have to do the scaling manually. */
    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);

    status = _cairo_meta_surface_replay (surface->meta, image);
    if (status)
	goto CLEANUP_IMAGE;

    pattern = cairo_pattern_create_for_surface (image);
    cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
    cairo_pattern_set_matrix (pattern, &matrix);

    status = _cairo_surface_paint (surface->target,
				   CAIRO_OPERATOR_SOURCE,
				   pattern);

    cairo_pattern_destroy (pattern);
CLEANUP_IMAGE:
    cairo_surface_destroy (image);

    return status;
}
Exemple #23
0
void
rsvg_cairo_clip (RsvgDrawingCtx * ctx, RsvgClipPath * clip, RsvgBbox * bbox)
{
    RsvgCairoClipRender *clip_render;
    RsvgCairoRender *save = RSVG_CAIRO_RENDER (ctx->render);
    cairo_t *cr;
    cairo_matrix_t affinesave;

    cr = save->cr;
    clip_render = RSVG_CAIRO_CLIP_RENDER (rsvg_cairo_clip_render_new (cr, save));
    ctx->render = &clip_render->super.super;

    /* Horribly dirty hack to have the bbox premultiplied to everything */
    if (clip->units == objectBoundingBox) {
        cairo_matrix_t bbtransform;
        cairo_matrix_init (&bbtransform,
                           bbox->rect.width,
                           0,
                           0,
                           bbox->rect.height,
                           bbox->rect.x,
                           bbox->rect.y);
        affinesave = clip->super.state->affine;
        cairo_matrix_multiply (&clip->super.state->affine, &bbtransform, &clip->super.state->affine);
    }

    rsvg_state_push (ctx);
    _rsvg_node_draw_children ((RsvgNode *) clip, ctx, 0);
    rsvg_state_pop (ctx);

    if (clip->units == objectBoundingBox)
        clip->super.state->affine = affinesave;

    g_assert (clip_render->super.cr_stack == NULL);
    g_assert (clip_render->super.bb_stack == NULL);
    g_assert (clip_render->super.surfaces_stack == NULL);

    g_free (ctx->render);
    cairo_clip (cr);
    ctx->render = &save->super;
}
Exemple #24
0
void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
{
    cairo_font_options_t* options = 0;
#if !PLATFORM(CLUTTER) && (!PLATFORM(EFL) || ENABLE(GLIB_SUPPORT))
    if (GdkScreen* screen = gdk_screen_get_default())
        options = cairo_font_options_copy(gdk_screen_get_font_options(screen));
#endif
    // gdk_screen_get_font_options() returns null if no default
    // options are set, so we always have to check.
    if (!options)
        options = cairo_font_options_create();

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
    else {
        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // The matrix from FontConfig does not include the scale.
        cairo_matrix_scale(&fontMatrix, m_size, m_size);
    }

    m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
    cairo_font_options_destroy(options);
}
void
ge_cairo_exchange_axis (cairo_t  *cr,
                        gint     *x,
                        gint     *y,
                        gint     *width,
                        gint     *height)
{
	gint tmp;
	cairo_matrix_t matrix;

	cairo_translate (cr, *x, *y);
	cairo_matrix_init (&matrix, 0, 1, 1, 0, 0, 0);

	cairo_transform (cr, &matrix);
	
	/* swap width/height */
	tmp = *width;
	*x = 0;
	*y = 0;
	*width = *height;
	*height = tmp;
}
void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
{
    if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
        return;

    cairo_t* cr = context->cr();
    context->save(); 

    RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
        const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4));

    cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);

    // OpenGL keeps the pixels stored bottom up, so we need to flip the image here.
    cairo_matrix_t matrix;
    cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, imageHeight);
    cairo_set_matrix(cr, &matrix);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_surface(cr, imageSurface.get(), 0, 0);
    cairo_fill(cr);
    context->restore();
}
Exemple #27
0
static void
prepare_context_for_layout (cairo_t *cr,
                            gdouble x,
                            gdouble y,
                            PangoLayout *layout)
{
  const PangoMatrix *matrix;

  matrix = pango_context_get_matrix (pango_layout_get_context (layout));

  cairo_move_to (cr, x, y);

  if (matrix)
    {
      cairo_matrix_t cairo_matrix;

      cairo_matrix_init (&cairo_matrix,
                         matrix->xx, matrix->yx,
                         matrix->xy, matrix->yy,
                         matrix->x0, matrix->y0);

      cairo_transform (cr, &cairo_matrix);
    }
}
Exemple #28
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);

        }
}
Exemple #29
0
static void
brush_start_element (GMarkupParseContext  *context,
                     const gchar          *element_name,
                     const gchar         **names,
                     const gchar         **values,
                     gpointer              user_data,
                     GError              **error)
{
        GXPSBrush *brush = (GXPSBrush *)user_data;

        if (strcmp (element_name, "SolidColorBrush") == 0) {
                const gchar *color_str = NULL;
                gint i;

                for (i = 0; names[i] != NULL; i++) {
                        if (strcmp (names[i], "Color") == 0) {
                                color_str = values[i];
                        } else if (strcmp (names[i], "Opacity") == 0) {
                                if (!gxps_value_get_double (values[i], &brush->opacity)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "SolidColorBrush", "Opacity",
                                                          values[i], error);
                                        return;
                                }
                        } else {
                                gxps_parse_error (context,
                                                  brush->ctx->page->priv->source,
                                                  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
                                                  "SolidColorBrush", names[i],
                                                  NULL, error);
                                return;
                        }
                }

                if (!color_str) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                                          "SolidColorBrush", "Color",
                                          NULL, error);
                        return;
                }

                GXPS_DEBUG (g_message ("set_fill_pattern (solid)"));
                if (!gxps_brush_solid_color_parse (color_str, brush->ctx->page->priv->zip,
                                                   brush->opacity, &brush->pattern)) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                          "SolidColorBrush", "Color",
                                          color_str, error);
                        return;
                }
        } else if (strcmp (element_name, "ImageBrush") == 0) {
                GXPSBrushImage *image;
                gchar *image_source = NULL;
                cairo_rectangle_t viewport = { 0, }, viewbox = { 0, };
                cairo_matrix_t matrix;
                cairo_extend_t extend = CAIRO_EXTEND_NONE;
                gint i;

                cairo_matrix_init_identity (&matrix);

                for (i = 0; names[i] != NULL; i++) {
                        if (strcmp (names[i], "ImageSource") == 0) {
                                image_source = gxps_resolve_relative_path (brush->ctx->page->priv->source,
                                                                           values[i]);
                        } else if (strcmp (names[i], "Transform") == 0) {
                                if (!gxps_matrix_parse (values[i], &matrix)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "ImageBrush", "Transform",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "Viewport") == 0) {
                                if (!gxps_box_parse (values[i], &viewport)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "ImageBrush", "Viewport",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ViewportUnits") == 0) {
                        } else if (strcmp (names[i], "Viewbox") == 0) {
                                if (!gxps_box_parse (values[i], &viewbox)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "ImageBrush", "Viewbox",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ViewboxUnits") == 0) {
                        } else if (strcmp (names[i], "TileMode") == 0) {
                                extend = gxps_tile_mode_parse (values[i]);
                        } else if (strcmp (names[i], "Opacity") == 0) {
                                if (!gxps_value_get_double (values[i], &brush->opacity)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "ImageBrush", "Opacity",
                                                          values[i], error);
                                        return;
                                }
                        } else  {
                                gxps_parse_error (context,
                                                  brush->ctx->page->priv->source,
                                                  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
                                                  "ImageBrush", names[i],
                                                  NULL, error);
                                return;
                        }

                }

                if (!image_source) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                                          element_name, "ImageSource",
                                          NULL, error);
                        return;
                }

                /* GXPSBrushImage takes ownership of image_source */
                image = gxps_brush_image_new (brush, image_source, &viewport, &viewbox);
                image->extend = extend;
                image->matrix = matrix;
                g_markup_parse_context_push (context, &brush_image_parser, image);
        } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
                gint           i;
                gdouble        x0, y0, x1, y1;
                cairo_extend_t extend = CAIRO_EXTEND_PAD;
                cairo_matrix_t matrix;

                x0 = y0 = x1 = y1 = -1;
                cairo_matrix_init_identity (&matrix);

                for (i = 0; names[i] != NULL; i++) {
                        if (strcmp (names[i], "MappingMode") == 0) {
                        } else if (strcmp (names[i], "StartPoint") == 0) {
                                if (!gxps_point_parse (values[i], &x0, &y0)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "LinearGradientBrush", "StartPoint",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "EndPoint") == 0) {
                                if (!gxps_point_parse (values[i], &x1, &y1)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "LinearGradientBrush", "EndPoint",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "SpreadMethod") == 0) {
                                extend = gxps_spread_method_parse (values[i]);
                        } else if (strcmp (names[i], "Opacity") == 0) {
                                if (!gxps_value_get_double (values[i], &brush->opacity)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "LinearGradientBrush", "Opacity",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "Transform") == 0) {
                                if (!gxps_matrix_parse (values[i], &matrix)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "LinearGradientBrush", "Transform",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ColorInterpolationMode") == 0) {
                                GXPS_DEBUG (g_debug ("Unsupported %s attribute: ColorInterpolationMode", element_name));
                        } else {
                                gxps_parse_error (context,
                                                  brush->ctx->page->priv->source,
                                                  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
                                                  element_name, names[i],
                                                  NULL, error);
                                return;
                        }
                }

                if (x0 == -1 || y0 == -1 || x1 == -1 || y1 == -1) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                                          element_name,
                                          (x0 == -1 || y0 == -1) ? "StartPoint" : "EndPoint",
                                          NULL, error);
                        return;
                }

                GXPS_DEBUG (g_message ("set_fill_pattern (linear)"));
                brush->pattern = cairo_pattern_create_linear (x0, y0, x1, y1);
                cairo_pattern_set_matrix (brush->pattern, &matrix);
                cairo_pattern_set_extend (brush->pattern, extend);
                g_markup_parse_context_push (context, &brush_gradient_parser, brush);
        } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
                gint           i;
                gdouble        cx0, cy0, r0, cx1, cy1, r1;
                cairo_extend_t extend = CAIRO_EXTEND_PAD;
                cairo_matrix_t matrix;

                cx0 = cy0 = r0 = cx1 = cy1 = r1 = -1;

                cairo_matrix_init_identity (&matrix);

                for (i = 0; names[i] != NULL; i++) {
                        if (strcmp (names[i], "MappingMode") == 0) {
                        } else if (strcmp (names[i], "GradientOrigin") == 0) {
                                if (!gxps_point_parse (values[i], &cx0, &cy0)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "GradientOrigin",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "Center") == 0) {
                                if (!gxps_point_parse (values[i], &cx1, &cy1)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "Center",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "RadiusX") == 0) {
                                if (!gxps_value_get_double (values[i], &r0)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "RadiusX",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "RadiusY") == 0) {
                                if (!gxps_value_get_double (values[i], &r1)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "RadiusY",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "SpreadMethod") == 0) {
                                extend = gxps_spread_method_parse (values[i]);
                        } else if (strcmp (names[i], "Opacity") == 0) {
                                if (!gxps_value_get_double (values[i], &brush->opacity)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "Opacity",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "Transform") == 0) {
                                if (!gxps_matrix_parse (values[i], &matrix)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "RadialGradientBrush", "Transform",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ColorInterpolationMode") == 0) {
                                GXPS_DEBUG (g_debug ("Unsupported %s attribute: ColorInterpolationMode", element_name));
                        } else {
                                gxps_parse_error (context,
                                                  brush->ctx->page->priv->source,
                                                  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
                                                  element_name, names[i],
                                                  NULL, error);
                                return;
                        }
                }

                if (cx0 == -1 || cy0 == -1 || cx1 == -1 || cy1 == -1) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                                          element_name,
                                          (cx0 == -1 || cy0 == -1) ? "GradientOrigin" : "Center",
                                          NULL, error);
                        return;
                }
                if (r0 == -1 || r1 == -1) {
                        gxps_parse_error (context,
                                          brush->ctx->page->priv->source,
                                          G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                                          element_name,
                                          (r0 == -1) ? "RadiusX" : "RadiusY",
                                          NULL, error);
                        return;
                }

                GXPS_DEBUG (g_message ("set_fill_pattern (radial)"));
                brush->pattern = cairo_pattern_create_radial (cx0, cy0, 0, cx1, cy1, r1);
                cairo_pattern_set_matrix (brush->pattern, &matrix);
                cairo_pattern_set_extend (brush->pattern, extend);
                g_markup_parse_context_push (context, &brush_gradient_parser, brush);
        } else if (strcmp (element_name, "VisualBrush") == 0) {
                GXPSBrushVisual *visual;
                GXPSRenderContext *sub_ctx;
                cairo_rectangle_t viewport = { 0, }, viewbox = { 0, };
                cairo_matrix_t matrix;
                cairo_extend_t extend = CAIRO_EXTEND_NONE;
                double width, height;
                gint i;

                cairo_matrix_init_identity (&matrix);

                for (i = 0; names[i] != NULL; i++) {
                        if (strcmp (names[i], "TileMode") == 0) {
                                extend = gxps_tile_mode_parse (values[i]);
                        } else if (strcmp (names[i], "Transform") == 0) {
                                if (!gxps_matrix_parse (values[i], &matrix)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "VisualBrush", "Transform",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "Viewport") == 0) {
                                if (!gxps_box_parse (values[i], &viewport)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "VisualBrush", "Viewport",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ViewportUnits") == 0) {
                        } else if (strcmp (names[i], "Viewbox") == 0) {
                                if (!gxps_box_parse (values[i], &viewbox)) {
                                        gxps_parse_error (context,
                                                          brush->ctx->page->priv->source,
                                                          G_MARKUP_ERROR_INVALID_CONTENT,
                                                          "VisualBrush", "Viewbox",
                                                          values[i], error);
                                        return;
                                }
                        } else if (strcmp (names[i], "ViewboxUnits") == 0) {
                        } else if (strcmp (names[i], "Opacity") == 0) {
                                GXPS_DEBUG (g_debug ("Unsupported %s attribute: Opacity", element_name));
                        } else if (strcmp (names[i], "Visual") == 0) {
                                GXPS_DEBUG (g_debug ("Unsupported %s attribute: Visual", element_name));
                        } else {
                                gxps_parse_error (context,
                                                  brush->ctx->page->priv->source,
                                                  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
                                                  element_name, names[i],
                                                  NULL, error);
                                return;
                        }
                }

                /* TODO: check required values */

                width = gxps_transform_hypot (&matrix, viewport.width, 0);
                height = gxps_transform_hypot (&matrix, 0, viewport.height);

                cairo_save (brush->ctx->cr);
                cairo_rectangle (brush->ctx->cr, 0, 0, width, height);
                cairo_clip (brush->ctx->cr);
                cairo_push_group (brush->ctx->cr);
                cairo_translate (brush->ctx->cr, -viewbox.x, -viewbox.y);
                cairo_scale (brush->ctx->cr, width / viewbox.width, height / viewbox.height);
                visual = gxps_brush_visual_new (brush, &viewport, &viewbox);
                visual->extend = extend;
                cairo_matrix_init (&visual->matrix, viewport.width / width, 0, 0,
                                   viewport.height / height, viewport.x, viewport.y);
                cairo_matrix_multiply (&visual->matrix, &visual->matrix, &matrix);
                cairo_matrix_invert (&visual->matrix);
                sub_ctx = g_slice_new0 (GXPSRenderContext);
                sub_ctx->page = brush->ctx->page;
                sub_ctx->cr = brush->ctx->cr;
                sub_ctx->visual = visual;
                gxps_page_render_parser_push (context, sub_ctx);
        } else {
                gxps_parse_error (context,
                                  brush->ctx->page->priv->source,
                                  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                                  element_name, NULL, NULL, error);
        }
}
Exemple #30
0
/*! \brief Draw a page.
 * \par Function Description
 * Draws the \a page on the Cairo context \a cr, which should have
 * dimensions \a cr_width and \a cr_height.  If the Pango context \a
 * pc is provided, it is used for rendering of text.  The parameter \a
 * is_color controls whether to enable color printing, and \a
 * is_raster should be set if drawing to a raster surface such as an
 * image.
 *
 * \param toplevel A #TOPLEVEL structure.
 * \param page     The #PAGE to be rendered.
 * \param cr       The Cairo context to render to.
 * \param pc       A Pango context for text rendering, or NULL.
 * \param cr_width The width of the drawing area.
 * \param cr_height The height of the drawing area.
 * \param is_color TRUE if drawing should be in color; FALSE otherwise.
 * \param is_raster TRUE if drawing to a raster image surface; FALSE otherwise.
 */
static void
x_print_draw_page (TOPLEVEL *toplevel, PAGE *page,
                   cairo_t *cr, PangoContext *pc,
                   double cr_width, double cr_height,
                   gboolean is_color, gboolean is_raster)
{
  EdaRenderer *renderer;
  cairo_matrix_t mtx;
  GArray *color_map;
  int status, wx_min, wy_min, wx_max, wy_max;
  double w_width, w_height, scale;
  GList *iter;

  /* First, calculate a transformation matrix for the cairo
   * context. We want to center the extents of the page in the
   * available page area. */
  status = world_get_object_glist_bounds (toplevel, s_page_objects (page),
                                          &wx_min, &wy_min, &wx_max, &wy_max);
  /* If there are no printable objects, draw nothing. */
  if (!status) return;

  w_width = wx_max - wx_min;
  w_height = wy_max - wy_min;
  scale = fmin (cr_width / w_width, cr_height / w_height);
  cairo_matrix_init (&mtx,
                     scale, 0,
                     0, -scale,
                     - (wx_min + 0.5*w_width) * scale + 0.5*cr_width,
                     (wy_min + 0.5*w_height) * scale + 0.5*cr_height);

  /* Second, build the color map.  If no color printing is desired,
   * transform the print color map into a black-and-white color map by
   * making the background color transparent and replacing all other
   * enabled colors with solid black. */
  color_map = g_array_sized_new (FALSE, FALSE, sizeof(GedaColor), MAX_COLORS);
  color_map = g_array_append_vals (color_map, print_colors, MAX_COLORS);
  if (!is_color) {
    int i;
    for (i = 0; i < MAX_COLORS; i++) {
      GedaColor *c = &g_array_index (color_map, GedaColor, i);
      if (!c->enabled) continue;

      /* Disable background color & fully-transparent colors */
      if (c->a == 0 || i == BACKGROUND_COLOR) {
        c->enabled = FALSE;
        continue;
      }

      /* Set any remaining colors solid black */
      c->r = 0;
      c->g = 0;
      c->b = 0;
      c->a = ~0;
    }
  }

  /* Thirdly, create and initialise a renderer */
  renderer = EDA_RENDERER (g_object_new (EDA_TYPE_RENDERER,
                                         "cairo-context", cr,
                                         "pango-context", pc,
                                         "color-map", color_map,
                                         "render-flags", is_raster ? EDA_RENDERER_FLAG_HINTING : 0,
                                         NULL));

  /* Finally, actually do drawing */
  cairo_save (cr);
  cairo_transform (cr, &mtx);

  /* Draw background */
  eda_cairo_set_source_color (cr, BACKGROUND_COLOR, color_map);
  cairo_paint (cr);

  /* Draw all objects and cues */
  for (iter = (GList *) s_page_objects (page);
       iter != NULL;
       iter = g_list_next (iter)) {
    eda_renderer_draw (renderer, (OBJECT *) iter->data);
  }
  for (iter = (GList *) s_page_objects (page);
       iter != NULL;
       iter = g_list_next (iter)) {
    eda_renderer_draw_cues (renderer, (OBJECT *) iter->data);
  }

  cairo_restore (cr);

  g_object_unref (renderer);
  g_array_free (color_map, TRUE);
}