yet another patch from Owen Taylor <otaylor@redhat.com> that impliments

nsFontMetricsGTK
This commit is contained in:
pavlov%pavlov.net 1998-11-07 23:21:18 +00:00
Родитель 0ae3117b58
Коммит a8799e5126
3 изменённых файлов: 318 добавлений и 15 удалений

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

@ -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,