From a8799e51260ba8fe1b8b9f007baaa879d5ed8253 Mon Sep 17 00:00:00 2001 From: "pavlov%pavlov.net" Date: Sat, 7 Nov 1998 23:21:18 +0000 Subject: [PATCH] yet another patch from Owen Taylor that impliments nsFontMetricsGTK --- gfx/src/gtk/nsFontMetricsGTK.cpp | 264 +++++++++++++++++++++++++- gfx/src/gtk/nsFontMetricsGTK.h | 16 +- gfx/src/gtk/nsRenderingContextGTK.cpp | 53 +++++- 3 files changed, 318 insertions(+), 15 deletions(-) diff --git a/gfx/src/gtk/nsFontMetricsGTK.cpp b/gfx/src/gtk/nsFontMetricsGTK.cpp index 61e489d056fb..2114d5f98e69 100644 --- a/gfx/src/gtk/nsFontMetricsGTK.cpp +++ b/gfx/src/gtk/nsFontMetricsGTK.cpp @@ -16,10 +16,13 @@ * Reserved. */ -#include - #include "xp_core.h" #include "nsFontMetricsGTK.h" +#include "nspr.h" + +#include +#include + 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(); + } +} diff --git a/gfx/src/gtk/nsFontMetricsGTK.h b/gfx/src/gtk/nsFontMetricsGTK.h index d88eeb812190..61198fdac074 100644 --- a/gfx/src/gtk/nsFontMetricsGTK.h +++ b/gfx/src/gtk/nsFontMetricsGTK.h @@ -26,7 +26,8 @@ #include "nsIDeviceContext.h" #include "nsCRT.h" -#include +#include +#include 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 diff --git a/gfx/src/gtk/nsRenderingContextGTK.cpp b/gfx/src/gtk/nsRenderingContextGTK.cpp index 8e262a3b5fe5..f4ef8166de91 100644 --- a/gfx/src/gtk/nsRenderingContextGTK.cpp +++ b/gfx/src/gtk/nsRenderingContextGTK.cpp @@ -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,