Как отобразить RichEdit Text на холст, сохранив плавность шрифта - PullRequest
1 голос
/ 14 марта 2011

Я пытаюсь сделать RichEdit для растрового изображения.Я хочу сделать Backgrond прозрачным.Я мог бы добиться этого с помощью кода выше.Проблема в том, что когда я устанавливаю растровое изображение как прозрачное, прозрачный цвет становится прозрачным.Есть ли способ обработки пикселей по краю, которые отличаются от цвета фона, а также отличаются от цвета шрифта.я имею в виду сделать пиксели полупрозрачными по краю, что обеспечивает плавный вид.

    Graphics::TBitmap *bitmap = new Graphics::TBitmap();
    bitmap->Width = RichEdit1->Width ;
    bitmap->Height = RichEdit1->Height ;


    TRect BoundingBox(0,0,RichEdit1->Width, RichEdit1->Height) ;

    // Render RichEdit to bitmap
    TFormatRange formatRange;
    int twipsPerPixel = 1440 / Screen->PixelsPerInch;

    formatRange.hdc = bitmap->Canvas->Handle;
    formatRange.hdcTarget = bitmap->Canvas->Handle;
    formatRange.chrg.cpMin = 0;
    formatRange.chrg.cpMax = -1;

    formatRange.rc.top = 2 * twipsPerPixel;
    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    // Measure text's height.
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);
    RichEdit1->Perform(EM_FORMATRANGE, 0, (LPARAM) &formatRange);

    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    formatRange.rcPage = formatRange.rc;


    /**
    * Draw..
    **************************************************************************/
    RichEdit1->Perform(EM_FORMATRANGE, 1, (LPARAM) &formatRange);
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);


   // Draw background
   // Use different background color to see the trasparency problem
   this->Canvas->Brush->Color = clRed ;
   this->Canvas->Rectangle(0,0,RichEdit1->Width , RichEdit1->Height );

   // Draw the transparent bitmap
   bitmap->Transparent = true ;
   bitmap->TransparentColor = RichEdit1->Color ;
   this->Canvas->Draw(0,0,bitmap);

Спасибо.

Ответы [ 2 ]

2 голосов
/ 14 марта 2011

Сглаживание шрифтов работает с частичной прозрачностью, используя альфа-канал.Поэтому свойства Transparent и TransparentColor для TBitmap неприменимы.

Вы еще не сказали, какую версию C ++ Builder / VCL вы используете, но более современные версии лучше поддерживают частичнуюпрозрачность, чем у некоторых старых.

Чтобы заставить это работать, вам нужно установить PixelFormat вашего растрового изображения на pf32bit.Вам также может потребоваться установить AlphaFormat на afDefined.

Если вы не можете заставить TBitmap делать то, что вам нужно, вам придется вернуться к командам GDI, чтобы создать подходящий HBITMAP.Вы можете по крайней мере присвоить это свойству Handle TBitmap, и обычно оттуда все ведет себя.

Обратите внимание, что я не пользователь C ++ Builder, но знаю VCL из Delphi.

ОБНОВЛЕНИЕ

Я попробовал это в Delphi, и у меня сработало следующее:

procedure TForm4.Button1ClickBMP(Sender: TObject);
var
  BMP: TBitmap;
  fmtRange: TFormatRange;
  intPPI, Flags: Integer;
begin
  BMP := TBitmap.Create;
  Try
    BMP.PixelFormat := pf32bit;
    BMP.SetSize(RichEdit1.Width, RichEdit1.Height);

    FillChar(fmtRange, SizeOf(fmtRange), 0);
    with fmtRange do begin
      hDC := BMP.Canvas.Handle;
      hdcTarget := hDC;
      intPPI := Screen.PixelsPerInch;
      rc := Rect(
        0,
        0,
        RichEdit1.Width*1440 div intPPI,
        RichEdit1.Height*1440 div intPPI
      );
      rcPage := rc;
      chrg.cpMin := 0;
      chrg.cpMax := -1;
    end;
    Flags := 1;
    RichEdit1.Perform(EM_FORMATRANGE, Flags, Longint(@fmtRange));
    RichEdit1.Perform(EM_FORMATRANGE, 0, 0);
    BMP.SaveToFile('c:\desktop\test.bmp');
  Finally
    FreeAndNil(BMP);
  End;
end;

Вывод выглядит так, несколько взорван досм. сглаживание:

enter image description here

Надеюсь, это поможет, потому что, похоже, вы совсем близко!

0 голосов
/ 04 ноября 2014

Как уже ответил Дэвид, субпиксельное сглаживание требует знания цвета фона. Это объясняется более подробно в этом ответе . По сути, когда вы используете субпиксельное сглаживание, вы рассматриваете три цветовых канала как имеющие разные пространственные смещения (отсюда и очевидное увеличение разрешения). Это означает, что им нужны разные альфа-значения, но, конечно, есть только один альфа-канал.

Конечно, вы можете выполнять регулярное сглаживание в полутоновых оттенках серого на прозрачном фоне. Возможно, этого было бы достаточно? Некоторые другие ответы в вопросе, связанном выше, предлагают способы достигнуть этого. Взгляните на ANTIALIASED_QUALITY (против CLEARTYPE_QUALITY) в структуре LOGFONT. (Я не пробовал это.)

...