зеркало из https://github.com/mozilla/pjs.git
Simple stuff for QT fonts (no crash)
This commit is contained in:
Родитель
5e0a95ec9d
Коммит
8262ab2fd7
|
@ -42,9 +42,11 @@
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
#include "gfxTypes.h"
|
#include "gfxTypes.h"
|
||||||
#include "gfxFont.h"
|
#include "gfxFont.h"
|
||||||
|
#include "gfxContext.h"
|
||||||
|
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
|
//#include <QFont>
|
||||||
|
|
||||||
|
|
||||||
class gfxQtFont : public gfxFont {
|
class gfxQtFont : public gfxFont {
|
||||||
|
@ -53,7 +55,31 @@ public:
|
||||||
const gfxFontStyle *aFontStyle);
|
const gfxFontStyle *aFontStyle);
|
||||||
virtual ~gfxQtFont ();
|
virtual ~gfxQtFont ();
|
||||||
|
|
||||||
|
virtual nsString GetUniqueName ();
|
||||||
|
|
||||||
|
virtual PRUint32 GetSpaceGlyph ()
|
||||||
|
{
|
||||||
|
NS_ASSERTION (GetStyle ()->size != 0,
|
||||||
|
"forgot to short-circuit a text run with zero-sized font?");
|
||||||
|
GetMetrics ();
|
||||||
|
return mSpaceGlyph;
|
||||||
|
}
|
||||||
|
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
|
virtual const gfxFont::Metrics& GetMetrics();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void *mQFont;
|
||||||
|
cairo_scaled_font_t *mCairoFont;
|
||||||
|
|
||||||
|
PRBool mHasMetrics;
|
||||||
|
PRUint32 mSpaceGlyph;
|
||||||
|
Metrics mMetrics;
|
||||||
|
gfxFloat mAdjustedSize;
|
||||||
|
|
||||||
|
virtual PRBool SetupCairoFont(gfxContext *aContext);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class THEBES_API gfxQtFontGroup : public gfxFontGroup {
|
class THEBES_API gfxQtFontGroup : public gfxFontGroup {
|
||||||
|
@ -69,6 +95,19 @@ public:
|
||||||
const Parameters *aParams, PRUint32 aFlags);
|
const Parameters *aParams, PRUint32 aFlags);
|
||||||
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||||
const Parameters *aParams, PRUint32 aFlags);
|
const Parameters *aParams, PRUint32 aFlags);
|
||||||
|
|
||||||
|
gfxQtFont * GetFontAt (PRInt32 i) {
|
||||||
|
return static_cast < gfxQtFont * >(static_cast < gfxFont * >(mFonts[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void InitTextRun (gfxTextRun * aTextRun, const char * aUTF8Text,
|
||||||
|
PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
|
||||||
|
PRBool aTake8BitPath);
|
||||||
|
|
||||||
|
|
||||||
|
static PRBool FontCallback (const nsAString & fontName, const nsACString & genericName, void *closure);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* GFX_QTFONTS_H */
|
#endif /* GFX_QTFONTS_H */
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "gfxPlatformQt.h"
|
#include "gfxPlatformQt.h"
|
||||||
|
#include "gfxTypes.h"
|
||||||
#include "gfxQtFonts.h"
|
#include "gfxQtFonts.h"
|
||||||
#include "qdebug.h"
|
#include "qdebug.h"
|
||||||
|
|
||||||
|
@ -50,35 +51,217 @@
|
||||||
* gfxQtFontGroup
|
* gfxQtFontGroup
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
FFRECountHyphens (const nsAString &aFFREName)
|
||||||
|
{
|
||||||
|
int h = 0;
|
||||||
|
PRInt32 hyphen = 0;
|
||||||
|
while ((hyphen = aFFREName.FindChar('-', hyphen)) >= 0) {
|
||||||
|
++h;
|
||||||
|
++hyphen;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
gfxQtFontGroup::FontCallback (const nsAString& fontName,
|
||||||
|
const nsACString& genericName,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d, fontname:%s, genName:%s\n", __PRETTY_FUNCTION__, __LINE__, NS_ConvertUTF16toUTF8(fontName).get(), nsCString(genericName).get());
|
||||||
|
nsStringArray *sa = static_cast<nsStringArray*>(closure);
|
||||||
|
|
||||||
|
// We ignore prefs that have three hypens since they are X style prefs.
|
||||||
|
if (genericName.Length() && FFRECountHyphens(fontName) >= 3)
|
||||||
|
return PR_TRUE;
|
||||||
|
|
||||||
|
if (sa->IndexOf(fontName) < 0) {
|
||||||
|
sa->AppendString(fontName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the font in the gfxFont cache. If we don't find it, create one.
|
||||||
|
* In either case, add a ref, append it to the aFonts array, and return it ---
|
||||||
|
* except for OOM in which case we do nothing and return null.
|
||||||
|
*/
|
||||||
|
static already_AddRefed<gfxQtFont>
|
||||||
|
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
||||||
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
|
||||||
|
if (!font) {
|
||||||
|
font = new gfxQtFont(aName, aStyle);
|
||||||
|
if (!font)
|
||||||
|
return nsnull;
|
||||||
|
gfxFontCache::GetCache()->AddNew(font);
|
||||||
|
}
|
||||||
|
gfxFont *f = nsnull;
|
||||||
|
font.swap(f);
|
||||||
|
return static_cast<gfxQtFont *>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gfxQtFontGroup::gfxQtFontGroup (const nsAString& families,
|
gfxQtFontGroup::gfxQtFontGroup (const nsAString& families,
|
||||||
const gfxFontStyle *aStyle)
|
const gfxFontStyle *aStyle)
|
||||||
: gfxFontGroup(families, aStyle)
|
: gfxFontGroup(families, aStyle)
|
||||||
{
|
{
|
||||||
qDebug("Func:%s::%d, fam:%s\n\tNeed to create font metrics, otherwise - CRASH\n\n", __PRETTY_FUNCTION__, __LINE__, NS_ConvertUTF16toUTF8(families).get());
|
qDebug("Func:%s::%d, fam:%s\n\tNeed to create font metrics, otherwise - CRASH\n\n", __PRETTY_FUNCTION__, __LINE__, NS_ConvertUTF16toUTF8(families).get());
|
||||||
|
nsStringArray familyArray;
|
||||||
|
|
||||||
|
// Leave non-existing fonts in the list so that fontconfig can get the
|
||||||
|
// best match.
|
||||||
|
ForEachFontInternal(families, aStyle->langGroup, PR_TRUE, PR_FALSE,
|
||||||
|
FontCallback, &familyArray);
|
||||||
|
|
||||||
|
// Construct a string suitable for fontconfig
|
||||||
|
nsAutoString fcFamilies;
|
||||||
|
if (familyArray.Count()) {
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
int i = 0;
|
||||||
|
while (1) {
|
||||||
|
fcFamilies.Append(*familyArray[i]);
|
||||||
|
++i;
|
||||||
|
if (i >= familyArray.Count())
|
||||||
|
break;
|
||||||
|
fcFamilies.Append(NS_LITERAL_STRING(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// XXX If there are no fonts, we should use dummy family.
|
||||||
|
// Pango will resolve from this.
|
||||||
|
// behdad: yep, looks good.
|
||||||
|
// printf("%s(%s)\n", NS_ConvertUTF16toUTF8(families).get(),
|
||||||
|
// aStyle->langGroup.get());
|
||||||
|
fcFamilies.Append(NS_LITERAL_STRING("sans-serif"));
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<gfxQtFont> font = GetOrMakeFont(fcFamilies, &mStyle);
|
||||||
|
if (font) {
|
||||||
|
mFonts.AppendElement(font);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxQtFontGroup::~gfxQtFontGroup()
|
gfxQtFontGroup::~gfxQtFontGroup()
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFontGroup *
|
gfxFontGroup *
|
||||||
gfxQtFontGroup::Copy(const gfxFontStyle *aStyle)
|
gfxQtFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
return new gfxQtFontGroup(mFamilies, aStyle);
|
return new gfxQtFontGroup(mFamilies, aStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_FAST_PATH_8BIT)
|
||||||
|
PRBool
|
||||||
|
gfxQtFontGroup::CanTakeFastPath(PRUint32 aFlags)
|
||||||
|
{
|
||||||
|
// Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't.
|
||||||
|
// We need to always use Pango for RTL text, in case glyph mirroring is
|
||||||
|
// required.
|
||||||
|
PRBool speed = aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
|
||||||
|
PRBool isRTL = aFlags & gfxTextRunFactory::TEXT_IS_RTL;
|
||||||
|
return speed && !isRTL
|
||||||
|
//&& PANGO_IS_FC_FONT(GetFontAt(0)->GetPangoFont())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxQtFontGroup::InitTextRun(gfxTextRun *aTextRun, const char *aUTF8Text,
|
||||||
|
PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
|
||||||
|
PRBool aTake8BitPath)
|
||||||
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d, Text:'%s'\n", __PRETTY_FUNCTION__, __LINE__, aUTF8Text);
|
||||||
|
#if defined(ENABLE_FAST_PATH_ALWAYS)
|
||||||
|
// CreateGlyphRunsFast(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||||
|
#else
|
||||||
|
#if defined(ENABLE_FAST_PATH_8BIT)
|
||||||
|
if (aTake8BitPath && CanTakeFastPath(aTextRun->GetFlags())) {
|
||||||
|
// nsresult rv = CreateGlyphRunsFast(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CreateGlyphRunsItemizing(aTextRun, aUTF8Text, aUTF8Length, aUTF8HeaderLength);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use this to append an LTR or RTL Override character to the start of the
|
||||||
|
* string. This forces Pango to honour our direction even if there are neutral characters
|
||||||
|
* in the string.
|
||||||
|
*/
|
||||||
|
static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
|
||||||
|
{
|
||||||
|
static const PRUnichar overrides[2][2] =
|
||||||
|
{ { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO
|
||||||
|
AppendUTF16toUTF8(overrides[aIsRTL], aString);
|
||||||
|
return 3; // both overrides map to 3 bytes in UTF8
|
||||||
|
}
|
||||||
|
|
||||||
gfxTextRun *
|
gfxTextRun *
|
||||||
gfxQtFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
gfxQtFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||||
const Parameters *aParams, PRUint32 aFlags)
|
const Parameters *aParams, PRUint32 aFlags)
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
|
||||||
|
gfxTextRun *run = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
|
||||||
|
if (!run)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
|
PRBool isRTL = run->IsRightToLeft();
|
||||||
|
if ((aFlags & TEXT_IS_ASCII) && !isRTL) {
|
||||||
|
// We don't need to send an override character here, the characters must be all LTR
|
||||||
|
const char *utf8Chars = reinterpret_cast<const char*>(aString);
|
||||||
|
InitTextRun(run, utf8Chars, aLength, 0, PR_TRUE);
|
||||||
|
} else {
|
||||||
|
// this is really gross...
|
||||||
|
const char *chars = reinterpret_cast<const char*>(aString);
|
||||||
|
NS_ConvertASCIItoUTF16 unicodeString(chars, aLength);
|
||||||
|
nsCAutoString utf8;
|
||||||
|
PRInt32 headerLen = AppendDirectionalIndicatorUTF8(isRTL, utf8);
|
||||||
|
AppendUTF16toUTF8(unicodeString, utf8);
|
||||||
|
InitTextRun(run, utf8.get(), utf8.Length(), headerLen, PR_TRUE);
|
||||||
|
}
|
||||||
|
run->FetchGlyphExtents(aParams->mContext);
|
||||||
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxTextRun *
|
gfxTextRun *
|
||||||
gfxQtFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
gfxQtFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||||
const Parameters *aParams, PRUint32 aFlags)
|
const Parameters *aParams, PRUint32 aFlags)
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
gfxTextRun *run = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
|
||||||
|
if (!run)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
|
run->RecordSurrogates(aString);
|
||||||
|
|
||||||
|
nsCAutoString utf8;
|
||||||
|
PRInt32 headerLen = AppendDirectionalIndicatorUTF8(run->IsRightToLeft(), utf8);
|
||||||
|
AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8);
|
||||||
|
PRBool is8Bit = PR_FALSE;
|
||||||
|
|
||||||
|
#if defined(ENABLE_FAST_PATH_8BIT)
|
||||||
|
if (CanTakeFastPath(aFlags)) {
|
||||||
|
PRUint32 allBits = 0;
|
||||||
|
PRUint32 i;
|
||||||
|
for (i = 0; i < aLength; ++i) {
|
||||||
|
allBits |= aString[i];
|
||||||
|
}
|
||||||
|
is8Bit = (allBits & 0xFF00) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
InitTextRun(run, utf8.get(), utf8.Length(), headerLen, is8Bit);
|
||||||
|
run->FetchGlyphExtents(aParams->mContext);
|
||||||
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,18 +270,92 @@ gfxQtFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||||
|
|
||||||
gfxQtFont::gfxQtFont(const nsAString &aName,
|
gfxQtFont::gfxQtFont(const nsAString &aName,
|
||||||
const gfxFontStyle *aFontStyle)
|
const gfxFontStyle *aFontStyle)
|
||||||
: gfxFont(aName, aFontStyle)
|
: gfxFont(aName, aFontStyle),
|
||||||
|
mQFont(nsnull), mCairoFont(nsnull),
|
||||||
|
mHasMetrics(PR_FALSE), mAdjustedSize(0)
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d, name:%s\n", __PRETTY_FUNCTION__, __LINE__, NS_ConvertUTF16toUTF8(aName).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxQtFont::~gfxQtFont()
|
gfxQtFont::~gfxQtFont()
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gfxFont::Metrics&
|
||||||
|
gfxQtFont::GetMetrics()
|
||||||
|
{
|
||||||
|
if (mHasMetrics)
|
||||||
|
return mMetrics;
|
||||||
|
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
#if 0
|
||||||
|
// printf("font name: %s %f %f\n", NS_ConvertUTF16toUTF8(mName).get(), GetStyle()->size, mAdjustedSize);
|
||||||
|
// printf ("pango font %s\n", pango_font_description_to_string (pango_font_describe (font)));
|
||||||
|
|
||||||
|
fprintf (stderr, "Font: %s\n", NS_ConvertUTF16toUTF8(mName).get());
|
||||||
|
fprintf (stderr, " emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
|
||||||
|
fprintf (stderr, " maxAscent: %f maxDescent: %f\n", mMetrics.maxAscent, mMetrics.maxDescent);
|
||||||
|
fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.externalLeading, mMetrics.internalLeading);
|
||||||
|
fprintf (stderr, " spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight);
|
||||||
|
fprintf (stderr, " uOff: %f uSize: %f stOff: %f stSize: %f suOff: %f suSize: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize, mMetrics.superscriptOffset, mMetrics.subscriptOffset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mHasMetrics = PR_TRUE;
|
||||||
|
return mMetrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsString
|
||||||
|
gfxQtFont::GetUniqueName()
|
||||||
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
nsString result;
|
||||||
|
/*
|
||||||
|
PangoFont *font = GetPangoFont();
|
||||||
|
PangoFontDescription *desc = pango_font_describe(font);
|
||||||
|
pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE);
|
||||||
|
char *str = pango_font_description_to_string(desc);
|
||||||
|
pango_font_description_free (desc);
|
||||||
|
|
||||||
|
CopyUTF8toUTF16(str, result);
|
||||||
|
g_free(str);*/
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
gfxQtFont::Shutdown()
|
gfxQtFont::Shutdown()
|
||||||
{
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
gfxQtFont::SetupCairoFont(gfxContext *aContext)
|
||||||
|
{
|
||||||
|
qDebug(">>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
cairo_t *cr = aContext->GetCairo();
|
||||||
|
cairo_matrix_t currentCTM;
|
||||||
|
cairo_get_matrix(cr, ¤tCTM);
|
||||||
|
|
||||||
|
if (mCairoFont) {
|
||||||
|
// Need to validate that its CTM is OK
|
||||||
|
cairo_matrix_t fontCTM;
|
||||||
|
cairo_scaled_font_get_ctm(mCairoFont, &fontCTM);
|
||||||
|
if (fontCTM.xx != currentCTM.xx || fontCTM.yy != currentCTM.yy ||
|
||||||
|
fontCTM.xy != currentCTM.xy || fontCTM.yx != currentCTM.yx) {
|
||||||
|
// Just recreate it from scratch, simplest way
|
||||||
|
cairo_scaled_font_destroy(mCairoFont);
|
||||||
|
mCairoFont = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mCairoFont) {
|
||||||
|
//mCairoFont = CreateScaledFont(cr, ¤tCTM, GetPangoFont());
|
||||||
|
}
|
||||||
|
if (cairo_scaled_font_status(mCairoFont) != CAIRO_STATUS_SUCCESS) {
|
||||||
|
// Don't cairo_set_scaled_font as that would propagate the error to
|
||||||
|
// the cairo_t, precluding any further drawing.
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
cairo_set_scaled_font(cr, mCairoFont);
|
||||||
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче