core text displayed text is drawn without spacing - macos

I'm trying to display text using coretext. Now it's on a delphi form, but I have code which seems to work fine getting the context for drawing shapes on (it just gets the FContext field from the form).
The text appears like this (it's upside down), it's suppose to be 'at'
Now here's the code, just put it in a formpaint
var
cgcontext : CGContextRef;
path : CGMutablePathRef;
framesetter : CTFramesetterRef;
frame : CTFrameRef;
attrString: CFAttributedStringRef;
function GetCGContextFromCanvas(ACanvas: TCanvas): CGContextRef;
var
Context: TRttiContext;
Field: TRttiField;
begin
Field := Context.GetType(ACanvas.ClassType).GetField('FContext');
Assert(Field <> nil);
Result := PPointer(Field.GetValue(ACanvas).GetReferenceToRawData)^;
end;
begin
cgcontext := GetCGContextFromCanvas(Canvas);
path := CGPathCreateMutable(); //1
CGPathAddRect(path, nil, CGRectMake(0,0,600,200));
attrString := CFAttributedStringCreate(kCFAllocatorDefault, CFSTR('at'), nil);
framesetter := CTFramesetterCreateWithAttributedString(attrString); //3
frame := CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 2), path, nil);
CTFrameDraw(frame, cgcontext); //4
end;
Any suggestions on why the spacing is wrong? Shouldn't it use the default spacing?

..it's because the textmatrix is set somewhere, but because it's not restored when you do CGContextSaveGState/CGContextRestoreGState the textmatrix is wrong. So just add a CGContextSetTextMatrix(cgcontext, CGAffineTransformIdentity);

Related

How to create label on bevel line in Inno Setup

Yesterday I found a new setup. It has a label on a bevel line. So, how to create and setting label on bevel line like this in Inno Setup?
That looks like a group box control (known as the TGroupBox in Delphi/VCL), not the bevel.
But the group box control is not exposed in Inno Setup.
As an alternative, just place a TLabel on top of the TBevel. Make sure you set label's Transparent property to False.
On Windows Vista and newer, you can also add a hair space around for a padding. You need Unicode version of Inno Setup for that (the only version as of Inno Setup 6).
procedure InitializeWizard;
var
Page: TWizardPage;
Bevel: TBevel;
Caption: TLabel;
begin
Page := CreateCustomPage(wpWelcome, '', '');
Bevel := TBevel.Create(WizardForm);
with Bevel do
begin
Parent := Page.Surface;
Shape := bsFrame;
Left := ScaleX(0);
Top := ScaleY(8);
Width := ScaleX(417);
Height := ScaleY(220);
end;
Caption := TLabel.Create(WizardForm);
with Caption do
begin
Parent := Page.Surface;
Left := Bevel.Left + ScaleX(8);
Top := Bevel.Top - ScaleY(6);
Transparent := False;
Caption := 'Caption';
{ On Vista and newer, add padding using a hair space }
if GetWindowsVersion >= $06000000 then
Caption := #$200A + Caption + #$200A;
end;
end;

Font Size Difference between Printer Canvas and Form Canvas

I use
Printer.BeginDoc;
Printer.Canvas.Font := Self.Font;
Printer.Canvas.Font.Name := 'Verdana';
Printer.Canvas.Font.Size := 10;
Printer.Canvas.TextOut(10,0,'Nom : Prenom Nom');
Printer.Canvas.TextOut(10,100,'Nom2 : Prenom2 Nom2');
Printer.EndDoc;
Now I wanted to make some kind of preview so decided to make a preview form.
But, I have to set the font size a lot bigger.
Form2.Canvas.Font := Self.Font;
Form2.Canvas.Font.Name := 'Verdana';
Form2.Canvas.Font.Size := 25; //<=======Have to set this a lot higher to resemble what is on the print.
Form2.Canvas.TextOut(10,0,'Nom : Prenom Nom');
Form2.Canvas.TextOut(10,100,'Nom2 : Prenom2 Nom2');
How come the font size doesn't behave the same on the printer.canvas and form.canvas?
this occur because depends of printer DPI, for example
the Printer.Canvas.Font.Size := 8 works on a printer with 300 DPI a
printer with 600 DPI needs .Size := 4 for the same result.
try this before Printer.beginDoc
Printer.Canvas.Font.PixelsPerInch := GetDeviceCaps(Printer.Handle,LOGPIXELSY);
or try this function always you need to change font size:
procedure TForm1.SetPixelsPerInch;
var
FontSize: integer;
begin
FontSize := Printer.Canvas.Font.Size;
Printer.Canvas.Font.PixelsPerInch := GetDeviceCaps(Printer.Handle,LOGPIXELSY);
Printer.Canvas.Font.Size := FontSize;
end;
See more details in http://www.delphigroups.info/2/e7/314459.html

