test_output_device.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: test_output_device.cpp
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-pdf.
00007  *
00008  * uds-plugin-pdf is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-pdf is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <gdk/gdktypes.h>
00030 #include "test_output_device.h"
00031 
00032 namespace test
00033 {
00034 
00035 OutputDevice::OutputDevice()
00036 : ctx()
00037 , shared_image(0)
00038 , color_dep(MONO_COLOR_DEPTH)
00039 , xor_gc(0)
00040 {
00041 }
00042 
00043 OutputDevice::~OutputDevice(void)
00044 {
00045     if (shared_image)
00046     {
00047         g_object_unref(shared_image);
00048     }
00049 
00050     if (xor_gc)
00051     {
00052         g_object_unref(xor_gc);
00053     }
00054 }
00055 
00056 void OutputDevice::map(OutputDeviceContext &context)
00057 {
00058     ctx.widget = context.widget;
00059     ctx.gc     = context.gc;
00060 
00061     if (xor_gc)
00062     {
00063         g_object_unref(xor_gc);
00064     }
00065 
00066     xor_gc = gdk_gc_new(ctx.widget->window);
00067 
00068     gdk_gc_set_function(xor_gc, GDK_XOR);
00069 
00070     GdkColor color = {0xffffffff, 0xffff, 0xffff, 0xffff};
00071 
00072     gdk_gc_set_foreground(xor_gc, &color);
00073 }
00074 
00075 void OutputDevice::update_shared_image(GtkWidget * widget)
00076 {
00077     gint width = 0, height = 0;
00078     
00079     ctx.widget = widget;
00080 
00081     //Retrieve the size of widget.
00082     gdk_drawable_get_size(widget->window, &width, &height);
00083 
00084     update_shared_image(width, height);
00085 }
00086 
00087 void OutputDevice::update_shared_image(int width, int height)
00088 {
00089     if (shared_image)
00090     {
00091         if (width == shared_image->width && height == shared_image->height)
00092         {
00093             return;
00094         }
00095         g_object_unref(shared_image);
00096         shared_image = 0;
00097     }
00098 
00099     GdkVisual * visual = gdk_drawable_get_visual(ctx.widget->window);
00100     
00101     //Create a gdk image for drawing.
00102     shared_image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
00103 
00104 }
00105 
00106 void OutputDevice::clear_background(const int color, bool flush)
00107 {
00108     update_shared_image(ctx.widget);
00109 
00110     // clear the image now
00111     unsigned char *p = (unsigned char *)shared_image->mem;
00112     memset(p, color, shared_image->height * shared_image->bpl);
00113 
00114     // draw the background immediately if necessary
00115     if (flush)
00116     {
00117         gdk_draw_image(ctx.widget->window, ctx.gc, shared_image, 0, 0, 
00118             ctx.widget->allocation.x, ctx.widget->allocation.y, 
00119             ctx.widget->allocation.width, ctx.widget->allocation.height); 
00120     }
00121 }
00122 
00123 void OutputDevice::invalidate_rectangle(const GdkRectangle& r)
00124 {
00125     GdkRectangle rect = r;
00126     gdk_window_invalidate_rect(ctx.widget->window, &rect, TRUE);
00127 }
00128 
00129 void OutputDevice::draw_line(int x1, int y1, int x2, int y2)
00130 {
00131     gdk_draw_line(ctx.widget->window, ctx.gc, x1, y1, x2, y2);
00132 }
00133 
00134 void OutputDevice::draw_highlight_rectangle(const GdkRectangle &rect)
00135 {
00136     gdk_draw_rectangle(ctx.widget->window, xor_gc, TRUE, rect.x, rect.y
00137        , rect.width, rect.height);
00138 }
00139 
00140 /// copy src (0, 0) - (width, height) to shared_image(xDest, yDest) - (xDest + width, yDest + height)
00141 /// copy data from shared_image to X server.
00142 void OutputDevice::draw_image(const unsigned char *src,
00143                               int width,
00144                               int height,
00145                               int row_stride,
00146                               int xDest,
00147                               int yDest)
00148 {
00149     // check at first, should also check xDest and yDest.
00150     if (src == 0 || width <= 0 || height <= 0) 
00151     {
00152         return;
00153     }
00154     
00155     //Only cover the situation that global color depth is "8" and 
00156     //output device's color depth is "32"
00157     update_shared_image(width, height);
00158     
00159     unsigned char *dst = (unsigned char *)shared_image->mem +
00160           (shared_image->bpl * yDest + xDest);
00161 
00162     bool transform_result = false;
00163 
00164     switch(shared_image->bits_per_pixel)
00165     {
00166     case RGB_COLOR_DEPTH:
00167         {
00168             switch(color_dep)
00169             {
00170             case RGB_COLOR_DEPTH:
00171                 
00172                 transform_result = transform_bitmap_with_same_depth(src, dst,
00173                     width, height, row_stride);
00174 
00175                 break;
00176             case ARGB_COLOR_DEPTH:
00177                 
00178                 //Print "Unsupport" message
00179                 transform_result = transform_bitmap_ARGB_to_RGB(src, dst,
00180                     width, height, row_stride);
00181                 
00182                 break;
00183             case MONO_COLOR_DEPTH:
00184 
00185                 transform_result = transform_bitmap_MONO_to_RGB(src, dst,
00186                     width, height, row_stride);
00187                 
00188                 break;
00189             default:
00190                 
00191                 //Print "Unsupport" message
00192                 
00193                 break;
00194             }
00195             break;
00196         }
00197     case ARGB_COLOR_DEPTH:
00198         {
00199             switch(color_dep)
00200             {
00201             case RGB_COLOR_DEPTH:
00202                 
00203                 transform_result = transform_bitmap_RGB_to_ARGB(src, dst,
00204                     width, height, row_stride);
00205                 
00206                 break;
00207             case ARGB_COLOR_DEPTH:
00208 
00209                 transform_result = transform_bitmap_with_same_depth(src, dst,
00210                     width, height, row_stride);
00211                 
00212                 break;
00213             case MONO_COLOR_DEPTH:
00214                 
00215                 transform_result = transform_bitmap_MONO_to_ARGB(src, dst,
00216                     width, height, row_stride);
00217                 
00218                 break;
00219             default:
00220 
00221                 //Print "Unsupport" message
00222                 
00223                 break;
00224             }
00225             break;
00226         }
00227     case MONO_COLOR_DEPTH:
00228         {
00229             switch(color_dep)
00230             {
00231             case RGB_COLOR_DEPTH:
00232 
00233                 transform_result = transform_bitmap_RGB_to_MONO(src, dst,
00234                     width, height, row_stride);
00235                 
00236                 break;
00237             case ARGB_COLOR_DEPTH:
00238 
00239                 transform_result = transform_bitmap_ARGB_to_MONO(src, dst,
00240                     width, height, row_stride);
00241                 
00242                 break;
00243             case MONO_COLOR_DEPTH:
00244                 
00245                 transform_result = transform_bitmap_with_same_depth(src, dst,
00246                     width, height, row_stride);
00247                 
00248                 break;
00249             default:
00250                 //Print "Unsupport" message
00251                 break;
00252             }
00253             break;
00254         }
00255     }
00256 
00257     // copy the buffer to gtk widget drawable. use the shared memory automatically.
00258     // make sure the #ifdef USE_SHM is ture.
00259     if (transform_result)
00260     {
00261         gdk_draw_image(ctx.widget->window, ctx.gc, shared_image, 0, 0, 
00262                        xDest, yDest, width, height);    
00263     }
00264 }
00265 
00266 
00267 /// Steps:
00268 /// 1. copy data from src to image buffer with transform.
00269 /// 2. draw the image on the widget.
00270 /// Caller should call clearBackground at first to update the image.
00271 /// Maybe we should update image here. TODO.
00272 void OutputDevice::draw_image_with_transform(const unsigned char *src, 
00273                                              int width, 
00274                                              int height,
00275                                              int row_stride,
00276                                              int xDest, 
00277                                              int yDest,
00278                                              int transform)
00279 {
00280     // copy data to gdkImage, check at first.
00281     if (src == 0 || width <= 0 || height <= 0) 
00282     {
00283         return;
00284     }        
00285 
00286     unsigned char * dst = 0;
00287 
00288     if (transform == PLUGIN_ORIENTATION_LANDSCAPE)
00289     {
00290         update_shared_image(height, width);     
00291     }
00292     else
00293     {
00294         update_shared_image(width, height);
00295     }
00296     
00297     dst = (unsigned char *)shared_image->mem +
00298           (shared_image->bpl * yDest + xDest);
00299 
00300     bool transform_result = false;
00301     
00302     switch(shared_image->bits_per_pixel)
00303     {
00304     case RGB_COLOR_DEPTH:
00305         {
00306             switch(color_dep)
00307             {
00308             case RGB_COLOR_DEPTH:
00309                 
00310                 transform_result = transform_bitmap_with_same_depth(src, dst,
00311                     width, height, row_stride, transform);
00312 
00313                 break;
00314             case ARGB_COLOR_DEPTH:
00315                 
00316                 //Print "Unsupport" message
00317                 
00318                 break;
00319             case MONO_COLOR_DEPTH:
00320 
00321                 transform_result = transform_bitmap_MONO_to_RGB(src, dst,
00322                     width, height, row_stride, transform);
00323                 
00324                 break;
00325             default:
00326                 
00327                 //Print "Unsupport" message
00328                 
00329                 break;
00330             }
00331             break;
00332         }
00333     case ARGB_COLOR_DEPTH:
00334         {
00335             switch(color_dep)
00336             {
00337             case RGB_COLOR_DEPTH:
00338                 
00339                 transform_result = transform_bitmap_RGB_to_ARGB(src, dst,
00340                     width, height, row_stride, transform);
00341                 
00342                 break;
00343             case ARGB_COLOR_DEPTH:
00344 
00345                 transform_result = transform_bitmap_with_same_depth(src, dst,
00346                     width, height, row_stride, transform);
00347                 
00348                 break;
00349             case MONO_COLOR_DEPTH:
00350                 
00351                 transform_result = transform_bitmap_MONO_to_ARGB(src, dst,
00352                     width, height, row_stride, transform);
00353                 
00354                 break;
00355             default:
00356 
00357                 //Print "Unsupport" message
00358                 
00359                 break;
00360             }
00361             break;
00362         }
00363     case MONO_COLOR_DEPTH:
00364         {
00365             switch(color_dep)
00366             {
00367             case RGB_COLOR_DEPTH:
00368 
00369                 transform_result = transform_bitmap_RGB_to_MONO(src, dst,
00370                     width, height, row_stride, transform);
00371                 
00372                 break;
00373             case ARGB_COLOR_DEPTH:
00374 
00375                 transform_result = transform_bitmap_ARGB_to_MONO(src, dst,
00376                     width, height, row_stride, transform);
00377                 
00378                 break;
00379             case MONO_COLOR_DEPTH:
00380                 
00381                 transform_result = transform_bitmap_with_same_depth(src, dst,
00382                     width, height, row_stride, transform);
00383                 
00384                 break;
00385             default:
00386                 //Print "Unsupport" message
00387                 break;
00388             }
00389             break;
00390         }
00391     }
00392 
00393     if (transform_result)
00394     {
00395         gdk_draw_image(ctx.widget->window, ctx.gc, shared_image, 0, 0, 
00396                        xDest, yDest, height, width);
00397     }
00398 }
00399 
00400 // Transform the bitmap with the same color depth
00401 bool OutputDevice::transform_bitmap_with_same_depth(const unsigned char *src,
00402                                                     unsigned char *dst,
00403                                                     int width,
00404                                                     int height, 
00405                                                     int row_stride,
00406                                                     int transform)
00407 {
00408     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00409     {
00410         for(int h = 0; h < height; ++h)
00411         {
00412             memcpy(dst, src, row_stride);
00413             dst += row_stride;
00414             src += row_stride;
00415         }
00416     }
00417     else
00418     {
00419         for(int h = 0; h < height; ++h)
00420         {
00421             const unsigned char * s = src;
00422             unsigned char * d = dst;
00423             for(int w = 0; w < width; ++w)
00424             {
00425                 *d = *s++; 
00426                 d += height;
00427             }
00428             src += row_stride;
00429             dst += height;
00430         }
00431     }
00432     return true;
00433 }
00434 
00435 /// Transform the bitmap from 24-depth to 32-depth
00436 bool OutputDevice::transform_bitmap_RGB_to_ARGB(const unsigned char *src,
00437                                       unsigned char *dst,
00438                                       int width,
00439                                       int height, 
00440                                       int row_stride,
00441                                       int transform)
00442 {
00443     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00444     {
00445         for(int h = 0; h < height; ++h)
00446         {
00447             unsigned char * d = dst;
00448             const unsigned char* s = src;
00449             for(int w = 0; w < width; ++w)
00450             {
00451                 //Set default value to alpha channel
00452                 s += 2;
00453                 *d++ = *s--; *d++ = *s--; *d++ = *s;
00454                 *d++ = DEFAULT_ALPHA_VALUE;
00455                 s += 3;
00456                 
00457             }
00458             src += row_stride;
00459             dst += (width * 4);
00460         }
00461     }
00462     else
00463     {
00464         int dst_heihgt = (height-1) * 4;
00465         for(int h = 0; h < height; ++h)
00466         {
00467             const unsigned char * s = src;
00468             unsigned char * d = dst;
00469             for(int w = 0; w < width; ++w)
00470             {
00471                 //Set value of alpha channel
00472                 *d++ = DEFAULT_ALPHA_VALUE;
00473                         
00474                 //Set value of R, G, B
00475                 for(int i = 0; i < 3; ++i)
00476                 {
00477                     *d++ = *s++;
00478                 }
00479                 d += dst_heihgt;
00480             }
00481             src += row_stride;
00482             dst += 4;
00483         }
00484     }
00485     
00486     return true;
00487 }
00488 
00489 // Transform the bitmap from 8-depth to 24-depth
00490 bool OutputDevice::transform_bitmap_MONO_to_RGB(const unsigned char *src,
00491                                                 unsigned char *dst,
00492                                                 int width,
00493                                                 int height, 
00494                                                 int row_stride,
00495                                                 int transform)
00496 {
00497     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00498     {
00499         for(int h = 0; h < height; ++h)
00500         {
00501             const unsigned char* s = src;
00502             for(int w = 0; w < width; ++w)
00503             {
00504                 //Set value of R, G, B
00505                 for(int i = 0; i < 3; i++)
00506                 {
00507                     *dst++ = *s;
00508                 }
00509                 s++;
00510             }
00511             src += row_stride;
00512         }
00513     }
00514     else
00515     {
00516         int dst_height = (height-1) * 3;
00517         for(int h = 0; h < height; ++h)
00518         {
00519             const unsigned char * s = src;
00520             unsigned char * d = dst;
00521             for(int w = 0; w < width; ++w)
00522             {
00523                 //Set value of R, G, B
00524                 for(int i = 0; i < 3; ++i)
00525                 {
00526                     *d++ = *s;
00527                 }
00528 
00529                 s++; 
00530                 d += dst_height;
00531             }
00532             src += row_stride;
00533             dst += 3;
00534         }
00535     }
00536     return true;
00537 }
00538 
00539 // Transform the bitmap from 8-depth to 32-depth
00540 bool OutputDevice::transform_bitmap_MONO_to_ARGB(const unsigned char *src,
00541                                                  unsigned char *dst,
00542                                                  int width,
00543                                                  int height, 
00544                                                  int row_stride,
00545                                                  int transform)
00546 {
00547     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00548     {
00549         for(int h = 0; h < height; ++h)
00550         {
00551             const unsigned char* s = src;
00552             for(int w = 0; w < width; ++w)
00553             {
00554                 //Set default value to alpha channel
00555                 *dst++ = DEFAULT_ALPHA_VALUE;
00556                 
00557                 //Set value of R, G, B
00558                 for(int i = 0; i < 3; i++)
00559                 {
00560                     *dst++ = *s;
00561                 }
00562                 s++;
00563             }
00564             src += row_stride;
00565         }
00566     }
00567     else
00568     {
00569         int dst_heihgt = (height-1) * 4;
00570         for(int h = 0; h < height; ++h)
00571         {
00572             const unsigned char * s = src;
00573             unsigned char * d = dst;
00574             for(int w = 0; w < width; ++w)
00575             {
00576                 //Set value of alpha channel
00577                 *d++ = DEFAULT_ALPHA_VALUE;
00578                         
00579                 //Set value of R, G, B
00580                 for(int i = 0; i < 3; ++i)
00581                 {
00582                     *d++ = *s;
00583                 }
00584 
00585                 s++; 
00586                 d += dst_heihgt;
00587             }
00588             src += row_stride;
00589             dst += 4;
00590         }
00591     }
00592     
00593     return true;
00594 }
00595 
00596 /// Transform the bitmap from 24-depth to 8-depth
00597 bool OutputDevice::transform_bitmap_RGB_to_MONO(const unsigned char *src,
00598                                                 unsigned char *dst,
00599                                                 int width,
00600                                                 int height, 
00601                                                 int row_stride,
00602                                                 int transform)
00603 
00604 {
00605     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00606     {
00607         for(int h = 0; h < height; ++h)
00608         {
00609             const unsigned char *s = src;
00610             for(int w = 0; w < width; ++w)
00611             {
00612                 //Set the grey to be (R+G+B)/3;
00613                 unsigned char red   = *s++;
00614                 unsigned char green = *s++;
00615                 unsigned char blue  = *s++;
00616                 *dst++ = (red + green + blue) / 3;
00617             }
00618             src += row_stride;
00619         }
00620     }
00621     else
00622     {
00623         for(int h = 0; h < height; ++h)
00624         {
00625             const unsigned char * s = src;
00626             unsigned char * d = dst;
00627             for(int w = 0; w < width; ++w)
00628             {
00629                 //Set the grey to be (R+G+B)/3;
00630                 unsigned char red   = *s++;
00631                 unsigned char green = *s++;
00632                 unsigned char blue  = *s++;
00633                 *d = (red + green + blue) / 3;
00634 
00635                 d += height;
00636             }
00637             src += row_stride;
00638             dst ++;
00639         }
00640     }
00641 
00642     return true;
00643 }
00644 
00645 // Transform the bitmap from 32-depth to 8-depth
00646 bool OutputDevice::transform_bitmap_ARGB_to_MONO(const unsigned char *src,
00647                                                  unsigned char *dst,
00648                                                  int width,
00649                                                  int height, 
00650                                                  int row_stride,
00651                                                  int transform)
00652 {
00653     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00654     {
00655         for(int h = 0; h < height; ++h)
00656         {
00657             const unsigned char *s = src;
00658             for(int w = 0; w < width; ++w)
00659             {
00660                 //Get the value of alpha channel
00661                 //This value should be abandoned.
00662                 //unsigned char alpha = *s++;
00663                 //Set the grey to be (R+G+B)/3;
00664                 unsigned char red   = *s++;
00665                 unsigned char green = *s++;
00666                 unsigned char blue  = *s++;
00667                 *dst++ = (red + green + blue) / 3;
00668             }
00669             src += row_stride;
00670         }
00671     }
00672     else
00673     {
00674         for(int h = 0; h < height; ++h)
00675         {
00676             const unsigned char * s = src;
00677             unsigned char * d = dst;
00678             for(int w = 0; w < width; ++w)
00679             {
00680                 //Get the value of alpha channel
00681                 //This value should be abandoned.
00682                 //unsigned char alpha = *s++;
00683                 //Set the grey to be (R+G+B)/3;
00684                 unsigned char red   = *s++;
00685                 unsigned char green = *s++;
00686                 unsigned char blue  = *s++;
00687                 *d = (red + green + blue) / 3;
00688 
00689                 d += height;
00690             }
00691             src += row_stride;
00692             dst ++;
00693         }
00694     }
00695 
00696     return true;
00697 }
00698 
00699 // Transform the bitmap from 32-depth to 24-depth
00700 bool OutputDevice::transform_bitmap_ARGB_to_RGB(const unsigned char *src,
00701                                                 unsigned char *dst,
00702                                                 int width,
00703                                                 int height, 
00704                                                 int row_stride,
00705                                                 int transform)
00706 {
00707     if (transform == PLUGIN_ORIENTATION_PORTRAIT)
00708     {
00709         for(int h = 0; h < height; ++h)
00710         {
00711             const unsigned char *s = src;
00712             for(int w = 0; w < width; ++w)
00713             {
00714                 //Get the value of alpha channel
00715                 //This value should be abandoned.
00716                 //unsigned char alpha = *s++;
00717                 //Set the grey to be (R+G+B)/3;
00718                 for(int i=0; i < 3; ++i)
00719                 {
00720                     *dst++ = *s++;
00721                 }
00722             }
00723             src += row_stride;
00724         }
00725     }
00726     else
00727     {
00728         int dst_height = (height - 1) * 3;
00729         for(int h = 0; h < height; ++h)
00730         {
00731             const unsigned char * s = src;
00732             unsigned char * d = dst;
00733             for(int w = 0; w < width; ++w)
00734             {
00735                 //Get the value of alpha channel
00736                 //This value should be abandoned.
00737                 //unsigned char alpha = *s++;
00738                 //Set the grey to be (R+G+B)/3;
00739                 for(int i=0; i < 3; ++i)
00740                 {
00741                     *dst++ = *s++;
00742                 }
00743 
00744                 d += dst_height;
00745             }
00746             src += row_stride;
00747             dst += 3;
00748         }
00749     }
00750     
00751     return true;
00752 }
00753 
00754 } //namespace view_helper
00755 
Generated by  doxygen 1.6.2-20100208