ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

gdiplus.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Google (Evan Stade)
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include <stdarg.h>
00020 #include <math.h>
00021 
00022 #include "windef.h"
00023 #include "winbase.h"
00024 #include "winerror.h"
00025 #include "wine/debug.h"
00026 #include "wingdi.h"
00027 
00028 #include "objbase.h"
00029 
00030 #include "winreg.h"
00031 #include "shlwapi.h"
00032 
00033 #include "gdiplus.h"
00034 #include "gdiplus_private.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
00037 
00038 static Status WINAPI NotificationHook(ULONG_PTR *token)
00039 {
00040     TRACE("%p\n", token);
00041     if(!token)
00042         return InvalidParameter;
00043 
00044     return Ok;
00045 }
00046 
00047 static void WINAPI NotificationUnhook(ULONG_PTR token)
00048 {
00049     TRACE("%ld\n", token);
00050 }
00051 
00052 /*****************************************************
00053  *      DllMain
00054  */
00055 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
00056 {
00057     TRACE("(%p, %d, %p)\n", hinst, reason, reserved);
00058 
00059     switch(reason)
00060     {
00061     case DLL_PROCESS_ATTACH:
00062         DisableThreadLibraryCalls( hinst );
00063         break;
00064 
00065     case DLL_PROCESS_DETACH:
00066         free_installed_fonts();
00067         break;
00068     }
00069     return TRUE;
00070 }
00071 
00072 /*****************************************************
00073  *      GdiplusStartup [GDIPLUS.@]
00074  */
00075 Status WINAPI GdiplusStartup(ULONG_PTR *token, const struct GdiplusStartupInput *input,
00076                              struct GdiplusStartupOutput *output)
00077 {
00078     if(!token || !input)
00079         return InvalidParameter;
00080 
00081     TRACE("%p %p %p\n", token, input, output);
00082     TRACE("GdiplusStartupInput %d %p %d %d\n", input->GdiplusVersion,
00083           input->DebugEventCallback, input->SuppressBackgroundThread,
00084           input->SuppressExternalCodecs);
00085 
00086     if(input->GdiplusVersion < 1 || input->GdiplusVersion > 2)
00087         return UnsupportedGdiplusVersion;
00088 
00089     if(input->SuppressBackgroundThread){
00090         if(!output)
00091             return InvalidParameter;
00092 
00093         output->NotificationHook = NotificationHook;
00094         output->NotificationUnhook = NotificationUnhook;
00095     }
00096 
00097     *token = 0xdeadbeef;
00098 
00099     /* FIXME: DebugEventCallback ignored */
00100 
00101     return Ok;
00102 }
00103 
00104 GpStatus WINAPI GdiplusNotificationHook(ULONG_PTR *token)
00105 {
00106     FIXME("%p\n", token);
00107     return NotificationHook(token);
00108 }
00109 
00110 void WINAPI GdiplusNotificationUnhook(ULONG_PTR token)
00111 {
00112     FIXME("%ld\n", token);
00113     NotificationUnhook(token);
00114 }
00115 
00116 /*****************************************************
00117  *      GdiplusShutdown [GDIPLUS.@]
00118  */
00119 ULONG WINAPI GdiplusShutdown_wrapper(ULONG_PTR token)
00120 {
00121     /* Notice the slightly different prototype from the official
00122      * signature which forces us to use the _wrapper suffix.
00123      */
00124 
00125     /* FIXME: no object tracking */
00126 
00127     /* "bricksntiles" expects a return value of 0, which native
00128      * coincidentally gives.
00129      */
00130     return 0;
00131 }
00132 
00133 /*****************************************************
00134  *      GdipAlloc [GDIPLUS.@]
00135  */
00136 void* WINGDIPAPI GdipAlloc(SIZE_T size)
00137 {
00138     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
00139 }
00140 
00141 /*****************************************************
00142  *      GdipFree [GDIPLUS.@]
00143  */
00144 void WINGDIPAPI GdipFree(void* ptr)
00145 {
00146     HeapFree(GetProcessHeap(), 0, ptr);
00147 }
00148 
00149 /* Calculates the bezier points needed to fill in the arc portion starting at
00150  * angle start and ending at end.  These two angles should be no more than 90
00151  * degrees from each other.  x1, y1, x2, y2 describes the bounding box (upper
00152  * left and width and height).  Angles must be in radians. write_first indicates
00153  * that the first bezier point should be written out (usually this is false).
00154  * pt is the array of GpPointFs that gets written to.
00155  **/
00156 static void add_arc_part(GpPointF * pt, REAL x1, REAL y1, REAL x2, REAL y2,
00157     REAL start, REAL end, BOOL write_first)
00158 {
00159     REAL center_x, center_y, rad_x, rad_y, cos_start, cos_end,
00160         sin_start, sin_end, a, half;
00161     INT i;
00162 
00163     rad_x = x2 / 2.0;
00164     rad_y = y2 / 2.0;
00165     center_x = x1 + rad_x;
00166     center_y = y1 + rad_y;
00167 
00168     cos_start = cos(start);
00169     cos_end = cos(end);
00170     sin_start = sin(start);
00171     sin_end = sin(end);
00172 
00173     half = (end - start) / 2.0;
00174     a = 4.0 / 3.0 * (1 - cos(half)) / sin(half);
00175 
00176     if(write_first){
00177         pt[0].X = cos_start;
00178         pt[0].Y = sin_start;
00179     }
00180     pt[1].X = cos_start - a * sin_start;
00181     pt[1].Y = sin_start + a * cos_start;
00182 
00183     pt[3].X = cos_end;
00184     pt[3].Y = sin_end;
00185     pt[2].X = cos_end + a * sin_end;
00186     pt[2].Y = sin_end - a * cos_end;
00187 
00188     /* expand the points back from the unit circle to the ellipse */
00189     for(i = (write_first ? 0 : 1); i < 4; i ++){
00190         pt[i].X = pt[i].X * rad_x + center_x;
00191         pt[i].Y = pt[i].Y * rad_y + center_y;
00192     }
00193 }
00194 
00195 /* We plot the curve as if it is on a circle then stretch the points.  This
00196  * adjusts the angles so that when we stretch the points they will end in the
00197  * right place. This is only complicated because atan and atan2 do not behave
00198  * conveniently. */
00199 static void unstretch_angle(REAL * angle, REAL rad_x, REAL rad_y)
00200 {
00201     REAL stretched;
00202     INT revs_off;
00203 
00204     *angle = deg2rad(*angle);
00205 
00206     if(fabs(cos(*angle)) < 0.00001 || fabs(sin(*angle)) < 0.00001)
00207         return;
00208 
00209     stretched = gdiplus_atan2(sin(*angle) / fabs(rad_y), cos(*angle) / fabs(rad_x));
00210     revs_off = roundr(*angle / (2.0 * M_PI)) - roundr(stretched / (2.0 * M_PI));
00211     stretched += ((REAL)revs_off) * M_PI * 2.0;
00212     *angle = stretched;
00213 }
00214 
00215 /* Stores the bezier points that correspond to the arc in points.  If points is
00216  * null, just return the number of points needed to represent the arc. */
00217 INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
00218     REAL startAngle, REAL sweepAngle)
00219 {
00220     INT i;
00221     REAL end_angle, start_angle, endAngle;
00222 
00223     endAngle = startAngle + sweepAngle;
00224     unstretch_angle(&startAngle, x2 / 2.0, y2 / 2.0);
00225     unstretch_angle(&endAngle, x2 / 2.0, y2 / 2.0);
00226 
00227     /* start_angle and end_angle are the iterative variables */
00228     start_angle = startAngle;
00229 
00230     for(i = 0; i < MAX_ARC_PTS - 1; i += 3){
00231         /* check if we've overshot the end angle */
00232         if( sweepAngle > 0.0 )
00233         {
00234             if (start_angle >= endAngle) break;
00235             end_angle = min(start_angle + M_PI_2, endAngle);
00236         }
00237         else
00238         {
00239             if (start_angle <= endAngle) break;
00240             end_angle = max(start_angle - M_PI_2, endAngle);
00241         }
00242 
00243         if (points)
00244             add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
00245 
00246         start_angle += M_PI_2 * (sweepAngle < 0.0 ? -1.0 : 1.0);
00247     }
00248 
00249     if (i == 0) return 0;
00250     else return i+1;
00251 }
00252 
00253 COLORREF ARGB2COLORREF(ARGB color)
00254 {
00255     /*
00256     Packing of these color structures:
00257     COLORREF:   00bbggrr
00258     ARGB:       aarrggbb
00259     FIXME:doesn't handle alpha channel
00260     */
00261     return ((color & 0x0000ff) << 16) +
00262            (color & 0x00ff00) +
00263            ((color & 0xff0000) >> 16);
00264 }
00265 
00266 HBITMAP ARGB2BMP(ARGB color)
00267 {
00268     BITMAPINFO bi;
00269     HBITMAP result;
00270     RGBQUAD *bits;
00271     int alpha;
00272 
00273     if ((color & 0xff000000) == 0xff000000) return 0;
00274 
00275     bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
00276     bi.bmiHeader.biWidth = 1;
00277     bi.bmiHeader.biHeight = 1;
00278     bi.bmiHeader.biPlanes = 1;
00279     bi.bmiHeader.biBitCount = 32;
00280     bi.bmiHeader.biCompression = BI_RGB;
00281     bi.bmiHeader.biSizeImage = 0;
00282     bi.bmiHeader.biXPelsPerMeter = 0;
00283     bi.bmiHeader.biYPelsPerMeter = 0;
00284     bi.bmiHeader.biClrUsed = 0;
00285     bi.bmiHeader.biClrImportant = 0;
00286 
00287     result = CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void*)&bits, NULL, 0);
00288 
00289     bits[0].rgbReserved = alpha = (color>>24)&0xff;
00290     bits[0].rgbRed = ((color>>16)&0xff)*alpha/255;
00291     bits[0].rgbGreen = ((color>>8)&0xff)*alpha/255;
00292     bits[0].rgbBlue = (color&0xff)*alpha/255;
00293 
00294     return result;
00295 }
00296 
00297 /* Like atan2, but puts angle in correct quadrant if dx is 0. */
00298 REAL gdiplus_atan2(REAL dy, REAL dx)
00299 {
00300     if((dx == 0.0) && (dy != 0.0))
00301         return dy > 0.0 ? M_PI_2 : -M_PI_2;
00302 
00303     return atan2(dy, dx);
00304 }
00305 
00306 GpStatus hresult_to_status(HRESULT res)
00307 {
00308     switch(res){
00309         case S_OK:
00310             return Ok;
00311         case E_OUTOFMEMORY:
00312             return OutOfMemory;
00313         case E_INVALIDARG:
00314             return InvalidParameter;
00315         default:
00316             return GenericError;
00317     }
00318 }
00319 
00320 /* converts a given unit to its value in pixels */
00321 REAL convert_unit(REAL logpixels, GpUnit unit)
00322 {
00323     switch(unit)
00324     {
00325         case UnitInch:
00326             return logpixels;
00327         case UnitPoint:
00328             return logpixels / 72.0;
00329         case UnitDocument:
00330             return logpixels / 300.0;
00331         case UnitMillimeter:
00332             return logpixels / 25.4;
00333         case UnitWorld:
00334             ERR("cannot convert UnitWorld\n");
00335             return 0.0;
00336         case UnitPixel:
00337         case UnitDisplay:
00338         default:
00339             return 1.0;
00340     }
00341 }
00342 
00343 /* Calculates Bezier points from cardinal spline points. */
00344 void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
00345     REAL *y1, REAL *x2, REAL *y2)
00346 {
00347     REAL xdiff, ydiff;
00348 
00349     /* calculate tangent */
00350     xdiff = pts[2].X - pts[0].X;
00351     ydiff = pts[2].Y - pts[0].Y;
00352 
00353     /* apply tangent to get control points */
00354     *x1 = pts[1].X - tension * xdiff;
00355     *y1 = pts[1].Y - tension * ydiff;
00356     *x2 = pts[1].X + tension * xdiff;
00357     *y2 = pts[1].Y + tension * ydiff;
00358 }
00359 
00360 /* Calculates Bezier points from cardinal spline endpoints. */
00361 void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
00362     REAL tension, REAL *x, REAL *y)
00363 {
00364     /* tangent at endpoints is the line from the endpoint to the adjacent point */
00365     *x = roundr(tension * (xadj - xend) + xend);
00366     *y = roundr(tension * (yadj - yend) + yend);
00367 }
00368 
00369 /* make sure path has enough space for len more points */
00370 BOOL lengthen_path(GpPath *path, INT len)
00371 {
00372     /* initial allocation */
00373     if(path->datalen == 0){
00374         path->datalen = len * 2;
00375 
00376         path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
00377         if(!path->pathdata.Points)   return FALSE;
00378 
00379         path->pathdata.Types = GdipAlloc(path->datalen);
00380         if(!path->pathdata.Types){
00381             GdipFree(path->pathdata.Points);
00382             return FALSE;
00383         }
00384     }
00385     /* reallocation, double size of arrays */
00386     else if(path->datalen - path->pathdata.Count < len){
00387         while(path->datalen - path->pathdata.Count < len)
00388             path->datalen *= 2;
00389 
00390         path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0,
00391             path->pathdata.Points, path->datalen * sizeof(PointF));
00392         if(!path->pathdata.Points)  return FALSE;
00393 
00394         path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0,
00395             path->pathdata.Types, path->datalen);
00396         if(!path->pathdata.Types)   return FALSE;
00397     }
00398 
00399     return TRUE;
00400 }
00401 
00402 void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height,
00403     BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride)
00404 {
00405     INT x, y;
00406     for (y=0; y<height; y++)
00407     {
00408         const BYTE *src=src_bits+y*src_stride;
00409         BYTE *dst=dst_bits+y*dst_stride;
00410         for (x=0; x<width; x++)
00411         {
00412             BYTE alpha=src[3];
00413             *dst++ = *src++ * alpha / 255;
00414             *dst++ = *src++ * alpha / 255;
00415             *dst++ = *src++ * alpha / 255;
00416             *dst++ = *src++;
00417         }
00418     }
00419 }
00420 
00421 /* recursive deletion of GpRegion nodes */
00422 void delete_element(region_element* element)
00423 {
00424     switch(element->type)
00425     {
00426         case RegionDataRect:
00427             break;
00428         case RegionDataPath:
00429             GdipDeletePath(element->elementdata.pathdata.path);
00430             break;
00431         case RegionDataEmptyRect:
00432         case RegionDataInfiniteRect:
00433             break;
00434         default:
00435             delete_element(element->elementdata.combine.left);
00436             delete_element(element->elementdata.combine.right);
00437             GdipFree(element->elementdata.combine.left);
00438             GdipFree(element->elementdata.combine.right);
00439             break;
00440     }
00441 }
00442 
00443 const char *debugstr_rectf(CONST RectF* rc)
00444 {
00445     if (!rc) return "(null)";
00446     return wine_dbg_sprintf("(%0.2f,%0.2f,%0.2f,%0.2f)", rc->X, rc->Y, rc->Width, rc->Height);
00447 }
00448 
00449 const char *debugstr_pointf(CONST PointF* pt)
00450 {
00451     if (!pt) return "(null)";
00452     return wine_dbg_sprintf("(%0.2f,%0.2f)", pt->X, pt->Y);
00453 }

Generated on Sun May 27 2012 04:23:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.