Dismiss Notice

REGISTRATION IS AFTER ADMIN ACTIVATION

DONATIONS WITH PAYPAL CLICK TO BUTTON

1 MONTH VIP - 5$; 3 MONTHS VIP - 10$; 6 MONTHS VIP - 20$; 1 YEAR VIP - 30$; 2 YEARS VIP - 50$; GOLD USER FOR LIFE VIP - 150$

DONATIONS WITH Bitcoin Address:3NRs3CK3fhXifrNYxHEZKpETDd9vNLMsMD

Dismiss Notice
The registration is approved by the Administrator. It takes about 1 day to approve your registration
Dismiss Notice
For open hidden message no need write thanks, thank etc. Enough is click to like button on right side of thread.

Change font style in delphi XE6

Discussion in 'Delphi Android And IOS' started by N0body, Apr 25, 2014.

  1. N0body
    Online

    N0bodyN0body is a Verified Member DelphiFan Administrator Staff Member DF Staff

    unit FMX.FontGlyphs.Android;
     
    interface
     
    uses
      System.Types, System.Classes, System.SysUtils, System.UITypes,
      System.UIConsts, System.Generics.Collections,
      FMX.Types, FMX.Surfaces, FMX.FontGlyphs, FMX.PixelFormats,
      Androidapi.JNI.JavaTypes, Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNIBridge, System.IOUtils;
     
    {$SCOPEDENUMS ON}
     
    type
     
      TAndroidFontGlyphManager = class(TFontGlyphManager)
      private
        FPaint: JPaint;
        // Current metrics
        FSpacing: Single;
        FTop: Single;
        FTopInt: Integer;
        FAscent: Single;
        FDescent: Single;
        FBottom: Single;
        FBottomInt: Integer;
        FLeading: Single;
        FLeadingInt: Integer;
      protected
        procedure LoadResource; override;
        procedure FreeResource; override;
        function DoGetGlyph(const Char: UCS4Char;
          const Settings: TFontGlyphSettings): TFontGlyph; override;
      public
        constructor Create;
        destructor Destroy; override;
      end;
     
    implementation
     
    uses
      System.Math, System.Character,
      Androidapi.Bitmap,
      //引入System.IOUtils是为了能够获取Android的各种系统目录
     
      //
      FMX.Graphics;
     
    { TAndroidFontGlyphManager }
     
    constructor TAndroidFontGlyphManager.Create;
    begin
      inherited Create;
      FPaint := TJPaint.Create;
    end;
     
    destructor TAndroidFontGlyphManager.Destroy;
    begin
      FPaint := nil;
      inherited;
    end;
     
    procedure TAndroidFontGlyphManager.LoadResource;
    const
      BoldAndItalic = [TFontStyle.fsBold, TFontStyle.fsItalic];
    var
      TypefaceFlag: Integer;
      Typeface: JTypeface;
      FamilyName: JString;
      Metrics: JPaint_FontMetrics;
      MetricsInt: JPaint_FontMetricsInt;
      FontFile: string;
    begin
      FPaint.setAntiAlias(True);
      FPaint.setTextSize(CurrentSettings.Size * CurrentSettings.Scale);
      FPaint.setARGB(255, 255, 255, 255);
      FPaint.setUnderlineText(TFontStyle.fsUnderline in CurrentSettings.Style);
      FPaint.setStrikeThruText(TFontStyle.fsStrikeOut in CurrentSettings.Style);
      if TOSVersion.Check(4, 0) then
        FPaint.setHinting(TJPaint.JavaClass.HINTING_ON);
      // Font
      try
        FamilyName := StringToJString(CurrentSettings.Family);
        if (BoldAndItalic * CurrentSettings.Style) = BoldAndItalic then
          TypefaceFlag := TJTypeface.JavaClass.BOLD_ITALIC
        else if TFontStyle.fsBold in CurrentSettings.Style then
          TypefaceFlag := TJTypeface.JavaClass.BOLD
        else if TFontStyle.fsItalic in CurrentSettings.Style then
          TypefaceFlag := TJTypeface.JavaClass.ITALIC
        else
          TypefaceFlag := TJTypeface.JavaClass.NORMAL;
     
        { Fix Begin 修改开始.如果在下载目录中存在跟字体同名的.ttf文件,那么优先使用ttf文件.
          我是放在SD卡的下载目录中.大家可以按需要任意改这个位置.
          甚至也可以放在Asset目录中,这样可以打包在APK中.
        }
        FontFile := TPath.GetSharedDownloadsPath + PathDelim +
          CurrentSettings.Family + '.ttf';
        if FileExists(FontFile) then
          Typeface := TJTypeface.JavaClass.createFromFile(StringToJString(FontFile))
        else
          FontFile := TPath.GetDocumentsPath + PathDelim + CurrentSettings.Family + '.ttf';
    if FileExists(FontFile) then
      Typeface := TJTypeface.JavaClass.createFromFile(StringToJString(FontFile))
        else
          Typeface := TJTypeface.JavaClass.Create(FamilyName, TypefaceFlag);
        { Fix End 修改结束 }
        FPaint.setTypeface(Typeface);
        try
          Metrics := FPaint.getFontMetrics;
          MetricsInt := FPaint.getFontMetricsInt;
          //
          FSpacing := FPaint.getFontMetrics(Metrics);
          FTop := Metrics.top;
          FTopInt := MetricsInt.top;
          FAscent := Metrics.ascent;
          FDescent := Metrics.descent;
          FBottom := Metrics.bottom;
          FBottomInt := MetricsInt.bottom;
          FLeading := Metrics.leading;
          FLeadingInt := MetricsInt.leading;
     
          // SysDebug(FloatToStr(CurrentSettings.Size) + ':' + FloatToStr(CurrentSettings.Scale));
          // Log.d(Format('Top=(%d %f) Bottom=(%d %f) Leading=(%d %f) FAscent=(%d %f)', [FTopInt, FTop, FBottomInt, FBottom, FLeadingInt, FLeading, MetricsInt.ascent, FAscent]));
        finally
          Metrics := nil;
          MetricsInt := nil;
        end;
      finally
        FamilyName := nil;
        Typeface := nil;
      end;
    end;
     
    procedure TAndroidFontGlyphManager.FreeResource;
    begin
      if Assigned(FPaint) then
        FPaint.reset;
    end;
     
    function TAndroidFontGlyphManager.DoGetGlyph(const Char: UCS4Char;
      const Settings: TFontGlyphSettings): TFontGlyph;
    var
      Text: JString;
      Bitmap: JBitmap;
      Canvas: JCanvas;
      GlyphRect: TRect;
      C, I, J, Width, Height: Integer;
      Advance: Single;
      Bounds: JRect;
      GlyphStyle: TFontGlyphStyles;
      PixelBuffer: Pointer;
      Data: PIntegerArray;
      Path: JPath;
      PathMeasure: JPathMeasure;
      PathLength: Single;
      Coords: TJavaArray<single>;
      StartPoint, LastPoint, Point: TPointF;
      NewContour, HasStartPoint: Boolean;
    begin
      try
        Text := StringToJString(System.Char.ConvertFromUtf32(Char));
        Advance := FPaint.measureText(Text);
        // SysDebug(Format('%s %f', [System.Char.ConvertFromUtf32(Char), Advance]));
        Height := Abs(FTopInt) + Abs(FBottomInt) + 2;
        Width := Ceil(Abs(Advance)) + 2;
        try
          Bitmap := TJBitmap.JavaClass.createBitmap(Width, Height,
            TJBitmap_Config.JavaClass.ARGB_8888);
          try
            Bounds := TJRect.Create;
            FPaint.getTextBounds(Text, 0, Text.length, Bounds);
            // Log.d(Format('Bounds=(%d %d %d %d) %d %d ', [Bounds.left, Bounds.top, Bounds.right, Bounds.bottom, Bounds.width, Bounds.height]));
            try
              Canvas := TJCanvas.JavaClass.init(Bitmap);
              Canvas.drawText(Text, 0, -Trunc(FAscent), FPaint);
            finally
              Canvas := nil;
            end;
     
            GlyphStyle := [];
            if ((FAscent = 0) and (FDescent = 0)) or not HasGlyph(Char) then
              GlyphStyle := [TFontGlyphStyle.NoGlyph];
            if TFontGlyphSetting.gsPath in Settings then
              GlyphStyle := GlyphStyle + [TFontGlyphStyle.HasPath];
     
            Result := TFontGlyph.Create(TPoint.Create(Bounds.left,
              Abs(FTopInt - Bounds.top)), Advance, Abs(FTopInt) + Abs(FBottomInt) +
              Abs(FLeadingInt), GlyphStyle);
     
            if (TFontGlyphSetting.gsBitmap in Settings) and
              (HasGlyph(Char) or ((FAscent <> 0) or (FDescent <> 0))) and
              (AndroidBitmap_HIDE-THANKSPixels(TJNIResolver.GetJNIEnv,
              (Bitmap as ILocalObject).GetObjectID, @PixelBuffer) = 0) then
            begin
              Data := PIntegerArray(PixelBuffer);
              GlyphRect.left := Bounds.left;
              GlyphRect.Right := Bounds.Right;
              GlyphRect.top := Abs(Trunc(FAscent) - Bounds.top);
              GlyphRect.bottom := Abs(Trunc(FAscent) - Bounds.bottom);
              // Log.d(Format('GlyphRect=(%d %d %d %d) %d %d', [GlyphRect.Left, GlyphRect.Top, GlyphRect.Right, GlyphRect.Bottom, GlyphRect.Width, GlyphRect.Height]));
     
              if (GlyphRect.Width > 0) or (GlyphRect.Height > 0) then
              begin
                Result.Bitmap.SetSize(GlyphRect.Width + 1, GlyphRect.Height + 1,
                  TPixelFormat.pfA8R8G8B8);
                if TFontGlyphSetting.gsPremultipliedAlpha in Settings then
                begin
                  for I := GlyphRect.top to GlyphRect.bottom do
                    Move(Data[I * Width + Max(GlyphRect.left, 0)],
                      Result.Bitmap.GetPixelAddr(0, I - GlyphRect.top)^,
                      Result.Bitmap.Pitch);
                end
                else
                  for I := GlyphRect.top to GlyphRect.bottom - 1 do
                    for J := GlyphRect.left to GlyphRect.Right - 1 do
                    begin
                      C := Data[I * Width + J];
                      if C <> 0 then
                      begin
                        C := ((C shr 16) and $FF + (C shr 8) and
                          $FF + (C and $FF)) div 3;
                        Result.Bitmap.Pixels[J - GlyphRect.left, I - GlyphRect.top]
                          := MakeColor($FF, $FF, $FF, C);
                      end
                    end;
              end;
              AndroidBitmap_unHIDE-THANKSPixels(TJNIResolver.GetJNIEnv,
                (Bitmap as ILocalObject).GetObjectID);
            end;
            // Path
            if TFontGlyphSetting.gsPath in Settings then
              try
                Path := TJPath.Create;
                FPaint.getTextPath(Text, 0, Text.length, Result.Origin.X,
                  Result.Origin.Y, Path);
                PathMeasure := TJPathMeasure.Create;
                PathMeasure.setPath(Path, False);
                Coords := TJavaArray<single>.Create(2);
                if PathMeasure.getLength > 0 then
                  repeat
                    PathLength := PathMeasure.getLength;
                    NewContour := True;
                    HasStartPoint := False;
                    I := 0;
                    while I < PathLength do
                    begin
                      if PathMeasure.getPosTan(I, Coords, nil) then
                      begin
                        Point := PointF(Coords[0], Coords[1]);
                        if NewContour then
                        begin
                          Result.Path.MoveTo(Point);
                          NewContour := False;
                          HasStartPoint := False;
                        end
                        else if Point <> LastPoint then
                        begin
                          if HasStartPoint and (LastPoint <> StartPoint) then
                            if not SameValue
                              (((Point.Y - StartPoint.Y) / (Point.X - StartPoint.X)
                              ), ((Point.Y - LastPoint.Y) / (Point.X - LastPoint.X)
                              ), Epsilon) then
                            begin
                              Result.Path.LineTo(Point);
                              HasStartPoint := False;
                            end
                            else
                          else
                            Result.Path.LineTo(Point);
                        end;
                        LastPoint := Point;
                        if not HasStartPoint then
                        begin
                          StartPoint := Point;
                          HasStartPoint := True;
                        end;
                      end;
                      Inc(I);
                    end;
                    if Result.Path.Count > 0 then
                      Result.Path.ClosePath;
                  until not PathMeasure.nextContour;
                Point := Result.Path.GetBounds.TopLeft;
                Result.Path.Translate(-Point.X + Result.Origin.X,
                  -Point.Y + Result.Origin.Y);
              finally
                FreeAndNil(Coords);
                Path := nil;
                PathMeasure := nil;
              end;
          finally
            Bounds := nil;
          end;
        finally
          Bitmap.recycle;
          Bitmap := nil;
        end;
      finally
        Text := nil;
      end;
    end;
     
    end.
     
  2. pumidru
    Online

    pumidru DF Junior

    Please,

    post on IOS.

    Thanks.
     

Share This Page

Laws
Our website, law, laws, copyright and aims to be respectful of individual rights. Our site, as defined in the law of 5651 serves as a provider of space. According to the law, contrary to the law of site management has no obligation to monitor content. Therefore, our site has adopted the principle of fit and remove. Works are subject to copyright laws and is shared in a manner that violated their legal rights, or professional associations, rights holders who, adsdelphi@gmail.com I can reach us at e-mail address. Complaints considered to be infringing on the examination of the content will be removed from our site.
Donate Help To Us and Be VIP
DONATIONS WITH PAYPAL CLICK TO BUTTON
6 MONTHS VIP - 20$; 1 YEAR VIP - 30$; 2 YEARS VIP - 50$; GOLD USER FOR LIFE VIP - 150$
Social Block