How to change picture delphi timage in run time

I use a timage in a form which load a background image.
The problem is when i choose another picture in run time and change it by
Img_Bk.Picture.LoadFromFile( SaveFileName );
It doesnt work (Picture did n't change ). I mean it shows previous picture and doesn't show the new image during run time. Id like to change application background image during run time in my company by users which main form is a mdi form .
I use delphi 7 .
try
Img_Bk.Picture := nil ;
if FileSize > 100 then
begin
Img_Bk.Picture.LoadFromFile( SaveFileName );
end;
Img_Bk.Stretch := True ;
except
end;
LoadFromFile is known to work. So there must be a more prosaic explanation.
The first possible explanation is that FileSize is not greater than 100 and the if condition evaluates false.
Another possible explanation is that the image in the file that you specify is not the one you are expecting.
Otherwise, your code has a swallow all exception handler. And so when the call to LoadFromFile fails and raises an exception, your code ignores that and carries on as if nothing un-toward had happened. Remove the try/except, and deal with the error that will be revealed.
The real lesson for you to learn is never to write such an exception handler again.
This program should prove to you that LoadFromFile is just fine:
program ImageDemo;
uses
Types, Math, IOUtils, SHFolder, Forms, Controls, StdCtrls, ExtCtrls, jpeg;
var
Form: TForm;
Image: TImage;
Timer: TTimer;
ImageIndex: Integer = -1;
MyPictures: string;
Images: TStringDynArray;
type
THelper = class
class procedure Timer(Sender: TObject);
end;
class procedure THelper.Timer(Sender: TObject);
begin
inc(ImageIndex);
if ImageIndex>high(Images) then
ImageIndex := 0;
if ImageIndex>high(Images) then
exit;
Image.Picture.LoadFromFile(Images[ImageIndex]);
end;
function GetMyPictures: string;
var
Str: array[0..260] of Char;
begin
if SHGetFolderPath(0, CSIDL_MYPICTURES, 0, 0, Str) = S_OK then
Result := Str;
end;
procedure BuildForm;
begin
Form.ClientWidth := 700;
Form.ClientHeight := 500;
Image := TImage.Create(Form);
Image.Parent := Form;
Image.Align := alClient;
Image.Stretch := True;
Timer := TTimer.Create(Form);
Timer.OnTimer := THelper.Timer;
Timer.Interval := 100;
end;
begin
MyPictures := GetMyPictures;
Images := TDirectory.GetFiles(MyPictures, '*.jpg', TSearchOption.soAllDirectories);
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, Form);
BuildForm;
Application.Run;
end.
I had the same problem today. After the call of LoadFromFile() the image does not change. I have tried Refresh, Repaint, Invalidate and Update -> nothing helped. Then I found that resizing the from immediately updated the image.
Finally I found that setting property Visible to false and back to true updates the image, too.
FormMain.Image1.Visible := false;
FormMain.Image1.Picture.LoadFromFile(newImageFileName);
FormMain.Image1.Visible := true;
Perhaps not the best but it works for me.

Why doesn't OpenGL correctly display the image I loaded?

