C++界面库:在GDI上添加完全的alpha混合支持
做完了小型WCF之后,就是小型的WPF了。之前那个完全避免用户大部分的错误使用导致的死锁的方案还有一点点的问题,所以先休息一下,做做别的。为了在C++上重现一套类似WPF的工具,首先要解决绘图部分。
绘图的设备当然是需要可切换的,于是用bridge模式定义了大量的接口,这些接口用来创建画笔、画刷、字体和图形,然后图形用树的形式组织起来,最后放到一块跟窗口链接的画板上面,有需要的时候自动绘制。为了最快速地开始工作,我实现了一个GDI的绘图设备,以后有空再做DirectX的。但是我们知道GDI对alpha的支持是很弱的,只有一个叫alphablend的API用来贴bitmap,因此为了让画刷和画笔都能够支持alpha渐变、alpha位图和alpha颜色,做了很多的工作。下面是截图:
之所以不用GDI+仅仅是因为我不喜欢。下面是利用GDI组合出上面的效果的那部分代码:
1
#include
"
VL_GDIRenderer.h
"
2
3 namespace vl
4 {
5 namespace interaction
6 {
7 namespace renderer
8 {
9
10 enum IndirectFillReason
11 {
12 ifrDirectFill,
13 ifrLinearGradient,
14 ifrAlphaLinearGradient,
15 ifrAlphaBitmap,
16 };
17
18 IndirectFillReason GetIndirectFillReason( const VL_IrBrushRec & Brush)
19 {
20 switch (Brush.BrushKind)
21 {
22 case VL_IrBrushRec::bkSolid:
23 if (Brush.MainColor.A != 255 )
24 {
25 return ifrAlphaBitmap;
26 }
27 else
28 {
29 return ifrDirectFill;
30 }
31 case VL_IrBrushRec::bkLinearGradient:
32 if (Brush.MainColor.A != 255 || Brush.GradientColor.A != 255 )
33 {
34 return ifrAlphaLinearGradient;
35 }
36 else
37 {
38 return ifrLinearGradient;
39 }
40 case VL_IrBrushRec::bkBitmap:
41 if (Brush.Bitmap -> IsAlphaChannelBuilt())
42 {
43 return ifrAlphaBitmap;
44 }
45 else
46 {
47 return ifrDirectFill;
48 }
49 default :
50 return ifrDirectFill;
51 }
52 }
53
54 VBool IsBrushAlpha( const VL_IrBrushRec & Brush)
55 {
56 switch (GetIndirectFillReason(Brush))
57 {
58 case ifrAlphaBitmap:
59 return true ;
60 case ifrAlphaLinearGradient:
61 return true ;
62 default :
63 return false ;
64 }
65 }
66
67 VL_IrColor MixColor( const VL_IrColor & ColorA , const VL_IrColor & ColorB , VDouble Ratio)
68 {
69 return VL_IrColor(
70 ColorA.R + Round(Ratio * (ColorB.R - ColorA.R)),
71 ColorA.G + Round(Ratio * (ColorB.G - ColorA.G)),
72 ColorA.B + Round(Ratio * (ColorB.B - ColorA.B)),
73 ColorA.A + Round(Ratio * (ColorB.A - ColorA.A))
74 );
75 }
76
77 void SetColor(TRIVERTEX & Vertex , const VL_IrColor & Color)
78 {
79 Vertex.Red = Color.R << 8 ;
80 Vertex.Green = Color.G << 8 ;
81 Vertex.Blue = Color.G << 8 ;
82 Vertex.Alpha = Color.A << 8 ;
83 }
84
85 /* ********************************************************************************************************
86 VL_GDIBrush
87 ******************************************************************************************************** */
88
89 VL_GDIBrush::VL_GDIBrush(VL_GDIFactory * Factory , const VL_IrBrushRec & Brush)
90 {
91 FFactory = Factory;
92 FInternalData = Brush;
93 switch (FInternalData.BrushKind)
94 {
95 case VL_IrBrushRec::bkSolid:
96 FBrush = new VL_WinBrush(RGB(FInternalData.MainColor.R,FInternalData.MainColor.G,FInternalData.MainColor.B));
97 if (FInternalData.MainColor.A != 255 )
98 {
99 VL_WinBitmap::Ptr Bitmap = new VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
100 Bitmap -> GetWinDC() -> SetBrush(FBrush);
101 Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
102 Bitmap -> GenerateAlpha(FInternalData.MainColor.A);
103 Bitmap -> BuildAlphaChannel();
104 FInternalData.Bitmap = Bitmap;
105 }
106 break ;
107 case VL_IrBrushRec::bkLinearGradient:
108 break ;
109 case VL_IrBrushRec::bkBitmap:
110 FBrush = new VL_WinBrush(FInternalData.Bitmap);
111 break ;
112 default :
113 throw L " 内部错误 " ;
114 }
115 }
116
117 const VL_IrBrushRec & VL_GDIBrush::GetInternalData()
118 {
119 return FInternalData;
120 }
121
122 IVL_IrFactory * VL_GDIBrush::GetFactory()
123 {
124 return FFactory;
125 }
126
127 VL_WinBrush::Ptr VL_GDIBrush::GetGDIBrush()
128 {
129 return FBrush;
130 }
131
132 /* ********************************************************************************************************
133 VL_GDIPen
134 ******************************************************************************************************** */
135
136 VL_GDIPen::VL_GDIPen(VL_GDIFactory * Factory , const VL_IrBrushRec & Brush , const VL_IrPenRec & Pen)
137 {
138 FFactory = Factory;
139 FInternalBrush = Brush;
140 FInternalPen = Pen;
141
142 VInt EndCap = 0 ;
143 VInt Join = 0 ;
144 switch (FInternalPen.EndCap)
145 {
146 case VL_IrPenRec::ecFlat:
147 EndCap = PS_ENDCAP_FLAT;
148 break ;
149 case VL_IrPenRec::ecRound:
150 EndCap = PS_ENDCAP_ROUND;
151 break ;
152 case VL_IrPenRec::ecSquare:
153 EndCap = PS_ENDCAP_SQUARE;
154 break ;
155 default :
156 throw L " 内部错误 " ;
157 }
158 switch (FInternalPen.Join)
159 {
160 case VL_IrPenRec::jBevel:
161 Join = PS_JOIN_BEVEL;
162 break ;
163 case VL_IrPenRec::jMiter:
164 Join = PS_JOIN_MITER;
165 break ;
166 case VL_IrPenRec::jRound:
167 Join = PS_JOIN_ROUND;
168 break ;
169 default :
170 throw L " 内部错误 " ;
171 }
172
173 switch (FInternalBrush.BrushKind)
174 {
175 case VL_IrBrushRec::bkSolid:
176 FPen = new VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
177 if (FInternalBrush.MainColor.A != 255 )
178 {
179 VL_WinBrush::Ptr SolidBrush = new VL_WinBrush(RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
180 VL_WinBitmap::Ptr Bitmap = new VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
181 Bitmap -> GetWinDC() -> SetBrush(SolidBrush);
182 Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
183 Bitmap -> GenerateAlpha(FInternalBrush.MainColor.A);
184 Bitmap -> BuildAlphaChannel();
185 FInternalBrush.Bitmap = Bitmap;
186 }
187 break ;
188 case VL_IrBrushRec::bkLinearGradient:
189 FPen = new VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
190 break ;
191 case VL_IrBrushRec::bkBitmap:
192 FPen = new VL_WinPen(FInternalBrush.Bitmap,PS_SOLID,EndCap,Join,FInternalPen.Weight);
193 break ;
194 default :
195 throw L " 内部错误 " ;
196 }
197 }
198
199 VL_GDIPen:: ~ VL_GDIPen()
200 {
201 }
202
203 const VL_IrPenRec & VL_GDIPen::GetInternalPen()
204 {
205 return FInternalPen;
206 }
207
208 const VL_IrBrushRec & VL_GDIPen::GetInternalBrush()
209 {
210 return FInternalBrush;
211 }
212
213 IVL_IrFactory * VL_GDIPen::GetFactory()
214 {
215 return FFactory;
216 }
217
218 VL_WinPen::Ptr VL_GDIPen::GetGDIPen()
219 {
220 return FPen;
221 }
222
223 /* ********************************************************************************************************
224 VL_GDIFont
225 ******************************************************************************************************** */
226
227 VL_GDIFont::VL_GDIFont(VL_GDIFactory * Factory , const VL_IrFontRec & Font)
228 {
229 FFactory = Factory;
230 FInternalData = Font;
231 FFont = new VL_WinFont(FInternalData.Name,FInternalData.Height,FInternalData.Width, 0 , 0 ,FInternalData.Bold ? 900 : 400 ,FInternalData.Italic,FInternalData.Underline,FInternalData.StrikeOut, true );
232 }
233
234 VL_GDIFont:: ~ VL_GDIFont()
235 {
236 }
237
238 const VL_IrFontRec & VL_GDIFont::GetInternalData()
239 {
240 return FInternalData;
241 }
242
243 IVL_IrFactory * VL_GDIFont::GetFactory()
244 {
245 return FFactory;
246 }
247
248 VL_WinFont::Ptr VL_GDIFont::GetGDIFont()
249 {
250 return FFont;
251 }
252
253 /* ********************************************************************************************************
254 VL_GDIElement
255 ******************************************************************************************************** */
256
257 VL_WinDC * VL_GDIElement::GetDC()
258 {
259 return FCanvas ? FCanvas -> GetDC(): 0 ;
260 }
261
262 void VL_GDIElement::CreatePath()
263 {
264 FCanvas -> GetDC() -> BeginPath();
265 DrawForPath();
266 FCanvas -> GetDC() -> EndPath();
267 }
268
269 void VL_GDIElement::EnsureRegion()
270 {
271 if (FEnvironmentModified)
272 {
273 FEnvironmentModified = false ;
274 if (FCanvas)
275 {
276 if (FPen)
277 {
278 FCanvas -> GetDC() -> SetPen(FPen -> GetGDIPen());
279 CreatePath();
280 FCanvas -> GetDC() -> WidenPath();
281 FBorderRegion = FCanvas -> GetDC() -> RegionFromPath();
282 CreatePath();
283 FContentRegion = new VL_WinRegion(FCanvas -> GetDC() -> RegionFromPath(),FBorderRegion,RGN_DIFF);
284 }
285 else
286 {
287 CreatePath();
288 FContentRegion = FCanvas -> GetDC() -> RegionFromPath();
289 }
290 {
291 RECT Rect = { 0 , 0 , 0 , 0 };
292 if (FBorderRegion)
293 {
294 Rect = FBorderRegion -> GetBoundRect();
295 }
296 else if (FContentRegion)
297 {
298 Rect = FContentRegion -> GetBoundRect();
299 }
300 FElementRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
301 }
302 {
303 RECT Rect = { 0 , 0 , 0 , 0 };
304 if (FContentRegion)
305 {
306 Rect = FContentRegion -> GetBoundRect();
307 }
308 FClientRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
309 }
310 }
311 }
312 }
313
314 void VL_GDIElement::EnvironmentModified(VL_GDICanvas * Canvas)
315 {
316 if (FCanvas || Canvas)
317 {
318 FCanvas = Canvas;
319 FBorderRegion = 0 ;
320 FContentRegion = 0 ;
321 FElementRectangle = VL_IrRect();
322 FClientRectangle = VL_IrRect();
323 FEnvironmentModified = true ;
324 for (VInt i = 0 ;i < FChildren.GetCount();i ++ )
325 {
326 FChildren[i] -> EnvironmentModified(Canvas);
327 }
328 }
329 }
330
331 VL_WinRegion::Ptr VL_GDIElement::EnterClip(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region)
332 {
333 VL_WinRegion::Ptr Clip = CurrentClip ? new VL_WinRegion(CurrentClip,Region,RGN_AND):Region;
334 FCanvas -> GetDC() -> ClipRegion(Clip);
335 return Clip;
336 }
337
338 void VL_GDIElement::LeaveClip(VL_WinRegion::Ptr CurrentClip)
339 {
340 if (CurrentClip)
341 {
342 FCanvas -> GetDC() -> ClipRegion(CurrentClip);
343 }
344 else
345 {
346 FCanvas -> GetDC() -> RemoveClip();
347 }
348 }
349
350 void VL_GDIElement::FillLinearGradient(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region , const VL_IrBrushRec & Brush)
351 {
352 RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
353 VDouble Sin = sin(Brush.GradientAngle);
354 VDouble Cos = cos(Brush.GradientAngle);
355 if (Sin < 0 )
356 {
357 Cos =- Cos;
358 Sin =- Sin;
359 }
360
361 TRIVERTEX Vertices[ 4 ];
362 Vertices[ 0 ].x = BoundRect.left;
363 Vertices[ 0 ].y = BoundRect.top;
364 Vertices[ 1 ].x = BoundRect.right;
365 Vertices[ 1 ].y = BoundRect.top;
366 Vertices[ 2 ].x = BoundRect.left;
367 Vertices[ 2 ].y = BoundRect.bottom;
368 Vertices[ 3 ].x = BoundRect.right;
369 Vertices[ 3 ].y = BoundRect.bottom;
370 GRADIENT_TRIANGLE Triangles[ 2 ];
371 Triangles[ 0 ].Vertex1 = 0 ;
372 Triangles[ 0 ].Vertex2 = 1 ;
373 Triangles[ 0 ].Vertex3 = 2 ;
374 Triangles[ 1 ].Vertex1 = 1 ;
375 Triangles[ 1 ].Vertex2 = 2 ;
376 Triangles[ 1 ].Vertex3 = 3 ;
377
378 VInt Width = BoundRect.right - BoundRect.left;
379 VInt Height = BoundRect.bottom - BoundRect.top;
380 if (Cos > 0 )
381 {
382 VDouble Ratio = Height * Cos / (Width * Sin + Height * Cos);
383 SetColor(Vertices[ 0 ],Brush.MainColor);
384 SetColor(Vertices[ 1 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
385 SetColor(Vertices[ 2 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
386 SetColor(Vertices[ 3 ],Brush.GradientColor);
387 }
388 else
389 {
390 VDouble Ratio = Width * Sin / (Width * Sin - Height * Cos);
391 SetColor(Vertices[ 0 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
392 SetColor(Vertices[ 1 ],Brush.GradientColor);
393 SetColor(Vertices[ 2 ],Brush.MainColor);
394 SetColor(Vertices[ 3 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
395 }
396
397 if (Brush.MainColor.A == 255 && Brush.GradientColor.A == 255 )
398 {
399 FCanvas -> GetDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
400 }
401 else
402 {
403 FCanvas -> GetAlphaBuffer() -> GetWinDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
404 VInt X1 = BoundRect.left;
405 VInt X2 = BoundRect.right;
406 VInt Y1 = BoundRect.top;
407 VInt Y2 = BoundRect.bottom;
408 if (X1 < 0 )X1 = 0 ;
409 if (Y1 < 0 )Y1 = 0 ;
410 if (X2 > FCanvas -> GetSize().X)X2 = FCanvas -> GetSize().X;
411 if (Y2 > FCanvas -> GetSize().Y)Y2 = FCanvas -> GetSize().Y;
412 for (VInt y = Y1;y < Y2;y ++ )
413 {
414 BYTE * Colors = FCanvas -> GetAlphaBuffer() -> GetScanLines()[y] + X1 * 4 ;
415 for (VInt x = X1;x < X2;x ++ )
416 {
417 BYTE Alpha = Colors[ 3 ];
418 Colors[ 0 ] = Colors[ 0 ] * Alpha / 255 ;
419 Colors[ 1 ] = Colors[ 1 ] * Alpha / 255 ;
420 Colors[ 2 ] = Colors[ 2 ] * Alpha / 255 ;
421 Colors += 4 ;
422 }
423 }
424 FCanvas -> GetDC() -> Draw(X1,Y1,X2 - X1,Y2 - Y1,FCanvas -> GetAlphaBuffer(),X1,Y1,X2 - X1,Y2 - Y1);
425 }
426 LeaveClip(CurrentClip);
427 }
428
429 void VL_GDIElement::FillAlphaBitmap(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region , const VL_IrBrushRec & Brush)
430 {
431 RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
432 VInt W = Brush.Bitmap -> GetWidth();
433 VInt H = Brush.Bitmap -> GetHeight();
434 VInt StartCol = BoundRect.left / W;
435 VInt StartRow = BoundRect.top / H;
436 VInt EndCol = BoundRect.right / W;
437 VInt EndRow = BoundRect.bottom / H;
438 if (EndCol * W != BoundRect.right)
439 {
440 EndCol ++ ;
441 }
442 if (EndRow * H != BoundRect.bottom)
443 {
444 EndRow ++ ;
445 }
446 for (VInt i = StartCol;i <= EndCol;i ++ )
447 {
448 for (VInt j = StartRow;j < EndRow;j ++ )
449 {
450 FCanvas -> GetDC() -> Draw(i * W,j * H,Brush.Bitmap);
451 }
452 }
453 LeaveClip(CurrentClip);
454 }
455
456 void VL_GDIElement::DrawBorder(VL_WinRegion::Ptr CurrentClip)
457 {
458 if (FPen)
459 {
460 FCanvas -> GetDC() -> SetPen(FPen ? FPen -> GetGDIPen():FCanvas -> GetEmptyPen());
461 switch (GetIndirectFillReason(FPen -> GetInternalBrush()))
462 {
463 case ifrDirectFill:
464 if (FElementKind != ekCurve)
465 {
466 FCanvas -> GetDC() -> SetBrush(FCanvas -> GetEmptyBrush());
467 }
468 DrawShape( true );
469 break ;
470 case ifrLinearGradient: case ifrAlphaLinearGradient:
471 EnsureRegion();
472 FillLinearGradient(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
473 break ;
474 case ifrAlphaBitmap:
475 EnsureRegion();
476 FillAlphaBitmap(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
477 break ;
478 default :
479 throw L " 内部错误 " ;
480 }
481 }
482 }
483
484 void VL_GDIElement::DrawFilling(VL_WinRegion::Ptr CurrentClip)
485 {
486 if (FBrush)
487 {
488 switch (GetIndirectFillReason(FBrush -> GetInternalData()))
489 {
490 case ifrDirectFill:
491 FCanvas -> GetDC() -> SetBrush(FBrush -> GetGDIBrush());
492 FCanvas -> GetDC() -> SetPen(FCanvas -> GetEmptyPen());
493 if (FPen && IsBrushAlpha(FPen -> GetInternalBrush()))
494 {
495 EnsureRegion();
496 FCanvas -> GetDC() -> FillRegion(FContentRegion);
497 }
498 else
499 {
500 DrawShape( false );
501 }
502 break ;
503 case ifrLinearGradient: case ifrAlphaLinearGradient:
504 EnsureRegion();
505 FillLinearGradient(CurrentClip,FContentRegion,FBrush -> GetInternalData());
506 break ;
507 case ifrAlphaBitmap:
508 EnsureRegion();
509 FillAlphaBitmap(CurrentClip,FContentRegion,FBrush -> GetInternalData());
510 break ;
511 default :
512 throw L " 内部错误 " ;
513 }
514 }
515 }
516
517 void VL_GDIElement::Draw(VL_WinRegion::Ptr CurrentClip)
518 {
519 if (FVisible)
520 {
521 switch (FElementKind)
522 {
523 case ekCurve:
524 DrawBorder(CurrentClip);
525 break ;
526 case ekShape:
527 DrawFilling(CurrentClip);
528 DrawBorder(CurrentClip);
529 break ;
530 case ekContainerShape:
531 DrawFilling(CurrentClip);
532 if (FChildren.GetCount())
533 {
534 EnsureRegion();
535 VL_WinRegion::Ptr Clip = EnterClip(CurrentClip,FContentRegion);
536 for (VInt i = FChildren.GetCount() - 1 ;i >= 0 ;i -- )
537 {
538 FChildren[i] -> Draw(Clip);
539 }
540 LeaveClip(CurrentClip);
541 }
542 DrawBorder(CurrentClip);
543 break ;
544 }
545 }
546 }
547
548 void VL_GDIElement::DrawShape(VBool Border)
549 {
550 DrawForPath();
551 }
552
553 VL_GDIElement::VL_GDIElement(VL_GDIFactory * Factory , ElementKind aElementKind)
554 {
555 FFactory = Factory;
556 FCanvas = 0 ;
557 FParent = 0 ;
558 FEnvironmentModified = false ;
559 FVisible = true ;
560 FElementKind = aElementKind;
561 }
562
563 VL_GDIElement:: ~ VL_GDIElement()
564 {
565 }
566
567 VInt VL_GDIElement::ChildrenCount()
568 {
569 return FChildren.GetCount();
570 }
571
572 IVL_IrElement::Ptr VL_GDIElement::GetChild(VInt Index)
573 {
574 return FChildren[Index];
575 }
576
577 void VL_GDIElement::AddChild(IVL_IrElement::Ptr Element)
578 {
579 VL_GDIElement::Ptr e = Element;
580 if ( ! e) throw L " 内部错误 " ;
581 FChildren.Add(e);
582 e -> FParent = this ;
583 e -> EnvironmentModified(FCanvas);
584 }
585
586 void VL_GDIElement::InsertChild(VInt Index , IVL_IrElement::Ptr Element)
587 {
588 VL_GDIElement::Ptr e = Element;
589 if ( ! e) throw L " 内部错误 " ;
590 FChildren.Insert(Index,e);
591 e -> FParent = this ;
592 e -> EnvironmentModified(FCanvas);
593 }
594
595 IVL_IrElement::Ptr VL_GDIElement::DeleteChild(IVL_IrElement::Ptr Element)
596 {
597 VInt Index = FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
598 if (Index ==- 1 ) throw L " 内部错误 " ;
599 return DeleteChildAt(Index);
600 }
601
602 IVL_IrElement::Ptr VL_GDIElement::DeleteChildAt(VInt Index)
603 {
604 VL_GDIElement::Ptr e = FChildren.Fetch(Index);
605 e -> FParent = 0 ;
606 e -> EnvironmentModified(FCanvas);
607 return e;
608 }
609
610 VBool VL_GDIElement::HasChild(IVL_IrElement::Ptr Element)
611 {
612 return FChildren.Exists(dynamic_cast < VL_GDIElement *> (Element.Object()));
613 }
614
615 VInt VL_GDIElement::IndexOfChild(IVL_IrElement::Ptr Element)
616 {
617 return FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
618 }
619
620 void VL_GDIElement::MoveChild(VInt FromIndex , VInt ToIndex)
621 {
622 FChildren.Insert(ToIndex,FChildren.Fetch(FromIndex));
623 }
624
625 IVL_IrPen::Ptr VL_GDIElement::GetPen()
626 {
627 return FPen;
628 }
629
630 void VL_GDIElement::SetPen(IVL_IrPen::Ptr Pen)
631 {
632 FPen = Pen;
633 EnvironmentModified(FCanvas);
634 }
635
636 IVL_IrBrush::Ptr VL_GDIElement::GetBrush()
637 {
638 return FBrush;
639 }
640
641 void VL_GDIElement::SetBrush(IVL_IrBrush::Ptr Brush)
642 {
643 FBrush = Brush;
644 }
645
646 IVL_IrFont::Ptr VL_GDIElement::GetFont()
647 {
648 return FFont;
649 }
650
651 void VL_GDIElement::SetFont(IVL_IrFont::Ptr Font)
652 {
653 FFont = Font;
654 EnvironmentModified(FCanvas);
655 }
656
657 VBool VL_GDIElement::GetVisible()
658 {
659 return FVisible;
660 }
661
662 void VL_GDIElement::SetVisible(VBool Value)
663 {
664 FVisible = Value;
665 }
666
667 IVL_IrCanvas * VL_GDIElement::GetCanvas()
668 {
669 return FCanvas;
670 }
671
672 IVL_IrElement * VL_GDIElement::GetParent()
673 {
674 return dynamic_cast < IVL_IrElement *> (FParent);
675 }
676
677 IVL_IrFactory * VL_GDIElement::GetFactory()
678 {
679 return FFactory;
680 }
681
682 IVL_IrElement::HitTestResult VL_GDIElement::ContainedPoint(VL_IrPoint Point)
683 {
684 EnsureRegion();
685 POINT P = {Point.X,Point.Y};
686 if (FBorderRegion)
687 {
688 if (FBorderRegion -> ContainPoint(P))
689 {
690 return IVL_IrElement::htrBorder;
691 }
692 }
693 if (FContentRegion)
694 {
695 if (FContentRegion -> ContainPoint(P))
696 {
697 return IVL_IrElement::htrInternal;
698 }
699 }
700 return IVL_IrElement::htrNone;
701 }
702
703 VL_IrRect VL_GDIElement::GetElementRectangle()
704 {
705 EnsureRegion();
706 return FElementRectangle;
707 }
708
709 VL_IrRect VL_GDIElement::GetClientRectangle()
710 {
711 EnsureRegion();
712 return FClientRectangle;
713 }
714
715 /* ********************************************************************************************************
716 VL_GDILine
717 ******************************************************************************************************** */
718
719 void VL_GDILine::DrawForPath()
720 {
721 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
722 FCanvas -> GetDC() -> MoveTo(Offset.X + FStartPoint.X,Offset.Y + FStartPoint.Y);
723 FCanvas -> GetDC() -> LineTo(Offset.X + FEndPoint.X,Offset.Y + FEndPoint.Y);
724 }
725
726 VL_GDILine::VL_GDILine(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
727 {
728 }
729
730 VL_GDILine:: ~ VL_GDILine()
731 {
732 }
733
734 IVL_IrElementProperties * VL_GDILine::Properties()
735 {
736 return this ;
737 }
738
739 IVL_IrElementContainer * VL_GDILine::Container()
740 {
741 return 0 ;
742 }
743
744 VL_IrPoint VL_GDILine::GetStartPoint()
745 {
746 return FStartPoint;
747 }
748
749 VL_IrPoint VL_GDILine::GetEndPoint()
750 {
751 return FEndPoint;
752 }
753
754 void VL_GDILine::Update( const VL_IrPoint & Start , const VL_IrPoint & End)
755 {
756 FStartPoint = Start;
757 FEndPoint = End;
758 EnvironmentModified(FCanvas);
759 }
760
761 /* ********************************************************************************************************
762 VL_GDIRectangle
763 ******************************************************************************************************** */
764
765 void VL_GDIRectangle::DrawForPath()
766 {
767 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
768 FCanvas -> GetDC() -> Rectangle(
769 Offset.X + FPosition.X,
770 Offset.Y + FPosition.Y,
771 Offset.X + FPosition.X + FSize.X,
772 Offset.Y + FPosition.Y + FSize.Y
773 );
774 }
775
776 VL_GDIRectangle::VL_GDIRectangle(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
777 {
778 }
779
780 VL_GDIRectangle:: ~ VL_GDIRectangle()
781 {
782 }
783
784 IVL_IrElementProperties * VL_GDIRectangle::Properties()
785 {
786 return this ;
787 }
788
789 IVL_IrElementContainer * VL_GDIRectangle::Container()
790 {
791 return this ;
792 }
793
794 VL_IrPoint VL_GDIRectangle::GetPosition()
795 {
796 return FPosition;
797 }
798
799 VL_IrPoint VL_GDIRectangle::GetSize()
800 {
801 return FSize;
802 }
803
804 void VL_GDIRectangle::Update( const VL_IrPoint & Position , const VL_IrPoint & Size)
805 {
806 FPosition = Position;
807 FSize = Size;
808 EnvironmentModified(FCanvas);
809 }
810
811 void VL_GDIRectangle::Update( const VL_IrRect & Rectangle)
812 {
813 Update(Rectangle.Position,Rectangle.Size);
814 }
815
816 /* ********************************************************************************************************
817 VL_GDIRoundRectangle
818 ******************************************************************************************************** */
819
820 void VL_GDIRoundRectangle::DrawForPath()
821 {
822 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
823 FCanvas -> GetDC() -> RoundRect(
824 Offset.X + FPosition.X,
825 Offset.Y + FPosition.Y,
826 Offset.X + FPosition.X + FSize.X,
827 Offset.Y + FPosition.Y + FSize.Y,
828 FEllipse.X,
829 FEllipse.Y
830 );
831 }
832
833 VL_GDIRoundRectangle::VL_GDIRoundRectangle(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
834 {
835 }
836
837 VL_GDIRoundRectangle:: ~ VL_GDIRoundRectangle()
838 {
839 }
840
841 IVL_IrElementProperties * VL_GDIRoundRectangle::Properties()
842 {
843 return this ;
844 }
845
846 IVL_IrElementContainer * VL_GDIRoundRectangle::Container()
847 {
848 return this ;
849 }
850
851 VL_IrPoint VL_GDIRoundRectangle::GetPosition()
852 {
853 return FPosition;
854 }
855
856 VL_IrPoint VL_GDIRoundRectangle::GetSize()
857 {
858 return FSize;
859 }
860
861 VL_IrPoint VL_GDIRoundRectangle::GetEllipse()
862 {
863 return FEllipse;
864 }
865
866 void VL_GDIRoundRectangle::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , const VL_IrPoint & Ellipse)
867 {
868 FPosition = Position;
869 FSize = Size;
870 FEllipse = Ellipse;
871 EnvironmentModified(FCanvas);
872 }
873
874 void VL_GDIRoundRectangle::Update( const VL_IrRect & Rectangle , const VL_IrPoint & Ellipse)
875 {
876 Update(Rectangle.Position,Rectangle.Size,Ellipse);
877 }
878
879 /* ********************************************************************************************************
880 VL_GDIEllipse
881 ******************************************************************************************************** */
882
883 void VL_GDIEllipse::DrawForPath()
884 {
885 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
886 FCanvas -> GetDC() -> Ellipse(
887 Offset.X + FPosition.X,
888 Offset.Y + FPosition.Y,
889 Offset.X + FPosition.X + FSize.X,
890 Offset.Y + FPosition.Y + FSize.Y
891 );
892 }
893
894 VL_GDIEllipse::VL_GDIEllipse(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
895 {
896 }
897
898 VL_GDIEllipse:: ~ VL_GDIEllipse()
899 {
900 }
901
902 IVL_IrElementProperties * VL_GDIEllipse::Properties()
903 {
904 return this ;
905 }
906
907 IVL_IrElementContainer * VL_GDIEllipse::Container()
908 {
909 return this ;
910 }
911
912 VL_IrPoint VL_GDIEllipse::GetPosition()
913 {
914 return FPosition;
915 }
916
917 VL_IrPoint VL_GDIEllipse::GetSize()
918 {
919 return FSize;
920 }
921
922 void VL_GDIEllipse::Update( const VL_IrPoint & Position , const VL_IrPoint & Size)
923 {
924 FPosition = Position;
925 FSize = Size;
926 EnvironmentModified(FCanvas);
927 }
928
929 void VL_GDIEllipse::Update( const VL_IrRect & Rectangle)
930 {
931 Update(Rectangle.Position,Rectangle.Size);
932 }
933
934 /* ********************************************************************************************************
935 VL_GDIChord
936 ******************************************************************************************************** */
937
938 void VL_GDIChord::DrawForPath()
939 {
940 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
941 VInt StartX = Round(cos(FStartAngle) * 1000 );
942 VInt StartY = Round( - sin(FStartAngle) * 1000 );
943 VInt EndX = Round(cos(FEndAngle) * 1000 );
944 VInt EndY = Round( - sin(FEndAngle) * 1000 );
945 FCanvas -> GetDC() -> Chord(
946 Offset.X + FPosition.X,
947 Offset.Y + FPosition.Y,
948 Offset.X + FPosition.X + FSize.X,
949 Offset.Y + FPosition.Y + FSize.Y,
950 Offset.X + FPosition.X + FSize.X / 2 + StartX,
951 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
952 Offset.X + FPosition.X + FSize.X / 2 + EndX,
953 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
954 );
955 }
956
957 VL_GDIChord::VL_GDIChord(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
958 {
959 }
960
961 VL_GDIChord:: ~ VL_GDIChord()
962 {
963 }
964
965 IVL_IrElementProperties * VL_GDIChord::Properties()
966 {
967 return this ;
968 }
969
970 IVL_IrElementContainer * VL_GDIChord::Container()
971 {
972 return this ;
973 }
974
975 VL_IrPoint VL_GDIChord::GetPosition()
976 {
977 return FPosition;
978 }
979
980 VL_IrPoint VL_GDIChord::GetSize()
981 {
982 return FSize;
983 }
984
985 VDouble VL_GDIChord::GetStartAngle()
986 {
987 return FStartAngle;
988 }
989
990 VDouble VL_GDIChord::GetEndAngle()
991 {
992 return FEndAngle;
993 }
994
995 void VL_GDIChord::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
996 {
997 FPosition = Position;
998 FSize = Size;
999 FStartAngle = Start;
1000 FEndAngle = End;
1001 EnvironmentModified(FCanvas);
1002 }
1003
1004 void VL_GDIChord::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1005 {
1006 Update(Rectangle.Position,Rectangle.Size,Start,End);
1007 }
1008
1009 /* ********************************************************************************************************
1010 VL_GDIPie
1011 ******************************************************************************************************** */
1012
1013 void VL_GDIPie::DrawForPath()
1014 {
1015 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1016 VInt StartX = Round(cos(FStartAngle) * 1000 );
1017 VInt StartY = Round( - sin(FStartAngle) * 1000 );
1018 VInt EndX = Round(cos(FEndAngle) * 1000 );
1019 VInt EndY = Round( - sin(FEndAngle) * 1000 );
1020 FCanvas -> GetDC() -> Pie(
1021 Offset.X + FPosition.X,
1022 Offset.Y + FPosition.Y,
1023 Offset.X + FPosition.X + FSize.X,
1024 Offset.Y + FPosition.Y + FSize.Y,
1025 Offset.X + FPosition.X + FSize.X / 2 + StartX,
1026 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1027 Offset.X + FPosition.X + FSize.X / 2 + EndX,
1028 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1029 );
1030 }
1031
1032 VL_GDIPie::VL_GDIPie(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
1033 {
1034 }
1035
1036 VL_GDIPie:: ~ VL_GDIPie()
1037 {
1038 }
1039
1040 IVL_IrElementProperties * VL_GDIPie::Properties()
1041 {
1042 return this ;
1043 }
1044
1045 IVL_IrElementContainer * VL_GDIPie::Container()
1046 {
1047 return this ;
1048 }
1049
1050 VL_IrPoint VL_GDIPie::GetPosition()
1051 {
1052 return FPosition;
1053 }
1054
1055 VL_IrPoint VL_GDIPie::GetSize()
1056 {
1057 return FSize;
1058 }
1059
1060 VDouble VL_GDIPie::GetStartAngle()
1061 {
1062 return FStartAngle;
1063 }
1064
1065 VDouble VL_GDIPie::GetEndAngle()
1066 {
1067 return FEndAngle;
1068 }
1069
1070 void VL_GDIPie::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
1071 {
1072 FPosition = Position;
1073 FSize = Size;
1074 FStartAngle = Start;
1075 FEndAngle = End;
1076 EnvironmentModified(FCanvas);
1077 }
1078
1079 void VL_GDIPie::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1080 {
1081 Update(Rectangle.Position,Rectangle.Size,Start,End);
1082 }
1083
1084 /* ********************************************************************************************************
1085 VL_GDIArc
1086 ******************************************************************************************************** */
1087
1088 void VL_GDIArc::DrawForPath()
1089 {
1090 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1091 VInt StartX = Round(cos(FStartAngle) * 1000 );
1092 VInt StartY = Round( - sin(FStartAngle) * 1000 );
1093 VInt EndX = Round(cos(FEndAngle) * 1000 );
1094 VInt EndY = Round( - sin(FEndAngle) * 1000 );
1095 FCanvas -> GetDC() -> Arc(
1096 Offset.X + FPosition.X,
1097 Offset.Y + FPosition.Y,
1098 Offset.X + FPosition.X + FSize.X,
1099 Offset.Y + FPosition.Y + FSize.Y,
1100 Offset.X + FPosition.X + FSize.X / 2 + StartX,
1101 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1102 Offset.X + FPosition.X + FSize.X / 2 + EndX,
1103 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1104 );
1105 }
1106
1107 VL_GDIArc::VL_GDIArc(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1108 {
1109 }
1110
1111 VL_GDIArc:: ~ VL_GDIArc()
1112 {
1113 }
1114
1115 IVL_IrElementProperties * VL_GDIArc::Properties()
1116 {
1117 return this ;
1118 }
1119
1120 IVL_IrElementContainer * VL_GDIArc::Container()
1121 {
1122 return 0 ;
1123 }
1124
1125 VL_IrPoint VL_GDIArc::GetPosition()
1126 {
1127 return FPosition;
1128 }
1129
1130 VL_IrPoint VL_GDIArc::GetSize()
1131 {
1132 return FSize;
1133 }
1134
1135 VDouble VL_GDIArc::GetStartAngle()
1136 {
1137 return FStartAngle;
1138 }
1139
1140 VDouble VL_GDIArc::GetEndAngle()
1141 {
1142 return FEndAngle;
1143 }
1144
1145 void VL_GDIArc::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
1146 {
1147 FPosition = Position;
1148 FSize = Size;
1149 FStartAngle = Start;
1150 FEndAngle = End;
1151 EnvironmentModified(FCanvas);
1152 }
1153
1154 void VL_GDIArc::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1155 {
1156 Update(Rectangle.Position,Rectangle.Size,Start,End);
1157 }
1158
1159 /* ********************************************************************************************************
1160 VL_GDIPolyline
1161 ******************************************************************************************************** */
1162
1163 void VL_GDIPolyline::DrawForPath()
1164 {
1165 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1166 for (VInt i = 0 ;i < FCount;i ++ )
1167 {
1168 FBuffer[i].x = Offset.X + FPoints[i].X;
1169 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1170 }
1171 FCanvas -> GetDC() -> PolyLine(FBuffer,FCount);
1172 }
1173
1174 VL_GDIPolyline::VL_GDIPolyline(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1175 {
1176 FCount = 0 ;
1177 FPoints = 0 ;
1178 FBuffer = 0 ;
1179 }
1180
1181 VL_GDIPolyline:: ~ VL_GDIPolyline()
1182 {
1183 if (FPoints)delete[] FPoints;
1184 if (FBuffer)delete[] FBuffer;
1185 }
1186
1187 IVL_IrElementProperties * VL_GDIPolyline::Properties()
1188 {
1189 return this ;
1190 }
1191
1192 IVL_IrElementContainer * VL_GDIPolyline::Container()
1193 {
1194 return 0 ;
1195 }
1196
1197 VInt VL_GDIPolyline::GetHandlerCount()
1198 {
1199 return FCount;
1200 }
1201
1202 VL_IrPoint VL_GDIPolyline::GetHandler(VInt Index)
1203 {
1204 if (Index >= 0 && Index < FCount)
1205 {
1206 return FPoints[Index];
1207 }
1208 else
1209 {
1210 throw L " 内部错误 " ;
1211 }
1212 }
1213
1214 void VL_GDIPolyline::Update(VL_IrPoint * Handlers , VInt Count)
1215 {
1216 FCount = Count;
1217 if (FPoints)delete[] FPoints;
1218 FPoints = new VL_IrPoint[FCount];
1219 if (FBuffer)delete[] FBuffer;
1220 FBuffer = new POINT[FCount];
1221 for (VInt i = 0 ;i < FCount;i ++ )
1222 {
1223 FPoints[i] = Handlers[i];
1224 }
1225 EnvironmentModified(FCanvas);
1226 }
1227
1228 /* ********************************************************************************************************
1229 VL_GDIPolygon
1230 ******************************************************************************************************** */
1231
1232 void VL_GDIPolygon::DrawForPath()
1233 {
1234 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1235 for (VInt i = 0 ;i < FCount;i ++ )
1236 {
1237 FBuffer[i].x = Offset.X + FPoints[i].X;
1238 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1239 }
1240 FCanvas -> GetDC() -> PolyGon(FBuffer,FCount);
1241 }
1242
1243 VL_GDIPolygon::VL_GDIPolygon(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
1244 {
1245 FCount = 0 ;
1246 FPoints = 0 ;
1247 FBuffer = 0 ;
1248 }
1249
1250 VL_GDIPolygon:: ~ VL_GDIPolygon()
1251 {
1252 if (FPoints)delete[] FPoints;
1253 if (FBuffer)delete[] FBuffer;
1254 }
1255
1256 IVL_IrElementProperties * VL_GDIPolygon::Properties()
1257 {
1258 return this ;
1259 }
1260
1261 IVL_IrElementContainer * VL_GDIPolygon::Container()
1262 {
1263 return this ;
1264 }
1265
1266 VInt VL_GDIPolygon::GetHandlerCount()
1267 {
1268 return FCount;
1269 }
1270
1271 VL_IrPoint VL_GDIPolygon::GetHandler(VInt Index)
1272 {
1273 if (Index >= 0 && Index < FCount)
1274 {
1275 return FPoints[Index];
1276 }
1277 else
1278 {
1279 throw L " 内部错误 " ;
1280 }
1281 }
1282
1283 void VL_GDIPolygon::Update(VL_IrPoint * Handlers , VInt Count)
1284 {
1285 FCount = Count;
1286 if (FPoints)delete[] FPoints;
1287 FPoints = new VL_IrPoint[FCount];
1288 if (FBuffer)delete[] FBuffer;
1289 FBuffer = new POINT[FCount];
1290 for (VInt i = 0 ;i < FCount;i ++ )
1291 {
1292 FPoints[i] = Handlers[i];
1293 }
1294 EnvironmentModified(FCanvas);
1295 }
1296
1297 /* ********************************************************************************************************
1298 VL_GDIBezier
1299 ******************************************************************************************************** */
1300
1301 void VL_GDIBezier::DrawForPath()
1302 {
1303 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1304 for (VInt i = 0 ;i < FCount;i ++ )
1305 {
1306 FBuffer[i].x = Offset.X + FPoints[i].X;
1307 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1308 }
1309 FCanvas -> GetDC() -> PolyBezier(FBuffer,FCount);
1310 }
1311
1312 VL_GDIBezier::VL_GDIBezier(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1313 {
1314 FCount = 0 ;
1315 FPoints = 0 ;
1316 FBuffer = 0 ;
1317 }
1318
1319 VL_GDIBezier:: ~ VL_GDIBezier()
1320 {
1321 if (FPoints)delete[] FPoints;
1322 if (FBuffer)delete[] FBuffer;
1323 }
1324
1325 IVL_IrElementProperties * VL_GDIBezier::Properties()
1326 {
1327 return this ;
1328 }
1329
1330 IVL_IrElementContainer * VL_GDIBezier::Container()
1331 {
1332 return 0 ;
1333 }
1334
1335 VInt VL_GDIBezier::GetHandlerCount()
1336 {
1337 return FCount;
1338 }
1339
1340 VL_IrPoint VL_GDIBezier::GetHandler(VInt Index)
1341 {
1342 if (Index >= 0 && Index < FCount)
1343 {
1344 return FPoints[Index];
1345 }
1346 else
1347 {
1348 throw L " 内部错误 " ;
1349 }
1350 }
1351
1352 void VL_GDIBezier::Update(VL_IrPoint * Handlers , VInt Count)
1353 {
1354 FCount = Count;
1355 if (FPoints)delete[] FPoints;
1356 FPoints = new VL_IrPoint[FCount];
1357 if (FBuffer)delete[] FBuffer;
1358 FBuffer = new POINT[FCount];
1359 for (VInt i = 0 ;i < FCount;i ++ )
1360 {
1361 FPoints[i] = Handlers[i];
1362 }
1363 EnvironmentModified(FCanvas);
1364 }
1365
1366 /* ********************************************************************************************************
1367 VL_GDIText
1368 ******************************************************************************************************** */
1369
1370 void VL_GDIText::EnvironmentModified(VL_GDICanvas * Canvas)
1371 {
1372 VL_GDIElement::EnvironmentModified(Canvas);
1373 if (FCanvas && FFont)
1374 {
1375 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1376 SIZE Size = FCanvas -> GetDC() -> MeasureString(FText);
1377 FSize = VL_IrPoint(Size.cx,Size.cy);
1378 }
1379 else
1380 {
1381 FSize = VL_IrPoint();
1382 }
1383 }
1384
1385 void VL_GDIText::Draw(VL_WinRegion::Ptr CurrentClip)
1386 {
1387 VBool Painted = false ;
1388 if ( ! FFont)
1389 {
1390 Painted = true ;
1391 }
1392 else if ( ! FPen)
1393 {
1394 if (FBrush)
1395 {
1396 const VL_IrBrushRec & BrushRec = FBrush -> GetInternalData();
1397 if (BrushRec.BrushKind == VL_IrBrushRec::bkSolid && BrushRec.MainColor.A == 255 )
1398 {
1399 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1400 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1401 FCanvas -> GetDC() -> SetTextColor(RGB(BrushRec.MainColor.R,BrushRec.MainColor.G,BrushRec.MainColor.B));
1402 FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1403 Painted = true ;
1404 }
1405 }
1406 else
1407 {
1408 Painted = true ;
1409 }
1410 }
1411 if ( ! Painted)
1412 {
1413 VL_GDIElement::Draw(CurrentClip);
1414 }
1415 }
1416
1417 void VL_GDIText::DrawShape(VBool Border)
1418 {
1419 EnsureRegion();
1420 if (Border)
1421 {
1422 FCanvas -> GetDC() -> SetBrush(FPenBrush -> GetGDIBrush());
1423 FCanvas -> GetDC() -> FillRegion(FBorderRegion);
1424 }
1425 else
1426 {
1427 FCanvas -> GetDC() -> FillRegion(FContentRegion);
1428 }
1429 }
1430
1431 void VL_GDIText::DrawForPath()
1432 {
1433 if (FFont)
1434 {
1435 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1436 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1437 FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1438 }
1439 }
1440
1441 VL_GDIText::VL_GDIText(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekShape)
1442 {
1443 }
1444
1445 VL_GDIText:: ~ VL_GDIText()
1446 {
1447 }
1448
1449 IVL_IrElementProperties * VL_GDIText::Properties()
1450 {
1451 return this ;
1452 }
1453
1454 IVL_IrElementContainer * VL_GDIText::Container()
1455 {
1456 return 0 ;
1457 }
1458
1459 void VL_GDIText::SetPen(IVL_IrPen::Ptr Pen)
1460 {
1461 VL_GDIElement::SetPen(Pen);
1462 if (FPen)
1463 {
1464 FPenBrush = FFactory -> CreateBrush(FPen -> GetInternalBrush());
1465 }
1466 else
1467 {
1468 FPenBrush = 0 ;
1469 }
1470 }
1471
1472 VL_IrRect VL_GDIText::GetElementRectangle()
1473 {
1474 return VL_IrRect(FPosition,FSize);
1475 }
1476
1477 VL_IrRect VL_GDIText::GetClientRectangle()
1478 {
1479 return VL_IrRect(FPosition,FSize);
1480 }
1481
1482 VL_IrPoint VL_GDIText::GetPosition()
1483 {
1484 return FPosition;
1485 }
1486
1487 VUnicodeString VL_GDIText::GetText()
1488 {
1489 return FText;
1490 }
1491
1492 void VL_GDIText::Update(VL_IrPoint Position , VUnicodeString Text)
1493 {
1494 FPosition = Position;
1495 FText = Text;
1496 EnvironmentModified(FCanvas);
1497 }
1498
1499 /* ********************************************************************************************************
1500 VL_GDICanvas
1501 ******************************************************************************************************** */
1502
1503 void VL_GDICanvas::UpdateBuffer()
1504 {
1505 FBuffer = new VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1506 SetPolyFillMode(FBuffer -> GetWinDC() -> GetHandle(),WINDING);
1507 FBuffer -> GetWinDC() -> SetBackTransparent( true );
1508 FAlphaBuffer = new VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1509 FAlphaBuffer -> BuildAlphaChannel();
1510 if (FRootElement)
1511 {
1512 FRootElement -> EnvironmentModified( this );
1513 }
1514 Render();
1515 }
1516
1517 void VL_GDICanvas::HostPaint(VL_Base * Sender)
1518 {
1519 FHostDC -> Draw( 0 , 0 ,FBuffer);
1520 }
1521
1522 void VL_GDICanvas::HostSized(VL_Base * Sender)
1523 {
1524 UpdateBuffer();
1525 }
1526
1527 VL_GDICanvas::VL_GDICanvas(VL_GDIFactory * Factory , VL_WinControl * Control)
1528 {
1529 FFactory = Factory;
1530 FHost = Control;
1531 FHostDC = new VL_WinControlDC(FHost -> GetHandle());
1532 FEmptyPen = new VL_WinPen(PS_NULL, 1 , 0 );
1533 FEmptyBrush = new VL_WinBrush;
1534 FBackgroundBrush = new VL_WinBrush(RGB( 255 , 255 , 255 ));
1535 UpdateBuffer();
1536
1537 FHost -> OnPaint.Bind( this , & VL_GDICanvas::HostPaint);
1538 FHost -> OnSized.Bind( this , & VL_GDICanvas::HostSized);
1539 }
1540
1541 VL_GDICanvas:: ~ VL_GDICanvas()
1542 {
1543 FHost -> OnPaint.Unbind( this , & VL_GDICanvas::HostPaint);
1544 FHost -> OnSized.Unbind( this , & VL_GDICanvas::HostSized);
1545 delete FHostDC;
1546 }
1547
1548 IVL_IrFactory * VL_GDICanvas::GetFactory()
1549 {
1550 return FFactory;
1551 }
1552
1553 VL_IrPoint VL_GDICanvas::GetSize()
1554 {
1555 return VL_IrPoint(FBuffer -> GetWidth(),FBuffer -> GetHeight());
1556 }
1557
1558 IVL_IrElement::Ptr VL_GDICanvas::GetRootElement()
1559 {
1560 return FRootElement;
1561 }
1562
1563 void VL_GDICanvas::SetRootElement(IVL_IrElement::Ptr Element)
1564 {
1565 FRootElement = Element;
1566 if (Element)
1567 {
1568 if (FRootElement)
1569 {
1570 FRootElement -> EnvironmentModified( this );
1571 }
1572 else
1573 {
1574 throw L " 内部错误 " ;
1575 }
1576 }
1577 }
1578
1579 void VL_GDICanvas::Render()
1580 {
1581 FBuffer -> GetWinDC() -> SetBrush(FBackgroundBrush);
1582 FBuffer -> GetWinDC() -> FillRect( 0 , 0 ,FBuffer -> GetWidth(),FBuffer -> GetHeight());
1583 if (FRootElement)
1584 {
1585 FRootElement -> Draw( 0 );
1586 }
1587 UpdateWindow(FHost -> GetHandle());
1588 }
1589
1590 VL_WinDC * VL_GDICanvas::GetDC()
1591 {
1592 return FBuffer -> GetWinDC();
1593 }
1594
1595 VL_WinBitmap::Ptr VL_GDICanvas::GetAlphaBuffer()
1596 {
1597 return FAlphaBuffer;
1598 }
1599
1600 VL_WinPen::Ptr VL_GDICanvas::GetEmptyPen()
1601 {
1602 return FEmptyPen;
1603 }
1604
1605 VL_WinBrush::Ptr VL_GDICanvas::GetEmptyBrush()
1606 {
1607 return FEmptyBrush;
1608 }
1609
1610 /* ********************************************************************************************************
1611 VL_GDIFactory
1612 ******************************************************************************************************** */
1613
1614 class GDIFactoryRegister
1615 {
1616 public :
1617 static IVL_IrFactory::Ptr Constructor()
1618 {
1619 return new VL_GDIFactory;
1620 }
1621
1622 GDIFactoryRegister()
1623 {
1624 RegisterInteractionFactory(L " GDI " ,Constructor);
1625 }
1626 } _GDIFactoryRegister;
1627
1628 IVL_IrBrush::Ptr VL_GDIFactory::CreateBrush( const VL_IrBrushRec & Brush)
1629 {
1630 return new VL_GDIBrush( this ,Brush);
1631 }
1632
1633 IVL_IrPen::Ptr VL_GDIFactory::CreatePen( const VL_IrBrushRec & Brush , const VL_IrPenRec & Pen)
1634 {
1635 return new VL_GDIPen( this ,Brush,Pen);
1636 }
1637
1638 IVL_IrFont::Ptr VL_GDIFactory::CreateFont( const VL_IrFontRec & Font)
1639 {
1640 return new VL_GDIFont( this ,Font);
1641 }
1642
1643 IVL_IrLine::Ptr VL_GDIFactory::CreateLine()
1644 {
1645 return new VL_GDILine( this );
1646 }
1647
1648 IVL_IrRectangle::Ptr VL_GDIFactory::CreateRectangle()
1649 {
1650 return new VL_GDIRectangle( this );
1651 }
1652
1653 IVL_IrRoundRectangle::Ptr VL_GDIFactory::CreateRoundRectangle()
1654 {
1655 return new VL_GDIRoundRectangle( this );
1656 }
1657
1658 IVL_IrEllipse::Ptr VL_GDIFactory::CreateEllipse()
1659 {
1660 return new VL_GDIEllipse( this );
1661 }
1662
1663 IVL_IrChord::Ptr VL_GDIFactory::CreateChord()
1664 {
1665 return new VL_GDIChord( this );
1666 }
1667
1668 IVL_IrPie::Ptr VL_GDIFactory::CreatePie()
1669 {
1670 return new VL_GDIPie( this );
1671 }
1672
1673 IVL_IrArc::Ptr VL_GDIFactory::CreateArc()
1674 {
1675 return new VL_GDIArc( this );
1676 }
1677
1678 IVL_IrPolyline::Ptr VL_GDIFactory::CreatePolyline()
1679 {
1680 return new VL_GDIPolyline( this );
1681 }
1682
1683 IVL_IrPolygon::Ptr VL_GDIFactory::CreatePolygon()
1684 {
1685 return new VL_GDIPolygon( this );
1686 }
1687
1688 IVL_IrBezier::Ptr VL_GDIFactory::CreateBezier()
1689 {
1690 return new VL_GDIBezier( this );
1691 }
1692
1693 IVL_IrText::Ptr VL_GDIFactory::CreateText()
1694 {
1695 return new VL_GDIText( this );
1696 }
1697
1698 IVL_IrCanvas::Ptr VL_GDIFactory::CreateCanvas(VL_WinControl * Control)
1699 {
1700 return new VL_GDICanvas( this ,Control);
1701 }
1702 }
1703 }
1704 }
2
3 namespace vl
4 {
5 namespace interaction
6 {
7 namespace renderer
8 {
9
10 enum IndirectFillReason
11 {
12 ifrDirectFill,
13 ifrLinearGradient,
14 ifrAlphaLinearGradient,
15 ifrAlphaBitmap,
16 };
17
18 IndirectFillReason GetIndirectFillReason( const VL_IrBrushRec & Brush)
19 {
20 switch (Brush.BrushKind)
21 {
22 case VL_IrBrushRec::bkSolid:
23 if (Brush.MainColor.A != 255 )
24 {
25 return ifrAlphaBitmap;
26 }
27 else
28 {
29 return ifrDirectFill;
30 }
31 case VL_IrBrushRec::bkLinearGradient:
32 if (Brush.MainColor.A != 255 || Brush.GradientColor.A != 255 )
33 {
34 return ifrAlphaLinearGradient;
35 }
36 else
37 {
38 return ifrLinearGradient;
39 }
40 case VL_IrBrushRec::bkBitmap:
41 if (Brush.Bitmap -> IsAlphaChannelBuilt())
42 {
43 return ifrAlphaBitmap;
44 }
45 else
46 {
47 return ifrDirectFill;
48 }
49 default :
50 return ifrDirectFill;
51 }
52 }
53
54 VBool IsBrushAlpha( const VL_IrBrushRec & Brush)
55 {
56 switch (GetIndirectFillReason(Brush))
57 {
58 case ifrAlphaBitmap:
59 return true ;
60 case ifrAlphaLinearGradient:
61 return true ;
62 default :
63 return false ;
64 }
65 }
66
67 VL_IrColor MixColor( const VL_IrColor & ColorA , const VL_IrColor & ColorB , VDouble Ratio)
68 {
69 return VL_IrColor(
70 ColorA.R + Round(Ratio * (ColorB.R - ColorA.R)),
71 ColorA.G + Round(Ratio * (ColorB.G - ColorA.G)),
72 ColorA.B + Round(Ratio * (ColorB.B - ColorA.B)),
73 ColorA.A + Round(Ratio * (ColorB.A - ColorA.A))
74 );
75 }
76
77 void SetColor(TRIVERTEX & Vertex , const VL_IrColor & Color)
78 {
79 Vertex.Red = Color.R << 8 ;
80 Vertex.Green = Color.G << 8 ;
81 Vertex.Blue = Color.G << 8 ;
82 Vertex.Alpha = Color.A << 8 ;
83 }
84
85 /* ********************************************************************************************************
86 VL_GDIBrush
87 ******************************************************************************************************** */
88
89 VL_GDIBrush::VL_GDIBrush(VL_GDIFactory * Factory , const VL_IrBrushRec & Brush)
90 {
91 FFactory = Factory;
92 FInternalData = Brush;
93 switch (FInternalData.BrushKind)
94 {
95 case VL_IrBrushRec::bkSolid:
96 FBrush = new VL_WinBrush(RGB(FInternalData.MainColor.R,FInternalData.MainColor.G,FInternalData.MainColor.B));
97 if (FInternalData.MainColor.A != 255 )
98 {
99 VL_WinBitmap::Ptr Bitmap = new VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
100 Bitmap -> GetWinDC() -> SetBrush(FBrush);
101 Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
102 Bitmap -> GenerateAlpha(FInternalData.MainColor.A);
103 Bitmap -> BuildAlphaChannel();
104 FInternalData.Bitmap = Bitmap;
105 }
106 break ;
107 case VL_IrBrushRec::bkLinearGradient:
108 break ;
109 case VL_IrBrushRec::bkBitmap:
110 FBrush = new VL_WinBrush(FInternalData.Bitmap);
111 break ;
112 default :
113 throw L " 内部错误 " ;
114 }
115 }
116
117 const VL_IrBrushRec & VL_GDIBrush::GetInternalData()
118 {
119 return FInternalData;
120 }
121
122 IVL_IrFactory * VL_GDIBrush::GetFactory()
123 {
124 return FFactory;
125 }
126
127 VL_WinBrush::Ptr VL_GDIBrush::GetGDIBrush()
128 {
129 return FBrush;
130 }
131
132 /* ********************************************************************************************************
133 VL_GDIPen
134 ******************************************************************************************************** */
135
136 VL_GDIPen::VL_GDIPen(VL_GDIFactory * Factory , const VL_IrBrushRec & Brush , const VL_IrPenRec & Pen)
137 {
138 FFactory = Factory;
139 FInternalBrush = Brush;
140 FInternalPen = Pen;
141
142 VInt EndCap = 0 ;
143 VInt Join = 0 ;
144 switch (FInternalPen.EndCap)
145 {
146 case VL_IrPenRec::ecFlat:
147 EndCap = PS_ENDCAP_FLAT;
148 break ;
149 case VL_IrPenRec::ecRound:
150 EndCap = PS_ENDCAP_ROUND;
151 break ;
152 case VL_IrPenRec::ecSquare:
153 EndCap = PS_ENDCAP_SQUARE;
154 break ;
155 default :
156 throw L " 内部错误 " ;
157 }
158 switch (FInternalPen.Join)
159 {
160 case VL_IrPenRec::jBevel:
161 Join = PS_JOIN_BEVEL;
162 break ;
163 case VL_IrPenRec::jMiter:
164 Join = PS_JOIN_MITER;
165 break ;
166 case VL_IrPenRec::jRound:
167 Join = PS_JOIN_ROUND;
168 break ;
169 default :
170 throw L " 内部错误 " ;
171 }
172
173 switch (FInternalBrush.BrushKind)
174 {
175 case VL_IrBrushRec::bkSolid:
176 FPen = new VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
177 if (FInternalBrush.MainColor.A != 255 )
178 {
179 VL_WinBrush::Ptr SolidBrush = new VL_WinBrush(RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
180 VL_WinBitmap::Ptr Bitmap = new VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
181 Bitmap -> GetWinDC() -> SetBrush(SolidBrush);
182 Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
183 Bitmap -> GenerateAlpha(FInternalBrush.MainColor.A);
184 Bitmap -> BuildAlphaChannel();
185 FInternalBrush.Bitmap = Bitmap;
186 }
187 break ;
188 case VL_IrBrushRec::bkLinearGradient:
189 FPen = new VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
190 break ;
191 case VL_IrBrushRec::bkBitmap:
192 FPen = new VL_WinPen(FInternalBrush.Bitmap,PS_SOLID,EndCap,Join,FInternalPen.Weight);
193 break ;
194 default :
195 throw L " 内部错误 " ;
196 }
197 }
198
199 VL_GDIPen:: ~ VL_GDIPen()
200 {
201 }
202
203 const VL_IrPenRec & VL_GDIPen::GetInternalPen()
204 {
205 return FInternalPen;
206 }
207
208 const VL_IrBrushRec & VL_GDIPen::GetInternalBrush()
209 {
210 return FInternalBrush;
211 }
212
213 IVL_IrFactory * VL_GDIPen::GetFactory()
214 {
215 return FFactory;
216 }
217
218 VL_WinPen::Ptr VL_GDIPen::GetGDIPen()
219 {
220 return FPen;
221 }
222
223 /* ********************************************************************************************************
224 VL_GDIFont
225 ******************************************************************************************************** */
226
227 VL_GDIFont::VL_GDIFont(VL_GDIFactory * Factory , const VL_IrFontRec & Font)
228 {
229 FFactory = Factory;
230 FInternalData = Font;
231 FFont = new VL_WinFont(FInternalData.Name,FInternalData.Height,FInternalData.Width, 0 , 0 ,FInternalData.Bold ? 900 : 400 ,FInternalData.Italic,FInternalData.Underline,FInternalData.StrikeOut, true );
232 }
233
234 VL_GDIFont:: ~ VL_GDIFont()
235 {
236 }
237
238 const VL_IrFontRec & VL_GDIFont::GetInternalData()
239 {
240 return FInternalData;
241 }
242
243 IVL_IrFactory * VL_GDIFont::GetFactory()
244 {
245 return FFactory;
246 }
247
248 VL_WinFont::Ptr VL_GDIFont::GetGDIFont()
249 {
250 return FFont;
251 }
252
253 /* ********************************************************************************************************
254 VL_GDIElement
255 ******************************************************************************************************** */
256
257 VL_WinDC * VL_GDIElement::GetDC()
258 {
259 return FCanvas ? FCanvas -> GetDC(): 0 ;
260 }
261
262 void VL_GDIElement::CreatePath()
263 {
264 FCanvas -> GetDC() -> BeginPath();
265 DrawForPath();
266 FCanvas -> GetDC() -> EndPath();
267 }
268
269 void VL_GDIElement::EnsureRegion()
270 {
271 if (FEnvironmentModified)
272 {
273 FEnvironmentModified = false ;
274 if (FCanvas)
275 {
276 if (FPen)
277 {
278 FCanvas -> GetDC() -> SetPen(FPen -> GetGDIPen());
279 CreatePath();
280 FCanvas -> GetDC() -> WidenPath();
281 FBorderRegion = FCanvas -> GetDC() -> RegionFromPath();
282 CreatePath();
283 FContentRegion = new VL_WinRegion(FCanvas -> GetDC() -> RegionFromPath(),FBorderRegion,RGN_DIFF);
284 }
285 else
286 {
287 CreatePath();
288 FContentRegion = FCanvas -> GetDC() -> RegionFromPath();
289 }
290 {
291 RECT Rect = { 0 , 0 , 0 , 0 };
292 if (FBorderRegion)
293 {
294 Rect = FBorderRegion -> GetBoundRect();
295 }
296 else if (FContentRegion)
297 {
298 Rect = FContentRegion -> GetBoundRect();
299 }
300 FElementRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
301 }
302 {
303 RECT Rect = { 0 , 0 , 0 , 0 };
304 if (FContentRegion)
305 {
306 Rect = FContentRegion -> GetBoundRect();
307 }
308 FClientRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
309 }
310 }
311 }
312 }
313
314 void VL_GDIElement::EnvironmentModified(VL_GDICanvas * Canvas)
315 {
316 if (FCanvas || Canvas)
317 {
318 FCanvas = Canvas;
319 FBorderRegion = 0 ;
320 FContentRegion = 0 ;
321 FElementRectangle = VL_IrRect();
322 FClientRectangle = VL_IrRect();
323 FEnvironmentModified = true ;
324 for (VInt i = 0 ;i < FChildren.GetCount();i ++ )
325 {
326 FChildren[i] -> EnvironmentModified(Canvas);
327 }
328 }
329 }
330
331 VL_WinRegion::Ptr VL_GDIElement::EnterClip(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region)
332 {
333 VL_WinRegion::Ptr Clip = CurrentClip ? new VL_WinRegion(CurrentClip,Region,RGN_AND):Region;
334 FCanvas -> GetDC() -> ClipRegion(Clip);
335 return Clip;
336 }
337
338 void VL_GDIElement::LeaveClip(VL_WinRegion::Ptr CurrentClip)
339 {
340 if (CurrentClip)
341 {
342 FCanvas -> GetDC() -> ClipRegion(CurrentClip);
343 }
344 else
345 {
346 FCanvas -> GetDC() -> RemoveClip();
347 }
348 }
349
350 void VL_GDIElement::FillLinearGradient(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region , const VL_IrBrushRec & Brush)
351 {
352 RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
353 VDouble Sin = sin(Brush.GradientAngle);
354 VDouble Cos = cos(Brush.GradientAngle);
355 if (Sin < 0 )
356 {
357 Cos =- Cos;
358 Sin =- Sin;
359 }
360
361 TRIVERTEX Vertices[ 4 ];
362 Vertices[ 0 ].x = BoundRect.left;
363 Vertices[ 0 ].y = BoundRect.top;
364 Vertices[ 1 ].x = BoundRect.right;
365 Vertices[ 1 ].y = BoundRect.top;
366 Vertices[ 2 ].x = BoundRect.left;
367 Vertices[ 2 ].y = BoundRect.bottom;
368 Vertices[ 3 ].x = BoundRect.right;
369 Vertices[ 3 ].y = BoundRect.bottom;
370 GRADIENT_TRIANGLE Triangles[ 2 ];
371 Triangles[ 0 ].Vertex1 = 0 ;
372 Triangles[ 0 ].Vertex2 = 1 ;
373 Triangles[ 0 ].Vertex3 = 2 ;
374 Triangles[ 1 ].Vertex1 = 1 ;
375 Triangles[ 1 ].Vertex2 = 2 ;
376 Triangles[ 1 ].Vertex3 = 3 ;
377
378 VInt Width = BoundRect.right - BoundRect.left;
379 VInt Height = BoundRect.bottom - BoundRect.top;
380 if (Cos > 0 )
381 {
382 VDouble Ratio = Height * Cos / (Width * Sin + Height * Cos);
383 SetColor(Vertices[ 0 ],Brush.MainColor);
384 SetColor(Vertices[ 1 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
385 SetColor(Vertices[ 2 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
386 SetColor(Vertices[ 3 ],Brush.GradientColor);
387 }
388 else
389 {
390 VDouble Ratio = Width * Sin / (Width * Sin - Height * Cos);
391 SetColor(Vertices[ 0 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
392 SetColor(Vertices[ 1 ],Brush.GradientColor);
393 SetColor(Vertices[ 2 ],Brush.MainColor);
394 SetColor(Vertices[ 3 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
395 }
396
397 if (Brush.MainColor.A == 255 && Brush.GradientColor.A == 255 )
398 {
399 FCanvas -> GetDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
400 }
401 else
402 {
403 FCanvas -> GetAlphaBuffer() -> GetWinDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
404 VInt X1 = BoundRect.left;
405 VInt X2 = BoundRect.right;
406 VInt Y1 = BoundRect.top;
407 VInt Y2 = BoundRect.bottom;
408 if (X1 < 0 )X1 = 0 ;
409 if (Y1 < 0 )Y1 = 0 ;
410 if (X2 > FCanvas -> GetSize().X)X2 = FCanvas -> GetSize().X;
411 if (Y2 > FCanvas -> GetSize().Y)Y2 = FCanvas -> GetSize().Y;
412 for (VInt y = Y1;y < Y2;y ++ )
413 {
414 BYTE * Colors = FCanvas -> GetAlphaBuffer() -> GetScanLines()[y] + X1 * 4 ;
415 for (VInt x = X1;x < X2;x ++ )
416 {
417 BYTE Alpha = Colors[ 3 ];
418 Colors[ 0 ] = Colors[ 0 ] * Alpha / 255 ;
419 Colors[ 1 ] = Colors[ 1 ] * Alpha / 255 ;
420 Colors[ 2 ] = Colors[ 2 ] * Alpha / 255 ;
421 Colors += 4 ;
422 }
423 }
424 FCanvas -> GetDC() -> Draw(X1,Y1,X2 - X1,Y2 - Y1,FCanvas -> GetAlphaBuffer(),X1,Y1,X2 - X1,Y2 - Y1);
425 }
426 LeaveClip(CurrentClip);
427 }
428
429 void VL_GDIElement::FillAlphaBitmap(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region , const VL_IrBrushRec & Brush)
430 {
431 RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
432 VInt W = Brush.Bitmap -> GetWidth();
433 VInt H = Brush.Bitmap -> GetHeight();
434 VInt StartCol = BoundRect.left / W;
435 VInt StartRow = BoundRect.top / H;
436 VInt EndCol = BoundRect.right / W;
437 VInt EndRow = BoundRect.bottom / H;
438 if (EndCol * W != BoundRect.right)
439 {
440 EndCol ++ ;
441 }
442 if (EndRow * H != BoundRect.bottom)
443 {
444 EndRow ++ ;
445 }
446 for (VInt i = StartCol;i <= EndCol;i ++ )
447 {
448 for (VInt j = StartRow;j < EndRow;j ++ )
449 {
450 FCanvas -> GetDC() -> Draw(i * W,j * H,Brush.Bitmap);
451 }
452 }
453 LeaveClip(CurrentClip);
454 }
455
456 void VL_GDIElement::DrawBorder(VL_WinRegion::Ptr CurrentClip)
457 {
458 if (FPen)
459 {
460 FCanvas -> GetDC() -> SetPen(FPen ? FPen -> GetGDIPen():FCanvas -> GetEmptyPen());
461 switch (GetIndirectFillReason(FPen -> GetInternalBrush()))
462 {
463 case ifrDirectFill:
464 if (FElementKind != ekCurve)
465 {
466 FCanvas -> GetDC() -> SetBrush(FCanvas -> GetEmptyBrush());
467 }
468 DrawShape( true );
469 break ;
470 case ifrLinearGradient: case ifrAlphaLinearGradient:
471 EnsureRegion();
472 FillLinearGradient(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
473 break ;
474 case ifrAlphaBitmap:
475 EnsureRegion();
476 FillAlphaBitmap(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
477 break ;
478 default :
479 throw L " 内部错误 " ;
480 }
481 }
482 }
483
484 void VL_GDIElement::DrawFilling(VL_WinRegion::Ptr CurrentClip)
485 {
486 if (FBrush)
487 {
488 switch (GetIndirectFillReason(FBrush -> GetInternalData()))
489 {
490 case ifrDirectFill:
491 FCanvas -> GetDC() -> SetBrush(FBrush -> GetGDIBrush());
492 FCanvas -> GetDC() -> SetPen(FCanvas -> GetEmptyPen());
493 if (FPen && IsBrushAlpha(FPen -> GetInternalBrush()))
494 {
495 EnsureRegion();
496 FCanvas -> GetDC() -> FillRegion(FContentRegion);
497 }
498 else
499 {
500 DrawShape( false );
501 }
502 break ;
503 case ifrLinearGradient: case ifrAlphaLinearGradient:
504 EnsureRegion();
505 FillLinearGradient(CurrentClip,FContentRegion,FBrush -> GetInternalData());
506 break ;
507 case ifrAlphaBitmap:
508 EnsureRegion();
509 FillAlphaBitmap(CurrentClip,FContentRegion,FBrush -> GetInternalData());
510 break ;
511 default :
512 throw L " 内部错误 " ;
513 }
514 }
515 }
516
517 void VL_GDIElement::Draw(VL_WinRegion::Ptr CurrentClip)
518 {
519 if (FVisible)
520 {
521 switch (FElementKind)
522 {
523 case ekCurve:
524 DrawBorder(CurrentClip);
525 break ;
526 case ekShape:
527 DrawFilling(CurrentClip);
528 DrawBorder(CurrentClip);
529 break ;
530 case ekContainerShape:
531 DrawFilling(CurrentClip);
532 if (FChildren.GetCount())
533 {
534 EnsureRegion();
535 VL_WinRegion::Ptr Clip = EnterClip(CurrentClip,FContentRegion);
536 for (VInt i = FChildren.GetCount() - 1 ;i >= 0 ;i -- )
537 {
538 FChildren[i] -> Draw(Clip);
539 }
540 LeaveClip(CurrentClip);
541 }
542 DrawBorder(CurrentClip);
543 break ;
544 }
545 }
546 }
547
548 void VL_GDIElement::DrawShape(VBool Border)
549 {
550 DrawForPath();
551 }
552
553 VL_GDIElement::VL_GDIElement(VL_GDIFactory * Factory , ElementKind aElementKind)
554 {
555 FFactory = Factory;
556 FCanvas = 0 ;
557 FParent = 0 ;
558 FEnvironmentModified = false ;
559 FVisible = true ;
560 FElementKind = aElementKind;
561 }
562
563 VL_GDIElement:: ~ VL_GDIElement()
564 {
565 }
566
567 VInt VL_GDIElement::ChildrenCount()
568 {
569 return FChildren.GetCount();
570 }
571
572 IVL_IrElement::Ptr VL_GDIElement::GetChild(VInt Index)
573 {
574 return FChildren[Index];
575 }
576
577 void VL_GDIElement::AddChild(IVL_IrElement::Ptr Element)
578 {
579 VL_GDIElement::Ptr e = Element;
580 if ( ! e) throw L " 内部错误 " ;
581 FChildren.Add(e);
582 e -> FParent = this ;
583 e -> EnvironmentModified(FCanvas);
584 }
585
586 void VL_GDIElement::InsertChild(VInt Index , IVL_IrElement::Ptr Element)
587 {
588 VL_GDIElement::Ptr e = Element;
589 if ( ! e) throw L " 内部错误 " ;
590 FChildren.Insert(Index,e);
591 e -> FParent = this ;
592 e -> EnvironmentModified(FCanvas);
593 }
594
595 IVL_IrElement::Ptr VL_GDIElement::DeleteChild(IVL_IrElement::Ptr Element)
596 {
597 VInt Index = FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
598 if (Index ==- 1 ) throw L " 内部错误 " ;
599 return DeleteChildAt(Index);
600 }
601
602 IVL_IrElement::Ptr VL_GDIElement::DeleteChildAt(VInt Index)
603 {
604 VL_GDIElement::Ptr e = FChildren.Fetch(Index);
605 e -> FParent = 0 ;
606 e -> EnvironmentModified(FCanvas);
607 return e;
608 }
609
610 VBool VL_GDIElement::HasChild(IVL_IrElement::Ptr Element)
611 {
612 return FChildren.Exists(dynamic_cast < VL_GDIElement *> (Element.Object()));
613 }
614
615 VInt VL_GDIElement::IndexOfChild(IVL_IrElement::Ptr Element)
616 {
617 return FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
618 }
619
620 void VL_GDIElement::MoveChild(VInt FromIndex , VInt ToIndex)
621 {
622 FChildren.Insert(ToIndex,FChildren.Fetch(FromIndex));
623 }
624
625 IVL_IrPen::Ptr VL_GDIElement::GetPen()
626 {
627 return FPen;
628 }
629
630 void VL_GDIElement::SetPen(IVL_IrPen::Ptr Pen)
631 {
632 FPen = Pen;
633 EnvironmentModified(FCanvas);
634 }
635
636 IVL_IrBrush::Ptr VL_GDIElement::GetBrush()
637 {
638 return FBrush;
639 }
640
641 void VL_GDIElement::SetBrush(IVL_IrBrush::Ptr Brush)
642 {
643 FBrush = Brush;
644 }
645
646 IVL_IrFont::Ptr VL_GDIElement::GetFont()
647 {
648 return FFont;
649 }
650
651 void VL_GDIElement::SetFont(IVL_IrFont::Ptr Font)
652 {
653 FFont = Font;
654 EnvironmentModified(FCanvas);
655 }
656
657 VBool VL_GDIElement::GetVisible()
658 {
659 return FVisible;
660 }
661
662 void VL_GDIElement::SetVisible(VBool Value)
663 {
664 FVisible = Value;
665 }
666
667 IVL_IrCanvas * VL_GDIElement::GetCanvas()
668 {
669 return FCanvas;
670 }
671
672 IVL_IrElement * VL_GDIElement::GetParent()
673 {
674 return dynamic_cast < IVL_IrElement *> (FParent);
675 }
676
677 IVL_IrFactory * VL_GDIElement::GetFactory()
678 {
679 return FFactory;
680 }
681
682 IVL_IrElement::HitTestResult VL_GDIElement::ContainedPoint(VL_IrPoint Point)
683 {
684 EnsureRegion();
685 POINT P = {Point.X,Point.Y};
686 if (FBorderRegion)
687 {
688 if (FBorderRegion -> ContainPoint(P))
689 {
690 return IVL_IrElement::htrBorder;
691 }
692 }
693 if (FContentRegion)
694 {
695 if (FContentRegion -> ContainPoint(P))
696 {
697 return IVL_IrElement::htrInternal;
698 }
699 }
700 return IVL_IrElement::htrNone;
701 }
702
703 VL_IrRect VL_GDIElement::GetElementRectangle()
704 {
705 EnsureRegion();
706 return FElementRectangle;
707 }
708
709 VL_IrRect VL_GDIElement::GetClientRectangle()
710 {
711 EnsureRegion();
712 return FClientRectangle;
713 }
714
715 /* ********************************************************************************************************
716 VL_GDILine
717 ******************************************************************************************************** */
718
719 void VL_GDILine::DrawForPath()
720 {
721 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
722 FCanvas -> GetDC() -> MoveTo(Offset.X + FStartPoint.X,Offset.Y + FStartPoint.Y);
723 FCanvas -> GetDC() -> LineTo(Offset.X + FEndPoint.X,Offset.Y + FEndPoint.Y);
724 }
725
726 VL_GDILine::VL_GDILine(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
727 {
728 }
729
730 VL_GDILine:: ~ VL_GDILine()
731 {
732 }
733
734 IVL_IrElementProperties * VL_GDILine::Properties()
735 {
736 return this ;
737 }
738
739 IVL_IrElementContainer * VL_GDILine::Container()
740 {
741 return 0 ;
742 }
743
744 VL_IrPoint VL_GDILine::GetStartPoint()
745 {
746 return FStartPoint;
747 }
748
749 VL_IrPoint VL_GDILine::GetEndPoint()
750 {
751 return FEndPoint;
752 }
753
754 void VL_GDILine::Update( const VL_IrPoint & Start , const VL_IrPoint & End)
755 {
756 FStartPoint = Start;
757 FEndPoint = End;
758 EnvironmentModified(FCanvas);
759 }
760
761 /* ********************************************************************************************************
762 VL_GDIRectangle
763 ******************************************************************************************************** */
764
765 void VL_GDIRectangle::DrawForPath()
766 {
767 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
768 FCanvas -> GetDC() -> Rectangle(
769 Offset.X + FPosition.X,
770 Offset.Y + FPosition.Y,
771 Offset.X + FPosition.X + FSize.X,
772 Offset.Y + FPosition.Y + FSize.Y
773 );
774 }
775
776 VL_GDIRectangle::VL_GDIRectangle(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
777 {
778 }
779
780 VL_GDIRectangle:: ~ VL_GDIRectangle()
781 {
782 }
783
784 IVL_IrElementProperties * VL_GDIRectangle::Properties()
785 {
786 return this ;
787 }
788
789 IVL_IrElementContainer * VL_GDIRectangle::Container()
790 {
791 return this ;
792 }
793
794 VL_IrPoint VL_GDIRectangle::GetPosition()
795 {
796 return FPosition;
797 }
798
799 VL_IrPoint VL_GDIRectangle::GetSize()
800 {
801 return FSize;
802 }
803
804 void VL_GDIRectangle::Update( const VL_IrPoint & Position , const VL_IrPoint & Size)
805 {
806 FPosition = Position;
807 FSize = Size;
808 EnvironmentModified(FCanvas);
809 }
810
811 void VL_GDIRectangle::Update( const VL_IrRect & Rectangle)
812 {
813 Update(Rectangle.Position,Rectangle.Size);
814 }
815
816 /* ********************************************************************************************************
817 VL_GDIRoundRectangle
818 ******************************************************************************************************** */
819
820 void VL_GDIRoundRectangle::DrawForPath()
821 {
822 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
823 FCanvas -> GetDC() -> RoundRect(
824 Offset.X + FPosition.X,
825 Offset.Y + FPosition.Y,
826 Offset.X + FPosition.X + FSize.X,
827 Offset.Y + FPosition.Y + FSize.Y,
828 FEllipse.X,
829 FEllipse.Y
830 );
831 }
832
833 VL_GDIRoundRectangle::VL_GDIRoundRectangle(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
834 {
835 }
836
837 VL_GDIRoundRectangle:: ~ VL_GDIRoundRectangle()
838 {
839 }
840
841 IVL_IrElementProperties * VL_GDIRoundRectangle::Properties()
842 {
843 return this ;
844 }
845
846 IVL_IrElementContainer * VL_GDIRoundRectangle::Container()
847 {
848 return this ;
849 }
850
851 VL_IrPoint VL_GDIRoundRectangle::GetPosition()
852 {
853 return FPosition;
854 }
855
856 VL_IrPoint VL_GDIRoundRectangle::GetSize()
857 {
858 return FSize;
859 }
860
861 VL_IrPoint VL_GDIRoundRectangle::GetEllipse()
862 {
863 return FEllipse;
864 }
865
866 void VL_GDIRoundRectangle::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , const VL_IrPoint & Ellipse)
867 {
868 FPosition = Position;
869 FSize = Size;
870 FEllipse = Ellipse;
871 EnvironmentModified(FCanvas);
872 }
873
874 void VL_GDIRoundRectangle::Update( const VL_IrRect & Rectangle , const VL_IrPoint & Ellipse)
875 {
876 Update(Rectangle.Position,Rectangle.Size,Ellipse);
877 }
878
879 /* ********************************************************************************************************
880 VL_GDIEllipse
881 ******************************************************************************************************** */
882
883 void VL_GDIEllipse::DrawForPath()
884 {
885 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
886 FCanvas -> GetDC() -> Ellipse(
887 Offset.X + FPosition.X,
888 Offset.Y + FPosition.Y,
889 Offset.X + FPosition.X + FSize.X,
890 Offset.Y + FPosition.Y + FSize.Y
891 );
892 }
893
894 VL_GDIEllipse::VL_GDIEllipse(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
895 {
896 }
897
898 VL_GDIEllipse:: ~ VL_GDIEllipse()
899 {
900 }
901
902 IVL_IrElementProperties * VL_GDIEllipse::Properties()
903 {
904 return this ;
905 }
906
907 IVL_IrElementContainer * VL_GDIEllipse::Container()
908 {
909 return this ;
910 }
911
912 VL_IrPoint VL_GDIEllipse::GetPosition()
913 {
914 return FPosition;
915 }
916
917 VL_IrPoint VL_GDIEllipse::GetSize()
918 {
919 return FSize;
920 }
921
922 void VL_GDIEllipse::Update( const VL_IrPoint & Position , const VL_IrPoint & Size)
923 {
924 FPosition = Position;
925 FSize = Size;
926 EnvironmentModified(FCanvas);
927 }
928
929 void VL_GDIEllipse::Update( const VL_IrRect & Rectangle)
930 {
931 Update(Rectangle.Position,Rectangle.Size);
932 }
933
934 /* ********************************************************************************************************
935 VL_GDIChord
936 ******************************************************************************************************** */
937
938 void VL_GDIChord::DrawForPath()
939 {
940 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
941 VInt StartX = Round(cos(FStartAngle) * 1000 );
942 VInt StartY = Round( - sin(FStartAngle) * 1000 );
943 VInt EndX = Round(cos(FEndAngle) * 1000 );
944 VInt EndY = Round( - sin(FEndAngle) * 1000 );
945 FCanvas -> GetDC() -> Chord(
946 Offset.X + FPosition.X,
947 Offset.Y + FPosition.Y,
948 Offset.X + FPosition.X + FSize.X,
949 Offset.Y + FPosition.Y + FSize.Y,
950 Offset.X + FPosition.X + FSize.X / 2 + StartX,
951 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
952 Offset.X + FPosition.X + FSize.X / 2 + EndX,
953 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
954 );
955 }
956
957 VL_GDIChord::VL_GDIChord(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
958 {
959 }
960
961 VL_GDIChord:: ~ VL_GDIChord()
962 {
963 }
964
965 IVL_IrElementProperties * VL_GDIChord::Properties()
966 {
967 return this ;
968 }
969
970 IVL_IrElementContainer * VL_GDIChord::Container()
971 {
972 return this ;
973 }
974
975 VL_IrPoint VL_GDIChord::GetPosition()
976 {
977 return FPosition;
978 }
979
980 VL_IrPoint VL_GDIChord::GetSize()
981 {
982 return FSize;
983 }
984
985 VDouble VL_GDIChord::GetStartAngle()
986 {
987 return FStartAngle;
988 }
989
990 VDouble VL_GDIChord::GetEndAngle()
991 {
992 return FEndAngle;
993 }
994
995 void VL_GDIChord::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
996 {
997 FPosition = Position;
998 FSize = Size;
999 FStartAngle = Start;
1000 FEndAngle = End;
1001 EnvironmentModified(FCanvas);
1002 }
1003
1004 void VL_GDIChord::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1005 {
1006 Update(Rectangle.Position,Rectangle.Size,Start,End);
1007 }
1008
1009 /* ********************************************************************************************************
1010 VL_GDIPie
1011 ******************************************************************************************************** */
1012
1013 void VL_GDIPie::DrawForPath()
1014 {
1015 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1016 VInt StartX = Round(cos(FStartAngle) * 1000 );
1017 VInt StartY = Round( - sin(FStartAngle) * 1000 );
1018 VInt EndX = Round(cos(FEndAngle) * 1000 );
1019 VInt EndY = Round( - sin(FEndAngle) * 1000 );
1020 FCanvas -> GetDC() -> Pie(
1021 Offset.X + FPosition.X,
1022 Offset.Y + FPosition.Y,
1023 Offset.X + FPosition.X + FSize.X,
1024 Offset.Y + FPosition.Y + FSize.Y,
1025 Offset.X + FPosition.X + FSize.X / 2 + StartX,
1026 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1027 Offset.X + FPosition.X + FSize.X / 2 + EndX,
1028 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1029 );
1030 }
1031
1032 VL_GDIPie::VL_GDIPie(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
1033 {
1034 }
1035
1036 VL_GDIPie:: ~ VL_GDIPie()
1037 {
1038 }
1039
1040 IVL_IrElementProperties * VL_GDIPie::Properties()
1041 {
1042 return this ;
1043 }
1044
1045 IVL_IrElementContainer * VL_GDIPie::Container()
1046 {
1047 return this ;
1048 }
1049
1050 VL_IrPoint VL_GDIPie::GetPosition()
1051 {
1052 return FPosition;
1053 }
1054
1055 VL_IrPoint VL_GDIPie::GetSize()
1056 {
1057 return FSize;
1058 }
1059
1060 VDouble VL_GDIPie::GetStartAngle()
1061 {
1062 return FStartAngle;
1063 }
1064
1065 VDouble VL_GDIPie::GetEndAngle()
1066 {
1067 return FEndAngle;
1068 }
1069
1070 void VL_GDIPie::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
1071 {
1072 FPosition = Position;
1073 FSize = Size;
1074 FStartAngle = Start;
1075 FEndAngle = End;
1076 EnvironmentModified(FCanvas);
1077 }
1078
1079 void VL_GDIPie::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1080 {
1081 Update(Rectangle.Position,Rectangle.Size,Start,End);
1082 }
1083
1084 /* ********************************************************************************************************
1085 VL_GDIArc
1086 ******************************************************************************************************** */
1087
1088 void VL_GDIArc::DrawForPath()
1089 {
1090 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1091 VInt StartX = Round(cos(FStartAngle) * 1000 );
1092 VInt StartY = Round( - sin(FStartAngle) * 1000 );
1093 VInt EndX = Round(cos(FEndAngle) * 1000 );
1094 VInt EndY = Round( - sin(FEndAngle) * 1000 );
1095 FCanvas -> GetDC() -> Arc(
1096 Offset.X + FPosition.X,
1097 Offset.Y + FPosition.Y,
1098 Offset.X + FPosition.X + FSize.X,
1099 Offset.Y + FPosition.Y + FSize.Y,
1100 Offset.X + FPosition.X + FSize.X / 2 + StartX,
1101 Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1102 Offset.X + FPosition.X + FSize.X / 2 + EndX,
1103 Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1104 );
1105 }
1106
1107 VL_GDIArc::VL_GDIArc(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1108 {
1109 }
1110
1111 VL_GDIArc:: ~ VL_GDIArc()
1112 {
1113 }
1114
1115 IVL_IrElementProperties * VL_GDIArc::Properties()
1116 {
1117 return this ;
1118 }
1119
1120 IVL_IrElementContainer * VL_GDIArc::Container()
1121 {
1122 return 0 ;
1123 }
1124
1125 VL_IrPoint VL_GDIArc::GetPosition()
1126 {
1127 return FPosition;
1128 }
1129
1130 VL_IrPoint VL_GDIArc::GetSize()
1131 {
1132 return FSize;
1133 }
1134
1135 VDouble VL_GDIArc::GetStartAngle()
1136 {
1137 return FStartAngle;
1138 }
1139
1140 VDouble VL_GDIArc::GetEndAngle()
1141 {
1142 return FEndAngle;
1143 }
1144
1145 void VL_GDIArc::Update( const VL_IrPoint & Position , const VL_IrPoint & Size , VDouble Start , VDouble End)
1146 {
1147 FPosition = Position;
1148 FSize = Size;
1149 FStartAngle = Start;
1150 FEndAngle = End;
1151 EnvironmentModified(FCanvas);
1152 }
1153
1154 void VL_GDIArc::Update( const VL_IrRect & Rectangle , VDouble Start , VDouble End)
1155 {
1156 Update(Rectangle.Position,Rectangle.Size,Start,End);
1157 }
1158
1159 /* ********************************************************************************************************
1160 VL_GDIPolyline
1161 ******************************************************************************************************** */
1162
1163 void VL_GDIPolyline::DrawForPath()
1164 {
1165 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1166 for (VInt i = 0 ;i < FCount;i ++ )
1167 {
1168 FBuffer[i].x = Offset.X + FPoints[i].X;
1169 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1170 }
1171 FCanvas -> GetDC() -> PolyLine(FBuffer,FCount);
1172 }
1173
1174 VL_GDIPolyline::VL_GDIPolyline(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1175 {
1176 FCount = 0 ;
1177 FPoints = 0 ;
1178 FBuffer = 0 ;
1179 }
1180
1181 VL_GDIPolyline:: ~ VL_GDIPolyline()
1182 {
1183 if (FPoints)delete[] FPoints;
1184 if (FBuffer)delete[] FBuffer;
1185 }
1186
1187 IVL_IrElementProperties * VL_GDIPolyline::Properties()
1188 {
1189 return this ;
1190 }
1191
1192 IVL_IrElementContainer * VL_GDIPolyline::Container()
1193 {
1194 return 0 ;
1195 }
1196
1197 VInt VL_GDIPolyline::GetHandlerCount()
1198 {
1199 return FCount;
1200 }
1201
1202 VL_IrPoint VL_GDIPolyline::GetHandler(VInt Index)
1203 {
1204 if (Index >= 0 && Index < FCount)
1205 {
1206 return FPoints[Index];
1207 }
1208 else
1209 {
1210 throw L " 内部错误 " ;
1211 }
1212 }
1213
1214 void VL_GDIPolyline::Update(VL_IrPoint * Handlers , VInt Count)
1215 {
1216 FCount = Count;
1217 if (FPoints)delete[] FPoints;
1218 FPoints = new VL_IrPoint[FCount];
1219 if (FBuffer)delete[] FBuffer;
1220 FBuffer = new POINT[FCount];
1221 for (VInt i = 0 ;i < FCount;i ++ )
1222 {
1223 FPoints[i] = Handlers[i];
1224 }
1225 EnvironmentModified(FCanvas);
1226 }
1227
1228 /* ********************************************************************************************************
1229 VL_GDIPolygon
1230 ******************************************************************************************************** */
1231
1232 void VL_GDIPolygon::DrawForPath()
1233 {
1234 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1235 for (VInt i = 0 ;i < FCount;i ++ )
1236 {
1237 FBuffer[i].x = Offset.X + FPoints[i].X;
1238 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1239 }
1240 FCanvas -> GetDC() -> PolyGon(FBuffer,FCount);
1241 }
1242
1243 VL_GDIPolygon::VL_GDIPolygon(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekContainerShape)
1244 {
1245 FCount = 0 ;
1246 FPoints = 0 ;
1247 FBuffer = 0 ;
1248 }
1249
1250 VL_GDIPolygon:: ~ VL_GDIPolygon()
1251 {
1252 if (FPoints)delete[] FPoints;
1253 if (FBuffer)delete[] FBuffer;
1254 }
1255
1256 IVL_IrElementProperties * VL_GDIPolygon::Properties()
1257 {
1258 return this ;
1259 }
1260
1261 IVL_IrElementContainer * VL_GDIPolygon::Container()
1262 {
1263 return this ;
1264 }
1265
1266 VInt VL_GDIPolygon::GetHandlerCount()
1267 {
1268 return FCount;
1269 }
1270
1271 VL_IrPoint VL_GDIPolygon::GetHandler(VInt Index)
1272 {
1273 if (Index >= 0 && Index < FCount)
1274 {
1275 return FPoints[Index];
1276 }
1277 else
1278 {
1279 throw L " 内部错误 " ;
1280 }
1281 }
1282
1283 void VL_GDIPolygon::Update(VL_IrPoint * Handlers , VInt Count)
1284 {
1285 FCount = Count;
1286 if (FPoints)delete[] FPoints;
1287 FPoints = new VL_IrPoint[FCount];
1288 if (FBuffer)delete[] FBuffer;
1289 FBuffer = new POINT[FCount];
1290 for (VInt i = 0 ;i < FCount;i ++ )
1291 {
1292 FPoints[i] = Handlers[i];
1293 }
1294 EnvironmentModified(FCanvas);
1295 }
1296
1297 /* ********************************************************************************************************
1298 VL_GDIBezier
1299 ******************************************************************************************************** */
1300
1301 void VL_GDIBezier::DrawForPath()
1302 {
1303 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1304 for (VInt i = 0 ;i < FCount;i ++ )
1305 {
1306 FBuffer[i].x = Offset.X + FPoints[i].X;
1307 FBuffer[i].y = Offset.Y + FPoints[i].Y;
1308 }
1309 FCanvas -> GetDC() -> PolyBezier(FBuffer,FCount);
1310 }
1311
1312 VL_GDIBezier::VL_GDIBezier(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekCurve)
1313 {
1314 FCount = 0 ;
1315 FPoints = 0 ;
1316 FBuffer = 0 ;
1317 }
1318
1319 VL_GDIBezier:: ~ VL_GDIBezier()
1320 {
1321 if (FPoints)delete[] FPoints;
1322 if (FBuffer)delete[] FBuffer;
1323 }
1324
1325 IVL_IrElementProperties * VL_GDIBezier::Properties()
1326 {
1327 return this ;
1328 }
1329
1330 IVL_IrElementContainer * VL_GDIBezier::Container()
1331 {
1332 return 0 ;
1333 }
1334
1335 VInt VL_GDIBezier::GetHandlerCount()
1336 {
1337 return FCount;
1338 }
1339
1340 VL_IrPoint VL_GDIBezier::GetHandler(VInt Index)
1341 {
1342 if (Index >= 0 && Index < FCount)
1343 {
1344 return FPoints[Index];
1345 }
1346 else
1347 {
1348 throw L " 内部错误 " ;
1349 }
1350 }
1351
1352 void VL_GDIBezier::Update(VL_IrPoint * Handlers , VInt Count)
1353 {
1354 FCount = Count;
1355 if (FPoints)delete[] FPoints;
1356 FPoints = new VL_IrPoint[FCount];
1357 if (FBuffer)delete[] FBuffer;
1358 FBuffer = new POINT[FCount];
1359 for (VInt i = 0 ;i < FCount;i ++ )
1360 {
1361 FPoints[i] = Handlers[i];
1362 }
1363 EnvironmentModified(FCanvas);
1364 }
1365
1366 /* ********************************************************************************************************
1367 VL_GDIText
1368 ******************************************************************************************************** */
1369
1370 void VL_GDIText::EnvironmentModified(VL_GDICanvas * Canvas)
1371 {
1372 VL_GDIElement::EnvironmentModified(Canvas);
1373 if (FCanvas && FFont)
1374 {
1375 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1376 SIZE Size = FCanvas -> GetDC() -> MeasureString(FText);
1377 FSize = VL_IrPoint(Size.cx,Size.cy);
1378 }
1379 else
1380 {
1381 FSize = VL_IrPoint();
1382 }
1383 }
1384
1385 void VL_GDIText::Draw(VL_WinRegion::Ptr CurrentClip)
1386 {
1387 VBool Painted = false ;
1388 if ( ! FFont)
1389 {
1390 Painted = true ;
1391 }
1392 else if ( ! FPen)
1393 {
1394 if (FBrush)
1395 {
1396 const VL_IrBrushRec & BrushRec = FBrush -> GetInternalData();
1397 if (BrushRec.BrushKind == VL_IrBrushRec::bkSolid && BrushRec.MainColor.A == 255 )
1398 {
1399 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1400 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1401 FCanvas -> GetDC() -> SetTextColor(RGB(BrushRec.MainColor.R,BrushRec.MainColor.G,BrushRec.MainColor.B));
1402 FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1403 Painted = true ;
1404 }
1405 }
1406 else
1407 {
1408 Painted = true ;
1409 }
1410 }
1411 if ( ! Painted)
1412 {
1413 VL_GDIElement::Draw(CurrentClip);
1414 }
1415 }
1416
1417 void VL_GDIText::DrawShape(VBool Border)
1418 {
1419 EnsureRegion();
1420 if (Border)
1421 {
1422 FCanvas -> GetDC() -> SetBrush(FPenBrush -> GetGDIBrush());
1423 FCanvas -> GetDC() -> FillRegion(FBorderRegion);
1424 }
1425 else
1426 {
1427 FCanvas -> GetDC() -> FillRegion(FContentRegion);
1428 }
1429 }
1430
1431 void VL_GDIText::DrawForPath()
1432 {
1433 if (FFont)
1434 {
1435 VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1436 FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1437 FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1438 }
1439 }
1440
1441 VL_GDIText::VL_GDIText(VL_GDIFactory * Factory):VL_GDIElement(Factory,ekShape)
1442 {
1443 }
1444
1445 VL_GDIText:: ~ VL_GDIText()
1446 {
1447 }
1448
1449 IVL_IrElementProperties * VL_GDIText::Properties()
1450 {
1451 return this ;
1452 }
1453
1454 IVL_IrElementContainer * VL_GDIText::Container()
1455 {
1456 return 0 ;
1457 }
1458
1459 void VL_GDIText::SetPen(IVL_IrPen::Ptr Pen)
1460 {
1461 VL_GDIElement::SetPen(Pen);
1462 if (FPen)
1463 {
1464 FPenBrush = FFactory -> CreateBrush(FPen -> GetInternalBrush());
1465 }
1466 else
1467 {
1468 FPenBrush = 0 ;
1469 }
1470 }
1471
1472 VL_IrRect VL_GDIText::GetElementRectangle()
1473 {
1474 return VL_IrRect(FPosition,FSize);
1475 }
1476
1477 VL_IrRect VL_GDIText::GetClientRectangle()
1478 {
1479 return VL_IrRect(FPosition,FSize);
1480 }
1481
1482 VL_IrPoint VL_GDIText::GetPosition()
1483 {
1484 return FPosition;
1485 }
1486
1487 VUnicodeString VL_GDIText::GetText()
1488 {
1489 return FText;
1490 }
1491
1492 void VL_GDIText::Update(VL_IrPoint Position , VUnicodeString Text)
1493 {
1494 FPosition = Position;
1495 FText = Text;
1496 EnvironmentModified(FCanvas);
1497 }
1498
1499 /* ********************************************************************************************************
1500 VL_GDICanvas
1501 ******************************************************************************************************** */
1502
1503 void VL_GDICanvas::UpdateBuffer()
1504 {
1505 FBuffer = new VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1506 SetPolyFillMode(FBuffer -> GetWinDC() -> GetHandle(),WINDING);
1507 FBuffer -> GetWinDC() -> SetBackTransparent( true );
1508 FAlphaBuffer = new VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1509 FAlphaBuffer -> BuildAlphaChannel();
1510 if (FRootElement)
1511 {
1512 FRootElement -> EnvironmentModified( this );
1513 }
1514 Render();
1515 }
1516
1517 void VL_GDICanvas::HostPaint(VL_Base * Sender)
1518 {
1519 FHostDC -> Draw( 0 , 0 ,FBuffer);
1520 }
1521
1522 void VL_GDICanvas::HostSized(VL_Base * Sender)
1523 {
1524 UpdateBuffer();
1525 }
1526
1527 VL_GDICanvas::VL_GDICanvas(VL_GDIFactory * Factory , VL_WinControl * Control)
1528 {
1529 FFactory = Factory;
1530 FHost = Control;
1531 FHostDC = new VL_WinControlDC(FHost -> GetHandle());
1532 FEmptyPen = new VL_WinPen(PS_NULL, 1 , 0 );
1533 FEmptyBrush = new VL_WinBrush;
1534 FBackgroundBrush = new VL_WinBrush(RGB( 255 , 255 , 255 ));
1535 UpdateBuffer();
1536
1537 FHost -> OnPaint.Bind( this , & VL_GDICanvas::HostPaint);
1538 FHost -> OnSized.Bind( this , & VL_GDICanvas::HostSized);
1539 }
1540
1541 VL_GDICanvas:: ~ VL_GDICanvas()
1542 {
1543 FHost -> OnPaint.Unbind( this , & VL_GDICanvas::HostPaint);
1544 FHost -> OnSized.Unbind( this , & VL_GDICanvas::HostSized);
1545 delete FHostDC;
1546 }
1547
1548 IVL_IrFactory * VL_GDICanvas::GetFactory()
1549 {
1550 return FFactory;
1551 }
1552
1553 VL_IrPoint VL_GDICanvas::GetSize()
1554 {
1555 return VL_IrPoint(FBuffer -> GetWidth(),FBuffer -> GetHeight());
1556 }
1557
1558 IVL_IrElement::Ptr VL_GDICanvas::GetRootElement()
1559 {
1560 return FRootElement;
1561 }
1562
1563 void VL_GDICanvas::SetRootElement(IVL_IrElement::Ptr Element)
1564 {
1565 FRootElement = Element;
1566 if (Element)
1567 {
1568 if (FRootElement)
1569 {
1570 FRootElement -> EnvironmentModified( this );
1571 }
1572 else
1573 {
1574 throw L " 内部错误 " ;
1575 }
1576 }
1577 }
1578
1579 void VL_GDICanvas::Render()
1580 {
1581 FBuffer -> GetWinDC() -> SetBrush(FBackgroundBrush);
1582 FBuffer -> GetWinDC() -> FillRect( 0 , 0 ,FBuffer -> GetWidth(),FBuffer -> GetHeight());
1583 if (FRootElement)
1584 {
1585 FRootElement -> Draw( 0 );
1586 }
1587 UpdateWindow(FHost -> GetHandle());
1588 }
1589
1590 VL_WinDC * VL_GDICanvas::GetDC()
1591 {
1592 return FBuffer -> GetWinDC();
1593 }
1594
1595 VL_WinBitmap::Ptr VL_GDICanvas::GetAlphaBuffer()
1596 {
1597 return FAlphaBuffer;
1598 }
1599
1600 VL_WinPen::Ptr VL_GDICanvas::GetEmptyPen()
1601 {
1602 return FEmptyPen;
1603 }
1604
1605 VL_WinBrush::Ptr VL_GDICanvas::GetEmptyBrush()
1606 {
1607 return FEmptyBrush;
1608 }
1609
1610 /* ********************************************************************************************************
1611 VL_GDIFactory
1612 ******************************************************************************************************** */
1613
1614 class GDIFactoryRegister
1615 {
1616 public :
1617 static IVL_IrFactory::Ptr Constructor()
1618 {
1619 return new VL_GDIFactory;
1620 }
1621
1622 GDIFactoryRegister()
1623 {
1624 RegisterInteractionFactory(L " GDI " ,Constructor);
1625 }
1626 } _GDIFactoryRegister;
1627
1628 IVL_IrBrush::Ptr VL_GDIFactory::CreateBrush( const VL_IrBrushRec & Brush)
1629 {
1630 return new VL_GDIBrush( this ,Brush);
1631 }
1632
1633 IVL_IrPen::Ptr VL_GDIFactory::CreatePen( const VL_IrBrushRec & Brush , const VL_IrPenRec & Pen)
1634 {
1635 return new VL_GDIPen( this ,Brush,Pen);
1636 }
1637
1638 IVL_IrFont::Ptr VL_GDIFactory::CreateFont( const VL_IrFontRec & Font)
1639 {
1640 return new VL_GDIFont( this ,Font);
1641 }
1642
1643 IVL_IrLine::Ptr VL_GDIFactory::CreateLine()
1644 {
1645 return new VL_GDILine( this );
1646 }
1647
1648 IVL_IrRectangle::Ptr VL_GDIFactory::CreateRectangle()
1649 {
1650 return new VL_GDIRectangle( this );
1651 }
1652
1653 IVL_IrRoundRectangle::Ptr VL_GDIFactory::CreateRoundRectangle()
1654 {
1655 return new VL_GDIRoundRectangle( this );
1656 }
1657
1658 IVL_IrEllipse::Ptr VL_GDIFactory::CreateEllipse()
1659 {
1660 return new VL_GDIEllipse( this );
1661 }
1662
1663 IVL_IrChord::Ptr VL_GDIFactory::CreateChord()
1664 {
1665 return new VL_GDIChord( this );
1666 }
1667
1668 IVL_IrPie::Ptr VL_GDIFactory::CreatePie()
1669 {
1670 return new VL_GDIPie( this );
1671 }
1672
1673 IVL_IrArc::Ptr VL_GDIFactory::CreateArc()
1674 {
1675 return new VL_GDIArc( this );
1676 }
1677
1678 IVL_IrPolyline::Ptr VL_GDIFactory::CreatePolyline()
1679 {
1680 return new VL_GDIPolyline( this );
1681 }
1682
1683 IVL_IrPolygon::Ptr VL_GDIFactory::CreatePolygon()
1684 {
1685 return new VL_GDIPolygon( this );
1686 }
1687
1688 IVL_IrBezier::Ptr VL_GDIFactory::CreateBezier()
1689 {
1690 return new VL_GDIBezier( this );
1691 }
1692
1693 IVL_IrText::Ptr VL_GDIFactory::CreateText()
1694 {
1695 return new VL_GDIText( this );
1696 }
1697
1698 IVL_IrCanvas::Ptr VL_GDIFactory::CreateCanvas(VL_WinControl * Control)
1699 {
1700 return new VL_GDICanvas( this ,Control);
1701 }
1702 }
1703 }
1704 }