198
198
function TWidgetSet.CreateRoundRectRgn(X1, Y1, X2, Y2, nWidthEllipse, nHeightEllipse: Integer): HRGN;
200
200
RoundRgn, CornerSquareRgn, CornerCutRgn: HRGN;
201
nHalfX,nHalfY:integer;
204
205
// The resulting region
205
206
Result := CreateRectRgn(X1, Y1, X2, Y2);
208
nHalfX := nWidthEllipse div 2;
209
nHalfY := nHeightEllipse div 2;
207
211
// We create this region with dummy values just because
208
212
// CombineRgn requires an existing region to receive the result
209
213
CornerCutRgn := CreateRectRgn(0, 0, nWidthEllipse, nHeightEllipse);
211
215
// Top-left corner
212
RoundRgn := CreateEllipticRgn(X1, Y1, X1 + nWidthEllipse * 2, Y1 + nHeightEllipse * 2);
213
CornerSquareRgn := CreateRectRgn(X1, Y1, X1 + nWidthEllipse, Y1 + nHeightEllipse);
216
RoundRgn := CreateEllipticRgn(X1, Y1, X1 + nWidthEllipse, Y1 + nHeightEllipse);
217
CornerSquareRgn := CreateRectRgn(X1, Y1, X1 + nHalfX, Y1 + nHalfY);
214
218
CombineRgn(CornerCutRgn, RoundRgn, CornerSquareRgn, RGN_AND);
215
219
CombineRgn(CornerCutRgn, CornerSquareRgn, CornerCutRgn, RGN_DIFF);
216
220
CombineRgn(Result, Result, CornerCutRgn, RGN_DIFF);
1095
{ Returns in MaxCount how many characters fit into a given MaxWidth
1096
It also returns the width of each character
1098
MaxCount is given in the number of UTF-8 characters, not bytes
1091
1100
function TWidgetSet.GetTextExtentExPoint(DC: HDC; Str: PChar;
1092
1101
Count, MaxWidth: Integer; MaxCount, PartialWidths: PInteger;
1093
1102
var Size: TSize): Boolean;
1104
lPasStr, lCurSubStr: String;
1105
lPasStrLen, i: PtrInt;
1107
lBestFitFound: Boolean = False;
1095
if MaxCount<>nil then MaxCount^:=Count;
1096
if PartialWidths<>nil then
1097
DebugLn('Warning: TWidgetSet.GetTextExtentExPoint PartialWidths not implemented yet');
1109
// First obtain the size information which duplicates GetTextExtentPoint
1098
1110
Result := GetTextExtentPoint(DC,Str,Count,Size);
1111
// Now calculate MaxCount and PartialWidths
1112
lPasStr := StrPas(Str);
1113
if (Str = nil) or (Count <= 0) or (lPasStr = '') then
1116
if MaxCount <> nil then
1120
lPasStrLen := UTF8Length(lPasStr);
1121
for i := 1 to lPasStrLen do
1123
if (not lBestFitFound) then
1125
lCurSubStr := UTF8Copy(lPasStr, 1, i);
1126
Self.GetTextExtentPoint(DC, PChar(lCurSubStr), Length(lCurSubStr), lCurSize);
1128
// Calculate the summed partial widths
1129
if PartialWidths<>nil then PartialWidths[i-1] := lCurSize.cx;
1131
// Calculate the width until the utilized size gets bigger then the desired one
1132
// Give up when the size surpases MaxWidth to be faster
1133
if (MaxCount <> nil) then
1135
if lCurSize.cx <= MaxWidth then MaxCount^ := i
1136
else lBestFitFound := True;
1142
// Note that Count is the number of bytes in the utf-8 encoded string Str
1101
1143
function TWidgetSet.GetTextExtentPoint(DC: HDC; Str: PChar; Count: Integer;
1102
1144
var Size: TSize): Boolean;
1159
function TWidgetSet.GradientFill(DC: HDC; Vertices: PTriVertex;
1160
NumVertices : Longint; Meshes: Pointer; NumMeshes : Longint;
1161
Mode : Longint): Boolean;
1201
{------------------------------------------------------------------------------
1202
Function: GradientFill
1203
Params: DC - DeviceContext to perform on
1204
Vertices - array of Points W/Color & Alpha
1205
NumVertices - Number of Vertices
1206
Meshes - array of Triangle or Rectangle Meshes,
1207
each mesh representing one Gradient Fill
1208
NumMeshes - Number of Meshes
1209
Mode - Gradient Type, either Triangle,
1210
Vertical Rect, Horizontal Rect
1212
Returns: true on success
1214
Performs multiple Gradient Fills, either a Three way Triangle Gradient,
1215
or a two way Rectangle Gradient, each Vertex point also supports optional
1216
Alpha/Transparency for more advanced Gradients.
1217
------------------------------------------------------------------------------}
1218
function TWidgetSet.GradientFill(DC: HDC; Vertices: PTriVertex; NumVertices: Longint;
1219
Meshes: Pointer; NumMeshes: Longint; Mode: Longint): Boolean;
1221
function DoFillTriangle: Boolean; inline;
1223
Result := (Mode and GRADIENT_FILL_TRIANGLE) = GRADIENT_FILL_TRIANGLE;
1226
function DoFillVRect: Boolean; inline;
1228
Result := (Mode and GRADIENT_FILL_RECT_V) = GRADIENT_FILL_RECT_V;
1231
function CreateIntfImage(W, H: Integer; Clear: Boolean): TLazIntfImage;
1233
Result := TLazIntfImage.Create(W, H, [riqfRGB, riqfAlpha, riqfUpdate]);
1236
Result.FillPixels(FPColor(0, 0, 0, $0000));
1239
procedure DrawIntfImage(Image: TLazIntfImage; R: TRect);
1241
Bmp, Mask, Old: HBitmap;
1244
Image.CreateBitmaps(Bmp, Mask, True);
1245
BmpDC := CreateCompatibleDC(0);
1246
Old := SelectObject(BmpDC, Bmp);
1247
MaskBlt(DC, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, BmpDC, 0, 0, Mask, 0, 0);
1248
DeleteObject(SelectObject(BmpDC, Old));
1254
function GetRectangleGradientColor(const BeginColor, EndColor: TFPColor; const Position, TotalSteps: Longint): TFPColor; inline;
1256
A1: Word absolute BeginColor.alpha;
1257
R1: Word absolute BeginColor.red;
1258
G1: Word absolute BeginColor.green;
1259
B1: Word absolute BeginColor.blue;
1260
A2: Word absolute Endcolor.alpha;
1261
R2: Word absolute Endcolor.red;
1262
G2: Word absolute Endcolor.green;
1263
B2: Word absolute Endcolor.blue;
1265
Result.alpha := (A1 + (Position * (A2 - A1) div TotalSteps));
1266
Result.red := (R1 + (Position * (R2 - R1) div TotalSteps));
1267
Result.green := (G1 + (Position * (G2 - G1) div TotalSteps));
1268
Result.blue := (B1 + (Position * (B2 - B1) div TotalSteps));
1271
function GetTriangleBounds(const v1, v2, v3: TTriVertex): TRect;
1277
BottomRight := TopLeft;
1304
implementation of Arjen Nienhuis:
1305
http://www.winehq.org/pipermail/wine-patches/2003-June/006544.html
1306
Arjen has granted us the rights to include this code with our modified LGPL2 license
1309
procedure GradientFillTriangle(Image: TLazIntfImage; v1, v2, v3: TTriVertex);
1312
y, y2, dy, dy2: Integer;
1313
x, x1, x2, r1, r2, g1, g2, b1, b2: Integer;
1316
if (v1.y > v2.y) then
1323
if (v2.y > v3.y) then
1328
if (v1.y > v2.y) then
1335
// v1.y <= v2.y <= v3.y
1337
for y := 0 to dy - 1 do
1340
if y < (v2.y - v1.y) then
1344
// (v.y <= y < v2.y) || (v2.y <= y < v.y)
1346
y2 := y + v1.y - v.y;
1347
x1 := (v3.x * y + v1.x * (dy - y )) div dy;
1348
x2 := (v2.x * y2 + v. x * (dy2 - y2)) div dy2;
1349
r1 := (v3.Red * y + v1.Red * (dy - y )) div dy;
1350
r2 := (v2.Red * y2 + v. Red * (dy2 - y2)) div dy2;
1351
g1 := (v3.Green * y + v1.Green * (dy - y )) div dy;
1352
g2 := (v2.Green * y2 + v. Green * (dy2 - y2)) div dy2;
1353
b1 := (v3.Blue * y + v1.Blue * (dy - y )) div dy;
1354
b2 := (v2.Blue * y2 + v. Blue * (dy2 - y2)) div dy2;
1358
for x := 0 to dx - 1 do
1359
Image.Colors[x + x1, y + v1.y] := FPColor(
1360
(r1 * (dx - x) + r2 * x) div dx,
1361
(g1 * (dx - x) + g2 * x) div dx,
1362
(b1 * (dx - x) + b2 * x) div dx);
1367
for x := 0 to dx - 1 do
1368
Image.Colors[x + x2, y + v1.y] := FPColor(
1369
(r2 * (dx - x) + r1 * x) div dx,
1370
(g2 * (dx - x) + g1 * x) div dx,
1371
(b2 * (dx - x) + b1 * x) div dx);
1377
function FillTriMesh(Mesh: TGradientTriangle): Boolean;
1379
v1, v2, v3: TTriVertex;
1381
Image: TLazIntfImage;
1386
(Vertex1 < Cardinal(NumVertices)) and (Vertex1 >= 0) and
1387
(Vertex2 < Cardinal(NumVertices)) and (Vertex2 >= 0) and
1388
(Vertex3 < Cardinal(NumVertices)) and (Vertex3 >= 0);
1390
if (Vertex1 = Vertex2) or (Vertex1 = Vertex3) or (Vertex2 = Vertex3) or not Result then
1394
v1 := Vertices[Mesh.Vertex1];
1395
v2 := Vertices[Mesh.Vertex2];
1396
v3 := Vertices[Mesh.Vertex3];
1397
R := GetTriangleBounds(v1, v2, v3);
1409
Image := CreateIntfImage(R.Right - R.Left, R.Bottom - R.Top, True);
1410
GradientFillTriangle(Image, v1, v2, v3);
1411
DrawIntfImage(Image, R);
1416
function FillRectMesh(Mesh: TGradientRect): Boolean;
1419
StartColor, EndColor, CurColor: TFPColor;
1421
SwapColors: Boolean;
1423
Image: TLazIntfImage;
1428
Result := (UpperLeft < Cardinal(NumVertices)) and (LowerRight < Cardinal(NumVertices));
1429
if (LowerRight = UpperLeft) or not Result then
1431
TL := Vertices[UpperLeft];
1432
BR := Vertices[LowerRight];
1433
SwapColors := (BR.Y < TL.Y) and (BR.X < TL.X);
1446
StartColor := FPColor(TL.Red, TL.Green, TL.Blue);
1447
EndColor := FPColor(BR.Red, BR.Green, BR.Blue);
1450
CurColor := StartColor;
1451
StartColor := EndColor;
1452
EndColor := CurColor;
1455
R := Rect(TL.X, TL.Y, BR.X, BR.Y);
1460
Image := CreateIntfImage(BR.X, BR.Y, False);
1465
for I := 0 to Steps - 1 do
1467
CurColor := GetRectangleGradientColor(StartColor, EndColor, I, Steps);
1468
for J := TL.X to BR.X - 1 do
1469
Image.Colors[J, I] := CurColor;
1475
for I := 0 to Steps - 1 do
1477
CurColor := GetRectangleGradientColor(StartColor, EndColor, I, Steps);
1478
for J := TL.Y to BR.Y - 1 do
1479
Image.Colors[I, J] := CurColor;
1482
DrawIntfImage(Image, R);
1488
MeshSize: array[Boolean] of PtrUInt = (
1489
SizeOf(tagGradientRect),
1490
SizeOf(tagGradientTriangle)
1495
Result := Assigned(Meshes) and (NumMeshes >= 1) and (NumVertices >= 2) and Assigned(Vertices);
1496
if Result and DoFillTriangle then
1497
Result := NumVertices >= 3;
1502
//Sanity Checks For Vertices Size vs. Count
1503
if MemSize(Vertices) < PtrUInt(SizeOf(TTriVertex) * NumVertices) then
1506
//Sanity Checks For Meshes Size vs. Count
1507
if MemSize(Meshes) < (MeshSize[DoFillTriangle] * Cardinal(NumMeshes)) then
1510
for I := 0 to NumMeshes - 1 do
1512
if DoFillTriangle then
1514
if not FillTriMesh(PGradientTriangle(Meshes)[I]) then
1519
if not FillRectMesh(PGradientRect(Meshes)[I]) then
1166
1527
function TWidgetSet.HideCaret(hWnd: HWND): Boolean;
1179
1540
Result := (Shift = []) and (Key = VK_F1);
1182
function TWidgetSet.AppHandle: Thandle;
1184
DebugLn('Warning: AppHandle is not implemented for this widgetset yet');
1188
1543
procedure TWidgetSet.InitializeCriticalSection(var CritSection: TCriticalSection);
1190
1545
DebugLn('TWidgetSet.InitializeCriticalSection Not implemented yet');
1193
function TWidgetSet.IntersectClipRect(dc: hdc;
1194
Left, Top, Right, Bottom: Integer): Integer;
1548
function TWidgetSet.IntersectClipRect(DC: HDC; Left, Top, Right, Bottom: Integer): Integer;
1198
RRGN := CreateRectRgn(Left, Top, Right, Bottom);
1199
//DebugLn('TWidgetSet.IntersectClipRect A RGN=',DbgS(RRGN),
1200
// ' ',dbgs(Left),',',dbgs(Top),',',dbgs(Right),',',dbgs(Bottom));
1201
If not DCClipRegionValid(DC) then
1553
R := Rect(Left, Top, Right, Bottom);
1556
RRGN := CreateRectRgn(Left, Top, Right, Bottom);
1557
if not DCClipRegionValid(DC) then
1202
1558
Result := SelectClipRGN(DC, RRGN)
1204
1560
Result := ExtSelectClipRGN(DC, RRGN, RGN_AND);