I have two images, both are 24 color .bmp 32x32 pixels. If I load one with OpenGL it works, if I load the other with OpenGL it just shows black and white lines.
Is there something else that could be different, thus not letting one of the images show?
This one does not work in code:
This one does work in code:
Also checked info size and file header size. Both images were 40 on info and 14 on file size. Both images biWidth and BiHeight were still 32x32.
This shows how I texture a hex with the image grass
//GRASS
glTexImage2d(GL_TEXTURE_2D,Level,Colorcomps,sGrass,tGrass,Border,GL_RGB,GL_UNSIGNED_BYTE,grass);
glLoadName(1);
glBegin(GL_POLYGON);
for I := 0 to 6 do
begin
glTexCoord2f(COS(i/6.0*2*PI),SIN(i/6.0*2*pi));
glVertex3f((((COS(i/6.0*2*PI)/12)+offsetx)+0.2),((SIN(i/6.0*2*pi)/12)+offsety),-2);
end;
glEnd;
grass is a pointer and filled like so:
grass := Readbitmap('Grass.bmp',sGrass,tGrass);
And how do I get the image data (which should be OK as it works with other images, I really think its something else about an image that would make the two different)?
Function TFCreateMap.ReadBitmap(const FilePath:String;var sWidth,tHeight:GLsizei):pointer;
const
szh=SizeOf(TBitmapFileHeader);
szi=SizeOf(TBitmapInfoHeader);
var
bmpfile: file;
bfh:TBitmapFileHeader;
bmi:TBitmapInfoHeader;
t:byte;
x,
fpos,
size: integer;
begin
assignfile(bmpfile,FilePath);
reset(bmpfile,1);
size := FileSize(bmpfile)-szh-szi;
blockread(bmpfile,bfh,szh);
if bfh.bfType<>$4D42 then
raise EinvalidGraphic.Create('Invalid Bitmap');
blockread(bmpfile,bmi,szi);
with bmi do
begin
sWidth := biWidth;
tHeight := biHeight;
end;
getmem(result,size);
blockread(bmpfile,result^,size);
for x := 0 to sWidth*tHeight-1 do
with TWrap(result^)[x] do
begin
t := r;
r := b;
b := t;
end;
end;
Your bitmaps differ at least in bit depth. The one which fails you to load is 8-bit, whilst the working one is 24-bit. What you need is to convert your 8-bit bitmap to 24-bit (because of the used format parameter value in your glTexImage2D function call).
Code review:
I've made a review of your code and here's the result; the following code uses file stream for reading the file (since I'm not a fan of the old style I/O routines; anyway you forgot on file closing), removes the color channel rotation part which was, as #Rob pointed wrong (for the reason mentioned below). I've added a check for the necessary bit depth value (which must be 24-bit with the format flag you will use for the glTexImage2D function call):
function TFCreateMap.ReadBitmap(const AFilePath: string; var AWidth,
AHeight: GLsizei): Pointer;
var
DataSize: Integer;
FileStream: TFileStream;
FileHeader: TBitmapFileHeader;
InfoHeader: TBitmapInfoHeader;
const
FileTypeBitmap = $4D42;
FileHeaderSize = SizeOf(TBitmapFileHeader);
InfoHeaderSize = SizeOf(TBitmapInfoHeader);
begin
Result := nil;
FileStream := TFileStream.Create(AFilePath, fmOpenRead);
try
FileStream.ReadBuffer(FileHeader, FileHeaderSize);
if (FileHeader.bfType <> FileTypeBitmap) then
raise EinvalidGraphic.Create('Invalid file type!');
FileStream.ReadBuffer(InfoHeader, InfoHeaderSize);
if (InfoHeader.biBitCount <> 24) then
raise EinvalidGraphic.Create('Invalid bit depth!');
DataSize := FileStream.Size - FileHeaderSize - InfoHeaderSize;
GetMem(Result, DataSize);
FileStream.ReadBuffer(Result^, DataSize);
AWidth := InfoHeader.biWidth;
AHeight := InfoHeader.biHeight;
finally
FileStream.Free;
end;
end;
Now to the reason, why I removed the color channel rotation; I have almost no experience with OpenGL, but something tells me, that GL_BGR value of the format parameter of the glTexImage2D function might simplify this part, because I'd say that the function then expects the BGR pixel array for its data parameter and that's how your bitmaps are stored. So my guess is that you can leave the color channel rotation and call the glTexImage2D function with GL_BGR value of the format parameter:
glTexImage2D(GL_TEXTURE_2D, Level, Colorcomps, sGrass, tGrass, Border, GL_BGR,
GL_UNSIGNED_BYTE, grass);
...
First image has index color format, but second image have RGB. You can try to change color format using GIMP or other editor.

How to get images to show up on TExtButton in ExtPascal?

I've been trying for hours in Lazarus following from the sample code in the
AdvancedTabs unit, to make am image appear on a button.
The sample code has this:
constructor TAdvancedTabs.Create;
var
I : integer;
begin
inherited;
with SelfSession do begin
SetCodePress;
SetStyle('.new-tab{background-image:url(' + ExtPath + '/examples/feed-viewer/images/new_tab.gif) !important}');
SetStyle('.tabs{background:url(' + ExtPath + '/examples/desktop/images/tabs.gif)}');
end;
with TExtButton.Create do begin
RenderTo := 'body';
Text := 'Add Tab using AJAX!';
IconCls := 'new-tab';
Handler := Ajax(AddTab);
OnClick := HandleExtButtonClick; // Delphi style event handler
end;
...
I have this:
extPath := (CurrentFCGIThread as TExtThread).ExtPath;
(CurrentFCGIThread as TExtThread).SetStyle('.backbtn{background-image:url(' + ExtPath + '/basxv2/back.png) !important}');
btnClose := TV2ExtButton.Create;
with btnClose.AddTo(Items) do
begin
Id := 'frmManualOrder_btnClose';
X := MarginLeft;
Height := ButtonHeight;
Y := ScreenHeight-12*MarginLeft;
Width := ButtonWidth-10;
RenderTo := 'body';
IconCls := 'backbtn';
...
I have tried a number of different things, converting the image to a
gif, for example, and in most cases the button is either blank (if I
don't set the Text property) or shows the text nudged to the right a
few pixels as if making room for an invisible image. A few times the image appears with the top and bottom clipped.
Can anyone see what I am doing wrong?
TIA
Mark

Resources