⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pixbuf-render.c

📁 This GTK+ version 2.12.3. GTK+ is a multi-platform toolkit for creating graphical user interfaces.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* GTK+ Pixbuf Engine * Copyright (C) 1998-2000 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. * * Written by Owen Taylor <otaylor@redhat.com>, based on code by * Carsten Haitzler <raster@rasterman.com> */#include <string.h>#include "pixbuf.h"#include <gdk-pixbuf/gdk-pixbuf.h>static GCache *pixbuf_cache = NULL;static GdkPixbuf *bilinear_gradient (GdkPixbuf    *src,		   gint          src_x,		   gint          src_y,		   gint          width,		   gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guint src_rowstride = gdk_pixbuf_get_rowstride (src);  guchar *src_pixels = gdk_pixbuf_get_pixels (src);  guchar *p1, *p2, *p3, *p4;  guint dest_rowstride;  guchar *dest_pixels;  GdkPixbuf *result;  int i, j, k;  if (src_x == 0 || src_y == 0)    {      g_warning ("invalid source position for bilinear gradient\n");      return NULL;    }  p1 = src_pixels + (src_y - 1) * src_rowstride + (src_x - 1) * n_channels;  p2 = p1 + n_channels;  p3 = src_pixels + src_y * src_rowstride + (src_x - 1) * n_channels;  p4 = p3 + n_channels;  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);  for (i = 0; i < height; i++)    {      guchar *p = dest_pixels + dest_rowstride *i;      guint v[4];      gint dv[4];      for (k = 0; k < n_channels; k++)	{	  guint start = ((height - i) * p1[k] + (1 + i) * p3[k]) / (height + 1);	  guint end = ((height -  i) * p2[k] + (1 + i) * p4[k]) / (height + 1);	  dv[k] = (((gint)end - (gint)start) << 16) / (width + 1);	  v[k] = (start << 16) + dv[k] + 0x8000;	}      for (j = width; j; j--)	{	  for (k = 0; k < n_channels; k++)	    {	      *(p++) = v[k] >> 16;	      v[k] += dv[k];	    }	}    }  return result;}static GdkPixbuf *horizontal_gradient (GdkPixbuf    *src,		     gint          src_x,		     gint          src_y,		     gint          width,		     gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guint src_rowstride = gdk_pixbuf_get_rowstride (src);  guchar *src_pixels = gdk_pixbuf_get_pixels (src);  guint dest_rowstride;  guchar *dest_pixels;  GdkPixbuf *result;  int i, j, k;  if (src_x == 0)    {      g_warning ("invalid source position for horizontal gradient\n");      return NULL;    }  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);  for (i = 0; i < height; i++)    {      guchar *p = dest_pixels + dest_rowstride *i;      guchar *p1 = src_pixels + (src_y + i) * src_rowstride + (src_x - 1) * n_channels;      guchar *p2 = p1 + n_channels;      guint v[4];      gint dv[4];      for (k = 0; k < n_channels; k++)	{	  dv[k] = (((gint)p2[k] - (gint)p1[k]) << 16) / (width + 1);	  v[k] = (p1[k] << 16) + dv[k] + 0x8000;	}            for (j = width; j; j--)	{	  for (k = 0; k < n_channels; k++)	    {	      *(p++) = v[k] >> 16;	      v[k] += dv[k];	    }	}    }  return result;}static GdkPixbuf *vertical_gradient (GdkPixbuf    *src,		   gint          src_x,		   gint          src_y,		   gint          width,		   gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guint src_rowstride = gdk_pixbuf_get_rowstride (src);  guchar *src_pixels = gdk_pixbuf_get_pixels (src);  guchar *top_pixels, *bottom_pixels;  guint dest_rowstride;  guchar *dest_pixels;  GdkPixbuf *result;  int i, j;  if (src_y == 0)    {      g_warning ("invalid source position for vertical gradient\n");      return NULL;    }  top_pixels = src_pixels + (src_y - 1) * src_rowstride + (src_x) * n_channels;  bottom_pixels = top_pixels + src_rowstride;  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);  for (i = 0; i < height; i++)    {      guchar *p = dest_pixels + dest_rowstride *i;      guchar *p1 = top_pixels;      guchar *p2 = bottom_pixels;      for (j = width * n_channels; j; j--)	*(p++) = ((height - i) * *(p1++) + (1 + i) * *(p2++)) / (height + 1);    }  return result;}static GdkPixbuf *replicate_single (GdkPixbuf    *src,		  gint          src_x,		  gint          src_y,		  gint          width,		  gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guchar *pixels = (gdk_pixbuf_get_pixels (src) +		    src_y * gdk_pixbuf_get_rowstride (src) +		    src_x * n_channels);  guchar r = *(pixels++);  guchar g = *(pixels++);  guchar b = *(pixels++);  guint dest_rowstride;  guchar *dest_pixels;  guchar a = 0;  GdkPixbuf *result;  int i, j;  if (n_channels == 4)    a = *(pixels++);  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);    for (i = 0; i < height; i++)    {      guchar *p = dest_pixels + dest_rowstride *i;      for (j = 0; j < width; j++)	{	  *(p++) = r;	  *(p++) = g;	  *(p++) = b;	  if (n_channels == 4)	    *(p++) = a;	}    }  return result;}static GdkPixbuf *replicate_rows (GdkPixbuf    *src,		gint          src_x,		gint          src_y,		gint          width,		gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guint src_rowstride = gdk_pixbuf_get_rowstride (src);  guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels);  guchar *dest_pixels;  GdkPixbuf *result;  guint dest_rowstride;  int i;  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);  for (i = 0; i < height; i++)    memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width);  return result;}static GdkPixbuf *replicate_cols (GdkPixbuf    *src,		gint          src_x,		gint          src_y,		gint          width,		gint          height){  guint n_channels = gdk_pixbuf_get_n_channels (src);  guint src_rowstride = gdk_pixbuf_get_rowstride (src);  guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels);  guchar *dest_pixels;  GdkPixbuf *result;  guint dest_rowstride;  int i, j;  result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,			   width, height);  dest_rowstride = gdk_pixbuf_get_rowstride (result);  dest_pixels = gdk_pixbuf_get_pixels (result);  for (i = 0; i < height; i++)    {      guchar *p = dest_pixels + dest_rowstride * i;      guchar *q = pixels + src_rowstride * i;      guchar r = *(q++);      guchar g = *(q++);      guchar b = *(q++);      guchar a = 0;            if (n_channels == 4)	a = *(q++);      for (j = 0; j < width; j++)	{	  *(p++) = r;	  *(p++) = g;	  *(p++) = b;	  if (n_channels == 4)	    *(p++) = a;	}    }  return result;}/* Scale the rectangle (src_x, src_y, src_width, src_height) * onto the rectangle (dest_x, dest_y, dest_width, dest_height) * of the destination, clip by clip_rect and render */static voidpixbuf_render (GdkPixbuf    *src,	       guint         hints,	       GdkWindow    *window,	       GdkBitmap    *mask,	       GdkRectangle *clip_rect,	       gint          src_x,	       gint          src_y,	       gint          src_width,	       gint          src_height,	       gint          dest_x,	       gint          dest_y,	       gint          dest_width,	       gint          dest_height){  GdkPixbuf *tmp_pixbuf = NULL;  GdkRectangle rect;  int x_offset, y_offset;  gboolean has_alpha = gdk_pixbuf_get_has_alpha (src);  gint src_rowstride = gdk_pixbuf_get_rowstride (src);  gint src_n_channels = gdk_pixbuf_get_n_channels (src);  if (dest_width <= 0 || dest_height <= 0)    return;  rect.x = dest_x;  rect.y = dest_y;  rect.width = dest_width;  rect.height = dest_height;  if (hints & THEME_MISSING)    return;  /* FIXME: Because we use the mask to shape windows, we don't use   * clip_rect to clip what we draw to the mask, only to clip   * what we actually draw. But this leads to the horrible ineffiency   * of scale the whole image to get a little bit of it.   */  if (!mask && clip_rect)    {      if (!gdk_rectangle_intersect (clip_rect, &rect, &rect))	return;    }  if (dest_width == src_width && dest_height == src_height)    {      tmp_pixbuf = g_object_ref (src);      x_offset = src_x + rect.x - dest_x;      y_offset = src_y + rect.y - dest_y;    }  else if (src_width == 0 && src_height == 0)    {      tmp_pixbuf = bilinear_gradient (src, src_x, src_y, dest_width, dest_height);                  x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if (src_width == 0 && dest_height == src_height)    {      tmp_pixbuf = horizontal_gradient (src, src_x, src_y, dest_width, dest_height);                  x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if (src_height == 0 && dest_width == src_width)    {      tmp_pixbuf = vertical_gradient (src, src_x, src_y, dest_width, dest_height);            x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if ((hints & THEME_CONSTANT_COLS) && (hints & THEME_CONSTANT_ROWS))    {      tmp_pixbuf = replicate_single (src, src_x, src_y, dest_width, dest_height);      x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if (dest_width == src_width && (hints & THEME_CONSTANT_COLS))    {      tmp_pixbuf = replicate_rows (src, src_x, src_y, dest_width, dest_height);      x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if (dest_height == src_height && (hints & THEME_CONSTANT_ROWS))    {      tmp_pixbuf = replicate_cols (src, src_x, src_y, dest_width, dest_height);      x_offset = rect.x - dest_x;      y_offset = rect.y - dest_y;    }  else if (src_width > 0 && src_height > 0)    {      double x_scale = (double)dest_width / src_width;      double y_scale = (double)dest_height / src_height;      guchar *pixels;      GdkPixbuf *partial_src;            pixels = (gdk_pixbuf_get_pixels (src)		+ src_y * src_rowstride		+ src_x * src_n_channels);      partial_src = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB,					      has_alpha,					      8, src_width, src_height,					      src_rowstride,					      NULL, NULL);						  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -