Browse Source

glyph alignment (need to set GlyphOldPlacement to False)

Johann 6 years ago
parent
commit
180b8945ee
6 changed files with 478 additions and 777 deletions
  1. 60 74
      bcbutton.pas
  2. 54 71
      bcbuttonfocus.pas
  3. 242 12
      bctools.pas
  4. 103 562
      test/BGRA Ribbon Custom/uMain.lfm
  5. 0 56
      test/BGRA Ribbon Custom/uMain.pas
  6. 19 2
      test/BGRA Ribbon Custom/uRibbon.pas

+ 60 - 74
bcbutton.pas

@@ -113,6 +113,8 @@ type
     FFlipArrow: boolean;
     FFlipArrow: boolean;
     FActiveButt: TBCButtonStyle;
     FActiveButt: TBCButtonStyle;
     FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
     FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
+    FGlyphAlignment: TBCAlignment;
+    FGlyphOldPlacement: boolean;
     FInnerMargin: single;
     FInnerMargin: single;
     FMemoryUsage: TBCButtonMemoryUsage;
     FMemoryUsage: TBCButtonMemoryUsage;
     FPreserveGlyphOnAssign: boolean;
     FPreserveGlyphOnAssign: boolean;
@@ -135,7 +137,7 @@ type
     AutoSizeExtraY: integer;
     AutoSizeExtraY: integer;
     AutoSizeExtraX: integer;
     AutoSizeExtraX: integer;
     // MORA
     // MORA
-    FClickOffest: boolean;
+    FClickOffset: boolean;
     FDropDownArrow: boolean;
     FDropDownArrow: boolean;
     FDropDownMenu: TPopupMenu;
     FDropDownMenu: TPopupMenu;
     FDropDownMenuVisible: boolean;
     FDropDownMenuVisible: boolean;
@@ -149,7 +151,6 @@ type
     FShowCaption: boolean;
     FShowCaption: boolean;
     procedure AssignDefaultStyle;
     procedure AssignDefaultStyle;
     procedure CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
     procedure CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
-    procedure ConvertToGrayScale(ABGRA: TBGRABitmap);
     procedure DropDownClosed(Sender: TObject);
     procedure DropDownClosed(Sender: TObject);
     procedure RenderAll(ANow: boolean = False);
     procedure RenderAll(ANow: boolean = False);
     function GetButtonRect: TRect;
     function GetButtonRect: TRect;
@@ -166,7 +167,9 @@ type
     procedure SetDropDownWidth(AValue: integer);
     procedure SetDropDownWidth(AValue: integer);
     procedure SetFlipArrow(AValue: boolean);
     procedure SetFlipArrow(AValue: boolean);
     procedure SetGlyph(const AValue: TBitmap);
     procedure SetGlyph(const AValue: TBitmap);
+    procedure SetGlyphAlignment(AValue: TBCAlignment);
     procedure SetGlyphMargin(const AValue: integer);
     procedure SetGlyphMargin(const AValue: integer);
+    procedure SetGlyphOldPlacement(AValue: boolean);
     procedure SetImageIndex(AValue: integer);
     procedure SetImageIndex(AValue: integer);
     procedure SetImages(AValue: TCustomImageList);
     procedure SetImages(AValue: TCustomImageList);
     procedure SetInnerMargin(AValue: single);
     procedure SetInnerMargin(AValue: single);
@@ -207,7 +210,7 @@ type
     procedure Render(ABGRA: TBGRABitmapEx; AState: TBCButtonState); virtual;
     procedure Render(ABGRA: TBGRABitmapEx; AState: TBCButtonState); virtual;
     procedure RenderState(ABGRA: TBGRABitmapEx; AState: TBCButtonState;
     procedure RenderState(ABGRA: TBGRABitmapEx; AState: TBCButtonState;
       const ARect: TRect; ARounding: TBCRounding); virtual;
       const ARect: TRect; ARounding: TBCRounding); virtual;
-    property ClickOffset: boolean read FClickOffest write SetClickOffset default False;
+    property ClickOffset: boolean read FClickOffset write SetClickOffset default False;
     property DropDownArrow: boolean
     property DropDownArrow: boolean
       read FDropDownArrow write SetDropDownArrow default False;
       read FDropDownArrow write SetDropDownArrow default False;
     property DropDownMenu: TPopupMenu read FDropDownMenu write FDropDownMenu;
     property DropDownMenu: TPopupMenu read FDropDownMenu write FDropDownMenu;
@@ -239,6 +242,8 @@ type
     property FlipArrow: boolean read FFlipArrow write SetFlipArrow default False;
     property FlipArrow: boolean read FFlipArrow write SetFlipArrow default False;
     property Glyph: TBitmap read GetGlyph write SetGlyph;
     property Glyph: TBitmap read GetGlyph write SetGlyph;
     property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
     property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
+    property GlyphAlignment: TBCAlignment read FGlyphAlignment write SetGlyphAlignment default bcaCenter;
+    property GlyphOldPlacement: boolean read FGlyphOldPlacement write SetGlyphOldPlacement default true;
     property Style: TBCButtonStyle read FStyle write SetStyle default bbtButton;
     property Style: TBCButtonStyle read FStyle write SetStyle default bbtButton;
     property StaticButton: boolean
     property StaticButton: boolean
       read FStaticButton write SetStaticButton default False;
       read FStaticButton write SetStaticButton default False;
@@ -314,6 +319,8 @@ type
     property GlobalOpacity;
     property GlobalOpacity;
     { The glyph icon. }
     { The glyph icon. }
     property Glyph;
     property Glyph;
+    property GlyphAlignment;
+    property GlyphOldPlacement;
     property PreserveGlyphOnAssign;
     property PreserveGlyphOnAssign;
     { The margin of the glyph icon. }
     { The margin of the glyph icon. }
     property GlyphMargin;
     property GlyphMargin;
@@ -640,28 +647,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TCustomBCButton.ConvertToGrayScale(ABGRA: TBGRABitmap);
-var
-  bounds: TRect;
-  px: PBGRAPixel;
-  xb, yb: integer;
-begin
-  bounds := ABGRA.GetImageBounds;
-  if (bounds.Right <= bounds.Left) or (bounds.Bottom <= Bounds.Top) then
-    exit;
-
-  for yb := bounds.Top to bounds.bottom - 1 do
-  begin
-    px := ABGRA.scanline[yb] + bounds.left;
-    for xb := bounds.left to bounds.right - 1 do
-    begin
-      px^ := BGRAToGrayscale(px^);
-      Inc(px);
-    end;
-  end;
-  ABGRA.InvalidateBitmap;
-end;
-
 procedure TCustomBCButton.RenderAll(ANow: boolean);
 procedure TCustomBCButton.RenderAll(ANow: boolean);
 begin
 begin
   if (csCreating in ControlState) or IsUpdating or (FBGRANormal = nil) then
   if (csCreating in ControlState) or IsUpdating or (FBGRANormal = nil) then
@@ -717,51 +702,32 @@ begin
 end;
 end;
 
 
 procedure TCustomBCButton.Render(ABGRA: TBGRABitmapEx; AState: TBCButtonState);
 procedure TCustomBCButton.Render(ABGRA: TBGRABitmapEx; AState: TBCButtonState);
-var
-  r, r_a: TRect;
-
-  { TODO: Create customizable glyph position by creating TBCGlyph type
-          and method in BCTools which render it }
-  procedure _RenderGlyph;
-  var
-    w, h, t, l: integer;
-    bitmap: TBitmap;
+
+  function GetActualGlyph: TBitmap;
   begin
   begin
-    // MORA: getting image to draw
-    if Assigned(FGlyph) and not FGlyph.Empty then
-      bitmap := FGlyph
-    else
+    if Assigned(FGlyph) and not FGlyph.Empty then result := FGlyph else
     if Assigned(FImages) and (FImageIndex > -1) and (FImageIndex < FImages.Count) then
     if Assigned(FImages) and (FImageIndex > -1) and (FImageIndex < FImages.Count) then
     begin
     begin
-      bitmap := TBitmap.Create;
+      result := TBitmap.Create;
       {$IFDEF FPC}
       {$IFDEF FPC}
-      FImages.GetBitmap(FImageIndex, bitmap);
+      FImages.GetBitmap(FImageIndex, result);
       {$ELSE}
       {$ELSE}
-      FImages.GetBitmapRaw(FImageIndex, bitmap);
+      FImages.GetBitmapRaw(FImageIndex, result);
       {$ENDIF}
       {$ENDIF}
-    end
-    else
-      bitmap := nil;
-
-    if (bitmap <> nil) and (not bitmap.Empty) then
-    begin
-      if not FShowCaption then
-      begin
-        w := 0;
-        h := 0;
-      end
-      else
-        CalculateTextSize(Caption, AState.FontEx, w, h);
-      l := r.Right - Round(((r.Right - r.Left) + w + bitmap.Width) / 2);
-      t := r.Bottom - Round(((r.Bottom - r.Top) + bitmap.Height) / 2);
-      ABGRA.PutImage(l, t, bitmap, dmLinearBlend);
-      Inc(r.Left, l + bitmap.Width + FGlyphMargin);
-    end;
+    end else exit(nil);
+  end;
 
 
-    if bitmap <> FGlyph then
-      bitmap.Free;
+  procedure RenderGlyph(ARect: TRect; AGlyph: TBitmap);
+  begin
+    if ARect.IsEmpty or (AGlyph = nil) then exit;
+    ABGRA.PutImage(ARect.Left, ARect.Top, AGlyph, dmLinearBlend);
   end;
   end;
 
 
+var
+  r, r_a, r_g: TRect;
+  g: TBitmap;
+  actualCaption: TCaption;
+
 begin
 begin
   if (csCreating in ControlState) or IsUpdating then
   if (csCreating in ControlState) or IsUpdating then
     Exit;
     Exit;
@@ -788,7 +754,7 @@ begin
     CalculateBorderRect(AState.Border, r_a);
     CalculateBorderRect(AState.Border, r_a);
 
 
     // Click offset for arrow
     // Click offset for arrow
-    if FClickOffest and (AState = FStateClicked) then
+    if FClickOffset and (AState = FStateClicked) then
     begin
     begin
       Inc(r_a.Left, 2);
       Inc(r_a.Left, 2);
       Inc(r_a.Top, 2);
       Inc(r_a.Top, 2);
@@ -803,7 +769,7 @@ begin
   end;
   end;
 
 
   // Click offset for text and glyph
   // Click offset for text and glyph
-  if FClickOffest and (AState = FStateClicked) then
+  if FClickOffset and (AState = FStateClicked) then
   begin
   begin
     Inc(r.Left, 2);
     Inc(r.Left, 2);
     Inc(r.Top, 2);
     Inc(r.Top, 2);
@@ -823,13 +789,14 @@ begin
     Dec(R.Right, FDropDownWidth);
     Dec(R.Right, FDropDownWidth);
   end;
   end;
 
 
+  g := GetActualGlyph;
+  if FShowCaption then actualCaption := self.Caption else actualCaption := '';
+  r_g := ComputeGlyphPosition(r, g, GlyphAlignment, GlyphMargin, actualCaption, AState.FontEx, GlyphOldPlacement);
   if FTextApplyGlobalOpacity then
   if FTextApplyGlobalOpacity then
   begin
   begin
     { Drawing text }
     { Drawing text }
-    _RenderGlyph;
-    if FShowCaption then
-      RenderText(r, AState.FontEx, Self.Caption, TBGRABitmap(ABGRA));
-
+    RenderText(r, AState.FontEx, actualCaption, ABGRA);
+    RenderGlyph(r_g, g);
     { Set global opacity }
     { Set global opacity }
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
   end
   end
@@ -838,14 +805,13 @@ begin
     { Set global opacity }
     { Set global opacity }
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     { Drawing text }
     { Drawing text }
-    _RenderGlyph;
-    if FShowCaption then
-      RenderText(r, AState.FontEx, Self.Caption, TBGRABitmap(ABGRA));
+    RenderText(r, AState.FontEx, actualCaption, ABGRA);
+    RenderGlyph(r_g, g);
   end;
   end;
+  if g <> FGlyph then g.Free;
 
 
   { Convert to gray if not enabled }
   { Convert to gray if not enabled }
-  if not Enabled then
-    ConvertToGrayScale(ABGRA);
+  if not Enabled then ABGRA.InplaceGrayscale;
 
 
   if Assigned(FOnAfterRenderBCButton) then
   if Assigned(FOnAfterRenderBCButton) then
     FOnAfterRenderBCButton(Self, ABGRA, AState, r);
     FOnAfterRenderBCButton(Self, ABGRA, AState, r);
@@ -933,9 +899,9 @@ end;
 
 
 procedure TCustomBCButton.SetClickOffset(AValue: boolean);
 procedure TCustomBCButton.SetClickOffset(AValue: boolean);
 begin
 begin
-  if FClickOffest = AValue then
+  if FClickOffset = AValue then
     Exit;
     Exit;
-  FClickOffest := AValue;
+  FClickOffset := AValue;
   RenderControl;
   RenderControl;
 end;
 end;
 
 
@@ -1018,6 +984,15 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TCustomBCButton.SetGlyphAlignment(AValue: TBCAlignment);
+begin
+  if FGlyphAlignment=AValue then Exit;
+  FGlyphAlignment:=AValue;
+  RenderControl;
+  UpdateSize;
+  Invalidate;
+end;
+
 procedure TCustomBCButton.SetGlyphMargin(const AValue: integer);
 procedure TCustomBCButton.SetGlyphMargin(const AValue: integer);
 begin
 begin
   if FGlyphMargin = AValue then
   if FGlyphMargin = AValue then
@@ -1029,6 +1004,15 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TCustomBCButton.SetGlyphOldPlacement(AValue: boolean);
+begin
+  if FGlyphOldPlacement=AValue then Exit;
+  FGlyphOldPlacement:=AValue;
+  RenderControl;
+  UpdateSize;
+  Invalidate;
+end;
+
 procedure TCustomBCButton.SetImageIndex(AValue: integer);
 procedure TCustomBCButton.SetImageIndex(AValue: integer);
 begin
 begin
   if FImageIndex = AValue then
   if FImageIndex = AValue then
@@ -1724,6 +1708,8 @@ begin
     FGlyph := TBitmap.Create;
     FGlyph := TBitmap.Create;
     FGlyph.OnChange := OnChangeGlyph;
     FGlyph.OnChange := OnChangeGlyph;
     FGlyphMargin := 5;
     FGlyphMargin := 5;
+    FGlyphAlignment:= bcaCenter;
+    FGlyphOldPlacement:= true;
     FStyle := bbtButton;
     FStyle := bbtButton;
     FStaticButton := False;
     FStaticButton := False;
     FActiveButt := bbtButton;
     FActiveButt := bbtButton;

+ 54 - 71
bcbuttonfocus.pas

@@ -112,6 +112,8 @@ type
     FFlipArrow: boolean;
     FFlipArrow: boolean;
     FActiveButt: TBCButtonFocusStyle;
     FActiveButt: TBCButtonFocusStyle;
     FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
     FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
+    FGlyphAlignment: TBCAlignment;
+    FGlyphOldPlacement: boolean;
     FInnerMargin: single;
     FInnerMargin: single;
     FMemoryUsage: TBCButtonFocusMemoryUsage;
     FMemoryUsage: TBCButtonFocusMemoryUsage;
     FOnPaintButton: TNotifyEvent;
     FOnPaintButton: TNotifyEvent;
@@ -148,7 +150,6 @@ type
     FShowCaption: boolean;
     FShowCaption: boolean;
     procedure AssignDefaultStyle;
     procedure AssignDefaultStyle;
     procedure CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
     procedure CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
-    procedure ConvertToGrayScale(ABGRA: TBGRABitmap);
     procedure DropDownClosed(Sender: TObject);
     procedure DropDownClosed(Sender: TObject);
     procedure RenderAll(ANow: boolean = False);
     procedure RenderAll(ANow: boolean = False);
     function GetButtonRect: TRect;
     function GetButtonRect: TRect;
@@ -165,7 +166,9 @@ type
     procedure SetDropDownWidth(AValue: integer);
     procedure SetDropDownWidth(AValue: integer);
     procedure SetFlipArrow(AValue: boolean);
     procedure SetFlipArrow(AValue: boolean);
     procedure SetGlyph(const AValue: TBitmap);
     procedure SetGlyph(const AValue: TBitmap);
+    procedure SetGlyphAlignment(AValue: TBCAlignment);
     procedure SetGlyphMargin(const AValue: integer);
     procedure SetGlyphMargin(const AValue: integer);
+    procedure SetGlyphOldPlacement(AValue: boolean);
     procedure SetImageIndex(AValue: integer);
     procedure SetImageIndex(AValue: integer);
     procedure SetImages(AValue: TCustomImageList);
     procedure SetImages(AValue: TCustomImageList);
     procedure SetInnerMargin(AValue: single);
     procedure SetInnerMargin(AValue: single);
@@ -243,6 +246,8 @@ type
     property FlipArrow: boolean read FFlipArrow write SetFlipArrow default False;
     property FlipArrow: boolean read FFlipArrow write SetFlipArrow default False;
     property Glyph: TBitmap read GetGlyph write SetGlyph;
     property Glyph: TBitmap read GetGlyph write SetGlyph;
     property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
     property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
+    property GlyphAlignment: TBCAlignment read FGlyphAlignment write SetGlyphAlignment default bcaCenter;
+    property GlyphOldPlacement: boolean read FGlyphOldPlacement write SetGlyphOldPlacement default true;
     property Style: TBCButtonFocusStyle read FStyle write SetStyle default bbtButtonF;
     property Style: TBCButtonFocusStyle read FStyle write SetStyle default bbtButtonF;
     property StaticButton: boolean
     property StaticButton: boolean
       read FStaticButton write SetStaticButton default False;
       read FStaticButton write SetStaticButton default False;
@@ -319,6 +324,8 @@ type
     property GlobalOpacity;
     property GlobalOpacity;
     { The glyph icon. }
     { The glyph icon. }
     property Glyph;
     property Glyph;
+    property GlyphAlignment;
+    property GlyphOldPlacement;
     property PreserveGlyphOnAssign;
     property PreserveGlyphOnAssign;
     { The margin of the glyph icon. }
     { The margin of the glyph icon. }
     property GlyphMargin;
     property GlyphMargin;
