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:
@@ -31,7 +31,7 @@ THE SOFTWARE.
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <StorageKit.h>
|
#include <StorageKit.h>
|
||||||
#include "Fonts.h"
|
#include "Fonts.h"
|
||||||
|
#include "Report.h"
|
||||||
|
|
||||||
// FontFile
|
// FontFile
|
||||||
|
|
||||||
@@ -277,7 +277,8 @@ Fonts::LookupFontFiles(BPath path)
|
|||||||
|
|
||||||
if (entry.GetSize(&size) != B_OK)
|
if (entry.GetSize(&size) != B_OK)
|
||||||
size = 1024*1024*1024;
|
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));
|
fFontFiles.AddItem(new FontFile(fn, name.Path(), size, ft, size < 100*1024));
|
||||||
} // while dir.GetNextEntry()...
|
} // while dir.GetNextEntry()...
|
||||||
|
|
||||||
@@ -532,3 +533,28 @@ static status_t psf_get_fontname(const char * path, char * fontname, size_t fn_s
|
|||||||
return status;
|
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,
|
korean_encoding,
|
||||||
first_cjk_encoding = japanese_encoding,
|
first_cjk_encoding = japanese_encoding,
|
||||||
no_of_cjk_encodings = korean_encoding - first_cjk_encoding + 1,
|
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;
|
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
|
#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
|
void
|
||||||
PDFWriter::GetFontName(BFont *font, char *fontname, bool &embed, font_encoding encoding)
|
PDFWriter::GetFontName(BFont *font, char *fontname)
|
||||||
{
|
{
|
||||||
font_family family;
|
font_family family;
|
||||||
font_style style;
|
font_style style;
|
||||||
|
|
||||||
font->GetFamilyAndStyle(&family, &style);
|
font->GetFamilyAndStyle(&family, &style);
|
||||||
|
|
||||||
strcat(strcat(strcpy(fontname, 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) {
|
switch (encoding) {
|
||||||
case japanese_encoding:
|
case japanese_encoding:
|
||||||
strcpy(fontname, "HeiseiMin-W3"); return;
|
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;
|
strcpy(fontname, "STSong-Light"); return;
|
||||||
case korean_encoding:
|
case korean_encoding:
|
||||||
strcpy(fontname, "HYGoThic-Medium"); return;
|
strcpy(fontname, "HYGoThic-Medium"); return;
|
||||||
return;
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,12 +263,24 @@ PDFWriter::FindFont(char* fontName, bool embed, font_encoding encoding)
|
|||||||
|
|
||||||
if (embed) embed = EmbedFont(fontName);
|
if (embed) embed = EmbedFont(fontName);
|
||||||
|
|
||||||
REPORT(kDebug, fPage, "Create new font");
|
BString s;
|
||||||
int font = PDF_findfont(fPdf, fontName, encoding_names[encoding], embed);
|
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) {
|
if (font != -1) {
|
||||||
REPORT(kDebug, fPage, "font created");
|
REPORT(kDebug, fPage, "font created");
|
||||||
cache = new Font(fontName, font, encoding);
|
cache = new Font(fontName, font, encoding);
|
||||||
fFontCache.AddItem(cache);
|
fFontCache.AddItem(cache);
|
||||||
|
} else {
|
||||||
|
REPORT(kError, fPage, "Could not create font '%s'", fontName);
|
||||||
}
|
}
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@@ -334,43 +378,66 @@ PDFWriter::DrawChar(uint16 unicode, const char* utf8, int16 size)
|
|||||||
// try to convert from utf8 to MacRoman encoding schema...
|
// try to convert from utf8 to MacRoman encoding schema...
|
||||||
int32 srcLen = size;
|
int32 srcLen = size;
|
||||||
int32 destLen = 1;
|
int32 destLen = 1;
|
||||||
char dest[2] = "\0";
|
char dest[3] = "\0\0";
|
||||||
int32 state = 0;
|
int32 state = 0;
|
||||||
bool embed = true;
|
bool embed = true;
|
||||||
font_encoding encoding = macroman_encoding;
|
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 ) {
|
if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, utf8, &srcLen, dest, &destLen, &state, 0) != B_OK || dest[0] == 0 ) {
|
||||||
// could not convert to MacRoman
|
// could not convert to MacRoman
|
||||||
uint8 enc;
|
uint8 enc;
|
||||||
uint16 index;
|
uint16 index;
|
||||||
font_encoding fenc;
|
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)) {
|
if (find_encoding(unicode, enc, index)) {
|
||||||
// LOG((fLog, "encoding for %x -> %d %d\n", unicode, (int)enc, (int)index));
|
// is code point in the Adobe Glyph List?
|
||||||
// use one of the user defined encodings
|
// 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) {
|
if (fState->beFont.FileFormat() == B_TRUETYPE_WINDOWS) {
|
||||||
encoding = font_encoding(enc + tt_encoding0);
|
encoding = font_encoding(enc + tt_encoding0);
|
||||||
} else {
|
} else {
|
||||||
encoding = font_encoding(enc + t1_encoding0);
|
encoding = font_encoding(enc + t1_encoding0);
|
||||||
}
|
}
|
||||||
*dest = index;
|
*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)) {
|
} 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[0] = unicode / 256;
|
||||||
dest[1] = unicode % 256;
|
dest[1] = unicode % 256;
|
||||||
destLen = 2;
|
destLen = 2;
|
||||||
encoding = fenc;
|
encoding = fenc;
|
||||||
embed = false;
|
embed = false;
|
||||||
} else {
|
} 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
|
*dest = 0; // paint a box (is 0 a box in MacRoman) or
|
||||||
return; // simply skip character
|
return; // simply skip character
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// else LOG((fLog, "macroman srcLen=%d destLen=%d dest= %d %d!\n", srcLen, destLen, (int)dest[0], (int)dest[1]));
|
REPORT(kDebug, -1, "macroman srcLen=%d destLen=%d dest= %d %d!", srcLen, destLen, (int)dest[0], (int)dest[1]);
|
||||||
|
}
|
||||||
char fontName[B_FONT_FAMILY_LENGTH+B_FONT_STYLE_LENGTH+1];
|
|
||||||
|
// Note we have to build the user defined encoding before it is used in PDF_find_font!
|
||||||
|
if (!MakesPDF()) return;
|
||||||
|
|
||||||
int font;
|
int font;
|
||||||
|
|
||||||
GetFontName(&fState->beFont, fontName, embed, encoding);
|
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);
|
float w = font.StringWidth(c, s);
|
||||||
|
|
||||||
if (MakesPDF()) {
|
if (MakesPDF() && IsClipping()) {
|
||||||
if (IsClipping()) {
|
ClipChar(&font, (char*)u, c, s, w);
|
||||||
ClipChar(&font, (char*)u, c, s, w);
|
} else {
|
||||||
} else {
|
DrawChar(u[0]*256+u[1], c, s);
|
||||||
DrawChar(u[0]*256+u[1], c, s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// position of next character
|
// 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);
|
void ClipChar(BFont* font, const char* unicode, const char *utf8, int16 size, float width);
|
||||||
bool EmbedFont(const char* n);
|
bool EmbedFont(const char* n);
|
||||||
status_t DeclareFonts();
|
status_t DeclareFonts();
|
||||||
|
void RecordFont(const char* family, const char* style, float size);
|
||||||
|
|
||||||
// BPicture playback handlers
|
// BPicture playback handlers
|
||||||
void Op(int number);
|
void Op(int number);
|
||||||
@@ -325,6 +326,8 @@ class PDFWriter : public PrinterDriver, public PictureIterator
|
|||||||
XRefDests *fXRefDests;
|
XRefDests *fXRefDests;
|
||||||
font_encoding fFontSearchOrder[no_of_cjk_encodings];
|
font_encoding fFontSearchOrder[no_of_cjk_encodings];
|
||||||
TextLine fTextLine;
|
TextLine fTextLine;
|
||||||
|
TList<UsedFont> fUsedFonts;
|
||||||
|
UserDefinedEncodings fUserDefinedEncodings;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -361,8 +364,10 @@ class PDFWriter : public PrinterDriver, public PictureIterator
|
|||||||
|
|
||||||
bool StoreTranslatorBitmap(BBitmap *bitmap, const char *filename, uint32 type);
|
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);
|
void GetFontName(BFont *font, char *fontname, bool &embed, font_encoding encoding);
|
||||||
int FindFont(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
|
// alpha transparency
|
||||||
Transparency* FindTransparency(uint8 alpha);
|
Transparency* FindTransparency(uint8 alpha);
|
||||||
|
|||||||
Reference in New Issue
Block a user