partial fix for font fallbacks. bug 324560. also fixes 324712. r=vlad

This commit is contained in:
pavlov%pavlov.net 2006-02-24 05:15:21 +00:00
Родитель 8895e6b3ba
Коммит 0fe1ba3ddd
14 изменённых файлов: 351 добавлений и 65 удалений

Просмотреть файл

@ -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;
}