@@ -643,28 +650,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TCustomBCButtonFocus.ConvertToGrayScale(ABGRA: TBGRABitmap);
-var
-  bounds: TRect;
-  px: PBGRAPixel;
-  xb, yb: integer;
-begin
-  bounds := ABGRA.GetImageBounds;
-  if (bounds.Right <= bounds.Left) or (bounds.Bottom <= Bounds.Top) then
-    exit;
-
-  for yb := bounds.Top to bounds.bottom - 1 do
-  begin
-    px := ABGRA.scanline[yb] + bounds.left;
-    for xb := bounds.left to bounds.right - 1 do
-    begin
-      px^ := BGRAToGrayscale(px^);
-      Inc(px);
-    end;
-  end;
-  ABGRA.InvalidateBitmap;
-end;
-
 procedure TCustomBCButtonFocus.RenderAll(ANow: boolean);
 procedure TCustomBCButtonFocus.RenderAll(ANow: boolean);
 begin
 begin
   if (csCreating in ControlState) or IsUpdating or (FBGRANormal = nil) then
   if (csCreating in ControlState) or IsUpdating or (FBGRANormal = nil) then
@@ -720,54 +705,32 @@ begin
 end;
 end;
 
 
 procedure TCustomBCButtonFocus.Render(ABGRA: TBGRABitmapEx; AState: TBCButtonFocusState);
 procedure TCustomBCButtonFocus.Render(ABGRA: TBGRABitmapEx; AState: TBCButtonFocusState);
-var
-  r, r_a: TRect;
-
-  { TODO: Create customizable glyph position by creating TBCGlyph type
-          and method in BCTools which render it }
-  procedure _RenderGlyph;
-  var
-    w, h, t, l: integer;
-    g: TBGRABitmap;
-    bitmap: TBitmap;
+
+  function GetActualGlyph: TBitmap;
   begin
   begin
-    // MORA: getting image to draw
-    if Assigned(FGlyph) and not FGlyph.Empty then
-      bitmap := FGlyph
-    else
+    if Assigned(FGlyph) and not FGlyph.Empty then result := FGlyph else
     if Assigned(FImages) and (FImageIndex > -1) and (FImageIndex < FImages.Count) then
     if Assigned(FImages) and (FImageIndex > -1) and (FImageIndex < FImages.Count) then
     begin
     begin
-      bitmap := TBitmap.Create;
+      result := TBitmap.Create;
       {$IFDEF FPC}
       {$IFDEF FPC}
-      FImages.GetBitmap(FImageIndex, bitmap);
+      FImages.GetBitmap(FImageIndex, result);
       {$ELSE}
       {$ELSE}
-      FImages.GetBitmapRaw(FImageIndex, bitmap);
+      FImages.GetBitmapRaw(FImageIndex, result);
       {$ENDIF}
       {$ENDIF}
-    end
-    else
-      bitmap := nil;
-
-    if (bitmap <> nil) and (not bitmap.Empty) then
-    begin
-      if not FShowCaption then
-      begin
-        w := 0;
-        h := 0;
-      end
-      else
-        CalculateTextSize(Caption, AState.FontEx, w, h);
-      l := r.Right - Round(((r.Right - r.Left) + w + bitmap.Width) / 2);
-      t := r.Bottom - Round(((r.Bottom - r.Top) + bitmap.Height) / 2);
-      g := TBGRABitmap.Create(bitmap);
-      ABGRA.BlendImage(l, t, g, boLinearBlend);
-      g.Free;
-      Inc(r.Left, l + bitmap.Width + FGlyphMargin);
-    end;
+    end else exit(nil);
+  end;
 
 
-    if bitmap <> FGlyph then
-      bitmap.Free;
+  procedure RenderGlyph(ARect: TRect; AGlyph: TBitmap);
+  begin
+    if ARect.IsEmpty or (AGlyph = nil) then exit;
+    ABGRA.PutImage(ARect.Left, ARect.Top, AGlyph, dmLinearBlend);
   end;
   end;
 
 
+var
+  r, r_a, r_g: TRect;
+  g: TBitmap;
+  actualCaption: TCaption;
+
 begin
 begin
   if (csCreating in ControlState) or IsUpdating then
   if (csCreating in ControlState) or IsUpdating then
     Exit;
     Exit;
@@ -829,13 +792,14 @@ begin
     Dec(R.Right, FDropDownWidth);
     Dec(R.Right, FDropDownWidth);
   end;
   end;
 
 
+  g := GetActualGlyph;
+  if FShowCaption then actualCaption := self.Caption else actualCaption := '';
+  r_g := ComputeGlyphPosition(r, g, GlyphAlignment, GlyphMargin, actualCaption, AState.FontEx, GlyphOldPlacement);
   if FTextApplyGlobalOpacity then
   if FTextApplyGlobalOpacity then
   begin
   begin
     { Drawing text }
     { Drawing text }
-    _RenderGlyph;
-    if FShowCaption then
-      RenderText(r, AState.FontEx, Self.Caption, TBGRABitmap(ABGRA));
-
+    RenderText(r, AState.FontEx, actualCaption, ABGRA);
+    RenderGlyph(r_g, g);
     { Set global opacity }
     { Set global opacity }
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
   end
   end
@@ -844,14 +808,13 @@ begin
     { Set global opacity }
     { Set global opacity }
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
     { Drawing text }
     { Drawing text }
-    _RenderGlyph;
-    if FShowCaption then
-      RenderText(r, AState.FontEx, Self.Caption, TBGRABitmap(ABGRA));
+    RenderText(r, AState.FontEx, actualCaption, ABGRA);
+    RenderGlyph(r_g, g);
   end;
   end;
+  if g <> FGlyph then g.Free;
 
 
   { Convert to gray if not enabled }
   { Convert to gray if not enabled }
-  if not Enabled then
-    ConvertToGrayScale(ABGRA);
+  if not Enabled then ABGRA.InplaceGrayscale;
 
 
   if Assigned(FOnAfterRenderBCButton) then
   if Assigned(FOnAfterRenderBCButton) then
     FOnAfterRenderBCButton(Self, ABGRA, AState, r);
     FOnAfterRenderBCButton(Self, ABGRA, AState, r);
