diff options
author | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2010-09-09 01:48:52 +0200 |
---|---|---|
committer | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2010-09-09 01:50:25 +0200 |
commit | e9a184546b18cf3b796bd560561f312934004c54 (patch) | |
tree | aa785af9a8d03f8ce276c9e9ecec78397005ec22 /cd/src/win32/cdwin.c | |
parent | 92efe73791d0998536042bfab5a1babc67d168c7 (diff) |
Upgrading to CD 5.4 - and cleaning up.
Diffstat (limited to 'cd/src/win32/cdwin.c')
-rwxr-xr-x | cd/src/win32/cdwin.c | 313 |
1 files changed, 212 insertions, 101 deletions
diff --git a/cd/src/win32/cdwin.c b/cd/src/win32/cdwin.c index 313e833..e2eb9ea 100755 --- a/cd/src/win32/cdwin.c +++ b/cd/src/win32/cdwin.c @@ -626,6 +626,7 @@ static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style) ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush); ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); break; + /* the remaining styles must recreate the current brush */ case CD_HATCH: cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); break; @@ -642,10 +643,26 @@ static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style) return style; } +static void sUpdateFill(cdCtxCanvas* ctxcanvas, int fill) +{ + if (fill) + { + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN)) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + } + else + { + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + } +} + +/*******************************************************************************/ + static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) { - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); MoveToEx( ctxcanvas->hDC, x1, y1, NULL ); LineTo( ctxcanvas->hDC, x2, y2 ); @@ -656,8 +673,7 @@ static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ym { HBRUSH oldBrush; - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); oldBrush = SelectObject(ctxcanvas->hDC, GetStockObject(NULL_BRUSH)); /* tira o desenho do interior */ Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+1, ymax+1); /* +1 porque nao inclue right/bottom */ @@ -666,9 +682,7 @@ static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ym static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) { - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->canvas->new_region) { @@ -696,40 +710,46 @@ typedef struct _winArcParam YEndArc; /* second radial ending point */ } winArcParam; -static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc) +static void sCalcArc(cdCanvas* canvas, int xc, int yc, int w, int h, double a1, double a2, winArcParam* arc, int swap) { - arc->LeftRect = xc - w/2; - arc->RightRect = xc + w/2 + 1; - arc->XStartArc = xc + cdRound(w * cos(CD_DEG2RAD * angle1) / 2.0); - arc->XEndArc = xc + cdRound(w * cos(CD_DEG2RAD * angle2) / 2.0); + /* computation is done as if the angles are counter-clockwise, + and yaxis is NOT inverted. */ - if (ctxcanvas->canvas->invert_yaxis) + arc->LeftRect = xc - w/2; + arc->TopRect = yc - h/2; + arc->RightRect = xc + w/2 + 1; + arc->BottomRect = yc + h/2 + 1; + + /* GDI orientation is the same as CD */ + + if (!canvas->invert_yaxis) + _cdSwapInt(arc->BottomRect, arc->TopRect); /* not necessary, but done for clarity */ + + cdCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, &(arc->XStartArc), &(arc->YStartArc), &(arc->XEndArc), &(arc->YEndArc)); + + if (canvas->invert_yaxis) { - arc->TopRect = yc - h/2; - arc->BottomRect = yc + h/2 + 1; - arc->YStartArc = yc - cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); - arc->YEndArc = yc - cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); + /* fix axis orientation */ + arc->YStartArc = 2*yc - arc->YStartArc; + arc->YEndArc = 2*yc - arc->YEndArc; } else { - arc->BottomRect = yc - h/2; - arc->TopRect = yc + h/2 + 1; - arc->YStartArc = yc + cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); - arc->YEndArc = yc + cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); - - /* it is clock-wise when axis inverted */ - _cdSwapInt(arc->XStartArc, arc->XEndArc); - _cdSwapInt(arc->YStartArc, arc->YEndArc); + /* it is clock-wise when axis NOT inverted */ + if (swap) + { + _cdSwapInt(arc->XStartArc, arc->XEndArc); + _cdSwapInt(arc->YStartArc, arc->YEndArc); + } } } static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) { winArcParam arc; - calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1); - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); } @@ -737,11 +757,9 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) { winArcParam arc; - calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1); - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (angle1==0 && angle2==360) { @@ -781,11 +799,9 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) { winArcParam arc; - calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1); - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (angle1==0 && angle2==360) { @@ -828,6 +844,105 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) POINT* pnt; HPEN oldPen = NULL, Pen = NULL; + if (mode == CD_PATH) + { + int p, current_set; + + /* if there is any current path, remove it */ + BeginPath(ctxcanvas->hDC); + current_set = 0; + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + EndPath(ctxcanvas->hDC); + BeginPath(ctxcanvas->hDC); + current_set = 0; + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + MoveToEx(ctxcanvas->hDC, poly[i].x, poly[i].y, NULL); + current_set = 1; + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + LineTo(ctxcanvas->hDC, poly[i].x, poly[i].y); + current_set = 1; + i++; + break; + case CD_PATH_ARC: + { + int xc, yc, w, h, old_arcmode = 0; + double a1, a2; + winArcParam arc; + + if (i+3 > n) return; + + if (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arc, 0); + + if (current_set) + LineTo(ctxcanvas->hDC, arc.XStartArc, arc.YStartArc); + + if ((a2-a1)<0) /* can be clockwise */ + { + /* Arc behave diferent when GM_ADVANCED is set */ + old_arcmode = SetArcDirection(ctxcanvas->hDC, ctxcanvas->canvas->invert_yaxis? AD_CLOCKWISE: AD_COUNTERCLOCKWISE); + } + + ArcTo(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); + + if (old_arcmode) /* restore */ + SetArcDirection(ctxcanvas->hDC, old_arcmode); + + current_set = 1; + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) return; + PolyBezierTo(ctxcanvas->hDC, (POINT*)(poly + i), 3); + current_set = 1; + i += 3; + break; + case CD_PATH_CLOSE: + CloseFigure(ctxcanvas->hDC); + break; + case CD_PATH_FILL: + sUpdateFill(ctxcanvas, 1); + SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + EndPath(ctxcanvas->hDC); + FillPath(ctxcanvas->hDC); + break; + case CD_PATH_STROKE: + sUpdateFill(ctxcanvas, 0); + EndPath(ctxcanvas->hDC); + StrokePath(ctxcanvas->hDC); + break; + case CD_PATH_FILLSTROKE: + sUpdateFill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 0); + SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + EndPath(ctxcanvas->hDC); + StrokeAndFillPath(ctxcanvas->hDC); + break; + case CD_PATH_CLIP: + SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + EndPath(ctxcanvas->hDC); + SelectClipPath(ctxcanvas->hDC, RGN_AND); + break; + } + } + return; + } + switch( mode ) { case CD_CLOSED_LINES: @@ -836,13 +951,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) n++; /* continua */ case CD_OPEN_LINES: - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); Polyline(ctxcanvas->hDC, (POINT*)poly, n); break; case CD_BEZIER: - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); PolyBezier(ctxcanvas->hDC, (POINT*)poly, n); break; case CD_FILL: @@ -857,14 +970,10 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) } else { - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN)) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') - { SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ - } else { Pen = CreatePen(PS_SOLID, 1, ctxcanvas->fg); @@ -875,9 +984,7 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) Polygon(ctxcanvas->hDC, (POINT*)poly, n); if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') - { SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ - } else { SelectObject(ctxcanvas->hDC, oldPen); @@ -963,8 +1070,37 @@ static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) else { ctxcanvas->canvas->invert_yaxis = 1; - ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); - SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); + + if (ctxcanvas->rotate_angle) + { + XFORM xForm; + + /* the rotation must be corrected because of the Y axis orientation */ + + SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + + xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle); + xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle); + xForm.eM21 = (FLOAT) -xForm.eM12; + xForm.eM22 = (FLOAT) xForm.eM11; + xForm.eDx = (FLOAT) ctxcanvas->rotate_center_x; + xForm.eDy = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + xForm.eM11 = (FLOAT) 1; + xForm.eM12 = (FLOAT) 0; + xForm.eM21 = (FLOAT) 0; + xForm.eM22 = (FLOAT) 1; + xForm.eDx = (FLOAT) -ctxcanvas->rotate_center_x; + xForm.eDy = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + } + else + { + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); + } } } @@ -1581,11 +1717,12 @@ static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned c if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) { + /* reset to the identity. */ GetWorldTransform(ctxcanvas->hDC, &xForm); ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); } - if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + if (ctxcanvas->canvas->invert_yaxis==0) /* if 0, invert because the transform was reset here */ y = _cdInvertYAxis(ctxcanvas->canvas, y); yr = y - (h - 1); /* y starts at the bottom of the image */ @@ -1622,10 +1759,12 @@ static void sFixImageY(cdCanvas* canvas, int *y, int *h) /* Here, y is from top to bottom, is at the bottom-left corner of the image if h>0 is at the top-left corner of the image if h<0. (Undocumented feature) + cdCalcZoom expects Y at top-left if h>0 and Y at bottom-left if h<0 if h<0 then eh<0 to StretchDIBits mirror the image. - BUT!!!!!! AlphaBlend will NOT mirror the image. */ + BUT!!!!!! AlphaBlend will NOT mirror the image. + So it must be manually made there. */ if (!canvas->invert_yaxis) *h = -(*h); @@ -1741,26 +1880,16 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int width, int height, co return; } - cdwDIBEncodeRGBARect(&dib, red, green, blue, alpha, bx, by, width, height); - if (eh < 0) /* must mirror the image */ { - XFORM xForm; - + /* Fix position */ eh = -eh; + ey = ey - eh; - SetGraphicsMode(hDCMem, GM_ADVANCED); - ModifyWorldTransform(hDCMem, NULL, MWT_IDENTITY); - - /* configure a bottom-up coordinate system */ - xForm.eM11 = (FLOAT)1; - xForm.eM12 = (FLOAT)0; - xForm.eM21 = (FLOAT)0; - xForm.eM22 = (FLOAT)-1; - xForm.eDx = (FLOAT)0; - xForm.eDy = (FLOAT)(bh-1); - ModifyWorldTransform(hDCMem, &xForm, MWT_LEFTMULTIPLY); + cdwDIBEncodeRGBARectMirror(&dib, red, green, blue, alpha, bx, by, width, height); } + else + cdwDIBEncodeRGBARect(&dib, red, green, blue, alpha, bx, by, width, height); hOldBitmap = SelectObject(hDCMem, hBitmap); @@ -1891,20 +2020,21 @@ static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height) static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y) { - int yr; XFORM xForm; if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) { + /* reset to the identity. */ GetWorldTransform(ctxcanvas->hDC, &xForm); ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); } - if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + if (ctxcanvas->canvas->invert_yaxis==0) /* if 0, invert because the transform was reset here */ y = _cdInvertYAxis(ctxcanvas->canvas, y); - yr = y - (ctximage->h - 1); - BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, yr, SRCCOPY); + /* y is the bottom-left of the image in CD, must be at upper-left */ + y -= ctximage->h-1; + BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, y, SRCCOPY); if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); @@ -1971,18 +2101,15 @@ static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, i { XFORM xForm; RECT rect; - rect.left = xmin; - rect.right = xmax+1; - rect.top = ymin; - rect.bottom = ymax+1; if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) { + /* reset to the identity. */ GetWorldTransform(ctxcanvas->hDC, &xForm); ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); } - if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + if (ctxcanvas->canvas->invert_yaxis==0) /* if 0, invert because the transform was reset here */ { dy = -dy; ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); @@ -1990,6 +2117,11 @@ static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, i _cdSwapInt(ymin, ymax); } + rect.left = xmin; + rect.right = xmax+1; + rect.top = ymin; + rect.bottom = ymax+1; + ScrollDC(ctxcanvas->hDC, dx, dy, &rect, NULL, NULL, NULL); if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) @@ -2136,47 +2268,25 @@ static cdAttribute img_points_attrib = static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) { - /* ignore ROTATE if transform is set */ + /* ignore ROTATE if transform is set, + because there is native support for transformations */ if (ctxcanvas->canvas->use_matrix) return; if (data) { - XFORM xForm; sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, &ctxcanvas->rotate_center_x, &ctxcanvas->rotate_center_y); - - /* the rotation must be corrected because of the Y axis orientation */ - - SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); - ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); - - xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle); - xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle); - xForm.eM21 = (FLOAT) -xForm.eM12; - xForm.eM22 = (FLOAT) xForm.eM11; - xForm.eDx = (FLOAT) ctxcanvas->rotate_center_x; - xForm.eDy = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); - ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); - - xForm.eM11 = (FLOAT) 1; - xForm.eM12 = (FLOAT) 0; - xForm.eM21 = (FLOAT) 0; - xForm.eM22 = (FLOAT) 1; - xForm.eDx = (FLOAT) -ctxcanvas->rotate_center_x; - xForm.eDy = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); - ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); } else { ctxcanvas->rotate_angle = 0; ctxcanvas->rotate_center_x = 0; ctxcanvas->rotate_center_y = 0; - - ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); - SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); } + + cdtransform(ctxcanvas, NULL); } static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) @@ -2325,6 +2435,7 @@ void cdwInitTable(cdCanvas* canvas) canvas->cxSector = cdsector; canvas->cxChord = cdchord; canvas->cxText = cdtext; + canvas->cxGetFontDim = cdgetfontdim; canvas->cxGetTextSize = cdgettextsize; canvas->cxPutImageRectRGB = cdputimagerectrgb; |