How do I get my PostScript program to show G clef character from Bravura font? According to this SMuFL document the Unicode code point for a G (treble) clef in Bravura is U+E050 (see page 48 Clefs (U+E050–U+E07F)). The PostScript glyph name might be gClef (not sure).
Here is my best attempt so far to get the unicode characters on page. I am using GhostScript 9.25 to produce a PDF. This is the output from GhostScript:
GPL Ghostscript 9.25 (2018-09-13)
Copyright (C) 2018 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Scanning C:/Windows/Fonts for fonts... 550 files, 358 scanned, 337 new fonts.
Can't find (or can't open) font file %rom%Resource/Font/Calibri.
Can't find (or can't open) font file Calibri.
Loading Calibri font from C:/Windows/Fonts/calibri.ttf... 8525920 7081126 4118548 2767358 1 done.
Can't find (or can't open) font file %rom%Resource/Font/BravuraText.
Can't find (or can't open) font file BravuraText.
Loading BravuraText font from C:/Windows/Fonts/BravuraText.otf... 9545496 7985907 8185868 6762307 1 done.
GPL Ghostscript 9.25: Can't embed the complete font BravuraText as it is too large, embedding a subset.
Main
And this is the minimal PostScript program:
%!PS-Adobe-3.0
%%Title: unicode.ps
%%LanguageLevel: 3
%%EndComments
%%BeginProlog
userdict begin
%%EndProlog
%%BeginSetup
/mm { 25.4 div 72 mul } bind def
/A4Landscape [297 mm 210 mm] def
/PageSize //A4Landscape def
<< /PageSize PageSize >> setpagedevice
% ‘‘ReEncodeSmall’’ generates a new re-encoded font. It
% takes 3 arguments: the name of the font to be
% re-encoded, a new name, and an array of new character
% encoding and character name pairs (see the definition of
% the ‘‘scandvec’’ array below for the format of this
% array). This method has the advantage that it allows the
% user to make changes to an existing encoding vector
% without having to specify an entire new encoding
% vector. It also saves space when the character encoding
% and name pairs array is smaller than an entire encoding
% vector.
% Usage: /Times-Roman /Times-Roman-Scand scandvec new-font-encoding
/new-font-encoding { <<>> begin
/newcodesandnames exch def
/newfontname exch def
/basefontname exch def
/basefontdict basefontname findfont def % Get the font dictionary on which to base the re-encoded version.
/newfont basefontdict maxlength dict def % Create a dictionary to hold the description for the re-encoded font.
basefontdict
{ exch dup /FID ne % Copy all the entries in the base font dictionary to the new dictionary except for the FID field.
{ dup /Encoding eq
{ exch dup length array copy % Make a copy of the Encoding field.
newfont 3 1 roll put }
{ exch newfont 3 1 roll put }
ifelse
}
{ pop pop } % Ignore the FID pair.
ifelse
} forall
newfont /FontName newfontname put % Install the new name.
newcodesandnames aload pop % Modify the encoding vector. First load the new encoding and name pairs onto the operand stack.
newcodesandnames length 2 idiv
{ newfont /Encoding get 3 1 roll put}
repeat % For each pair on the stack, put the new name into the designated position in the encoding vector.
newfontname newfont definefont pop % Now make the re-encoded font description into a POSTSCRIPT font. Ignore the modified dictionary returned on the operand stack by the definefont operator.
end} def
/Calibri /TextFont [
16#41 /Scaron % A (/Scaron Š U+0160)
16#42 /quarternote % B U+2669
16#43 /musicalnote % C
16#44 /eighthnotebeamed % D
16#45 /musicalnotedbl % E
16#46 /beamedsixteenthnotes % F
16#47 /musicflatsign % G
16#47 /musicsharpsign % H U+266F
] new-font-encoding
% https://github.com/steinbergmedia/bravura
% The Unicode code point for a G (treble) clef in Bravura Text is U+E050
% http://www.smufl.org/files/smufl-0.9.pdf
% p48 Clefs (U+E050–U+E07F)
% U+E050 (and U+1D11E) gClef G clef
% http://www.jdawiseman.com/papers/trivia/character-entities.html
/Bravura /MusicFont [
16#41 /gClef % A
16#42 /quarternote % B U+2669
16#43 /musicalnote % C
16#44 /eighthnotebeamed % D
16#45 /musicalnotedbl % E
16#46 /beamedsixteenthnotes % F
16#47 /musicflatsign % G
16#47 /musicsharpsign % H U+266F
] new-font-encoding
/MusicFont findfont 48 scalefont setfont
%%EndSetup
%%BeginScript
%% Main
(Main\n) print
<<>>begin
/TextFont findfont 48 scalefont setfont
0 setgray
72 72 moveto
(#ABCDEFGHIJKL) show
0 72 translate
/MusicFont findfont 48 scalefont setfont
0 setgray
72 72 moveto
(#ABCDEFGHIJKL) show
end
showpage
%%EndScript
%%Trailer
%%EOF
The first question is how you are defining Bravura and Calibri. These fonts are not part of the standard Ghostscript installation, so they must be added in some fashion, possibly via fontconfig (on Linux), but I see you are using Windows (from the path name). How have you added the fonts ?
Now you are (again from the back channel messages) loading TrueType fonts and using them as substitutes for missing PostScript fonts. That's a non-standard feature, so Ghostscript has to do a lot of guessing in order to try and create a Type 42 font (PostScript font with TrueType outlines) from a TrueType font. There's no guarantee it'll get it right, though it is pretty good these days.
By the way, this is nothing to do with Unicode :-)
In PostScript you use a character code for each character you want to display. In your case you have used 0x40 (#) to 0x4C (L) consecutively. When rendering the glyph, the interpreter takes the character code, and looks up the Encoding at that position. Note that your Encoding arrays only contain entries from 0x41 to 0x47, so codes 0x48 to 0x4C will be undefined.
Lets think about your 'TextFont', which is Calibri. At position 0x41 in the Encoding you have a glyph name 'Scaron'. So the interpreter then consults the CharStrings dictionary of the font. The CharStrings dictionary contains key/value pairs, the key (in this case) is a name, and the value is an executable program which defines how to render the glyph.
So the interpreter looks for a key called /Scaron in the CharStrings dictionary, and then executes the program associated with it. If it can't find the key /Scaron, then it looks up the key /.notdef (all fonts are required to have a .notdef) and executes that instead.
You haven't actually said what you're getting out. I'm assuming there's a problem, because you've posted a question (which doesn't seem to contain any actual questions....) but you have't said what it is. If you are getting hollow rectangles instead of the expected glyph, then that's because the interpreter is executing the /.notdef which for TrueType fonts is often a rectangle (PostScript fonts often have a completely blank .notdef, but both font types can have anything they want)
In which case the problem is that you are using a glyph name (eg /muscialnote) which doesn't exist in the CharStrings dictionary. Unless the TrueType font had a POST table (most do not) then that's not surprising, because /musicalnote is a very non-standard name for a glyph.
If I add Calibri to fontmap.GS and then do:
%!
/Calibri findfont /CharStrings get {== ==} forall
Then I see many entries of the form:
0
/_6756
0
/_6689
these are mapping the names (eg /_6576) to the TrueType GID. When using a TrueType font Ghostscript needs the GID so that it can find the glyph program in the font from the GLYF table. When defining a TrueType font for use as a type 42, this is somethign Ghostscript has to try and create for itself (a real Type 42 font is defined with this dictionary as part of the font). How it achieves this is heuristic, ie it guesses a lot.
In this case the GID is 0, which is the TrueType reserved GID for the .notdef glyph, so these names will all map to the .notdef.
I also see a number of entries like:
4
/A
These (obviously) are the glyphs that you can use, in this case the name /A maps to GID 4. Checking the output, there is no name 'quarternote, 'musicalnote' etc. There is an Scaron, so I expect that your '#' character will render as a capital S with a caron accent. The remaining glyphs will render as empty squares, or nothing at all. Testing here shows (interestingly) a rectangle with a question mark in it.
Now it may be that the Calibri font contains the glyphs you want, if it doe, then I'm afraid the only way to access them (from PostScript) is to identify the name that Ghostscript associated with the glyph. The same is true of the Bravura font.
A little PostScript programming (seems like you're more than competent to write this) would allow you to retrieve the CharStrings dictionary from the font, iterate through it, and build an array of all the names which have a non-zero value. You could then print a page (probably many pages) where you print a named glyph from the font, and under it print the name associated with that glyph. There's your map, now you can build an Encoding which maps the glyph name to the character code you want to use in your PostScript program to draw that glyph.
FWIW when I try to use Bravura (which is an OpenType font, not a TrueType font) I get a syntax error whie loading the font. Same for BravuraText.
This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 7 years ago.
I'm trying to import float data from a text file. In order to do so, I load the individual lines from the file to a string and than parse it with sscanf (textscan shows similar behavior). For some reason, sscanf adds some deviations in the last few decimal places as can be seen when outputting variables as long
'8.2' --> 8.199999999999999.
In addition, after converting 8.2 GHz to 8.2e9 Hz (Imported_array=Imported_array*10^9), the call
Bin=find(Imported_array==Lookup_Value);
returns an empty matrix.
A minimal example looks as follows:
clc;
clear;
format long;
% String to Parse from Textfile(f in GHz)
string='8.200000000 1.406320e-01 -8.175100e-02 -6.981310e-04 1.972470e-03 -1.049100e-03 1.868090e-03 1.620270e-01 -8.879710e-02';
% Same Problem with a single number
% string='8.2';
% Lookup Value (in Hz)
fstart=8.2e9;
% Parse String
f=sscanf(string, '%f')
% Convert GHz to Hz
f=f*10^9
% Search Bin
Bin=find(f==fstart)
When using string='8.2', the same problem occurs.
For string=8 and fstart=8e9 everything works fine.
textscan shows similar behavior.
Where do I go wrong in the above example?
The problem occurs in R2015a,b and R2014a as well, both on MAC OS and Win machines.
Any hints are highly appreciated!
Regards
You should never compare two floats for equality without incorporating a tolerance. See: What Every Computer Scientist Should Know About Floating-Point Arithmetic and Accuracy of Floating Point Data.
One potential method:
% String to Parse from Textfile(f in GHz)
string='8.200000000 1.406320e-01 -8.175100e-02 -6.981310e-04 1.972470e-03 -1.049100e-03 1.868090e-03 1.620270e-01 -8.879710e-02';
% Lookup Value (in Hz)
fstart=8.2e9;
% Parse String
f=sscanf(string, '%f')
% Convert GHz to Hz
f=f*10^9
% Search Bin within tolerance
diffs = abs(f - fstart);
tol = 10^-6;
Bin=find(diffs < tol)
Which returns:
Bin =
1
It's worth noting here that when you multiply f by 10^9 you're also multiplying the error, which is the reason for such a (relatively) large tolerance. In cases where you're not manipulating the number before testing for equality you generally can check for equality by seeing if the absolute difference is less than eps, which is the machine's floating-point relative accuracy.
I have the following code which works on matlab R2015 until the concatenation of I2D but stops at imadjust because I'm out of memory. I'm treating 2249 images of 1984*1984 pixels on a 16 Go RAM and 64 bit.
When I run the same code a more powerful computer (24 Go RAM) but with the R2009 version of Matlab, the code stops at the cat step saying the arguments dimensions are not consistent.
I don't get why it is working on R2015 and not on R2009. Notice that I will have to run the code on R2009 (but that's another story). Therefore, the problem of out of memory will maybe not be important but I don't know yat because it is not working on the R2009 version (24 Go RAM).
%reading data and inverting the GV
for k=1:n
I = imread(fullfile(rep,list1(k).name),ext(3:end));
for i=1:Row
for j=1:Col
I(i,j)=255-I(i,j);
end
end
nomFichier=sprintf('Xa1_3D_%04d.bmp',k);
imwrite(I,fullfile(rep2,nomFichier),ext(3:end));
end
%Now, we want to read all the images at once to have all the available
%informations for the histogram adjustement
chemin = fullfile(rep2,ext);
list2 = dir(chemin);
o=numel(list2);
I2{o}=ones;
for k=1:o
I2{k} = imread(fullfile(rep2,list2(k).name),ext(3:end));
end
%Combination of images in 2D matrix and hist adjustement
I2D=cat(2,I2{:});
I2D=imadjust(I2D);
I use octave 3.8.2 (with gnuplot) under Windows. I want to write "special character" in the axis labels of plots. The umlaut 'ä' and special character µ are displayed in the figure but not saved to the image file using print. Partly, I can use the TeX command: '\mu' instead of 'µ' but for umlauts '\"a' instead of 'ä' does not work.
plot(1:10);
%set (findall (gcf (), "-property", "interpreter"), "interpreter", "TeX") % does not work
xlabel('Länge in µm');
ylabel('Breite in \mum');
print('umlaute.jpg', '-djpeg');
graphics_toolkit("gnuplot") and pngcairo or pdfcairo produce a better output.
graphics_toolkit("gnuplot")
plot(1:10)
xlabel('Länge in µm')
ylabel('Breite in \mum')
print('umlaute.png', '-dpngcairo') # or
# print('umlaute.pdf', '-dpdfcairo')
With octave 3.8.2 under linux, the ouput is
Using Octave 4.4.0 on Windows the bug seems to be fixed as least for graphics_toolkits gnuplot and qt with the print option '-dpngcairo'. So this script gives me a fine output in the file umlaute4-cairo.png .
% graphics_toolkit("gnuplot")
graphics_toolkit("qt")
% Do a simple plot with a German umlaut and a Greek micron signs
plot(1:10);
ylabel('Breite in \mum')
xlabel('Länge in \mum')
print('umlaute4.jpg', '-djpg') # not OK, bad umlauts
print('umlaute4.png', '-dpng') # not OK, bad umlauts
print('umlaute4-cairo.png', '-dpngcairo') # OK with gnuplot and qt
Using Octave 5.1 on Windows with the qt graphics toolkit and latin1-coding it does now finally work!
graphics_toolkit("qt");
x=1:10;
plot(x, x);
title('Ä Ö Ü');
xlabel('H_2 in µm');
ylabel('Percent in %');
[![enter image description here][1]][1]print("test_umlaute.png");
Other combiations like UTF8 and and other graphics toolkit do not work.
There is a problem in Octave 5.1 that the selected encoding for .m files is not restored on startup.
You can either change the encoding in the settings and call "clear functions" to trigger the .m files being parsed again. Or you could call the internal function "mfile_encoding". For UTF-8 encoding that would be:
__mfile_encoding__ ("utf-8");
clear functions
https://savannah.gnu.org/bugs/?56782
I am working with some matlab code that processes data (in a Kalman Filter) and creates a series of contour plots. It has been running on a RHEL 4 server in matlab 2006a for a few years, but my boss recently requested that all servers be updated to RHEL 6...and at least matlab 2007a. I have worked out all the depreciations between these versions, but I am still having one major problem.
The code that creates and prints different contour plots is working for whichever of the three plots is created first. It looks like this:
Unfortunately the next two plots look like this:
The three figures are plotted independently in separate functions and I use clf("reset"); before and after creating each figure. Each function works in and of itself, but when all three are plotted the second and third figures are all messed up. Has anyone else had this problem? Here is the code that creates one of the figures.
function Crd = TEC_plot(ITEC,RT,Param,Input,t,OutPath,RxExtAll,Time)
% Generate TEC plot
Function_for_Spline_Smoothing = [.05 .1 .05; .1 .4 .1; .05 .1 .05];
ITEC = conv2(ITEC,Function_for_Spline_Smoothing,'same'); % add more of these lines to make contours smoother
ITEC = conv2(ITEC,Function_for_Spline_Smoothing,'same'); % add more of these lines to make contours smoother
% ITEC = conv2(ITEC,Function_for_Spline_Smoothing,'same'); % add more of these lines to make contours smoother
% ITEC = conv2(ITEC,Function_for_Spline_Smoothing,'same'); % add more of these lines to make contours smoother
earth('CAMERA',RT.Camera,'FIG',1);
figure;
warning off; hold on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Changed 13 February 2007 to make plots prettier
thinning_scale=2; % (1 to 10) increase this value to thin the density of the contour number labels
[cscale,hgt]=m_contour(Param.Grid.LonAxis,Param.Grid.LatAxis,ITEC, ...
round(RT.Levels(1:thinning_scale:end)/5)*5);
hold on
m_contourf(Param.Grid.LonAxis,Param.Grid.LatAxis,ITEC,RT.Levels);
shading flat
m_coast('line','color','y','LineWidth',1);
clabel(cscale,hgt,'labelspacing',72,'rotation',0,'fontsize',10 ...
,'FontAngle','italic','color','w');
axis([-.65 .6 .25 1.32]) % hardwiring axis length since the coastline runs off of the plot
% Changed 13 February 2007
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %-------------------- to include different station markers for different sources -------------------
if ~isempty(Input.Data) % Plot receivers used in this inversion
Crd=uniquerows(double(cat(1,RxExtAll)));
RxType=round(Crd(:,4));
Crd=cartsph(Crd)*180/pi;
i1 = find( (Crd(:,3) > RT.Camera(3)).*(Crd(:,3) < RT.Camera(4)).*...
(Crd(:,2) > RT.Camera(1)).*(Crd(:,2) < RT.Camera(2)).*...
(RxType==1) );
i2 = find( (Crd(:,3) > RT.Camera(3)).*(Crd(:,3) < RT.Camera(4)).*...
(Crd(:,2) > RT.Camera(1)).*(Crd(:,2) < RT.Camera(2)).*...
(RxType==2) );
i3 = find( (Crd(:,3) > RT.Camera(3)).*(Crd(:,3) < RT.Camera(4)).*...
(Crd(:,2) > RT.Camera(1)).*(Crd(:,2) < RT.Camera(2)).*...
(RxType==3) );
m_plot(Crd(i1,3),Crd(i1,2),'ro','markersize',5,'LineWidth',2);
% m_plot(Crd(i1,3),Crd(i1,2),'r.','markersize',6,'LineWidth',2);
m_plot(Crd(i2,3),Crd(i2,2),'r^','markersize',5,'LineWidth',2);
% m_plot(Crd(i2,3),Crd(i2,2),'r.','markersize',6,'LineWidth',2);
m_plot(Crd(i3,3),Crd(i3,2),'rp','markersize',5,'LineWidth',2);
plot(-.6,.45,'ro','markersize',5,'LineWidth',2);text(-.55,.45,'CORS','Color','k')
plot(-.6,.39,'r^','markersize',5,'LineWidth',2);text(-.55,.39,'GPS/Met','Color','k')
plot(-.6,.33,'rp','markersize',5,'LineWidth',2);text(-.55,.33,'RTIGS','Color','k')
end
% % -------------------------------------------------------------------------------
hold off; warning on;axis off;
% caxis([RT.Levels(1),(RT.Levels(length(RT.Levels)))/2]); colorbar('vert'); %Color bar from 0 to 50 --- for Low Solar Activity
caxis([RT.Levels(1),(RT.Levels(length(RT.Levels)))]); colorbar('vert'); %Color bar from 0 to 100 --- for High Solar Activity
title(sprintf('Total Electron Content Units x 10^1^6 m^-^2'),'Fontsize',11)
if size(Crd,1)==0,
title(sprintf('Total Electron Content Units x 10^1^6 m^-^2 Caution: No Data Available, IRI95 Only'),'Fontsize',10)
end
whitebg('w')
text(-0.6,0.22,sprintf('%s from %s to %s UT NOAA/SWPC Boulder, CO USA (op.ver. 1.0)',datestr(Time(t)+1E-8,1),datestr(Time(t)+1E-8,15),datestr(Time(t)+1E-7+15/1440,15)),'Fontsize',11)
whitebg('w')
% This option print to a file
% set(gcf, 'Position', [0,0,1950,1467]);
% print('-f1','-dpng','-painters',filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC'],Time(t)));
% system(['convert ', filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.png'],Time(t)),' -scale 650x489 ',' -colors 256 ', filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.png'],Time(t))]);
% Printing a postscript file because requirements for the automatic reboot
print('-f1','-dpsc','-r1000','-painters', filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC'],Time(t)));
% Convert the postscript file to jpg using ghostscripts
system(['gs -q -dBATCH -dNOPAUSE -r300 -sDEVICE=jpeg -sOutputFile=',filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.jpg'],Time(t)),' ', filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.ps'],Time(t))]);
% Converting from jpg to png and reducing the size of the figure.
system(['convert ',filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.jpg'],Time(t)),' -crop 2050x1675+325+775 ',' -scale 650x489 ',' -colors 256 ', filename([OutPath,'{YYYY}{MM}{DD}{HRMN}_TEC.png'],Time(t))]);
% Removing the jpg and ps files (ask Cliff how can we put both files in just one command)
%system(['rm ',filename([OutPath,'*.jpg'],Time(t))]);
%system(['rm ',filename([OutPath,'*.ps'],Time(t))]);
end
Try to not use clf which will clear your whole figure but use the figure in between to open three independant figures. See it it'll work :)
Edit: That's just guessing without actually seeing your code
One guess might be with the code that generates your final PNG file. Your second figure appears to be incorrectly cropped when converting from JPG to PNG.
First the print command is fixed to use whatever is in figure 1. So, to ensure that you are plotting using figure 1 use the command figure(1) to specify this. Alternatively, change the print command to to read print(gcf ... to print the current figure.
Also, note you could generate the PNG file directly with print as in
print(gcf,'-dpng','-r1000',filename(...))
and skip the conversion from PS to JPG to PNG step.
The hard-coding the figure window in the print might explain why things work independently but not together if the you have multiple figure windows available. Just a guess.