@@ -1024,6 +987,15 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TCustomBCButtonFocus.SetGlyphAlignment(AValue: TBCAlignment);
+begin
+  if FGlyphAlignment=AValue then Exit;
+  FGlyphAlignment:=AValue;
+  RenderControl;
+  UpdateSize;
+  Invalidate;
+end;
+
 procedure TCustomBCButtonFocus.SetGlyphMargin(const AValue: integer);
 procedure TCustomBCButtonFocus.SetGlyphMargin(const AValue: integer);
 begin
 begin
   if FGlyphMargin = AValue then
   if FGlyphMargin = AValue then
@@ -1035,6 +1007,15 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TCustomBCButtonFocus.SetGlyphOldPlacement(AValue: boolean);
+begin
+  if FGlyphOldPlacement=AValue then Exit;
+  FGlyphOldPlacement:=AValue;
+  RenderControl;
+  UpdateSize;
+  Invalidate;
+end;
+
 procedure TCustomBCButtonFocus.SetImageIndex(AValue: integer);
 procedure TCustomBCButtonFocus.SetImageIndex(AValue: integer);
 begin
 begin
   if FImageIndex = AValue then
   if FImageIndex = AValue then
@@ -1794,6 +1775,8 @@ begin
     FGlyph := TBitmap.Create;
     FGlyph := TBitmap.Create;
     FGlyph.OnChange := OnChangeGlyph;
     FGlyph.OnChange := OnChangeGlyph;
     FGlyphMargin := 5;
     FGlyphMargin := 5;
+    FGlyphAlignment:= bcaCenter;
+    FGlyphOldPlacement:= true;
     FStyle := bbtButtonF;
     FStyle := bbtButtonF;
     FStaticButton := False;
     FStaticButton := False;
     FActiveButt := bbtButtonF;
     FActiveButt := bbtButtonF;

+ 242 - 12
bctools.pas

@@ -47,8 +47,22 @@ uses
 // This method prepare BGRABitmap for rendering BCFont type
 // This method prepare BGRABitmap for rendering BCFont type
 procedure AssignBCFont(AFont: TBCFont; var ATargetBGRA: TBGRABitmap);
 procedure AssignBCFont(AFont: TBCFont; var ATargetBGRA: TBGRABitmap);
 // Calculate text height and width (doesn't include wordwrap - just single line)
 // Calculate text height and width (doesn't include wordwrap - just single line)
-procedure CalculateTextSize(const AText: String; AFont: TBCFont;
-  out ANewWidth, ANewHeight: integer);
+procedure CalculateTextSize(const AText: String; AFont: TBCFont; out ANewWidth, ANewHeight: integer;
+  AShadowMargin: boolean = true);
+// Calculate text height and width (handles wordwrap and end ellipsis)
+procedure CalculateTextSizeEx(const AText: String; AFont: TBCFont; out ANewWidth, ANewHeight: integer;
+  AAvailableWidth: integer; AShadowMargin: boolean = false);
+// Determines the layout of the glyph
+procedure GetGlyphActualLayout(ACaption: string; AFont: TBCFont;
+  AGlyphAlignment: TBCAlignment; AGlyphMargin: integer; out AHorizAlign: TAlignment;
+  out AVertAlign: TTextLayout; out AGlyphRelativeHorizAlign: TAlignment;
+  out AGlyphRelativeVertAlign: TTextLayout; out AGlyphHorizMargin: integer;
+  out AGlyphVertMargin: integer);
+// Computes the position the glyph and update rAvail with the space dedicated to text.
+// Specify the flag AOldPlacement to have the old (buggy) version
+function ComputeGlyphPosition(var rAvail: TRect;
+  AGlyph: TBitmap; AGlyphAlignment: TBCAlignment; AGlyphMargin: integer;
+  ACaption: string; AFont: TBCFont; AOldPlacement: boolean): TRect;
 // This method correct TRect to border width. As far as border width is bigger,
 // This method correct TRect to border width. As far as border width is bigger,
 // BGRA drawing rectangle with offset (half border width)
 // BGRA drawing rectangle with offset (half border width)
 procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
 procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
@@ -82,7 +96,7 @@ function BCAlign2VAlign(AAlign: TBCAlignment): TTextLayout;
 
 
 implementation
 implementation
 
 
-uses BGRAPolygon, BGRAFillInfo, BGRAText, math;
+uses BGRAPolygon, BGRAFillInfo, BGRAText, math, BGRAUTF8, LazUTF8;
 
 
 procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
 procedure CalculateBorderRect(ABorder: TBCBorder; var ARect: TRect);
 var w: integer;
 var w: integer;
@@ -198,6 +212,8 @@ var
   st: TTextStyle;
   st: TTextStyle;
   r: TRect;
   r: TRect;
 begin
 begin
+  if AText = '' then exit;
+
   AssignBCFont(AFont,ATargetBGRA);
   AssignBCFont(AFont,ATargetBGRA);
 
 
   hal := BCAlign2HAlign(AFont.TextAlignment);
   hal := BCAlign2HAlign(AFont.TextAlignment);
@@ -299,7 +315,7 @@ begin
 end;
 end;
 
 
 procedure CalculateTextSize(const AText: String; AFont: TBCFont; out ANewWidth,
 procedure CalculateTextSize(const AText: String; AFont: TBCFont; out ANewWidth,
-  ANewHeight: integer);
+  ANewHeight: integer; AShadowMargin: boolean);
 var
 var
   s: TSize;
   s: TSize;
   tmp: TBGRABitmap;
   tmp: TBGRABitmap;
@@ -311,20 +327,13 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  {TODO: Check why BGRATextSize doesn't work. BGRABitmap call this method
-         and it work. Temporary I'm creating temp bitmap
-  }
-  {s := BGRAText.BGRATextSize(AFont,AFont.FontQuality,AText,FontAntialiasingLevel);
-  if (s.cy >= 24) and AFont.FontAntialias then
-    s := BGRAText.BGRATextSize(AFont,AFont.FontQuality,AText,4);}
   tmp := TBGRABitmap.Create(0,0);
   tmp := TBGRABitmap.Create(0,0);
   AssignBCFont(AFont, tmp);
   AssignBCFont(AFont, tmp);
-
   s := tmp.TextSize(AText);
   s := tmp.TextSize(AText);
   tmp.Free;
   tmp.Free;
 
 
   { shadow offset }
   { shadow offset }
