📄 graphics.c
字号:
/* * Enhanced MetaFile driver graphics functions * * Copyright 1999 Huw D M Davies * * 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.1 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 */#include "config.h"#include "wine/port.h"#include <stdlib.h>#include <string.h>#include "gdi.h"#include "enhmfdrv/enhmetafiledrv.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);/********************************************************************** * EMFDRV_MoveTo */BOOLEMFDRV_MoveTo(PHYSDEV dev, INT x, INT y){ EMRMOVETOEX emr; emr.emr.iType = EMR_MOVETOEX; emr.emr.nSize = sizeof(emr); emr.ptl.x = x; emr.ptl.y = y; return EMFDRV_WriteRecord( dev, &emr.emr );}/*********************************************************************** * EMFDRV_LineTo */BOOLEMFDRV_LineTo( PHYSDEV dev, INT x, INT y ){ EMRLINETO emr; RECTL bounds; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; DC *dc = physDev->dc; emr.emr.iType = EMR_LINETO; emr.emr.nSize = sizeof(emr); emr.ptl.x = x; emr.ptl.y = y; if(!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; bounds.left = min(x, dc->CursPosX); bounds.top = min(y, dc->CursPosY); bounds.right = max(x, dc->CursPosX); bounds.bottom = max(y, dc->CursPosY); EMFDRV_UpdateBBox( dev, &bounds ); return TRUE;}/*********************************************************************** * EMFDRV_ArcChordPie */static BOOLEMFDRV_ArcChordPie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend, DWORD iType ){ INT temp, xCentre, yCentre, i; double angleStart, angleEnd; double xinterStart, yinterStart, xinterEnd, yinterEnd; EMRARC emr; RECTL bounds; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; DC *dc = physDev->dc; if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(dc->GraphicsMode == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = iType; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; emr.ptlStart.x = xstart; emr.ptlStart.y = ystart; emr.ptlEnd.x = xend; emr.ptlEnd.x = yend; /* Now calculate the BBox */ xCentre = (left + right + 1) / 2; yCentre = (top + bottom + 1) / 2; xstart -= xCentre; ystart -= yCentre; xend -= xCentre; yend -= yCentre; /* invert y co-ords to get angle anti-clockwise from x-axis */ angleStart = atan2( -(double)ystart, (double)xstart); angleEnd = atan2( -(double)yend, (double)xend); /* These are the intercepts of the start/end lines with the arc */ xinterStart = (right - left + 1)/2 * cos(angleStart) + xCentre; yinterStart = -(bottom - top + 1)/2 * sin(angleStart) + yCentre; xinterEnd = (right - left + 1)/2 * cos(angleEnd) + xCentre; yinterEnd = -(bottom - top + 1)/2 * sin(angleEnd) + yCentre; if(angleStart < 0) angleStart += 2 * M_PI; if(angleEnd < 0) angleEnd += 2 * M_PI; if(angleEnd < angleStart) angleEnd += 2 * M_PI; bounds.left = min(xinterStart, xinterEnd); bounds.top = min(yinterStart, yinterEnd); bounds.right = max(xinterStart, xinterEnd); bounds.bottom = max(yinterStart, yinterEnd); for(i = 0; i <= 8; i++) { if(i * M_PI / 2 < angleStart) /* loop until we're past start */ continue; if(i * M_PI / 2 > angleEnd) /* if we're past end we're finished */ break; /* the arc touches the rectangle at the start of quadrant i, so adjust BBox to reflect this. */ switch(i % 4) { case 0: bounds.right = right; break; case 1: bounds.top = top; break; case 2: bounds.left = left; break; case 3: bounds.bottom = bottom; break; } } /* If we're drawing a pie then make sure we include the centre */ if(iType == EMR_PIE) { if(bounds.left > xCentre) bounds.left = xCentre; else if(bounds.right < xCentre) bounds.right = xCentre; if(bounds.top > yCentre) bounds.top = yCentre; else if(bounds.bottom < yCentre) bounds.right = yCentre; } if(!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; EMFDRV_UpdateBBox( dev, &bounds ); return TRUE;}/*********************************************************************** * EMFDRV_Arc */BOOLEMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ){ return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, xend, yend, EMR_ARC );}/*********************************************************************** * EMFDRV_Pie */BOOLEMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ){ return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, xend, yend, EMR_PIE );}/*********************************************************************** * EMFDRV_Chord */BOOLEMFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ){ return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, xend, yend, EMR_CHORD );}/*********************************************************************** * EMFDRV_Ellipse */BOOLEMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ){ EMRELLIPSE emr; INT temp; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; DC *dc = physDev->dc; TRACE("%d,%d - %d,%d\n", left, top, right, bottom); if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(dc->GraphicsMode == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_ELLIPSE; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr );}/*********************************************************************** * EMFDRV_Rectangle */BOOLEMFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom){ EMRRECTANGLE emr; INT temp; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; DC *dc = physDev->dc; TRACE("%d,%d - %d,%d\n", left, top, right, bottom); if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(dc->GraphicsMode == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_RECTANGLE; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr );}/*********************************************************************** * EMFDRV_RoundRect */BOOLEMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height ){ EMRROUNDRECT emr; INT temp; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; DC *dc = physDev->dc; if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(dc->GraphicsMode == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_ROUNDRECT; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; emr.szlCorner.cx = ell_width; emr.szlCorner.cy = ell_height; EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr );}/*********************************************************************** * EMFDRV_SetPixel */COLORREFEMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ){ EMRSETPIXELV emr; emr.emr.iType = EMR_SETPIXELV; emr.emr.nSize = sizeof(emr); emr.ptlPixel.x = x; emr.ptlPixel.y = y; emr.crColor = color; if (EMFDRV_WriteRecord( dev, &emr.emr )) { RECTL bounds; bounds.left = bounds.right = x; bounds.top = bounds.bottom = y; EMFDRV_UpdateBBox( dev, &bounds ); return color; } return -1;}/********************************************************************** * EMFDRV_Polylinegon * * Helper for EMFDRV_Poly{line|gon} */static BOOLEMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ){ EMRPOLYLINE *emr; DWORD size; INT i; BOOL ret; size = sizeof(EMRPOLYLINE) + sizeof(POINTL) * (count - 1); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = iType; emr->emr.nSize = size; emr->rclBounds.left = emr->rclBounds.right = pt[0].x; emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y; for(i = 1; i < count; i++) { if(pt[i].x < emr->rclBounds.left) emr->rclBounds.left = pt[i].x; else if(pt[i].x > emr->rclBounds.right) emr->rclBounds.right = pt[i].x; if(pt[i].y < emr->rclBounds.top) emr->rclBounds.top = pt[i].y; else if(pt[i].y > emr->rclBounds.bottom) emr->rclBounds.bottom = pt[i].y; } emr->cptl = count; memcpy(emr->aptl, pt, count * sizeof(POINTL)); ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -