/* Based on GTK code by the Chromium Authors. The original header for that code * continues below */ /* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 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. */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include #include #include #include #include #include "GdkSkia.h" static GdkGC *gdk_skia_create_gc (GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask mask); static void gdk_skia_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height); static void gdk_skia_draw_arc (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height, gint angle1, gint angle2); static void gdk_skia_draw_polygon (GdkDrawable *drawable, GdkGC *gc, gboolean filled, GdkPoint *points, gint npoints); static void gdk_skia_draw_text (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length); static void gdk_skia_draw_text_wc (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const GdkWChar *text, gint text_length); static void gdk_skia_draw_drawable (GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height); static void gdk_skia_draw_points (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints); static void gdk_skia_draw_segments (GdkDrawable *drawable, GdkGC *gc, GdkSegment *segs, gint nsegs); static void gdk_skia_draw_lines (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints); static void gdk_skia_draw_glyphs (GdkDrawable *drawable, GdkGC *gc, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs); static void gdk_skia_draw_glyphs_transformed (GdkDrawable *drawable, GdkGC *gc, PangoMatrix *matrix, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs); static void gdk_skia_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height); static void gdk_skia_draw_pixbuf (GdkDrawable *drawable, GdkGC *gc, GdkPixbuf *pixbuf, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height, GdkRgbDither dither, gint x_dither, gint y_dither); static void gdk_skia_draw_trapezoids (GdkDrawable *drawable, GdkGC *gc, GdkTrapezoid *trapezoids, gint n_trapezoids); static void gdk_skia_real_get_size (GdkDrawable *drawable, gint *width, gint *height); static GdkImage* gdk_skia_copy_to_image (GdkDrawable *drawable, GdkImage *image, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height); static cairo_surface_t *gdk_skia_ref_cairo_surface (GdkDrawable *drawable); static GdkVisual* gdk_skia_real_get_visual (GdkDrawable *drawable); static gint gdk_skia_real_get_depth (GdkDrawable *drawable); static void gdk_skia_real_set_colormap (GdkDrawable *drawable, GdkColormap *cmap); static GdkColormap* gdk_skia_real_get_colormap (GdkDrawable *drawable); static GdkScreen* gdk_skia_real_get_screen (GdkDrawable *drawable); static void gdk_skia_init (GdkSkiaObject *skia); static void gdk_skia_class_init (GdkSkiaObjectClass *klass); static void gdk_skia_finalize (GObject *object); static gpointer parent_class = NULL; // ----------------------------------------------------------------------------- // Usually GDK code is C code. However, since we are interfacing to a C++ // library, we must compile in C++ mode to parse its headers etc. Thankfully, // these are the only non-static symbol in the file so we can just wrap them in // an extern decl to disable name mangling and everything should be happy. // ----------------------------------------------------------------------------- extern "C" { GType gdk_skia_get_type (void) { static GType object_type = 0; if (!object_type) object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE, "GdkSkia", sizeof (GdkSkiaObjectClass), (GClassInitFunc) gdk_skia_class_init, sizeof (GdkSkiaObject), (GInstanceInitFunc) gdk_skia_init, (GTypeFlags) 0); return object_type; } GdkSkia* gdk_skia_new(SkCanvas *canvas) { GdkSkia *skia = GDK_SKIA(g_object_new (GDK_TYPE_SKIA, NULL)); reinterpret_cast(skia)->canvas = canvas; return skia; } } // extern "C" static void gdk_skia_init (GdkSkiaObject *skia) { /* 0 initialization is fine for us */ } static void gdk_skia_class_init (GdkSkiaObjectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gdk_skia_finalize; drawable_class->create_gc = gdk_skia_create_gc; drawable_class->draw_rectangle = gdk_skia_draw_rectangle; drawable_class->draw_arc = gdk_skia_draw_arc; drawable_class->draw_polygon = gdk_skia_draw_polygon; drawable_class->draw_text = gdk_skia_draw_text; drawable_class->draw_text_wc = gdk_skia_draw_text_wc; drawable_class->draw_drawable = gdk_skia_draw_drawable; drawable_class->draw_points = gdk_skia_draw_points; drawable_class->draw_segments = gdk_skia_draw_segments; drawable_class->draw_lines = gdk_skia_draw_lines; drawable_class->draw_glyphs = gdk_skia_draw_glyphs; drawable_class->draw_glyphs_transformed = gdk_skia_draw_glyphs_transformed; drawable_class->draw_image = gdk_skia_draw_image; drawable_class->draw_pixbuf = gdk_skia_draw_pixbuf; drawable_class->draw_trapezoids = gdk_skia_draw_trapezoids; drawable_class->get_depth = gdk_skia_real_get_depth; drawable_class->get_screen = gdk_skia_real_get_screen; drawable_class->get_size = gdk_skia_real_get_size; drawable_class->set_colormap = gdk_skia_real_set_colormap; drawable_class->get_colormap = gdk_skia_real_get_colormap; drawable_class->get_visual = gdk_skia_real_get_visual; drawable_class->_copy_to_image = gdk_skia_copy_to_image; drawable_class->ref_cairo_surface = gdk_skia_ref_cairo_surface; } static void gdk_skia_finalize (GObject *object) { GdkSkiaObject *const skia = (GdkSkiaObject *) object; if (skia->surface) cairo_surface_destroy(skia->surface); G_OBJECT_CLASS (parent_class)->finalize(object); } #define NOTIMPLEMENTED fprintf(stderr, "GDK Skia not implemented: %s\n", __PRETTY_FUNCTION__) static GdkGC * gdk_skia_create_gc(GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask mask) { NOTIMPLEMENTED; return NULL; } static void gc_set_paint(GdkGC *gc, SkPaint *paint) { GdkGCValues values; gdk_gc_get_values(gc, &values); paint->setARGB(255, values.foreground.pixel >> 16, values.foreground.pixel >> 8, values.foreground.pixel); paint->setStrokeWidth(values.line_width); } static void gdk_skia_draw_rectangle(GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height) { GdkSkiaObject *skia = (GdkSkiaObject *) drawable; SkPaint paint; gc_set_paint(gc, &paint); if (filled) { paint.setStyle(SkPaint::kFill_Style); } else { paint.setStyle(SkPaint::kStroke_Style); } SkRect rect; rect.set(x, y, x + width, y + height); skia->canvas->drawRect(rect, paint); } static void gdk_skia_draw_arc(GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height, gint angle1, gint angle2) { NOTIMPLEMENTED; } static void gdk_skia_draw_polygon(GdkDrawable *drawable, GdkGC *gc, gboolean filled, GdkPoint *points, gint npoints) { NOTIMPLEMENTED; } static void gdk_skia_draw_text(GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length) { NOTIMPLEMENTED; } static void gdk_skia_draw_text_wc(GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const GdkWChar *text, gint text_length) { NOTIMPLEMENTED; } static void gdk_skia_draw_drawable(GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height) { NOTIMPLEMENTED; } static void gdk_skia_draw_points(GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints) { NOTIMPLEMENTED; } static void gdk_skia_draw_segments(GdkDrawable *drawable, GdkGC *gc, GdkSegment *segs, gint nsegs) { GdkSkiaObject *skia = (GdkSkiaObject *) drawable; GdkGCValues values; SkPaint paint; int nskip = 1; gc_set_paint(gc, &paint); gdk_gc_get_values(gc, &values); // TODO(jhawkins): how to set line width in skia? // GDK_LINE_ON_OFF_DASH only renders the even segments if (values.line_style == GDK_LINE_ON_OFF_DASH) nskip++; for (int i = 0; i < nsegs; i += nskip) { // TODO(jhawkins): GDK_LINE_DOUBLE_DASH skia->canvas->drawLine(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2, paint); } } static void gdk_skia_draw_lines(GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints) { NOTIMPLEMENTED; } static void gdk_skia_draw_glyphs(GdkDrawable *drawable, GdkGC *gc, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs) { NOTIMPLEMENTED; } static void gdk_skia_draw_glyphs_transformed(GdkDrawable *drawable, GdkGC *gc, PangoMatrix *matrix, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs) { NOTIMPLEMENTED; } static void gdk_skia_draw_image(GdkDrawable *drawable, GdkGC *gc, GdkImage *image, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height) { NOTIMPLEMENTED; } static void gdk_skia_draw_pixbuf(GdkDrawable *drawable, GdkGC *gc, GdkPixbuf *pixbuf, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height, GdkRgbDither dither, gint x_dither, gint y_dither) { NOTIMPLEMENTED; } static void gdk_skia_draw_trapezoids(GdkDrawable *drawable, GdkGC *gc, GdkTrapezoid *trapezoids, gint n_trapezoids) { NOTIMPLEMENTED; } static void gdk_skia_real_get_size(GdkDrawable *drawable, gint *width, gint *height) { GdkSkiaObject *const skia = (GdkSkiaObject *) drawable; SkDevice *const dev = skia->canvas->getDevice(); *width = dev->width(); *height = dev->height(); } static GdkImage* gdk_skia_copy_to_image(GdkDrawable *drawable, GdkImage *image, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height) { NOTIMPLEMENTED; return NULL; } static cairo_surface_t * gdk_skia_ref_cairo_surface(GdkDrawable *drawable) { GdkSkiaObject *const skia = (GdkSkiaObject *) drawable; if (!skia->surface) { SkDevice *const dev = skia->canvas->getDevice(); const SkBitmap *const bm = &dev->accessBitmap(true); skia->surface = cairo_image_surface_create_for_data ((unsigned char *) bm->getPixels(), CAIRO_FORMAT_ARGB32, dev->width(), dev->height(), bm->rowBytes()); } SkMatrix matrix = skia->canvas->getTotalMatrix(); int x_shift = SkScalarRound(matrix.getTranslateX()); int y_shift = SkScalarRound(matrix.getTranslateY()); cairo_surface_set_device_offset(skia->surface, x_shift, y_shift); return cairo_surface_reference(skia->surface); } static GdkVisual* gdk_skia_real_get_visual(GdkDrawable *drawable) { NOTIMPLEMENTED; return NULL; } static gint gdk_skia_real_get_depth(GdkDrawable *drawable) { GdkSkiaObject *skia = (GdkSkiaObject *) drawable; const SkBitmap::Config config = skia->canvas->getDevice()->config(); switch (config) { case SkBitmap::kARGB_8888_Config: return 24; default: // NOTREACHED *reinterpret_cast(NULL) = 0; return 0; } } static void gdk_skia_real_set_colormap(GdkDrawable *drawable, GdkColormap *cmap) { NOTIMPLEMENTED; } static GdkColormap* gdk_skia_real_get_colormap(GdkDrawable *drawable) { NOTIMPLEMENTED; return NULL; } static GdkScreen* gdk_skia_real_get_screen(GdkDrawable *drawable) { NOTIMPLEMENTED; return NULL; }