-  if AFont.Shadow then
+  if AShadowMargin and AFont.Shadow then
   begin
   begin
     Inc(s.cx, 2 * Abs(AFont.ShadowOffsetX) + 2 * AFont.ShadowRadius);
     Inc(s.cx, 2 * Abs(AFont.ShadowOffsetX) + 2 * AFont.ShadowRadius);
     Inc(s.cy, 2 * Abs(AFont.ShadowOffsetY) + 2 * AFont.ShadowRadius);
     Inc(s.cy, 2 * Abs(AFont.ShadowOffsetY) + 2 * AFont.ShadowRadius);
@@ -337,6 +346,227 @@ begin
   ANewHeight := s.cy;
   ANewHeight := s.cy;
 end;
 end;
 
 
+procedure CalculateTextSizeEx(const AText: String; AFont: TBCFont; out
+  ANewWidth, ANewHeight: integer; AAvailableWidth: integer; AShadowMargin: boolean);
+var
+  s: TSize;
+  tmp: TBGRABitmap;
+  extraX,extraY, fitCount: integer;
+  dotSize: LongInt;
+begin
+  if (AText = '') or (AFont = nil) then
+  begin
+    ANewWidth := 0;
+    ANewHeight := 0;
+    Exit;
+  end;
+
+  extraX := 0;
+  extraY := 0;
+  { shadow offset }
+  if AShadowMargin and AFont.Shadow then
+  begin
+    Inc(extraX, 2 * Abs(AFont.ShadowOffsetX) + 2 * AFont.ShadowRadius);
+    Inc(extraY, 2 * Abs(AFont.ShadowOffsetY) + 2 * AFont.ShadowRadius);
+  end;
+
+  inc(extraX, AFont.PaddingLeft+Afont.PaddingRight);
+  inc(extraY, AFont.PaddingTop+Afont.PaddingBottom);
+
+  dec(AAvailableWidth, extraX);
+  tmp := TBGRABitmap.Create(0,0);
+  AssignBCFont(AFont, tmp);
+  if AFont.WordBreak then
+    s := tmp.TextSize(AText, AAvailableWidth)
+  else
+  begin
+    s := tmp.TextSize(AText);
+    if AFont.EndEllipsis and (s.cx > AAvailableWidth) then
+    begin
+      dotSize := tmp.TextSize('...').cx;
+      fitCount := tmp.TextFitInfo(AText, AAvailableWidth-dotSize);
+      s.cx := tmp.TextSize(UTF8Copy(AText, 1, fitCount)).cx + dotSize;
+    end;
+  end;
+  tmp.Free;
+
+  ANewWidth := s.cx+extraX;
+  ANewHeight := s.cy+extraY;
+end;
+
+procedure GetGlyphActualLayout(ACaption: string; AFont: TBCFont;
+  AGlyphAlignment: TBCAlignment; AGlyphMargin: integer; out AHorizAlign: TAlignment;
+  out AVertAlign: TTextLayout; out AGlyphRelativeHorizAlign: TAlignment;
+  out AGlyphRelativeVertAlign: TTextLayout; out AGlyphHorizMargin: integer;
+  out AGlyphVertMargin: integer);
+begin
+  if AGlyphAlignment in [bcaLeftTop,bcaLeftCenter,bcaLeftBottom] then AHorizAlign := taLeftJustify
+  else if AGlyphAlignment  in [bcaRightTop,bcaRightCenter,bcaRightBottom] then AHorizAlign:= taRightJustify
+  else AHorizAlign:= taCenter;
+  if AGlyphAlignment in [bcaCenter,bcaLeftCenter,bcaRightCenter] then AVertAlign := tlCenter
+  else if AGlyphAlignment in [bcaLeftBottom,bcaCenterBottom,bcaRightBottom] then AVertAlign := tlBottom
+  else AVertAlign := tlTop;
+
+  if ACaption<>'' then
+  begin
+    AGlyphRelativeVertAlign:= AVertAlign;
+    if AVertAlign <> tlCenter then
+      AGlyphRelativeHorizAlign:= AHorizAlign else
+    begin
+      if AHorizAlign = taCenter then
+      begin
+        if IsRightToLeftUTF8(ACaption) then AGlyphRelativeHorizAlign := taRightJustify
+        else AGlyphRelativeHorizAlign := taLeftJustify;
+      end else
+        AGlyphRelativeHorizAlign:= AHorizAlign;
+    end;
+
+    if AFont.TextAlignment in [bcaLeftTop,bcaLeftCenter,bcaLeftBottom] then AHorizAlign := taLeftJustify
+    else if AFont.TextAlignment in [bcaRightTop,bcaRightCenter,bcaRightBottom] then AHorizAlign:= taRightJustify
+    else AHorizAlign := taCenter;
+    if AFont.TextAlignment in [bcaLeftTop,bcaCenterTop,bcaRightTop] then AVertAlign := tlTop
+    else if AFont.TextAlignment in [bcaLeftBottom,bcaCenterBottom,bcaRightBottom] then AVertAlign:= tlBottom
+    else AVertAlign:= tlCenter;
+
+    if AGlyphRelativeVertAlign in[tlTop,tlBottom] then
+    begin
+      if AGlyphRelativeHorizAlign <> taCenter then AGlyphHorizMargin:= AGlyphMargin
+      else AGlyphHorizMargin:= 0;
+      if AGlyphRelativeVertAlign = AVertAlign then AGlyphVertMargin:= AGlyphMargin
+      else AGlyphVertMargin:= 0;
+    end else
+    begin
+      if AGlyphRelativeHorizAlign = AHorizAlign then AGlyphHorizMargin:= AGlyphMargin
+      else AGlyphVertMargin:= 0;
+      AGlyphVertMargin:= 0;
+    end;
+  end else
+  begin
+    case AHorizAlign of
+      taCenter: AGlyphRelativeHorizAlign:= taCenter;
+      taRightJustify: AGlyphRelativeHorizAlign:= taLeftJustify;
+    else AGlyphRelativeHorizAlign:= taRightJustify;
+    end;
+    if AHorizAlign <> taCenter then AGlyphHorizMargin := AGlyphMargin
+    else AGlyphHorizMargin := 0;
+    case AVertAlign of
+      tlCenter: AGlyphRelativeVertAlign:= tlCenter;
+      tlBottom: AGlyphRelativeVertAlign:= tlTop;
+    else AGlyphRelativeVertAlign:= tlBottom;
+    end;
+    if AVertAlign <> tlCenter then AGlyphVertMargin := AGlyphMargin
+    else AGlyphVertMargin := 0;
+  end;
+end;
+
+function ComputeGlyphPosition(var rAvail: TRect;
+  AGlyph: TBitmap; AGlyphAlignment: TBCAlignment; AGlyphMargin: integer;
+  ACaption: string; AFont: TBCFont; AOldPlacement: boolean): TRect;
+var
+  gw,gh, w, h, w2,h2, glyphHorzMargin, glyphVertMargin: integer;
+  horizAlign, relHorizAlign: TAlignment;
+  vertAlign, relVertAlign: TTextLayout;
+  rText, rAll, rGlyph: TRect;
+  l,t: integer;
+
+  procedure AlignRect(var ARect: TRect; const ABounds: TRect; AHorizAlign: TAlignment;
+    AVertAlign: TTextLayout; AHorizMargin: integer = 0; AVertMargin: integer = 0);
+  begin
+    case AHorizAlign of
+      taCenter: ARect.Offset((ABounds.Left+ABounds.Right - (ARect.Right-ARect.Left)) div 2,0);
+      taRightJustify: ARect.Offset(ABounds.Right - AHorizMargin - (ARect.Right-ARect.Left),0);
+      else ARect.Offset(ABounds.Left + AHorizMargin,0);
+    end;
+    case AVertAlign of
+      tlCenter: ARect.Offset(0, (ABounds.Top+ABounds.Bottom - (ARect.Bottom-ARect.Top)) div 2);
+      tlBottom: ARect.Offset(0, ABounds.Bottom - AVertMargin - (ARect.Bottom-ARect.Top));
+      else ARect.Offset(0, ABounds.Top + AVertMargin);
+    end;
+  end;
+
+begin
+  if Assigned(AGlyph) and not AGlyph.Empty then
+  begin
+    gw := AGlyph.Width;
+    gh := AGlyph.Height;
+  end
+  else exit(EmptyRect);
+
+  if AOldPlacement then
+  begin
+    if ACaption = '' then
+    begin
+      w := 0;
+      h := 0;
+    end else
+      CalculateTextSize(ACaption, AFont, w, h);
+    l := rAvail.Right - Round(((rAvail.Right - rAvail.Left) + w + gw) / 2);
+    t := rAvail.Bottom - Round(((rAvail.Bottom - rAvail.Top) + gh) / 2);
+    result := rect(l,t,l+gw,t+gh);
+    Inc(rAvail.Left, l + gw + AGlyphMargin);
+    exit;
+  end;
+
+  GetGlyphActualLayout(ACaption, AFont, AGlyphAlignment, AGlyphMargin,
+    horizAlign, vertAlign, relHorizAlign, relVertAlign, glyphHorzMargin, glyphVertMargin);
+
+  if ACaption = '' then
+  begin
+    rGlyph := rect(0,0,gw,gh);
+    AlignRect(rGlyph, rAvail, horizAlign, vertAlign, glyphHorzMargin, glyphVertMargin);
+    exit(rGlyph);
+  end else
+    CalculateTextSizeEx(ACaption, AFont, w, h, rAvail.Right-rAvail.Left);
+
+  if relVertAlign in[tlTop,tlBottom] then
+  begin
+    w2 := max(w,gw+glyphHorzMargin);
+    h2 := h+gh+glyphVertMargin;
+  end else
+  begin
+    w2 := w+gw+glyphHorzMargin;
+    if (ACaption <> '') and (w2 > rAvail.Right-rAvail.Left) then
+    begin
+      CalculateTextSizeEx(ACaption, AFont, w, h, rAvail.Right-rAvail.Left - (gw+glyphHorzMargin));
+      w2 := w+gw+glyphHorzMargin;
+    end;
+    h2 := max(h,gh+glyphVertMargin);
+  end;
+  rAll := rect(0,0,w2,h2);
+  AlignRect(rAll, rAvail, horizAlign, vertAlign);
+
+  rText := rect(0,0,w,h);
+  rGlyph := rect(0,0,gw,gh);
+  case relVertAlign of
+    tlTop: begin
+      AlignRect(rGlyph, rAll, relHorizAlign, tlTop,
+        glyphHorzMargin, glyphVertMargin);
+      AlignRect(rText, rAll, horizAlign, tlBottom);
+    end;
+    tlBottom: begin
+      AlignRect(rGlyph, rAll, relHorizAlign, tlBottom,
+        glyphHorzMargin, glyphVertMargin);
+      AlignRect(rText, rAll, horizAlign, tlTop);
+    end;
+    else begin
+      if relHorizAlign = taRightJustify then
+      begin
+        AlignRect(rGlyph, rAll, taRightJustify, tlCenter,
+          glyphHorzMargin, glyphHorzMargin);
+        AlignRect(rText, rAll, taLeftJustify, tlCenter);
+      end else
+      begin
+        AlignRect(rGlyph, rAll, taLeftJustify, tlCenter,
+          glyphHorzMargin, glyphHorzMargin);
+        AlignRect(rText, rAll, taRightJustify, tlCenter);
+      end;
+    end;
+  end;
+  result := rGlyph;
+  if AFont.WordBreak and (rText.Right < rAvail.Right) then inc(rText.Right); //word-break computation may be one pixel off
+  rAvail := rText;
+end;
+
 procedure RenderArrow(ATargetBGRA: TBGRABitmap; const ARect: TRect;
 procedure RenderArrow(ATargetBGRA: TBGRABitmap; const ARect: TRect;
   ASize: Integer; ADirection: TBCArrowDirection; AColor: TColor; AOpacity: Byte);
   ASize: Integer; ADirection: TBCArrowDirection; AColor: TColor; AOpacity: Byte);
 var
 var

