* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkprintoperation-private.h"
-#include "gtkalias.h"
+
+
+/**
+ * SECTION:gtkprintcontext
+ * @Short_description: Encapsulates context for drawing pages
+ * @Title: GtkPrintContext
+ *
+ * A GtkPrintContext encapsulates context information that is required when
+ * drawing pages for printing, such as the cairo context and important
+ * parameters like page size and resolution. It also lets you easily
+ * create #PangoLayout and #PangoContext objects that match the font metrics
+ * of the cairo surface.
+ *
+ * GtkPrintContext objects gets passed to the #GtkPrintOperation::begin-print,
+ * #GtkPrintOperation::end-print, #GtkPrintOperation::request-page-setup and
+ * #GtkPrintOperation::draw-page signals on the #GtkPrintOperation.
+ *
+ * <example>
+ * <title>Using GtkPrintContext in a #GtkPrintOperation::draw-page callback</title>
+ * <programlisting>
+ * static void
+ * draw_page (GtkPrintOperation *operation,
+ * GtkPrintContext *context,
+ * int page_nr)
+ * {
+ * cairo_t *cr;
+ * PangoLayout *layout;
+ * PangoFontDescription *desc;
+ *
+ * cr = gtk_print_context_get_cairo_context (context);
+ *
+ * // Draw a red rectangle, as wide as the paper (inside the margins)
+ * cairo_set_source_rgb (cr, 1.0, 0, 0);
+ * cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
+ *
+ * cairo_fill (cr);
+ *
+ * // Draw some lines
+ * cairo_move_to (cr, 20, 10);
+ * cairo_line_to (cr, 40, 20);
+ * cairo_arc (cr, 60, 60, 20, 0, M_PI);
+ * cairo_line_to (cr, 80, 20);
+ *
+ * cairo_set_source_rgb (cr, 0, 0, 0);
+ * cairo_set_line_width (cr, 5);
+ * cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ * cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ *
+ * cairo_stroke (cr);
+ *
+ * // Draw some text
+ * layout = gtk_print_context_create_layout (context);
+ * pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
+ * desc = pango_font_description_from_string ("sans 28");
+ * pango_layout_set_font_description (layout, desc);
+ * pango_font_description_free (desc);
+ *
+ * cairo_move_to (cr, 30, 20);
+ * pango_cairo_layout_path (cr, layout);
+ *
+ * // Font Outline
+ * cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
+ * cairo_set_line_width (cr, 0.5);
+ * cairo_stroke_preserve (cr);
+ *
+ * // Font Fill
+ * cairo_set_source_rgb (cr, 0, 0.0, 1.0);
+ * cairo_fill (cr);
+ *
+ * g_object_unref (layout);
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * Printing support was added in GTK+ 2.10.
+ */
+
typedef struct _GtkPrintContextClass GtkPrintContextClass;
GtkPrintOperation *op;
cairo_t *cr;
GtkPageSetup *page_setup;
- PangoFontMap *fontmap;
+ gdouble surface_dpi_x;
+ gdouble surface_dpi_y;
+
gdouble pixels_per_unit_x;
gdouble pixels_per_unit_y;
+
+ gboolean has_hard_margins;
+ gdouble hard_margin_top;
+ gdouble hard_margin_bottom;
+ gdouble hard_margin_left;
+ gdouble hard_margin_right;
+
};
struct _GtkPrintContextClass
{
GtkPrintContext *context = GTK_PRINT_CONTEXT (object);
- g_object_unref (context->fontmap);
if (context->page_setup)
g_object_unref (context->page_setup);
- cairo_destroy (context->cr);
-
+ if (context->cr)
+ cairo_destroy (context->cr);
G_OBJECT_CLASS (gtk_print_context_parent_class)->finalize (object);
}
GtkPrintContext *
_gtk_print_context_new (GtkPrintOperation *op)
{
- GtkPrintOperationPrivate *priv = op->priv;
GtkPrintContext *context;
context = g_object_new (GTK_TYPE_PRINT_CONTEXT, NULL);
context->op = op;
- context->cr = cairo_create (priv->surface);
+ context->cr = NULL;
+ context->has_hard_margins = FALSE;
+
+ return context;
+}
+
+static PangoFontMap *
+_gtk_print_context_get_fontmap (GtkPrintContext *context)
+{
+ return pango_cairo_font_map_get_default ();
+}
- switch (priv->unit)
+/**
+ * gtk_print_context_set_cairo_context:
+ * @context: a #GtkPrintContext
+ * @cr: the cairo context
+ * @dpi_x: the horizontal resolution to use with @cr
+ * @dpi_y: the vertical resolution to use with @cr
+ *
+ * Sets a new cairo context on a print context.
+ *
+ * This function is intended to be used when implementing
+ * an internal print preview, it is not needed for printing,
+ * since GTK+ itself creates a suitable cairo context in that
+ * case.
+ *
+ * Since: 2.10
+ */
+void
+gtk_print_context_set_cairo_context (GtkPrintContext *context,
+ cairo_t *cr,
+ double dpi_x,
+ double dpi_y)
+{
+ if (context->cr)
+ cairo_destroy (context->cr);
+
+ context->cr = cairo_reference (cr);
+ context->surface_dpi_x = dpi_x;
+ context->surface_dpi_y = dpi_y;
+
+ switch (context->op->priv->unit)
{
default:
- case GTK_UNIT_PIXEL:
+ case GTK_UNIT_NONE:
/* Do nothing, this is the cairo default unit */
context->pixels_per_unit_x = 1.0;
context->pixels_per_unit_y = 1.0;
break;
case GTK_UNIT_POINTS:
- context->pixels_per_unit_x = priv->dpi_x / POINTS_PER_INCH;
- context->pixels_per_unit_y = priv->dpi_y / POINTS_PER_INCH;
+ context->pixels_per_unit_x = dpi_x / POINTS_PER_INCH;
+ context->pixels_per_unit_y = dpi_y / POINTS_PER_INCH;
break;
case GTK_UNIT_INCH:
- context->pixels_per_unit_x = priv->dpi_x;
- context->pixels_per_unit_y = priv->dpi_y;
+ context->pixels_per_unit_x = dpi_x;
+ context->pixels_per_unit_y = dpi_y;
break;
case GTK_UNIT_MM:
- context->pixels_per_unit_x = priv->dpi_x / MM_PER_INCH;
- context->pixels_per_unit_y = priv->dpi_y / MM_PER_INCH;
+ context->pixels_per_unit_x = dpi_x / MM_PER_INCH;
+ context->pixels_per_unit_y = dpi_y / MM_PER_INCH;
break;
}
cairo_scale (context->cr,
context->pixels_per_unit_x,
context->pixels_per_unit_y);
-
- context->fontmap = pango_cairo_font_map_new ();
- /* We use the unit-scaled resolution, as we still want fonts given in points to work */
- pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (context->fontmap),
- priv->dpi_y / context->pixels_per_unit_y);
-
- return context;
}
+
void
_gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context)
{
- GtkPrintOperationPrivate *priv = context->op->priv;
cairo_t *cr = context->cr;
cairo_matrix_t matrix;
GtkPaperSize *paper_size;
paper_size = gtk_page_setup_get_paper_size (context->page_setup);
width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
- width = width * priv->dpi_x / context->pixels_per_unit_x;
+ width = width * context->surface_dpi_x / context->pixels_per_unit_x;
height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
- height = height * priv->dpi_y / context->pixels_per_unit_y;
+ height = height * context->surface_dpi_y / context->pixels_per_unit_y;
switch (gtk_page_setup_get_orientation (context->page_setup))
{
case GTK_PAGE_ORIENTATION_PORTRAIT:
break;
case GTK_PAGE_ORIENTATION_LANDSCAPE:
- cairo_translate (cr, width, 0);
+ cairo_translate (cr, 0, height);
cairo_matrix_init (&matrix,
- 0, 1,
- -1, 0,
- 0, 0);
+ 0, -1,
+ 1, 0,
+ 0, 0);
cairo_transform (cr, &matrix);
break;
case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
cairo_transform (cr, &matrix);
break;
case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
- cairo_translate (cr, 0, height);
+ cairo_translate (cr, width, 0);
cairo_matrix_init (&matrix,
- 0, -1,
- 1, 0,
- 0, 0);
+ 0, 1,
+ -1, 0,
+ 0, 0);
+ cairo_transform (cr, &matrix);
+ break;
+ }
+}
+
+void
+_gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context)
+{
+ cairo_t *cr = context->cr;
+ cairo_matrix_t matrix;
+ gdouble width, height;
+
+ width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
+ width = width * context->surface_dpi_x / context->pixels_per_unit_x;
+ height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
+ height = height * context->surface_dpi_y / context->pixels_per_unit_y;
+
+ switch (gtk_page_setup_get_orientation (context->page_setup))
+ {
+ default:
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ break;
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+ cairo_translate (cr, width, height);
+ cairo_matrix_init (&matrix,
+ -1, 0,
+ 0, -1,
+ 0, 0);
cairo_transform (cr, &matrix);
break;
}
void
_gtk_print_context_translate_into_margin (GtkPrintContext *context)
{
- GtkPrintOperationPrivate *priv;
gdouble left, top;
g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
- priv = context->op->priv;
-
- /* We do it this way to also handle GTK_UNIT_PIXELS */
-
+ /* We do it this way to also handle GTK_UNIT_NONE */
left = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
top = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
cairo_translate (context->cr,
- left * priv->dpi_x / context->pixels_per_unit_x,
- top * priv->dpi_y / context->pixels_per_unit_y);
+ left * context->surface_dpi_x / context->pixels_per_unit_x,
+ top * context->surface_dpi_y / context->pixels_per_unit_y);
}
void
}
/**
- * gtk_print_context_get_cairo:
+ * gtk_print_context_get_cairo_context:
* @context: a #GtkPrintContext
*
* Obtains the cairo context that is associated with the
* #GtkPrintContext.
*
- * Return value: the cairo context of @context
+ * Return value: (transfer none): the cairo context of @context
*
* Since: 2.10
*/
cairo_t *
-gtk_print_context_get_cairo (GtkPrintContext *context)
+gtk_print_context_get_cairo_context (GtkPrintContext *context)
{
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
* Obtains the #GtkPageSetup that determines the page
* dimensions of the #GtkPrintContext.
*
- * Return value: the page setup of @context
+ * Return value: (transfer none): the page setup of @context
*
* Since: 2.10
*/
width = gtk_page_setup_get_page_width (context->page_setup, GTK_UNIT_INCH);
/* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
- return width * priv->dpi_x / context->pixels_per_unit_x;
+ return width * context->surface_dpi_x / context->pixels_per_unit_x;
}
/**
* gtk_print_context_get_height:
* @context: a #GtkPrintContext
*
- * Obtains the width of the #GtkPrintContext, in pixels.
+ * Obtains the height of the #GtkPrintContext, in pixels.
*
* Return value: the height of @context
*
else
height = gtk_page_setup_get_page_height (context->page_setup, GTK_UNIT_INCH);
- /* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
- return height * priv->dpi_y / context->pixels_per_unit_y;
+ /* Really dpi_y? What about landscape? what does dpi_y mean in that case? */
+ return height * context->surface_dpi_y / context->pixels_per_unit_y;
}
/**
{
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
- return context->op->priv->dpi_x;
+ return context->surface_dpi_x;
}
/**
{
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
- return context->op->priv->dpi_y;
+ return context->surface_dpi_y;
+}
+
+/**
+ * gtk_print_context_get_hard_margins:
+ * @context: a #GtkPrintContext
+ * @top: (out): top hardware printer margin
+ * @bottom: (out): bottom hardware printer margin
+ * @left: (out): left hardware printer margin
+ * @right: (out): right hardware printer margin
+ *
+ * Obtains the hardware printer margins of the #GtkPrintContext, in units.
+ *
+ * Return value: %TRUE if the hard margins were retrieved
+ *
+ * Since: 2.20
+ */
+gboolean
+gtk_print_context_get_hard_margins (GtkPrintContext *context,
+ gdouble *top,
+ gdouble *bottom,
+ gdouble *left,
+ gdouble *right)
+{
+ if (context->has_hard_margins)
+ {
+ *top = context->hard_margin_top / context->pixels_per_unit_y;
+ *bottom = context->hard_margin_bottom / context->pixels_per_unit_y;
+ *left = context->hard_margin_left / context->pixels_per_unit_x;
+ *right = context->hard_margin_right / context->pixels_per_unit_x;
+ }
+
+ return context->has_hard_margins;
+}
+
+/**
+ * gtk_print_context_set_hard_margins:
+ * @context: a #GtkPrintContext
+ * @top: top hardware printer margin
+ * @bottom: bottom hardware printer margin
+ * @left: left hardware printer margin
+ * @right: right hardware printer margin
+ *
+ * set the hard margins in pixel coordinates
+ */
+void
+_gtk_print_context_set_hard_margins (GtkPrintContext *context,
+ gdouble top,
+ gdouble bottom,
+ gdouble left,
+ gdouble right)
+{
+ context->hard_margin_top = top;
+ context->hard_margin_bottom = bottom;
+ context->hard_margin_left = left;
+ context->hard_margin_right = right;
+ context->has_hard_margins = TRUE;
}
/**
- * gtk_print_context_get_fontmap:
+ * gtk_print_context_get_pango_fontmap:
* @context: a #GtkPrintContext
*
- * Returns a #PangoFontMap that is suitable for use
+ * Returns a #PangoFontMap that is suitable for use
* with the #GtkPrintContext.
*
- * Return value: the font map of @context
+ * Return value: (transfer none): the font map of @context
*
* Since: 2.10
*/
PangoFontMap *
-gtk_print_context_get_fontmap (GtkPrintContext *context)
+gtk_print_context_get_pango_fontmap (GtkPrintContext *context)
{
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
- return context->fontmap;
+ return _gtk_print_context_get_fontmap (context);
}
/**
- * gtk_print_context_create_context:
- * @context: a #GtkPrintContext
+ * gtk_print_context_create_pango_context:
+ * @context: a #GtkPrintContext
*
* Creates a new #PangoContext that can be used with the
* #GtkPrintContext.
*
- * Return value: a new Pango context for @context
+ * Return value: (transfer full): a new Pango context for @context
*
* Since: 2.10
*/
PangoContext *
-gtk_print_context_create_context (GtkPrintContext *context)
+gtk_print_context_create_pango_context (GtkPrintContext *context)
{
PangoContext *pango_context;
+ cairo_font_options_t *options;
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
- pango_context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (context->fontmap));
+ pango_context = pango_font_map_create_context (_gtk_print_context_get_fontmap (context));
+
+ options = cairo_font_options_create ();
+ cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+ pango_cairo_context_set_font_options (pango_context, options);
+ cairo_font_options_destroy (options);
+ /* We use the unit-scaled resolution, as we still want
+ * fonts given in points to work
+ */
+ pango_cairo_context_set_resolution (pango_context,
+ context->surface_dpi_y / context->pixels_per_unit_y);
return pango_context;
}
/**
- * gtk_print_context_create_layout:
+ * gtk_print_context_create_pango_layout:
* @context: a #GtkPrintContext
*
* Creates a new #PangoLayout that is suitable for use
* with the #GtkPrintContext.
*
- * Return value: a new Pango layout for @context
+ * Return value: (transfer full): a new Pango layout for @context
*
* Since: 2.10
*/
PangoLayout *
-gtk_print_context_create_layout (GtkPrintContext *context)
+gtk_print_context_create_pango_layout (GtkPrintContext *context)
{
PangoContext *pango_context;
PangoLayout *layout;
g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
- pango_context = gtk_print_context_create_context (context);
+ pango_context = gtk_print_context_create_pango_context (context);
layout = pango_layout_new (pango_context);
pango_cairo_update_context (context->cr, pango_context);
return layout;
}
-
-
-#define __GTK_PRINT_CONTEXT_C__
-#include "gtkaliasdef.c"