fpvectorial: Some fixes in wmf reader (rounded rectangle, text positioning)

git-svn-id: trunk@52824 -
This commit is contained in:
wp 2016-08-17 23:10:45 +00:00
parent c0b60cfaa4
commit fb89d63113

View File

@ -86,8 +86,8 @@ type
procedure ReadPolygon(APage: TvVectorialPage; const AParams: TParamArray; procedure ReadPolygon(APage: TvVectorialPage; const AParams: TParamArray;
AFilled: boolean); AFilled: boolean);
procedure ReadPolyPolygon(APage: TvVectorialPage; const AParams: TParamArray); procedure ReadPolyPolygon(APage: TvVectorialPage; const AParams: TParamArray);
procedure ReadRectangle(APage: TvVectorialPage; const AParams: TParamArray); procedure ReadRectangle(APage: TvVectorialPage; const AParams: TParamArray;
procedure ReadRoundRect(APage: TvVectorialPage; const AParams: TParamArray); IsRounded: Boolean);
procedure ReadStretchDIB(AStream: TStream; APage: TvVectorialPage; procedure ReadStretchDIB(AStream: TStream; APage: TvVectorialPage;
const AParams: TParamArray); const AParams: TParamArray);
function ReadString(const AParams: TParamArray; function ReadString(const AParams: TParamArray;
@ -272,19 +272,28 @@ function TvWMFVectorialReader.CreateFont(const AParams: TParamArray): Integer;
var var
wmfFont: TWMFFont; wmfFont: TWMFFont;
fontRec: PWMFFontRecord; fontRec: PWMFFontRecord;
fntName: String;
idx: Integer;
begin begin
idx := Length(Aparams);
wmfFont := TWMFFont.Create; wmfFont := TWMFFont.Create;
fontRec := PWMFFontRecord(@AParams[0]); fontRec := PWMFFontRecord(@AParams[0]);
wmfFont.Font.Name := ISO_8859_1ToUTF8(fontRec^.FaceName); // Get font name
SetLength(fntName, 32);
idx := SizeOf(TWMFFontRecord) div SizeOf(word);
Move(AParams[idx], fntName[1], 32);
SetLength(fntName, StrLen(PChar(@fntName)));
wmfFont.Font.Name := ISO_8859_1ToUTF8(fntName);
wmfFont.Font.Size := round(ScaleSizeY(fontRec^.Height)); wmfFont.Font.Size := round(ScaleSizeY(fontRec^.Height));
wmfFont.Font.Color := colBlack; // to be replaced by FCurrTextColor wmfFont.Font.Color := colBlack; // to be replaced by FCurrTextColor
wmfFont.Font.Bold := fontRec^.Weight >= 700; wmfFont.Font.Bold := fontRec^.Weight >= 700;
wmfFont.Font.Italic := fontRec^.Italic <> 0; //Escapement <> 0; wmfFont.Font.Italic := fontRec^.Italic <> 0;
wmfFont.Font.Underline := fontRec^.UnderLine <> 0; wmfFont.Font.Underline := fontRec^.UnderLine <> 0;
wmfFont.Font.StrikeThrough := fontRec^.Strikeout <> 0; wmfFont.Font.StrikeThrough := fontRec^.Strikeout <> 0;
wmfFont.Font.Orientation := fontRec^.Orientation div 10; wmfFont.Font.Orientation := fontRec^.Orientation div 10;
wmfFont.RawHeight := fontRec^.Height; wmfFont.RawHeight := fontRec^.Height; //* 6 div 5; // Rough correction for y position
// add to WMF object list // add to WMF object list
Result := FObjList.Add(wmfFont); Result := FObjList.Add(wmfFont);
@ -465,6 +474,7 @@ var
R: TRect; R: TRect;
s: String; s: String;
txt: TvText; txt: TvText;
angle: Double;
begin begin
y := SmallInt(AParams[0]); // signed int y := SmallInt(AParams[0]); // signed int
x := SmallInt(AParams[1]); x := SmallInt(AParams[1]);
@ -482,19 +492,17 @@ begin
// Correct text position which is at baseline in case of fpvectorial, but // Correct text position which is at baseline in case of fpvectorial, but
// may be different depending on bits in the CurrTextAlign value. // may be different depending on bits in the CurrTextAlign value.
case FCurrTextAlign and (TA_BOTTOM + TA_BASELINE) of
0 : // TO DO: More testing of text positioning
{ In this case, the text should be top-aligned, but fpvectorial draws angle := DegToRad(FCurrFont.Orientation);
the text at the baseline --> move it down (and take care of text case FCurrTextAlign and $0018 of
rotation!) } 0:
offs := Rotate2DPoint(Point(0, FCurrRawFontHeight), Point(0, 0), DegToRad(FCurrFont.Orientation)); offs := Point(0, 0); //Rotate2DPoint(Point(0, +FCurrRawFontHeight), Point(0, 0), angle);
TA_BASELINE: TA_BASELINE:
{ This is the way how fpvectorial draws the text --> nothing to do } // offs := Rotate2DPoint(Point(0, -FCurrRawFontHeight*6 div 5), Point(0, 0), angle);
offs := Point(0, 0); offs := Rotate2DPoint(Point(0, +FCurrRawFontHeight), Point(0, 0), angle);
TA_BOTTOM: TA_BOTTOM:
{ Unfortunately we don't know the descender of the font here. Lets offs := Rotate2DPoint(Point(0, -FCurrRawFontHeight*7 div 5), Point(0, 0), angle);
assume it to be 1/5th of the font size. Move text up. }
offs := Rotate2DPoint(Point(0, -FCurrRawFontHeight div 5), Point(0, 0), DegToRad(FCurrFont.Orientation));
end; end;
// Pass text to fpvectorial // Pass text to fpvectorial
@ -502,7 +510,7 @@ begin
// Select the font // Select the font
txt.Font := FCurrFont; txt.Font := FCurrFont;
// Set horizontal text alignment. // Set horizontal text alignment.
case FCurrTextAlign and (TA_RIGHT + TA_CENTER) of case FCurrTextAlign and (TA_RIGHT or TA_CENTER) of
TA_RIGHT : txt.TextAnchor := vtaEnd; TA_RIGHT : txt.TextAnchor := vtaEnd;
TA_CENTER : txt.TextAnchor := vtaMiddle; TA_CENTER : txt.TextAnchor := vtaMiddle;
else txt.TextAnchor := vtaStart; else txt.TextAnchor := vtaStart;
@ -556,7 +564,7 @@ begin
// Test if file begins with a placeable meta file header // Test if file begins with a placeable meta file header
FHasPlaceableMetaHeader := false; FHasPlaceableMetaHeader := false;
AStream.ReadBuffer(buf, SizeOf(TPlaceableMetaHeader)); AStream.ReadBuffer(buf, SizeOf(TPlaceableMetaHeader));
if placeableMetaHdr.Key = $9AC6CDD7 then begin // yes! if placeableMetaHdr.Key = WMF_MAGIC_NUMBER then begin // yes!
FHasPlaceableMetaHeader := true; FHasPlaceableMetaHeader := true;
FBBox.Left := placeableMetaHdr.Left; FBBox.Left := placeableMetaHdr.Left;
FBBox.Top := placeableMetaHdr.Top; FBBox.Top := placeableMetaHdr.Top;
@ -663,8 +671,10 @@ begin
poly.Pen := FCurrPen; poly.Pen := FCurrPen;
if AFilled then if AFilled then
poly.Brush := FCurrBrush poly.Brush := FCurrBrush
else else begin
poly.Brush.Style := bsClear; poly.Brush.Style := bsClear;
poly.Brush.Kind := bkSimpleBrush;
end;
case FCurrPolyFillMode of case FCurrPolyFillMode of
ALTERNATE : poly.WindingRule := vcmEvenOddRule; ALTERNATE : poly.WindingRule := vcmEvenOddRule;
WINDING : poly.WindingRule := vcmNonZeroWindingRule; WINDING : poly.WindingRule := vcmNonZeroWindingRule;
@ -808,9 +818,9 @@ begin
META_POLYPOLYGON: META_POLYPOLYGON:
ReadPolyPolygon(page, params); ReadPolyPolygon(page, params);
META_RECTANGLE: META_RECTANGLE:
ReadRectangle(page, params); ReadRectangle(page, params, false);
META_ROUNDRECT: META_ROUNDRECT:
ReadRectangle(page, params); ReadRectangle(page, params, true);
META_SETPIXEL: META_SETPIXEL:
; ;
META_TEXTOUT: META_TEXTOUT:
@ -919,7 +929,7 @@ begin
SetLength(params, 0); SetLength(params, 0);
end; end;
(*
procedure TvWMFVectorialReader.ReadRectangle(APage: TvVectorialPage; procedure TvWMFVectorialReader.ReadRectangle(APage: TvVectorialPage;
const AParams: TParamArray); const AParams: TParamArray);
// To do: not tested, having not test file // To do: not tested, having not test file
@ -943,25 +953,29 @@ begin
poly.Brush := FCurrBrush; poly.Brush := FCurrBrush;
APage.AddEntity(poly); APage.AddEntity(poly);
end; end;
*)
procedure TvWMFVectorialReader.ReadRoundRect(APage: TvVectorialPage; procedure TvWMFVectorialReader.ReadRectangle(APage: TvVectorialPage;
const AParams: TParamArray); const AParams: TParamArray; IsRounded: Boolean);
// To do: not tested, having no test file
var var
rectRec: PWMFRectRecord; // coordinates are SmallInt rectRec: PWMFRectRecord; // coordinates are SmallInt
rx, ry: SmallInt; rx, ry: SmallInt;
rect: TvRectangle; rect: TvRectangle;
begin begin
ry := AParams[0]; if IsRounded then begin
rx := AParams[1]; ry := AParams[0];
rx := AParams[1];
rectRec := PWMFRectRecord(@AParams[4]); rectRec := PWMFRectRecord(@AParams[2]);
end else begin
rectRec := PWMFRectRecord(@AParams[0]);
rx := 0;
ry := 0;
end;
rect := TvRectangle.Create(APage); rect := TvRectangle.Create(APage);
rect.X := ScaleX(rectRec^.Left); rect.X := ScaleX(rectRec^.Left);
rect.Y := ScaleY(rectRec^.Top); rect.Y := ScaleY(rectRec^.Bottom); // since the axis goes down bottom and top are interchanged!
rect.CX := ScaleSizeX(rectRec^.Right - rectRec^.Left); rect.CX := ScaleSizeX(rectRec^.Right - rectRec^.Left);
rect.CY := ScaleSizeY(rectRec^.Bottom - rectRec^.Top); rect.CY := ScaleSizeY(rectRec^.Bottom - rectRec^.Top); // wmf: Top < Bottom!
rect.RX := ScaleSizeX(rx); rect.RX := ScaleSizeX(rx);
rect.RY := ScaleSizeY(ry); rect.RY := ScaleSizeY(ry);
rect.Pen := FCurrPen; rect.Pen := FCurrPen;
@ -1090,37 +1104,41 @@ var
s: String; s: String;
txt: TvText; txt: TvText;
offs: TPoint; offs: TPoint;
txtHeight: Integer;
begin begin
{ Record layout:
word - String length
even number of bytes - String, no trailing zero
smallInt - yStart
smallInt - xStart }
len := AParams[0]; len := AParams[0];
i := 1; i := 1;
s := ReadString(AParams, i, len); s := ReadString(AParams, i, len);
inc(i, len); if odd(len) then inc(len);
if odd(len) then inc(i); inc(i, len div 2);
y := SmallInt(AParams[i]); // signed int! y := SmallInt(AParams[i]); // signed int!
x := SmallInt(AParams[i + 1]); x := SmallInt(AParams[i + 1]);
// Correct text position which is at baseline in case of fpvectorial, but // Correct text position which is at baseline in case of fpvectorial, but
// may be different depending on bits in the CurrTextAlign value. // may be different depending on bits in the CurrTextAlign value.
case FCurrTextAlign and (TA_BOTTOM + TA_BASELINE) of
0 : // TO DO: More testing of text positioning.
{ In this case, the text should be top-aligned, but fpvectorial draws it case FCurrTextAlign and $0018 of
at the baseline --> move it down (and respect text rotation!) } 0:
offs := Rotate2DPoint(Point(0, FCurrRawFontHeight), Point(0, 0), DegToRad(FCurrFont.Orientation));
TA_BASELINE:
{ This is the way how fpvectorial draws the text --> nothing to do }
offs := Point(0, 0); offs := Point(0, 0);
TA_BASELINE:
offs := Rotate2DPoint(Point(0, FCurrRawFontHeight), Point(0, 0), DegToRad(FCurrFont.Orientation));
TA_BOTTOM: TA_BOTTOM:
{ Unfortunately we don't know the descender of the font here. Lets offs := Rotate2DPoint(Point(0, -FCurrRawFontHeight*7 div 5), Point(0, 0), DegToRad(FCurrFont.Orientation));
assume it to be 1/5th of the font size. Move text up. }
offs := Rotate2DPoint(Point(0, -FCurrRawFontHeight div 5), Point(0, 0), DegToRad(FCurrFont.Orientation));
end; end;
// Pass the text to fpvectorial // Pass the text to fpvectorial
txt := APage.AddText(x + offs.x, y + offs.y, s); txt := APage.AddText(ScaleX(x + offs.x), ScaleY(y + offs.y), s);
// Select the font // Select the font
txt.Font := FCurrFont; txt.Font := FCurrFont;
// Set horizontal text alignment. // Set horizontal text alignment.
case FCurrTextAlign and (TA_RIGHT + TA_CENTER) of case FCurrTextAlign and (TA_RIGHT or TA_CENTER) of
TA_RIGHT : txt.TextAnchor := vtaEnd; TA_RIGHT : txt.TextAnchor := vtaEnd;
TA_CENTER : txt.TextAnchor := vtaMiddle; TA_CENTER : txt.TextAnchor := vtaMiddle;
else txt.TextAnchor := vtaStart; else txt.TextAnchor := vtaStart;
@ -1203,6 +1221,7 @@ end;
function TvWMFVectorialReader.ScaleY(y: Integer): Double; function TvWMFVectorialReader.ScaleY(y: Integer): Double;
begin begin
Result := ScaleSizeY(y - FWindowOrigin.Y); // there is probably an issue with y direction Result := ScaleSizeY(y - FWindowOrigin.Y); // there is probably an issue with y direction
// Result := FPageHeight - ScaleSizeY(y);
end; end;
function TvWMFVectorialReader.ScaleSizeX(x: Integer): Double; function TvWMFVectorialReader.ScaleSizeX(x: Integer): Double;