File diff suppressed because it is too large
+ 103 - 562
test/BGRA Ribbon Custom/uMain.lfm


+ 0 - 56
test/BGRA Ribbon Custom/uMain.pas

@@ -105,8 +105,6 @@ type
     procedure btnMaximizeClick(Sender: TObject);
     procedure btnMaximizeClick(Sender: TObject);
     procedure btnMinimizeClick(Sender: TObject);
     procedure btnMinimizeClick(Sender: TObject);
     procedure btnNewClick(Sender: TObject);
     procedure btnNewClick(Sender: TObject);
-    procedure btnOpenAfterRenderBCButton(Sender: TObject;
-      const ABGRA: TBGRABitmap; AState: TBCButtonState; ARect: TRect);
     procedure btnFileMenuCloseMouseDown(Sender: TObject; Button: TMouseButton;
     procedure btnFileMenuCloseMouseDown(Sender: TObject; Button: TMouseButton;
       Shift: TShiftState; X, Y: integer);
       Shift: TShiftState; X, Y: integer);
     procedure btnFileMenuMouseDown(Sender: TObject; Button: TMouseButton;
     procedure btnFileMenuMouseDown(Sender: TObject; Button: TMouseButton;
@@ -363,17 +361,6 @@ begin
 
 
   { Showing Form.Caption in Title bar }
   { Showing Form.Caption in Title bar }
   lblTitle.Caption := frmMain.Caption;
   lblTitle.Caption := frmMain.Caption;
-
-  btnOpen.ShowCaption := False;
-  btnNew.ShowCaption := False;
-  btnExit.ShowCaption := False;
-  btnClipboard.ShowCaption := False;
-  btnColors.ShowCaption := False;
-  btnOpen.Images := nil;
-  btnNew.Images := nil;
-  btnExit.Images := nil;
-  btnClipboard.Images := nil;
-  btnColors.Images := nil;
 end;
 end;
 
 
 procedure TfrmMain.FormWindowStateChange(Sender: TObject);
 procedure TfrmMain.FormWindowStateChange(Sender: TObject);
@@ -597,49 +584,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TfrmMain.btnOpenAfterRenderBCButton(Sender: TObject;
-  const ABGRA: TBGRABitmap; AState: TBCButtonState; ARect: TRect);
-var
-  myText: string;
-  myRect: TRect;
-  tw: integer;
-  c: TBGRAPixel;
-begin
-{ Custom painting of Caption and Image needed, as standard routines misalign the
-  position of Caption and Image }
-
-  ABGRA.FontName := 'Segoe UI';
-  ABGRA.FontHeight := 14;
-
-  myText := TBCButton(Sender).Caption;
-
-  { Defining myRect with Bottom -12px }
-  myRect.Bottom := ARect.Bottom - 12;
-  myRect.Left := ARect.Left;
-  myRect.Right := ARect.Right;
-  myRect.Top := ARect.Left;
-
-  { Determining the width/height of Caption. We need only width }
-  tw := ABGRA.TextSize(mytext).cx;
-  c := uRibbon.BtnFntColor;
-
-  if tw > TBCButton(Sender).Width then
-  begin
-    { Caption doesnt fit in one line, reduce Fontsize }
-    ABGRA.FontHeight := 13;
-    ABGRA.TextRect(ARect, myText, taCenter, tlBottom, c);
-  end
-  else
-  begin
-    { Caption fits in one line }
-    ABGRA.TextRect(myRect, myText, taCenter, tlBottom, c);
-  end;
-
-  { Painting of Image on Button }
-  ImageList32.Draw(ABGRA.Canvas, (TBCButton(Sender).Width - 32) div 2, 4,
-    TBCButton(Sender).ImageIndex);
-end;
-
 procedure TfrmMain.btnExitClick(Sender: TObject);
 procedure TfrmMain.btnExitClick(Sender: TObject);
 begin
 begin
   Close;
   Close;

+ 19 - 2
test/BGRA Ribbon Custom/uRibbon.pas

@@ -43,11 +43,22 @@ implementation
 
 
 procedure StyleButtons(AControl: TControl; AButton: TBCButton);
 procedure StyleButtons(AControl: TControl; AButton: TBCButton);
 var
 var
-  i: integer;
+  i, prevNormalFontHeight, prevHoverFontHeight, prevClickedFontHeight: integer;
   WinControl: TWinControl;
   WinControl: TWinControl;
 begin
 begin
   if AControl is TBCButton then
   if AControl is TBCButton then
-    AControl.Assign(AButton);
+  begin
+    with TBCButton(AControl) do
+    begin
+      prevNormalFontHeight := StateNormal.FontEx.Height;
+      prevHoverFontHeight := StateHover.FontEx.Height;
+      prevClickedFontHeight := StateClicked.FontEx.Height;
+      AControl.Assign(AButton);
+      StateNormal.FontEx.Height := prevNormalFontHeight;
+      StateHover.FontEx.Height := prevHoverFontHeight;
+      StateClicked.FontEx.Height := prevClickedFontHeight;
+    end;
+  end;
   if AControl is TWinControl then
   if AControl is TWinControl then
   begin
   begin
     WinControl := TWinControl(AControl);
     WinControl := TWinControl(AControl);
@@ -223,6 +234,8 @@ begin
       FontEx.Name:='Segoe UI';
       FontEx.Name:='Segoe UI';
       FontEx.Shadow:=FALSE;
       FontEx.Shadow:=FALSE;
       FontEx.Color:=BtnFntColor;
       FontEx.Color:=BtnFntColor;
+      FontEx.WordBreak:= true;
+      FontEx.TextAlignment := bcaCenterTop;
       FontEx.Style:=[];
       FontEx.Style:=[];
     end;
     end;
     with StateHover do
     with StateHover do
@@ -233,6 +246,8 @@ begin
       FontEx.Name:='Segoe UI';
       FontEx.Name:='Segoe UI';
       FontEx.Shadow:=FALSE;
       FontEx.Shadow:=FALSE;
       FontEx.Color:=BtnFntColor;
       FontEx.Color:=BtnFntColor;
+      FontEx.WordBreak:= true;
+      FontEx.TextAlignment := bcaCenterTop;
       FontEx.Style:=[];
       FontEx.Style:=[];
     end;
     end;
     with StateClicked do
     with StateClicked do
@@ -243,6 +258,8 @@ begin
       FontEx.Name:='Segoe UI';
       FontEx.Name:='Segoe UI';
       FontEx.Shadow:=FALSE;
       FontEx.Shadow:=FALSE;
       FontEx.Color:=BtnFntColor;
       FontEx.Color:=BtnFntColor;
+      FontEx.WordBreak:= true;
+      FontEx.TextAlignment := bcaCenterTop;
       FontEx.Style:=[];
       FontEx.Style:=[];
     end;
     end;
   end;
   end;

Some files were not shown because too many files changed in this diff