зеркало из https://github.com/mozilla/gecko-dev.git
yet another patch from Owen Taylor <otaylor@redhat.com> that impliments
nsFontMetricsGTK
This commit is contained in:
Родитель
0ae3117b58
Коммит
a8799e5126
|
@ -16,10 +16,13 @@
|
|||
* Reserved.
|
||||
*/
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "xp_core.h"
|
||||
#include "nsFontMetricsGTK.h"
|
||||
#include "nspr.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
|
||||
|
@ -27,87 +30,336 @@ static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
|
|||
nsFontMetricsGTK :: nsFontMetricsGTK()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFont = nsnull;
|
||||
mFontHandle = nsnull;
|
||||
}
|
||||
|
||||
nsFontMetricsGTK :: ~nsFontMetricsGTK()
|
||||
{
|
||||
if (nsnull != mFont) {
|
||||
delete mFont;
|
||||
mFont = nsnull;
|
||||
}
|
||||
|
||||
if (nsnull != mFontHandle) {
|
||||
gdk_font_unref (mFontHandle);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsFontMetricsGTK, kIFontMetricsIID)
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::Init(const nsFont& aFont, nsIDeviceContext* aContext)
|
||||
{
|
||||
NS_ASSERTION(!(nsnull == aContext), "attempt to init fontmetrics with null device context");
|
||||
|
||||
nsAutoString firstFace;
|
||||
if (NS_OK != aContext->FirstExistingFont(aFont, firstFace)) {
|
||||
aFont.GetFirstFamily(firstFace);
|
||||
}
|
||||
|
||||
char **fnames = nsnull;
|
||||
PRInt32 namelen = firstFace.Length() + 1;
|
||||
char *wildstring = (char *)PR_Malloc((namelen << 1) + 200);
|
||||
int numnames = 0;
|
||||
char altitalicization = 0;
|
||||
XFontStruct *fonts;
|
||||
float t2d;
|
||||
aContext->GetTwipsToDevUnits(t2d);
|
||||
PRInt32 dpi = NSToIntRound(t2d * 1440);
|
||||
|
||||
if (nsnull == wildstring)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
mFont = new nsFont(aFont);
|
||||
mContext = aContext;
|
||||
mFontHandle = nsnull;
|
||||
|
||||
firstFace.ToCString(wildstring, namelen);
|
||||
|
||||
if (abs(dpi - 75) < abs(dpi - 100))
|
||||
dpi = 75;
|
||||
else
|
||||
dpi = 100;
|
||||
|
||||
#ifdef NOISY_FONTS
|
||||
fprintf(stderr, "looking for font %s (%d)", wildstring, aFont.size / 20);
|
||||
#endif
|
||||
|
||||
//font properties we care about:
|
||||
//name
|
||||
//weight (bold, medium)
|
||||
//slant (r = normal, i = italic, o = oblique)
|
||||
//size in nscoords >> 1
|
||||
|
||||
PR_snprintf(&wildstring[namelen + 1], namelen + 200,
|
||||
"*-%s-%s-%c-normal--*-*-%d-%d-*-*-*",
|
||||
wildstring,
|
||||
(aFont.weight <= NS_FONT_WEIGHT_NORMAL) ? "medium" : "bold",
|
||||
(aFont.style == NS_FONT_STYLE_NORMAL) ? 'r' :
|
||||
((aFont.style == NS_FONT_STYLE_ITALIC) ? 'i' : 'o'), dpi, dpi);
|
||||
|
||||
fnames = ::XListFontsWithInfo(GDK_DISPLAY(), &wildstring[namelen + 1], 200, &numnames, &fonts);
|
||||
|
||||
if (aFont.style == NS_FONT_STYLE_ITALIC)
|
||||
altitalicization = 'o';
|
||||
else if (aFont.style == NS_FONT_STYLE_OBLIQUE)
|
||||
altitalicization = 'i';
|
||||
|
||||
if ((numnames <= 0) && altitalicization)
|
||||
{
|
||||
PR_snprintf(&wildstring[namelen + 1], namelen + 200,
|
||||
"*-%s-%s-%c-normal--*-*-%d-%d-*-*-*",
|
||||
wildstring,
|
||||
(aFont.weight <= NS_FONT_WEIGHT_NORMAL) ? "medium" : "bold",
|
||||
altitalicization, dpi, dpi);
|
||||
|
||||
fnames = ::XListFontsWithInfo(GDK_DISPLAY(), &wildstring[namelen + 1], 200, &numnames, &fonts);
|
||||
}
|
||||
|
||||
|
||||
if (numnames <= 0)
|
||||
{
|
||||
//we were not able to match the font name at all...
|
||||
|
||||
char *newname = firstFace.ToNewCString();
|
||||
|
||||
PR_snprintf(&wildstring[namelen + 1], namelen + 200,
|
||||
"*-%s-%s-%c-normal--*-*-%d-%d-*-*-*",
|
||||
newname,
|
||||
(aFont.weight <= NS_FONT_WEIGHT_NORMAL) ? "medium" : "bold",
|
||||
(aFont.style == NS_FONT_STYLE_NORMAL) ? 'r' :
|
||||
((aFont.style == NS_FONT_STYLE_ITALIC) ? 'i' : 'o'), dpi, dpi);
|
||||
|
||||
fnames = ::XListFontsWithInfo(GDK_DISPLAY(), &wildstring[namelen + 1], 200, &numnames, &fonts);
|
||||
|
||||
if ((numnames <= 0) && altitalicization)
|
||||
{
|
||||
PR_snprintf(&wildstring[namelen + 1], namelen + 200,
|
||||
"*-%s-%s-%c-normal--*-*-%d-%d-*-*-*",
|
||||
newname,
|
||||
(aFont.weight <= NS_FONT_WEIGHT_NORMAL) ? "medium" : "bold",
|
||||
altitalicization, dpi, dpi);
|
||||
|
||||
fnames = ::XListFontsWithInfo(GDK_DISPLAY(), &wildstring[namelen + 1], 200, &numnames, &fonts);
|
||||
}
|
||||
|
||||
delete [] newname;
|
||||
}
|
||||
|
||||
if (numnames > 0)
|
||||
{
|
||||
char *nametouse = PickAppropriateSize(fnames, fonts, numnames, aFont.size);
|
||||
|
||||
mFontHandle = ::gdk_font_load(nametouse);
|
||||
|
||||
#ifdef NOISY_FONTS
|
||||
fprintf(stderr, " is: %s\n", nametouse);
|
||||
#endif
|
||||
|
||||
::XFreeFontInfo(fnames, fonts, numnames);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ack. we're in real trouble, go for fixed...
|
||||
|
||||
#ifdef NOISY_FONTS
|
||||
fprintf(stderr, " is: %s\n", "fixed (final fallback)");
|
||||
#endif
|
||||
|
||||
mFontHandle = ::gdk_font_load("fixed");
|
||||
}
|
||||
|
||||
RealizeFont();
|
||||
|
||||
PR_Free(wildstring);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::Destroy()
|
||||
{
|
||||
// NS_IF_RELEASE(mDeviceContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char * nsFontMetricsGTK::PickAppropriateSize(char **names, XFontStruct *fonts, int cnt, nscoord desired)
|
||||
{
|
||||
int idx;
|
||||
float app2dev;
|
||||
mContext->GetAppUnitsToDevUnits(app2dev);
|
||||
PRInt32 desiredpix = NSToIntRound(app2dev * desired);
|
||||
XFontStruct *curfont;
|
||||
PRInt32 closestmin = -1, minidx;
|
||||
|
||||
//first try an exact or closest smaller match...
|
||||
|
||||
for (idx = 0, curfont = fonts; idx < cnt; idx++, curfont++)
|
||||
{
|
||||
PRInt32 height = curfont->ascent + curfont->descent;
|
||||
|
||||
if (height == desiredpix)
|
||||
break;
|
||||
|
||||
if ((height < desiredpix) && (height > closestmin))
|
||||
{
|
||||
closestmin = height;
|
||||
minidx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx < cnt)
|
||||
return names[idx];
|
||||
else if (closestmin >= 0)
|
||||
return names[minidx];
|
||||
else
|
||||
{
|
||||
closestmin = 2000000;
|
||||
|
||||
for (idx = 0, curfont = fonts; idx < cnt; idx++, curfont++)
|
||||
{
|
||||
PRInt32 height = curfont->ascent + curfont->descent;
|
||||
|
||||
if ((height > desiredpix) && (height < closestmin))
|
||||
{
|
||||
closestmin = height;
|
||||
minidx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
return names[minidx];
|
||||
}
|
||||
}
|
||||
|
||||
void nsFontMetricsGTK::RealizeFont()
|
||||
{
|
||||
nsNativeWidget widget;
|
||||
mContext->GetNativeWidget(widget);
|
||||
XFontStruct *fontInfo;
|
||||
|
||||
fontInfo = (XFontStruct *)GDK_FONT_XFONT(mFontHandle);
|
||||
|
||||
float f;
|
||||
mContext->GetDevUnitsToAppUnits(f);
|
||||
|
||||
mAscent = nscoord(fontInfo->ascent * f);
|
||||
mDescent = nscoord(fontInfo->descent * f);
|
||||
mMaxAscent = nscoord(fontInfo->ascent * f) ;
|
||||
mMaxDescent = nscoord(fontInfo->descent * f);
|
||||
|
||||
mHeight = nscoord((fontInfo->ascent + fontInfo->descent) * f) ;
|
||||
mMaxAdvance = nscoord(fontInfo->max_bounds.width * f);
|
||||
|
||||
PRUint32 i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if ((i < fontInfo->min_char_or_byte2) || (i > fontInfo->max_char_or_byte2))
|
||||
mCharWidths[i] = mMaxAdvance;
|
||||
else
|
||||
mCharWidths[i] = nscoord((fontInfo->per_char[i - fontInfo->min_char_or_byte2].width) * f);
|
||||
}
|
||||
|
||||
mLeading = 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetXHeight(nscoord& aResult)
|
||||
{
|
||||
aResult = mMaxAscent / 2; // XXX temporary code!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetSuperscriptOffset(nscoord& aResult)
|
||||
{
|
||||
aResult = mMaxAscent / 2; // XXX temporary code!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetSubscriptOffset(nscoord& aResult)
|
||||
{
|
||||
aResult = mMaxAscent / 2; // XXX temporary code!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetStrikeout(nscoord& aOffset, nscoord& aSize)
|
||||
{
|
||||
aOffset = 0; /* XXX */
|
||||
aSize = 0; /* XXX */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetUnderline(nscoord& aOffset, nscoord& aSize)
|
||||
{
|
||||
aOffset = 0; /* XXX */
|
||||
aSize = 0; /* XXX */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetHeight(nscoord &aHeight)
|
||||
{
|
||||
aHeight = mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetLeading(nscoord &aLeading)
|
||||
{
|
||||
aLeading = mLeading;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetMaxAscent(nscoord &aAscent)
|
||||
{
|
||||
aAscent = mMaxAscent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetMaxDescent(nscoord &aDescent)
|
||||
{
|
||||
aDescent = mMaxDescent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetMaxAdvance(nscoord &aAdvance)
|
||||
{
|
||||
aAdvance = mMaxAdvance;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetFont(const nsFont*& aFont)
|
||||
{
|
||||
aFont = mFont;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFontMetricsGTK::GetFontHandle(nsFontHandle &aHandle)
|
||||
{
|
||||
aHandle = (nsFontHandle)mFontHandle;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX unused???
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MapGenericFamilyToFont(const nsString& aGenericFamily, nsIDeviceContext* aDC,
|
||||
nsString& aFontFace)
|
||||
{
|
||||
// the CSS generic names (conversions from Nav for now)
|
||||
// XXX this need to check availability with the dc
|
||||
PRBool aliased;
|
||||
if (aGenericFamily.EqualsIgnoreCase("serif")) {
|
||||
aDC->GetLocalFontName("times", aFontFace, aliased);
|
||||
}
|
||||
else if (aGenericFamily.EqualsIgnoreCase("sans-serif")) {
|
||||
aDC->GetLocalFontName("helvetica", aFontFace, aliased);
|
||||
}
|
||||
else if (aGenericFamily.EqualsIgnoreCase("cursive")) {
|
||||
aDC->GetLocalFontName("script", aFontFace, aliased); // XXX ???
|
||||
}
|
||||
else if (aGenericFamily.EqualsIgnoreCase("fantasy")) {
|
||||
aDC->GetLocalFontName("helvetica", aFontFace, aliased);
|
||||
}
|
||||
else if (aGenericFamily.EqualsIgnoreCase("monospace")) {
|
||||
aDC->GetLocalFontName("fixed", aFontFace, aliased);
|
||||
}
|
||||
else {
|
||||
aFontFace.Truncate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include "nsIDeviceContext.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
class nsFontMetricsGTK : public nsIFontMetrics
|
||||
{
|
||||
|
@ -61,7 +62,20 @@ public:
|
|||
NS_IMETHOD GetFontHandle(nsFontHandle &aHandle);
|
||||
|
||||
protected:
|
||||
char *PickAppropriateSize(char **names, XFontStruct *fonts, int cnt, nscoord desired);
|
||||
void RealizeFont();
|
||||
|
||||
nsFont *mFont;
|
||||
nsIDeviceContext *mContext;
|
||||
GdkFont *mFontHandle;
|
||||
nscoord mCharWidths[256];
|
||||
nscoord mHeight;
|
||||
nscoord mAscent;
|
||||
nscoord mDescent;
|
||||
nscoord mLeading;
|
||||
nscoord mMaxAscent;
|
||||
nscoord mMaxDescent;
|
||||
nscoord mMaxAdvance;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -87,8 +87,38 @@ nsRenderingContextGTK :: nsRenderingContextGTK()
|
|||
|
||||
nsRenderingContextGTK :: ~nsRenderingContextGTK()
|
||||
{
|
||||
NS_IF_RELEASE(mContext);
|
||||
if (mRegion) {
|
||||
::gdk_region_destroy(mRegion);
|
||||
mRegion = nsnull;
|
||||
}
|
||||
|
||||
mTMatrix = nsnull;
|
||||
|
||||
// Destroy the State Machine
|
||||
if (nsnull != mStateCache)
|
||||
{
|
||||
PRInt32 cnt = mStateCache->Count();
|
||||
|
||||
while (--cnt >= 0)
|
||||
{
|
||||
GraphicsState *state = (GraphicsState *)mStateCache->ElementAt(cnt);
|
||||
mStateCache->RemoveElementAt(cnt);
|
||||
|
||||
if (nsnull != state)
|
||||
delete state;
|
||||
}
|
||||
|
||||
delete mStateCache;
|
||||
mStateCache = nsnull;
|
||||
}
|
||||
|
||||
// Destroy the front buffer and it's GC if one was allocated for it
|
||||
if (nsnull != mOffscreenSurface) {
|
||||
delete mOffscreenSurface;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mFontMetrics);
|
||||
NS_IF_RELEASE(mContext);
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE(nsRenderingContextGTK, kRenderingContextIID)
|
||||
|
@ -107,7 +137,9 @@ NS_IMETHODIMP nsRenderingContextGTK::Init(nsIDeviceContext* aContext,
|
|||
mRenderingSurface->drawable = (GdkDrawable *)aWindow->GetNativeData(NS_NATIVE_WINDOW);
|
||||
mRenderingSurface->gc = (GdkGC *)aWindow->GetNativeData(NS_NATIVE_GRAPHIC);
|
||||
|
||||
return NS_OK;
|
||||
mOffscreenSurface = mRenderingSurface;
|
||||
|
||||
return (CommonInit());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::Init(nsIDeviceContext* aContext,
|
||||
|
@ -117,6 +149,17 @@ NS_IMETHODIMP nsRenderingContextGTK::Init(nsIDeviceContext* aContext,
|
|||
NS_IF_ADDREF(mContext);
|
||||
|
||||
mRenderingSurface = (nsDrawingSurfaceGTK *) aSurface;
|
||||
|
||||
return (CommonInit());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::CommonInit()
|
||||
{
|
||||
mContext->GetDevUnitsToAppUnits(mP2T);
|
||||
float app2dev;
|
||||
mContext->GetAppUnitsToDevUnits(app2dev);
|
||||
mTMatrix->AddScale(app2dev, app2dev);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -874,12 +917,6 @@ nsRenderingContextGTK::CopyOffScreenBits(nsDrawingSurface aSrcSurf,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//locals
|
||||
NS_IMETHODIMP nsRenderingContextGTK::CommonInit()
|
||||
{
|
||||
mContext->GetDevUnitsToAppUnits(mP2T);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRenderingContextGTK::SetClipRectInPixels(const nsRect& aRect,
|
||||
nsClipCombine aCombine,
|
||||
|
|
Загрузка…
Ссылка в новой задаче