зеркало из https://github.com/mozilla/gecko-dev.git
partial fix for font fallbacks. bug 324560. also fixes 324712. r=vlad
This commit is contained in:
Родитель
8895e6b3ba
Коммит
0fe1ba3ddd
|
@ -98,7 +98,8 @@ typedef struct {
|
|||
|
||||
HFONT scaled_hfont;
|
||||
HFONT unscaled_hfont;
|
||||
|
||||
|
||||
cairo_bool_t delete_scaled_hfont;
|
||||
} cairo_win32_scaled_font_t;
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -225,6 +226,7 @@ _get_system_quality (void)
|
|||
|
||||
static cairo_scaled_font_t *
|
||||
_win32_scaled_font_create (LOGFONTW *logfont,
|
||||
HFONT hfont,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
|
@ -270,9 +272,12 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
}
|
||||
|
||||
f->em_square = 0;
|
||||
f->scaled_hfont = NULL;
|
||||
f->scaled_hfont = hfont;
|
||||
f->unscaled_hfont = NULL;
|
||||
|
||||
/* don't delete the hfont if it was passed in to us */
|
||||
f->delete_scaled_hfont = !hfont;
|
||||
|
||||
cairo_matrix_multiply (&scale, font_matrix, ctm);
|
||||
_compute_transform (f, &scale);
|
||||
|
||||
|
@ -516,7 +521,7 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
if (!logfont.lfFaceName)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
scaled_font = _win32_scaled_font_create (&logfont, &toy_face->base,
|
||||
scaled_font = _win32_scaled_font_create (&logfont, NULL, &toy_face->base,
|
||||
font_matrix, ctm, options);
|
||||
if (!scaled_font)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -534,7 +539,7 @@ _cairo_win32_scaled_font_fini (void *abstract_font)
|
|||
if (scaled_font == NULL)
|
||||
return;
|
||||
|
||||
if (scaled_font->scaled_hfont)
|
||||
if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)
|
||||
DeleteObject (scaled_font->scaled_hfont);
|
||||
|
||||
if (scaled_font->unscaled_hfont)
|
||||
|
@ -1371,6 +1376,7 @@ typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
|
|||
struct _cairo_win32_font_face {
|
||||
cairo_font_face_t base;
|
||||
LOGFONTW logfont;
|
||||
HFONT hfont;
|
||||
};
|
||||
|
||||
/* implement the platform-specific interface */
|
||||
|
@ -1390,6 +1396,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
|||
cairo_win32_font_face_t *font_face = abstract_face;
|
||||
|
||||
*font = _win32_scaled_font_create (&font_face->logfont,
|
||||
font_face->hfont,
|
||||
&font_face->base,
|
||||
font_matrix, ctm, options);
|
||||
if (*font)
|
||||
|
@ -1430,6 +1437,26 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
|
|||
}
|
||||
|
||||
font_face->logfont = *logfont;
|
||||
font_face->hfont = NULL;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_hfont (HFONT font)
|
||||
{
|
||||
cairo_win32_font_face_t *font_face;
|
||||
|
||||
font_face = malloc (sizeof (cairo_win32_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->hfont = font;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
|
|||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_hfont (HFONT font);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
||||
HDC hdc);
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
#ifndef _NS_SYSTEMFONTSWIN_H_
|
||||
#define _NS_SYSTEMFONTSWIN_H_
|
||||
|
||||
#include <nsFont.h>
|
||||
#include <nsIDeviceContext.h>
|
||||
#include "nsFont.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
|
||||
class nsSystemFontsWin
|
||||
{
|
||||
|
|
|
@ -286,7 +286,8 @@ nsThebesFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength,
|
|||
nscoord& aWidth, PRInt32 *aFontID,
|
||||
nsThebesRenderingContext *aContext)
|
||||
{
|
||||
nsRefPtr<gfxTextRun> textrun = mFontGroup->MakeTextRun(nsDependentSubstring(aString, aString+aLength));
|
||||
const nsDependentSubstring& theString = nsDependentSubstring(aString, aString+aLength);
|
||||
nsRefPtr<gfxTextRun> textrun = mFontGroup->MakeTextRun(theString);
|
||||
|
||||
textrun->SetRightToLeft(mIsRTL);
|
||||
|
||||
|
@ -354,7 +355,8 @@ nsThebesFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
|
|||
{
|
||||
float app2dev = mDeviceContext->AppUnitsToDevUnits();
|
||||
|
||||
nsRefPtr<gfxTextRun> textrun = mFontGroup->MakeTextRun(nsDependentSubstring(aString, aString+aLength));
|
||||
const nsDependentSubstring& theString = nsDependentSubstring(aString, aString+aLength);
|
||||
nsRefPtr<gfxTextRun> textrun = mFontGroup->MakeTextRun(theString);
|
||||
|
||||
textrun->SetRightToLeft(mIsRTL);
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
class gfxAtsuiFontGroup;
|
||||
|
||||
class gfxAtsuiFont : public gfxFont {
|
||||
THEBES_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
public:
|
||||
gfxAtsuiFont(ATSUFontID fontID,
|
||||
gfxAtsuiFontGroup *fontGroup);
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "gfxTypes.h"
|
||||
#include "nsString.h"
|
||||
#include "gfxPoint.h"
|
||||
#include <vector>
|
||||
#include "nsTArray.h"
|
||||
|
||||
class gfxContext;
|
||||
class gfxTextRun;
|
||||
|
@ -121,6 +121,8 @@ struct NS_EXPORT gfxFontStyle {
|
|||
|
||||
/* a SPECIFIC single font family */
|
||||
class NS_EXPORT gfxFont {
|
||||
THEBES_DECL_REFCOUNTING_ABSTRACT
|
||||
|
||||
public:
|
||||
virtual ~gfxFont() {}
|
||||
|
||||
|
@ -159,15 +161,16 @@ protected:
|
|||
const gfxFontStyle *mStyle;
|
||||
};
|
||||
|
||||
typedef std::vector<gfxFont*> gfxFontVector;
|
||||
typedef nsTArray<gfxFont*> gfxFontVector;
|
||||
|
||||
class NS_EXPORT gfxFontGroup {
|
||||
public:
|
||||
gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle);
|
||||
|
||||
virtual ~gfxFontGroup() {
|
||||
for (gfxFontVector::iterator it = mFonts.begin(); it!=mFonts.end(); ++it)
|
||||
delete *it;
|
||||
for (PRUint32 i = 0; i < mFonts.Length(); ++i)
|
||||
NS_RELEASE(mFonts[i]);
|
||||
mFonts.Clear();
|
||||
}
|
||||
|
||||
gfxFontVector &GetFontList() { return mFonts; } // XXX this should really be const..
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include <pango/pango.h>
|
||||
|
||||
class gfxPangoFont : public gfxFont {
|
||||
THEBES_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
public:
|
||||
gfxPangoFont (const nsAString& aName,
|
||||
const gfxFontGroup *aFontGroup);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "gfxTypes.h"
|
||||
#include "gfxFont.h"
|
||||
|
||||
#include <Usp10.h>
|
||||
#include <cairo-win32.h>
|
||||
|
||||
|
||||
|
@ -52,14 +53,20 @@
|
|||
**********************************************************************/
|
||||
|
||||
class gfxWindowsFont : public gfxFont {
|
||||
THEBES_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
public:
|
||||
gfxWindowsFont(const nsAString &aName, const gfxFontGroup *aFontGroup, HDC aHWnd);
|
||||
gfxWindowsFont::gfxWindowsFont(HFONT aFont, const gfxFontGroup *aFontGroup, PRBool aIsMLangFont);
|
||||
|
||||
virtual ~gfxWindowsFont();
|
||||
|
||||
virtual const gfxFont::Metrics& GetMetrics() { return mMetrics; }
|
||||
|
||||
cairo_font_face_t *CairoFontFace() { return mFontFace; }
|
||||
cairo_scaled_font_t *CairoScaledFont() { return mScaledFont; }
|
||||
SCRIPT_CACHE *ScriptCache() { return &mScriptCache; }
|
||||
HFONT GetHFONT() { return mFont; }
|
||||
void UpdateFonts(cairo_t *cr);
|
||||
|
||||
protected:
|
||||
|
@ -71,11 +78,16 @@ private:
|
|||
void ComputeMetrics(HDC dc);
|
||||
|
||||
LOGFONTW mLogFont;
|
||||
HFONT mFont;
|
||||
|
||||
cairo_font_face_t *mFontFace;
|
||||
cairo_scaled_font_t *mScaledFont;
|
||||
|
||||
gfxFont::Metrics mMetrics;
|
||||
|
||||
SCRIPT_CACHE mScriptCache;
|
||||
|
||||
PRBool mIsMLangFont;
|
||||
};
|
||||
|
||||
|
||||
|
@ -120,12 +132,15 @@ public:
|
|||
virtual gfxFloat MeasureString(gfxContext *aContext);
|
||||
|
||||
private:
|
||||
PRInt32 MeasureOrDrawUniscribe(gfxContext *aContext,
|
||||
const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aDraw, PRInt32 aX, PRInt32 aY, const PRInt32 *aSpacing);
|
||||
gfxWindowsFont *FindFallbackFont(HDC aDC,
|
||||
const PRUnichar *aString, PRUint32 aLength,
|
||||
gfxWindowsFont *aFont);
|
||||
|
||||
PRInt32 MeasureOrDrawUniscribe(gfxContext *aContext, PRBool aDraw,
|
||||
PRInt32 aX, PRInt32 aY,
|
||||
const PRInt32 *aSpacing);
|
||||
|
||||
nsString mString;
|
||||
const nsAString& mString;
|
||||
gfxWindowsFontGroup *mGroup;
|
||||
};
|
||||
|
||||
|
|
|
@ -43,10 +43,13 @@
|
|||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <mlang.h>
|
||||
|
||||
class NS_EXPORT gfxWindowsPlatform : public gfxPlatform {
|
||||
public:
|
||||
gfxWindowsPlatform();
|
||||
//virtual ~gfxWindowsPlatform();
|
||||
virtual ~gfxWindowsPlatform();
|
||||
static gfxWindowsPlatform *GetPlatform() {
|
||||
return (gfxWindowsPlatform*) gfxPlatform::GetPlatform();
|
||||
}
|
||||
|
@ -59,8 +62,9 @@ public:
|
|||
const nsACString& aGenericFamily,
|
||||
nsStringArray& aListOfFonts);
|
||||
|
||||
IMultiLanguage *GetMLangService();
|
||||
|
||||
private:
|
||||
#if 0
|
||||
void Init();
|
||||
|
||||
static int CALLBACK FontEnumProc(const LOGFONT *logFont,
|
||||
|
@ -68,7 +72,7 @@ private:
|
|||
DWORD fontType, LPARAM data);
|
||||
|
||||
static nsStringArray *mFontList;
|
||||
#endif
|
||||
nsRefPtr<IMultiLanguage> mMLang;
|
||||
};
|
||||
|
||||
#endif /* GFX_WINDOWS_PLATFORM_H */
|
||||
|
|
|
@ -26,7 +26,7 @@ CPPSRCS = \
|
|||
gfxFont.cpp \
|
||||
gfxPlatform.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
SHARED_LIBRARY_LIBS += \
|
||||
$(DIST)/lib/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX) \
|
||||
|
@ -43,9 +43,10 @@ CPPSRCS += gfxWindowsFonts.cpp \
|
|||
gfxWindowsSurface.cpp \
|
||||
$(NULL)
|
||||
|
||||
_OS_LIBS = usp10
|
||||
_OS_LIBS = usp10 ole32
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,$(_OS_LIBS))
|
||||
|
||||
ACDEFINES += -UWIN32_LEAN_AND_MEAN
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_GFX_TOOLKIT),gtk2)
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
#include "cairo-atsui.h"
|
||||
|
||||
THEBES_IMPL_REFCOUNTING(gfxAtsuiFont)
|
||||
|
||||
gfxAtsuiFont::gfxAtsuiFont(ATSUFontID fontID,
|
||||
gfxAtsuiFontGroup *fontGroup)
|
||||
: mATSUFontID(fontID), mFontGroup(fontGroup)
|
||||
|
@ -136,16 +138,16 @@ gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
|
|||
#define NUM_STATIC_FIDS 16
|
||||
ATSUFontID static_fids[NUM_STATIC_FIDS];
|
||||
ATSUFontID *fids;
|
||||
if (mFonts.size() > NUM_STATIC_FIDS)
|
||||
fids = (ATSUFontID *) PR_Malloc(sizeof(ATSUFontID) * mFonts.size());
|
||||
if (mFonts.Length() > NUM_STATIC_FIDS)
|
||||
fids = (ATSUFontID *) PR_Malloc(sizeof(ATSUFontID) * mFonts.Length());
|
||||
else
|
||||
fids = static_fids;
|
||||
|
||||
for (unsigned int i = 0; i < mFonts.size(); i++)
|
||||
for (unsigned int i = 0; i < mFonts.Length(); i++)
|
||||
fids[i] = ((gfxAtsuiFont*)(mFonts[i]))->GetATSUFontID();
|
||||
|
||||
ATSUSetObjFontFallbacks(mFallbacks,
|
||||
mFonts.size(),
|
||||
mFonts.Length(),
|
||||
fids,
|
||||
kATSUSequentialFallbacksPreferred /* kATSUSequentialFallbacksExclusive? */);
|
||||
|
||||
|
@ -242,7 +244,7 @@ gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
|
|||
//fprintf (stderr, "FindATSUFont: %s -> %d (status: %d)\n", NS_ConvertUTF16toUTF8(aName).get(), (int) fontID, (int) status);
|
||||
|
||||
if (fontID != kATSUInvalidFontID)
|
||||
fontGroup->mFonts.push_back(new gfxAtsuiFont(fontID, fontGroup));
|
||||
fontGroup->mFonts.AppendElement(new gfxAtsuiFont(fontID, fontGroup));
|
||||
#endif
|
||||
|
||||
return PR_TRUE;
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
|
||||
#endif
|
||||
|
||||
THEBES_IMPL_REFCOUNTING(gfxPangoFont)
|
||||
|
||||
static PangoLanguage *GetPangoLanguage(const nsACString& aLangGroup);
|
||||
|
||||
/**
|
||||
|
@ -143,7 +145,8 @@ gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
|
|||
fixedFamilies.Truncate(fixedFamilies.Length() - 1); // remove final comma
|
||||
|
||||
gfxFont *f = new gfxPangoFont(fixedFamilies, this);
|
||||
mFonts.push_back(f);
|
||||
NS_ADDREF(f);
|
||||
mFonts.AppendElement(f);
|
||||
}
|
||||
|
||||
gfxPangoFontGroup::~gfxPangoFontGroup()
|
||||
|
|
|
@ -41,11 +41,12 @@
|
|||
#include "nsPromiseFlatString.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "gfxWindowsFonts.h"
|
||||
#include <math.h>
|
||||
#include <Usp10.h>
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <mlang.h>
|
||||
|
||||
#define NSToCoordRound(x) (floor((x) + 0.5))
|
||||
|
||||
|
@ -56,7 +57,10 @@
|
|||
*
|
||||
**********************************************************************/
|
||||
|
||||
THEBES_IMPL_REFCOUNTING(gfxWindowsFont)
|
||||
|
||||
gfxWindowsFont::gfxWindowsFont(const nsAString &aName, const gfxFontGroup *aFontGroup, HDC aDC)
|
||||
: mFont(nsnull), mScriptCache(nsnull), mIsMLangFont(PR_FALSE)
|
||||
{
|
||||
mName = aName;
|
||||
mGroup = aFontGroup;
|
||||
|
@ -76,10 +80,42 @@ gfxWindowsFont::gfxWindowsFont(const nsAString &aName, const gfxFontGroup *aFont
|
|||
ReleaseDC((HWND)nsnull, dc);
|
||||
}
|
||||
|
||||
gfxWindowsFont::gfxWindowsFont(HFONT aFont, const gfxFontGroup *aFontGroup, PRBool aIsMLangFont)
|
||||
: mScriptCache(nsnull), mIsMLangFont(aIsMLangFont)
|
||||
{
|
||||
mFont = aFont;
|
||||
mGroup = aFontGroup;
|
||||
mStyle = mGroup->GetStyle();
|
||||
|
||||
mFontFace = MakeCairoFontFace();
|
||||
NS_ASSERTION(mFontFace, "Failed to make font face");
|
||||
|
||||
mScaledFont = MakeCairoScaledFont(nsnull);
|
||||
NS_ASSERTION(mScaledFont, "Failed to make scaled font");
|
||||
|
||||
// don't bother creating the metrics.
|
||||
}
|
||||
|
||||
gfxWindowsFont::~gfxWindowsFont()
|
||||
{
|
||||
cairo_font_face_destroy(mFontFace);
|
||||
cairo_scaled_font_destroy(mScaledFont);
|
||||
|
||||
if (mIsMLangFont) {
|
||||
IMultiLanguage *ml = gfxWindowsPlatform::GetPlatform()->GetMLangService();
|
||||
if (ml) {
|
||||
nsRefPtr<IMLangFontLink2> fl;
|
||||
HRESULT rv = ml->QueryInterface(IID_IMLangFontLink2, getter_AddRefs(fl));
|
||||
if (SUCCEEDED(rv))
|
||||
fl->ReleaseFont(mFont);
|
||||
}
|
||||
mFont = nsnull;
|
||||
}
|
||||
|
||||
if (mFont)
|
||||
DeleteObject(mFont);
|
||||
|
||||
ScriptFreeCache(&mScriptCache);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -99,9 +135,11 @@ gfxWindowsFont::MakeCairoFontFace()
|
|||
{
|
||||
cairo_font_face_t *fontFace = nsnull;
|
||||
|
||||
FillLogFont();
|
||||
|
||||
fontFace = cairo_win32_font_face_create_for_logfontw(&mLogFont);
|
||||
if (!mFont) {
|
||||
FillLogFont();
|
||||
mFont = CreateFontIndirectW(&mLogFont);
|
||||
}
|
||||
fontFace = cairo_win32_font_face_create_for_hfont(mFont);
|
||||
|
||||
return fontFace;
|
||||
}
|
||||
|
@ -207,7 +245,7 @@ gfxWindowsFont::FillLogFont()
|
|||
{
|
||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||
|
||||
mLogFont.lfHeight = -NSToCoordRound(mStyle->size);
|
||||
mLogFont.lfHeight = -NSToCoordRound(mStyle->size * 32);
|
||||
|
||||
if (mLogFont.lfHeight == 0)
|
||||
mLogFont.lfHeight = -1;
|
||||
|
@ -246,7 +284,9 @@ PRBool
|
|||
gfxWindowsFontGroup::MakeFont(const nsAString& aName, const nsAString& aGenericName, void *closure)
|
||||
{
|
||||
gfxWindowsFontGroup *fg = NS_STATIC_CAST(gfxWindowsFontGroup*, closure);
|
||||
fg->mFonts.push_back(new gfxWindowsFont(aName, fg, (HDC)fg->mDC));
|
||||
gfxFont *font = new gfxWindowsFont(aName, fg, fg->mDC);
|
||||
NS_ADDREF(font);
|
||||
fg->mFonts.AppendElement(font);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -288,47 +328,79 @@ gfxWindowsTextRun::~gfxWindowsTextRun()
|
|||
void
|
||||
gfxWindowsTextRun::DrawString(gfxContext *aContext, gfxPoint pt)
|
||||
{
|
||||
MeasureOrDrawUniscribe(aContext, mString.get(), mString.Length(), PR_TRUE, pt.x, pt.y, nsnull);
|
||||
MeasureOrDrawUniscribe(aContext, PR_TRUE, pt.x, pt.y, nsnull);
|
||||
}
|
||||
|
||||
gfxFloat
|
||||
gfxWindowsTextRun::MeasureString(gfxContext *aContext)
|
||||
{
|
||||
return MeasureOrDrawUniscribe(aContext, mString.get(), mString.Length(), PR_FALSE, 0, 0, nsnull);
|
||||
return MeasureOrDrawUniscribe(aContext, PR_FALSE, 0, 0, nsnull);
|
||||
}
|
||||
|
||||
|
||||
gfxWindowsFont *
|
||||
gfxWindowsTextRun::FindFallbackFont(HDC aDC, const PRUnichar *aString, PRUint32 aLength, gfxWindowsFont *aFont)
|
||||
{
|
||||
HRESULT rv;
|
||||
IMultiLanguage *multiLanguage = gfxWindowsPlatform::GetPlatform()->GetMLangService();
|
||||
if (!multiLanguage)
|
||||
return nsnull;
|
||||
|
||||
// yes, that is right. we're using nsRefPtr's on MSCOM objects.
|
||||
nsRefPtr<IMLangFontLink2> langFontLink;
|
||||
rv = multiLanguage->QueryInterface(IID_IMLangFontLink2, getter_AddRefs(langFontLink));
|
||||
if (FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
DWORD fontCodePages;
|
||||
langFontLink->GetFontCodePages(aDC, aFont->GetHFONT(), &fontCodePages);
|
||||
|
||||
DWORD actualCodePages;
|
||||
long cchActual;
|
||||
rv = langFontLink->GetStrCodePages(aString, aLength, fontCodePages, &actualCodePages, &cchActual);
|
||||
|
||||
HFONT retFont;
|
||||
rv = langFontLink->MapFont(aDC, actualCodePages, aString[0], &retFont);
|
||||
if (FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
return new gfxWindowsFont(retFont, mGroup, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
gfxWindowsTextRun::MeasureOrDrawUniscribe(gfxContext *aContext,
|
||||
const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aDraw, PRInt32 aX, PRInt32 aY, const PRInt32 *aSpacing)
|
||||
PRBool aDraw,
|
||||
PRInt32 aX, PRInt32 aY,
|
||||
const PRInt32 *aSpacing)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surf = aContext->CurrentGroupSurface();
|
||||
if (!surf)
|
||||
surf = aContext->CurrentSurface();
|
||||
|
||||
HDC aDC = cairo_win32_surface_get_dc(surf->CairoSurface());
|
||||
NS_ASSERTION(aDC, "No DC");
|
||||
|
||||
const PRUnichar *aString = mString.BeginReading();
|
||||
const PRUint32 aLength = mString.Length();
|
||||
|
||||
// save the xform so that we can restore to it while cairo
|
||||
// munges it underneath us
|
||||
XFORM savedxform;
|
||||
GetWorldTransform(aDC, &savedxform);
|
||||
|
||||
int loops = 0;
|
||||
|
||||
cairo_t *cr = aContext->GetCairo();
|
||||
|
||||
PRBool isComplex = (::ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK);
|
||||
const PRBool isComplex = (::ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK);
|
||||
|
||||
PRInt32 length = 0;
|
||||
HRESULT rv;
|
||||
int numItems, maxItems = 2;
|
||||
int numItems, maxItems = 5;
|
||||
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
SCRIPT_CONTROL *control = nsnull;
|
||||
SCRIPT_STATE *state = nsnull;
|
||||
|
||||
PRBool rtl = IsRightToLeft();
|
||||
const PRBool rtl = IsRightToLeft();
|
||||
if (rtl) {
|
||||
control = (SCRIPT_CONTROL *)malloc(sizeof(SCRIPT_CONTROL));
|
||||
state = (SCRIPT_STATE *)malloc(sizeof(SCRIPT_STATE));
|
||||
|
@ -359,77 +431,145 @@ gfxWindowsTextRun::MeasureOrDrawUniscribe(gfxContext *aContext,
|
|||
cairo_font_face_t *fontFace = nsnull;
|
||||
cairo_scaled_font_t *scaledFont = nsnull;
|
||||
|
||||
TRY_AGAIN:
|
||||
PRBool fontSelected = PR_FALSE;
|
||||
|
||||
nsRefPtr<gfxWindowsFont> currentFont;
|
||||
nsRefPtr<gfxWindowsFont> fallbackFont;
|
||||
|
||||
DO_TRY_AGAIN:
|
||||
int fontIndex = 0;
|
||||
|
||||
TRY_AGAIN_SAME_SCRIPT:
|
||||
loops++;
|
||||
currentFont = NS_STATIC_CAST(gfxWindowsFont*, mGroup->mFonts[fontIndex]);
|
||||
|
||||
TRY_AGAIN_HOPE_FOR_THE_BEST:
|
||||
if (fallbackFont)
|
||||
currentFont = fallbackFont;
|
||||
|
||||
SaveDC(aDC);
|
||||
|
||||
gfxWindowsFont *currentFont = static_cast<gfxWindowsFont*>(mGroup->mFonts[fontIndex]);
|
||||
//currentFont->UpdateFonts(cr);
|
||||
fontFace = currentFont->CairoFontFace();
|
||||
scaledFont = currentFont->CairoScaledFont();
|
||||
|
||||
cairo_set_font_face(cr, fontFace);
|
||||
cairo_set_font_size(cr, mGroup->mStyle.size);
|
||||
fontSelected = PR_TRUE;
|
||||
|
||||
cairo_win32_scaled_font_select_font(scaledFont, aDC);
|
||||
|
||||
const double cairofontfactor = cairo_win32_scaled_font_get_metrics_factor(scaledFont);
|
||||
const double cairoToPixels = cairofontfactor * mGroup->mStyle.size;
|
||||
|
||||
if (!isComplex)
|
||||
if (!isComplex) {
|
||||
// disable shaping for non-complex scripts
|
||||
items[i].a.eScript = SCRIPT_UNDEFINED;
|
||||
} else {
|
||||
rv = ScriptGetCMap(aDC, currentFont->ScriptCache(),
|
||||
itemChars, itemLength,
|
||||
0, glyphs);
|
||||
|
||||
while ((rv = ScriptShape(aDC, &sc, itemChars, itemLength,
|
||||
if (rv == S_FALSE) {
|
||||
// Some of the Unicode code points were mapped to the default glyph.
|
||||
SCRIPT_FONTPROPERTIES scriptProperties;
|
||||
ScriptGetFontProperties(aDC, currentFont->ScriptCache(), &scriptProperties);
|
||||
|
||||
|
||||
if (glyphs[0] == scriptProperties.wgDefault) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDC scriptShapeDC = nsnull;
|
||||
TRY_AGAIN_JUST_SHAPE:
|
||||
while ((rv = ScriptShape(scriptShapeDC, currentFont->ScriptCache(),
|
||||
itemChars, itemLength,
|
||||
maxGlyphs, &items[i].a,
|
||||
glyphs, clusters,
|
||||
attr, &numGlyphs)) == E_OUTOFMEMORY) {
|
||||
|
||||
maxGlyphs *= 2;
|
||||
glyphs = (WORD *)realloc(glyphs, maxGlyphs*sizeof(WORD));
|
||||
attr = (SCRIPT_VISATTR *)realloc(attr, maxGlyphs*sizeof(SCRIPT_VISATTR));
|
||||
}
|
||||
|
||||
if (rv == E_PENDING) {
|
||||
scriptShapeDC = aDC;
|
||||
if (!fontSelected) {
|
||||
cairo_win32_scaled_font_select_font(scaledFont, aDC);
|
||||
fontSelected = PR_TRUE;
|
||||
}
|
||||
goto TRY_AGAIN_JUST_SHAPE;
|
||||
}
|
||||
|
||||
if (rv == USP_E_SCRIPT_NOT_IN_FONT) {
|
||||
if (fontIndex < mGroup->mFonts.size() - 1) {
|
||||
if (fontIndex < mGroup->mFonts.Length() - 1) {
|
||||
fontIndex++;
|
||||
cairo_win32_scaled_font_done_font(scaledFont);
|
||||
if (fontSelected)
|
||||
cairo_win32_scaled_font_done_font(scaledFont);
|
||||
fontSelected = PR_FALSE;
|
||||
RestoreDC(aDC, -1);
|
||||
goto TRY_AGAIN_SAME_SCRIPT;
|
||||
} else {
|
||||
// try again with SCRIPT_UNDEFINED
|
||||
items[i].a.eScript = SCRIPT_UNDEFINED;
|
||||
cairo_win32_scaled_font_done_font(scaledFont);
|
||||
if (fontSelected)
|
||||
cairo_win32_scaled_font_done_font(scaledFont);
|
||||
fontSelected = PR_FALSE;
|
||||
RestoreDC(aDC, -1);
|
||||
goto TRY_AGAIN;
|
||||
goto DO_TRY_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (numGlyphs > 0 && glyphs[0] == 0) {
|
||||
if (fontIndex < mGroup->mFonts.size() - 1) {
|
||||
if (fontIndex < mGroup->mFonts.Length() - 1) {
|
||||
fontIndex++;
|
||||
cairo_win32_scaled_font_done_font(scaledFont);
|
||||
RestoreDC(aDC, -1);
|
||||
goto TRY_AGAIN_SAME_SCRIPT;
|
||||
}
|
||||
|
||||
if (!fallbackFont) {
|
||||
// only look for a fallback font once
|
||||
fallbackFont = FindFallbackFont(aDC, itemChars, itemLength,
|
||||
NS_STATIC_CAST(gfxWindowsFont*, mGroup->mFonts[0]));
|
||||
|
||||
if (fallbackFont) {
|
||||
RestoreDC(aDC, -1);
|
||||
goto TRY_AGAIN_HOPE_FOR_THE_BEST;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise we fail to draw the characters so give up and continue on.
|
||||
#ifdef DEBUG_pavlov
|
||||
printf("failed to render glyphs :(\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
|
||||
if (FAILED(rv)) {
|
||||
printf("you lose!\n");
|
||||
}
|
||||
|
||||
if (SUCCEEDED(rv)) {
|
||||
ABC abc;
|
||||
GOFFSET *offsets = (GOFFSET *)malloc(numGlyphs*sizeof(GOFFSET));
|
||||
int *advance = (int *)malloc(numGlyphs*sizeof(int));
|
||||
rv = ScriptPlace(aDC, &sc, glyphs, numGlyphs, attr, &items[i].a,
|
||||
|
||||
HDC scriptPlaceDC = scriptShapeDC;
|
||||
TRY_AGAIN_JUST_PLACE:
|
||||
rv = ScriptPlace(scriptPlaceDC, currentFont->ScriptCache(),
|
||||
glyphs, numGlyphs,
|
||||
attr, &items[i].a,
|
||||
advance, offsets, &abc);
|
||||
|
||||
if (rv != S_OK)
|
||||
if (rv == E_PENDING) {
|
||||
scriptPlaceDC = aDC;
|
||||
goto TRY_AGAIN_JUST_PLACE;
|
||||
}
|
||||
|
||||
if (FAILED(rv))
|
||||
printf("error ScriptPlacing\n");
|
||||
#ifdef DEBUG_tor
|
||||
fprintf(stderr, "ABC[%d]: %d %d %d\n", i, abc.abcA, abc.abcB, abc.abcC);
|
||||
#endif
|
||||
|
||||
if (!aDraw) {
|
||||
length += NSToCoordRound((abs(abc.abcA) + abc.abcB + abs(abc.abcC)) * cairoToPixels);
|
||||
|
@ -509,7 +649,7 @@ TRY_AGAIN_SAME_SCRIPT:
|
|||
xform.eDy = dm[5];
|
||||
SetWorldTransform (aDC, &xform);
|
||||
|
||||
ScriptTextOut(aDC, &sc, aX, aY, 0, NULL, &items->a,
|
||||
ScriptTextOut(aDC, currentFont->ScriptCache(), aX, aY, 0, NULL, &items->a,
|
||||
NULL, 0, glyphs, numGlyphs,
|
||||
advance, NULL, offsets);
|
||||
|
||||
|
@ -523,6 +663,12 @@ TRY_AGAIN_SAME_SCRIPT:
|
|||
* We restore the transform to the start of this function while we're drawing.
|
||||
* Need to investigate this further.
|
||||
*/
|
||||
|
||||
if (!fontSelected) {
|
||||
cairo_win32_scaled_font_select_font(scaledFont, aDC);
|
||||
fontSelected = PR_TRUE;
|
||||
}
|
||||
|
||||
SaveDC(aDC);
|
||||
SetWorldTransform(aDC, &savedxform);
|
||||
|
||||
|
@ -564,6 +710,5 @@ TRY_AGAIN_SAME_SCRIPT:
|
|||
if (state)
|
||||
free(state);
|
||||
|
||||
// printf("loops: %d\n", loops - numItems);
|
||||
return length;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,43 @@
|
|||
#include "gfxImageSurface.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
|
||||
nsStringArray *gfxWindowsPlatform::mFontList = nsnull;
|
||||
|
||||
gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
{
|
||||
mFontList = new nsStringArray(20);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
gfxWindowsPlatform::~gfxWindowsPlatform()
|
||||
{
|
||||
delete mFontList;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::Init()
|
||||
{
|
||||
LOGFONT logFont;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfFaceName[0] = 0;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
|
||||
// Use the screen DC here.. should we use something else for printing?
|
||||
HDC dc = ::GetDC(nsnull);
|
||||
EnumFontFamilies(dc, nsnull, gfxWindowsPlatform::FontEnumProc, 0);
|
||||
::ReleaseDC(nsnull, dc);
|
||||
|
||||
mFontList->Sort();
|
||||
|
||||
PRInt32 len = mFontList->Count();
|
||||
for (PRInt32 i = len - 1; i >= 1; --i) {
|
||||
const nsString *string1 = mFontList->StringAt(i);
|
||||
const nsString *string2 = mFontList->StringAt(i-1);
|
||||
if (string1->Equals(*string2))
|
||||
mFontList->RemoveStringAt(i);
|
||||
}
|
||||
mFontList->Compact();
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
|
@ -52,10 +87,52 @@ gfxWindowsPlatform::CreateOffscreenSurface(PRUint32 width,
|
|||
return new gfxWindowsSurface(nsnull, width, height, imageFormat);
|
||||
}
|
||||
|
||||
int CALLBACK
|
||||
gfxWindowsPlatform::FontEnumProc(const LOGFONT *logFont,
|
||||
const TEXTMETRIC *metrics,
|
||||
DWORD fontType, LPARAM data)
|
||||
{
|
||||
// Ignore vertical fonts
|
||||
if (logFont->lfFaceName[0] == '@') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
PRUnichar name[LF_FACESIZE];
|
||||
name[0] = 0;
|
||||
::MultiByteToWideChar(CP_ACP, 0, logFont->lfFaceName,
|
||||
strlen(logFont->lfFaceName) + 1, name,
|
||||
sizeof(name)/sizeof(name[0]));
|
||||
|
||||
mFontList->AppendString(nsDependentString(name));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxWindowsPlatform::GetFontList(const nsACString& aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
nsStringArray& aListOfFonts)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
// XXX we need to pay attention to aLangGroup and aGenericFamily here.
|
||||
aListOfFonts.Clear();
|
||||
aListOfFonts = *mFontList;
|
||||
aListOfFonts.Sort();
|
||||
aListOfFonts.Compact();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
IMultiLanguage *
|
||||
gfxWindowsPlatform::GetMLangService()
|
||||
{
|
||||
if (!mMLang) {
|
||||
HRESULT rv;
|
||||
nsRefPtr<IMultiLanguage> multiLanguage;
|
||||
rv = CoCreateInstance(CLSID_CMultiLanguage, NULL,
|
||||
CLSCTX_ALL, IID_IMultiLanguage, getter_AddRefs(mMLang));
|
||||
if (FAILED(rv))
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return mMLang;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче