Added user defined encoding that is created at runtime. Display used fonts in status window.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4758 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
48f9fa477a
commit
8ce7304896
@ -31,7 +31,7 @@ THE SOFTWARE.
|
||||
#include <malloc.h>
|
||||
#include <StorageKit.h>
|
||||
#include "Fonts.h"
|
||||
|
||||
#include "Report.h"
|
||||
|
||||
// FontFile
|
||||
|
||||
@ -277,7 +277,8 @@ Fonts::LookupFontFiles(BPath path)
|
||||
|
||||
if (entry.GetSize(&size) != B_OK)
|
||||
size = 1024*1024*1024;
|
||||
|
||||
|
||||
REPORT(kDebug, -1, "Installed font %s -> %s", fn, name.Path());
|
||||
fFontFiles.AddItem(new FontFile(fn, name.Path(), size, ft, size < 100*1024));
|
||||
} // while dir.GetNextEntry()...
|
||||
|
||||
@ -532,3 +533,28 @@ static status_t psf_get_fontname(const char * path, char * fontname, size_t fn_s
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implementation of UserDefinedEncodings
|
||||
|
||||
UserDefinedEncodings::UserDefinedEncodings()
|
||||
: fCurrentEncoding(0)
|
||||
, fCurrentIndex(0)
|
||||
{
|
||||
memset(fUsedMask, 0, sizeof(fUsedMask));
|
||||
memset(fEncoding, 0, sizeof(fEncoding));
|
||||
memset(fIndex, 0, sizeof(fIndex));
|
||||
}
|
||||
|
||||
bool UserDefinedEncodings::Get(uint16 unicode, uint8 &encoding, uint8 &index) {
|
||||
bool missing = !IsUsed(unicode);
|
||||
if (missing) {
|
||||
SetUsed(unicode);
|
||||
fEncoding[unicode] = fCurrentEncoding; fIndex[unicode] = fCurrentIndex;
|
||||
if (fCurrentIndex == 255) {
|
||||
fCurrentIndex = 0; fCurrentEncoding ++;
|
||||
} else {
|
||||
fCurrentIndex ++;
|
||||
}
|
||||
}
|
||||
encoding = fEncoding[unicode]; index = fIndex[unicode];
|
||||
return missing;
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ enum font_encoding
|
||||
korean_encoding,
|
||||
first_cjk_encoding = japanese_encoding,
|
||||
no_of_cjk_encodings = korean_encoding - first_cjk_encoding + 1,
|
||||
invalid_encoding,
|
||||
invalid_encoding = korean_encoding + 1,
|
||||
user_defined_encoding_start
|
||||
};
|
||||
|
||||
|
||||
@ -133,4 +134,39 @@ public:
|
||||
bool GetCJKOrder(int i, font_encoding& enc, bool& active) const;
|
||||
};
|
||||
|
||||
class UsedFont {
|
||||
private:
|
||||
BString fFamily;
|
||||
BString fStyle;
|
||||
float fSize;
|
||||
|
||||
public:
|
||||
UsedFont(const char* family, const char* style, float size) : fFamily(family), fStyle(style), fSize(size) {}
|
||||
|
||||
const char* GetFamily() const { return fFamily.String(); }
|
||||
const char* GetStyle() const { return fStyle.String(); }
|
||||
float GetSize() const { return fSize; }
|
||||
|
||||
bool Equals(const char* family, const char* style, float size) const { return strcmp(GetFamily(), family) == 0 && strcmp(GetStyle(), style) == 0 && fSize == size; }
|
||||
};
|
||||
|
||||
|
||||
class UserDefinedEncodings {
|
||||
public:
|
||||
UserDefinedEncodings();
|
||||
// returns true if new encoding and index pair
|
||||
bool Get(uint16 unicode, uint8 &encoding, uint8 &index);
|
||||
|
||||
private:
|
||||
bool IsUsed(uint16 unicode) const { return (fUsedMask[unicode / 8] & (1 << (unicode % 8))) != 0; }
|
||||
void SetUsed(uint16 unicode) { fUsedMask[unicode / 8] |= 1 << (unicode % 8); }
|
||||
|
||||
uint8 fUsedMask[65536/8]; // exists an encoding and index for this code point?
|
||||
uint8 fEncoding[65536]; // the encoding for each code point
|
||||
uint8 fIndex[65536]; // the index for each code point
|
||||
|
||||
uint8 fCurrentEncoding;
|
||||
uint8 fCurrentIndex;
|
||||
};
|
||||
|
||||
#endif // FONTS_H
|
||||
|
@ -161,17 +161,50 @@ find_in_cid_tables(uint16 unicode, font_encoding &encoding, uint16 &index, font_
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
void
|
||||
PDFWriter::MakeUserDefinedEncoding(uint16 unicode, uint8 &enc, uint8 &index) {
|
||||
if (fUserDefinedEncodings.Get(unicode, enc, index)) {
|
||||
BString s("user");
|
||||
s << (int)enc;
|
||||
PDF_encoding_set_char(fPdf, s.String(), (int)index, NULL, (int)unicode);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void
|
||||
PDFWriter::RecordFont(const char* family, const char* style, float size) {
|
||||
const int32 n = fUsedFonts.CountItems();
|
||||
for (int32 i = 0; i < n; i ++) {
|
||||
if (fUsedFonts.ItemAt(i)->Equals(family, style, size)) return;
|
||||
}
|
||||
|
||||
UsedFont* font;
|
||||
font = new UsedFont(family, style, size);
|
||||
fUsedFonts.AddItem(font);
|
||||
|
||||
REPORT(kInfo, -1, "Used font: \"%s\" \"%s\" %f", family, style, size);
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void
|
||||
PDFWriter::GetFontName(BFont *font, char *fontname, bool &embed, font_encoding encoding)
|
||||
PDFWriter::GetFontName(BFont *font, char *fontname)
|
||||
{
|
||||
font_family family;
|
||||
font_style style;
|
||||
|
||||
font->GetFamilyAndStyle(&family, &style);
|
||||
|
||||
strcat(strcat(strcpy(fontname, family), "-"), style);
|
||||
|
||||
RecordFont(family, style, font->Size());
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void
|
||||
PDFWriter::GetFontName(BFont *font, char *fontname, bool &embed, font_encoding encoding)
|
||||
{
|
||||
GetFontName(font, fontname);
|
||||
|
||||
switch (encoding) {
|
||||
case japanese_encoding:
|
||||
strcpy(fontname, "HeiseiMin-W3"); return;
|
||||
@ -181,7 +214,6 @@ PDFWriter::GetFontName(BFont *font, char *fontname, bool &embed, font_encoding e
|
||||
strcpy(fontname, "STSong-Light"); return;
|
||||
case korean_encoding:
|
||||
strcpy(fontname, "HYGoThic-Medium"); return;
|
||||
return;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
@ -231,12 +263,24 @@ PDFWriter::FindFont(char* fontName, bool embed, font_encoding encoding)
|
||||
|
||||
if (embed) embed = EmbedFont(fontName);
|
||||
|
||||
REPORT(kDebug, fPage, "Create new font");
|
||||
int font = PDF_findfont(fPdf, fontName, encoding_names[encoding], embed);
|
||||
BString s;
|
||||
char user_defined[80];
|
||||
const char* encoding_name;
|
||||
if (encoding < user_defined_encoding_start) {
|
||||
encoding_name = encoding_names[encoding];
|
||||
} else {
|
||||
s = "user";
|
||||
s << (int)(encoding - user_defined_encoding_start);
|
||||
encoding_name = s.String();
|
||||
}
|
||||
REPORT(kDebug, fPage, "Create new font, %sembed, encoding %s", embed ? "" : "do not ", encoding_name);
|
||||
int font = PDF_findfont(fPdf, fontName, encoding_name, embed);
|
||||
if (font != -1) {
|
||||
REPORT(kDebug, fPage, "font created");
|
||||
cache = new Font(fontName, font, encoding);
|
||||
fFontCache.AddItem(cache);
|
||||
} else {
|
||||
REPORT(kError, fPage, "Could not create font '%s'", fontName);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
@ -334,43 +378,66 @@ PDFWriter::DrawChar(uint16 unicode, const char* utf8, int16 size)
|
||||
// try to convert from utf8 to MacRoman encoding schema...
|
||||
int32 srcLen = size;
|
||||
int32 destLen = 1;
|
||||
char dest[2] = "\0";
|
||||
char dest[3] = "\0\0";
|
||||
int32 state = 0;
|
||||
bool embed = true;
|
||||
font_encoding encoding = macroman_encoding;
|
||||
char fontName[B_FONT_FAMILY_LENGTH+B_FONT_STYLE_LENGTH+1];
|
||||
|
||||
if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, utf8, &srcLen, dest, &destLen, &state, 0) != B_OK || dest[0] == 0 ) {
|
||||
// could not convert to MacRoman
|
||||
uint8 enc;
|
||||
uint16 index;
|
||||
font_encoding fenc;
|
||||
|
||||
GetFontName(&fState->beFont, fontName);
|
||||
embed = EmbedFont(fontName);
|
||||
|
||||
// is code point in the Adobe Glyph List?
|
||||
REPORT(kDebug, -1, "find_encoding unicode %d\n", (int)unicode);
|
||||
if (find_encoding(unicode, enc, index)) {
|
||||
// LOG((fLog, "encoding for %x -> %d %d\n", unicode, (int)enc, (int)index));
|
||||
// use one of the user defined encodings
|
||||
// is code point in the Adobe Glyph List?
|
||||
// Note if rendering the glyphs only would be desired, we could always use
|
||||
// the second method below (MakeUserDefinedEncoding), but extracting text
|
||||
// from the generated PDF would be almost impossible (OCR!)
|
||||
REPORT(kDebug, -1, "encoding for %x -> %d %d", unicode, (int)enc, (int)index);
|
||||
// use one of the user pre-defined encodings
|
||||
if (fState->beFont.FileFormat() == B_TRUETYPE_WINDOWS) {
|
||||
encoding = font_encoding(enc + tt_encoding0);
|
||||
} else {
|
||||
encoding = font_encoding(enc + t1_encoding0);
|
||||
}
|
||||
*dest = index;
|
||||
} else if (embed) {
|
||||
// if the font is embedded, create a user defined encoding at runtime
|
||||
uint8 index;
|
||||
MakeUserDefinedEncoding(unicode, enc, index);
|
||||
*dest = index;
|
||||
encoding = font_encoding(user_defined_encoding_start + enc);
|
||||
} else if (find_in_cid_tables(unicode, fenc, index, fFontSearchOrder)) {
|
||||
// LOG((fLog, "cid table %d index = %d\n", (int)enc, (int)index));
|
||||
// font is not embedded use one of the CJK fonts for substitution
|
||||
REPORT(kDebug, -1, "cid table %d index = %d", (int)fenc, (int)index);
|
||||
dest[0] = unicode / 256;
|
||||
dest[1] = unicode % 256;
|
||||
destLen = 2;
|
||||
encoding = fenc;
|
||||
embed = false;
|
||||
} else {
|
||||
// LOG((fLog, "encoding for %x not found!\n", unicode));
|
||||
static bool found = false;
|
||||
REPORT(kDebug, -1, "encoding for %x not found!", (int)unicode);
|
||||
if (!found) {
|
||||
found = true;
|
||||
REPORT(kError, fPage, "Could not find an encoding for character with unicode %d! Message is not repeated for other unicode values.", (int)unicode);
|
||||
}
|
||||
*dest = 0; // paint a box (is 0 a box in MacRoman) or
|
||||
return; // simply skip character
|
||||
}
|
||||
}
|
||||
// else LOG((fLog, "macroman srcLen=%d destLen=%d dest= %d %d!\n", srcLen, destLen, (int)dest[0], (int)dest[1]));
|
||||
|
||||
char fontName[B_FONT_FAMILY_LENGTH+B_FONT_STYLE_LENGTH+1];
|
||||
} else {
|
||||
REPORT(kDebug, -1, "macroman srcLen=%d destLen=%d dest= %d %d!", srcLen, destLen, (int)dest[0], (int)dest[1]);
|
||||
}
|
||||
|
||||
// Note we have to build the user defined encoding before it is used in PDF_find_font!
|
||||
if (!MakesPDF()) return;
|
||||
|
||||
int font;
|
||||
|
||||
GetFontName(&fState->beFont, fontName, embed, encoding);
|
||||
@ -500,12 +567,10 @@ PDFWriter::DrawString(char *string, float escapement_nospace, float escapement_s
|
||||
|
||||
float w = font.StringWidth(c, s);
|
||||
|
||||
if (MakesPDF()) {
|
||||
if (IsClipping()) {
|
||||
ClipChar(&font, (char*)u, c, s, w);
|
||||
} else {
|
||||
DrawChar(u[0]*256+u[1], c, s);
|
||||
}
|
||||
if (MakesPDF() && IsClipping()) {
|
||||
ClipChar(&font, (char*)u, c, s, w);
|
||||
} else {
|
||||
DrawChar(u[0]*256+u[1], c, s);
|
||||
}
|
||||
|
||||
// position of next character
|
||||
|
@ -149,6 +149,7 @@ class PDFWriter : public PrinterDriver, public PictureIterator
|
||||
void ClipChar(BFont* font, const char* unicode, const char *utf8, int16 size, float width);
|
||||
bool EmbedFont(const char* n);
|
||||
status_t DeclareFonts();
|
||||
void RecordFont(const char* family, const char* style, float size);
|
||||
|
||||
// BPicture playback handlers
|
||||
void Op(int number);
|
||||
@ -325,6 +326,8 @@ class PDFWriter : public PrinterDriver, public PictureIterator
|
||||
XRefDests *fXRefDests;
|
||||
font_encoding fFontSearchOrder[no_of_cjk_encodings];
|
||||
TextLine fTextLine;
|
||||
TList<UsedFont> fUsedFonts;
|
||||
UserDefinedEncodings fUserDefinedEncodings;
|
||||
|
||||
enum
|
||||
{
|
||||
@ -361,8 +364,10 @@ class PDFWriter : public PrinterDriver, public PictureIterator
|
||||
|
||||
bool StoreTranslatorBitmap(BBitmap *bitmap, const char *filename, uint32 type);
|
||||
|
||||
void GetFontName(BFont *font, char *fontname);
|
||||
void GetFontName(BFont *font, char *fontname, bool &embed, font_encoding encoding);
|
||||
int FindFont(char *fontname, bool embed, font_encoding encoding);
|
||||
void MakeUserDefinedEncoding(uint16 unicode, uint8 &enc, uint8 &index);
|
||||
|
||||
// alpha transparency
|
||||
Transparency* FindTransparency(uint8 alpha);
|
||||
|
Loading…
x
Reference in New Issue
Block a user