| 1 | /* |
| 2 | * gdipluspen.h |
| 3 | * |
| 4 | * GDI+ Pen class |
| 5 | * |
| 6 | * This file is part of the w32api package. |
| 7 | * |
| 8 | * Contributors: |
| 9 | * Created by Markus Koenig <markus@stber-koenig.de> |
| 10 | * |
| 11 | * THIS SOFTWARE IS NOT COPYRIGHTED |
| 12 | * |
| 13 | * This source code is offered for use in the public domain. You may |
| 14 | * use, modify or distribute it freely. |
| 15 | * |
| 16 | * This code is distributed in the hope that it will be useful but |
| 17 | * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY |
| 18 | * DISCLAIMED. This includes but is not limited to warranties of |
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 20 | * |
| 21 | */ |
| 22 | |
| 23 | #ifndef __GDIPLUS_PEN_H |
| 24 | #define __GDIPLUS_PEN_H |
| 25 | #if __GNUC__ >=3 |
| 26 | #pragma GCC system_header |
| 27 | #endif |
| 28 | |
| 29 | #ifndef __cplusplus |
| 30 | #error "A C++ compiler is required to include gdipluspen.h." |
| 31 | #endif |
| 32 | |
| 33 | class Pen: public GdiplusBase |
| 34 | { |
| 35 | 	friend class Graphics; |
| 36 | 	friend class GraphicsPath; |
| 37 | |
| 38 | public: |
| 39 | 	Pen(const Color& color, REAL width = 1.0f): |
| 40 | 		nativePen(NULL), lastStatus(Ok) |
| 41 | 	{ |
| 42 | 		lastStatus = DllExports::GdipCreatePen1( |
| 43 | 				color.GetValue(), width, UnitWorld, |
| 44 | 				&nativePen); |
| 45 | 	} |
| 46 | 	Pen(const Brush *brush, REAL width = 1.0f): |
| 47 | 		nativePen(NULL), lastStatus(Ok) |
| 48 | 	{ |
| 49 | 		lastStatus = DllExports::GdipCreatePen2( |
| 50 | 				brush ? brush->nativeBrush : NULL, |
| 51 | 				width, UnitWorld, &nativePen); |
| 52 | 	} |
| 53 | 	~Pen() |
| 54 | 	{ |
| 55 | 		DllExports::GdipDeletePen(nativePen); |
| 56 | 	} |
| 57 | 	Pen* Clone() const |
| 58 | 	{ |
| 59 | 		GpPen *clonePen = NULL; |
| 60 | 		Status status = updateStatus(DllExports::GdipClonePen( |
| 61 | 				nativePen, &clonePen)); |
| 62 | 		if (status == Ok) { |
| 63 | 			Pen *result = new Pen(clonePen, lastStatus); |
| 64 | 			if (!result) { |
| 65 | 				DllExports::GdipDeletePen(clonePen); |
| 66 | 				lastStatus = OutOfMemory; |
| 67 | 			} |
| 68 | 			return result; |
| 69 | 		} else { |
| 70 | 			return NULL; |
| 71 | 		} |
| 72 | 	} |
| 73 | |
| 74 | 	PenAlignment GetAlignment() const |
| 75 | 	{ |
| 76 | 		PenAlignment result = PenAlignmentCenter; |
| 77 | 		updateStatus(DllExports::GdipGetPenMode(nativePen, &result)); |
| 78 | 		return result; |
| 79 | 	} |
| 80 | 	// TODO: implement Pen::GetBrush() |
| 81 | 	//Brush *GetBrush() const |
| 82 | 	//{ |
| 83 | 	//	// where is the pen brush allocated (static,member,new,other)? |
| 84 | 	//	// GdipGetPenBrushFill just returns a GpBrush* |
| 85 | 	//	updateStatus(NotImplemented); |
| 86 | 	//	return NULL; |
| 87 | 	//} |
| 88 | 	Status GetColor(Color *color) const |
| 89 | 	{ |
| 90 | 		return updateStatus(DllExports::GdipGetPenColor( |
| 91 | 				nativePen, color ? &color->Value : NULL)); |
| 92 | 	} |
| 93 | 	Status GetCompoundArray(REAL *compoundArray, INT count) const |
| 94 | 	{ |
| 95 | 		return updateStatus(DllExports::GdipGetPenCompoundArray( |
| 96 | 				nativePen, compoundArray, count)); |
| 97 | 	} |
| 98 | 	INT GetCompoundArrayCount() const |
| 99 | 	{ |
| 100 | 		INT result = 0; |
| 101 | 		updateStatus(DllExports::GdipGetPenCompoundCount( |
| 102 | 				nativePen, &result)); |
| 103 | 		return result; |
| 104 | 	} |
| 105 | 	Status GetCustomEndCap(CustomLineCap *customCap) const |
| 106 | 	{ |
| 107 | 		if (!customCap) return lastStatus = InvalidParameter; |
| 108 | 		// FIXME: do we need to call GdipDeleteCustomLineCap first? |
| 109 | 		return updateStatus(DllExports::GdipGetPenCustomEndCap( |
| 110 | 				nativePen, &customCap->nativeCustomLineCap)); |
| 111 | 	} |
| 112 | 	Status GetCustomStartCap(CustomLineCap *customCap) const |
| 113 | 	{ |
| 114 | 		if (!customCap) return lastStatus = InvalidParameter; |
| 115 | 		// FIXME: do we need to call GdipDeleteCustomLineCap first? |
| 116 | 		return updateStatus(DllExports::GdipGetPenCustomStartCap( |
| 117 | 				nativePen, &customCap->nativeCustomLineCap)); |
| 118 | 	} |
| 119 | 	DashCap GetDashCap() const |
| 120 | 	{ |
| 121 | 		DashCap result = DashCapFlat; |
| 122 | 		updateStatus(DllExports::GdipGetPenDashCap197819( |
| 123 | 				nativePen, &result)); |
| 124 | 		return result; |
| 125 | 	} |
| 126 | 	REAL GetDashOffset() const |
| 127 | 	{ |
| 128 | 		REAL result = 0.0f; |
| 129 | 		updateStatus(DllExports::GdipGetPenDashOffset( |
| 130 | 				nativePen, &result)); |
| 131 | 		return result; |
| 132 | 	} |
| 133 | 	Status GetDashPattern(REAL *dashArray, INT count) const |
| 134 | 	{ |
| 135 | 		return updateStatus(DllExports::GdipGetPenDashArray( |
| 136 | 				nativePen, dashArray, count)); |
| 137 | 	} |
| 138 | 	INT GetDashPatternCount() const |
| 139 | 	{ |
| 140 | 		INT result = 0; |
| 141 | 		updateStatus(DllExports::GdipGetPenDashCount( |
| 142 | 				nativePen, &result)); |
| 143 | 		return result; |
| 144 | 	} |
| 145 | 	DashStyle GetDashStyle() const |
| 146 | 	{ |
| 147 | 		DashStyle result = DashStyleSolid; |
| 148 | 		updateStatus(DllExports::GdipGetPenDashStyle( |
| 149 | 				nativePen, &result)); |
| 150 | 		return result; |
| 151 | 	} |
| 152 | 	LineCap GetEndCap() const |
| 153 | 	{ |
| 154 | 		LineCap result = LineCapFlat; |
| 155 | 		updateStatus(DllExports::GdipGetPenEndCap(nativePen, &result)); |
| 156 | 		return result; |
| 157 | 	} |
| 158 | 	Status GetLastStatus() const |
| 159 | 	{ |
| 160 | 		Status result = lastStatus; |
| 161 | 		lastStatus = Ok; |
| 162 | 		return result; |
| 163 | 	} |
| 164 | 	LineJoin GetLineJoin() const |
| 165 | 	{ |
| 166 | 		LineJoin result = LineJoinMiter; |
| 167 | 		updateStatus(DllExports::GdipGetPenLineJoin( |
| 168 | 				nativePen, &result)); |
| 169 | 		return result; |
| 170 | 	} |
| 171 | 	REAL GetMiterLimit() const |
| 172 | 	{ |
| 173 | 		REAL result = 10.0f; |
| 174 | 		updateStatus(DllExports::GdipGetPenMiterLimit( |
| 175 | 				nativePen, &result)); |
| 176 | 		return result; |
| 177 | 	} |
| 178 | 	PenType GetPenType() const |
| 179 | 	{ |
| 180 | 		PenType result = PenTypeUnknown; |
| 181 | 		updateStatus(DllExports::GdipGetPenFillType( |
| 182 | 				nativePen, &result)); |
| 183 | 		return result; |
| 184 | 	} |
| 185 | 	LineCap GetStartCap() const |
| 186 | 	{ |
| 187 | 		LineCap result = LineCapFlat; |
| 188 | 		updateStatus(DllExports::GdipGetPenStartCap( |
| 189 | 				nativePen, &result)); |
| 190 | 		return result; |
| 191 | 	} |
| 192 | 	Status GetTransform(Matrix *matrix) const |
| 193 | 	{ |
| 194 | 		return updateStatus(DllExports::GdipGetPenTransform( |
| 195 | 				nativePen, |
| 196 | 				matrix ? matrix->nativeMatrix : NULL)); |
| 197 | 	} |
| 198 | 	REAL GetWidth() const |
| 199 | 	{ |
| 200 | 		REAL result = 1.0f; |
| 201 | 		updateStatus(DllExports::GdipGetPenWidth(nativePen, &result)); |
| 202 | 		return result; |
| 203 | 	} |
| 204 | 	Status MultiplyTransform(const Matrix *matrix, |
| 205 | 			MatrixOrder order = MatrixOrderPrepend) |
| 206 | 	{ |
| 207 | 		return updateStatus(DllExports::GdipMultiplyPenTransform( |
| 208 | 				nativePen, |
| 209 | 				matrix ? matrix->nativeMatrix : NULL, order)); |
| 210 | 	} |
| 211 | 	Status ResetTransform() |
| 212 | 	{ |
| 213 | 		return updateStatus(DllExports::GdipResetPenTransform( |
| 214 | 				nativePen)); |
| 215 | 	} |
| 216 | 	Status RotateTransform(REAL angle, |
| 217 | 			MatrixOrder order = MatrixOrderPrepend) |
| 218 | 	{ |
| 219 | 		return updateStatus(DllExports::GdipRotatePenTransform( |
| 220 | 				nativePen, angle, order)); |
| 221 | 	} |
| 222 | 	Status ScaleTransform(REAL sx, REAL sy, |
| 223 | 			MatrixOrder order = MatrixOrderPrepend) |
| 224 | 	{ |
| 225 | 		return updateStatus(DllExports::GdipScalePenTransform( |
| 226 | 				nativePen, sx, sy, order)); |
| 227 | 	} |
| 228 | 	Status SetAlignment(PenAlignment penAlignment) |
| 229 | 	{ |
| 230 | 		return updateStatus(DllExports::GdipSetPenMode( |
| 231 | 				nativePen, penAlignment)); |
| 232 | 	} |
| 233 | 	Status SetBrush(const Brush *brush) |
| 234 | 	{ |
| 235 | 		return updateStatus(DllExports::GdipSetPenBrushFill( |
| 236 | 				nativePen, brush ? brush->nativeBrush : NULL)); |
| 237 | 	} |
| 238 | 	Status SetColor(const Color& color) |
| 239 | 	{ |
| 240 | 		return updateStatus(DllExports::GdipSetPenColor( |
| 241 | 				nativePen, color.GetValue())); |
| 242 | 	} |
| 243 | 	Status SetCompoundArray(const REAL *compoundArray, INT count) |
| 244 | 	{ |
| 245 | 		return updateStatus(DllExports::GdipSetPenCompoundArray( |
| 246 | 				nativePen, compoundArray, count)); |
| 247 | 	} |
| 248 | 	Status SetCustomEndCap(const CustomLineCap *customCap) |
| 249 | 	{ |
| 250 | 		return updateStatus(DllExports::GdipSetPenCustomEndCap( |
| 251 | 				nativePen, |
| 252 | 				customCap ? customCap->nativeCustomLineCap : NULL)); |
| 253 | 	} |
| 254 | 	Status SetCustomStartCap(const CustomLineCap *customCap) |
| 255 | 	{ |
| 256 | 		return updateStatus(DllExports::GdipSetPenCustomStartCap( |
| 257 | 				nativePen, |
| 258 | 				customCap ? customCap->nativeCustomLineCap : NULL)); |
| 259 | 	} |
| 260 | 	Status SetDashCap(DashCap dashCap) |
| 261 | 	{ |
| 262 | 		return updateStatus(DllExports::GdipSetPenDashCap197819( |
| 263 | 				nativePen, dashCap)); |
| 264 | 	} |
| 265 | 	Status SetDashOffset(REAL dashOffset) |
| 266 | 	{ |
| 267 | 		return updateStatus(DllExports::GdipSetPenDashOffset( |
| 268 | 				nativePen, dashOffset)); |
| 269 | 	} |
| 270 | 	Status SetDashPattern(const REAL *dashArray, INT count) |
| 271 | 	{ |
| 272 | 		return updateStatus(DllExports::GdipSetPenDashArray( |
| 273 | 				nativePen, dashArray, count)); |
| 274 | 	} |
| 275 | 	Status SetDashStyle(DashStyle dashStyle) |
| 276 | 	{ |
| 277 | 		return updateStatus(DllExports::GdipSetPenDashStyle( |
| 278 | 				nativePen, dashStyle)); |
| 279 | 	} |
| 280 | 	Status SetEndCap(LineCap endCap) |
| 281 | 	{ |
| 282 | 		return updateStatus(DllExports::GdipSetPenEndCap( |
| 283 | 				nativePen, endCap)); |
| 284 | 	} |
| 285 | 	Status SetLineCap(LineCap startCap, LineCap endCap, DashCap dashCap) |
| 286 | 	{ |
| 287 | 		return updateStatus(DllExports::GdipSetPenLineCap197819( |
| 288 | 				nativePen, startCap, endCap, dashCap)); |
| 289 | 	} |
| 290 | 	Status SetLineJoin(LineJoin lineJoin) |
| 291 | 	{ |
| 292 | 		return updateStatus(DllExports::GdipSetPenLineJoin( |
| 293 | 				nativePen, lineJoin)); |
| 294 | 	} |
| 295 | 	Status SetMiterLimit(REAL miterLimit) |
| 296 | 	{ |
| 297 | 		return updateStatus(DllExports::GdipSetPenMiterLimit( |
| 298 | 				nativePen, miterLimit)); |
| 299 | 	} |
| 300 | 	Status SetStartCap(LineCap startCap) |
| 301 | 	{ |
| 302 | 		return updateStatus(DllExports::GdipSetPenStartCap( |
| 303 | 				nativePen, startCap)); |
| 304 | 	} |
| 305 | 	Status SetTransform(const Matrix *matrix) |
| 306 | 	{ |
| 307 | 		return updateStatus(DllExports::GdipSetPenTransform( |
| 308 | 				nativePen, |
| 309 | 				matrix ? matrix->nativeMatrix : NULL)); |
| 310 | 	} |
| 311 | 	Status SetWidth(REAL width) |
| 312 | 	{ |
| 313 | 		return updateStatus(DllExports::GdipSetPenWidth( |
| 314 | 				nativePen, width)); |
| 315 | 	} |
| 316 | 	Status TranslateTransform(REAL dx, REAL dy, |
| 317 | 			MatrixOrder order = MatrixOrderPrepend) |
| 318 | 	{ |
| 319 | 		return updateStatus(DllExports::GdipTranslatePenTransform( |
| 320 | 				nativePen, dx, dy, order)); |
| 321 | 	} |
| 322 | |
| 323 | private: |
| 324 | 	Pen(GpPen *pen, Status status): nativePen(pen), lastStatus(status) {} |
| 325 | 	Pen(const Pen& pen); |
| 326 | 	Pen& operator=(const Pen&); |
| 327 | |
| 328 | 	Status updateStatus(Status newStatus) const |
| 329 | 	{ |
| 330 | 		if (newStatus != Ok) lastStatus = newStatus; |
| 331 | 		return newStatus; |
| 332 | 	} |
| 333 | |
| 334 | 	GpPen *nativePen; |
| 335 | 	mutable Status lastStatus; |
| 336 | }; |
| 337 | |
| 338 | #endif /* __GDIPLUS_PEN_H */ |